/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./node_modules/eventemitter3/index.js": /*!*********************************************!*\ !*** ./node_modules/eventemitter3/index.js ***! \*********************************************/ /***/ ((module) => { var has = Object.prototype.hasOwnProperty , prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new Events().__proto__) prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') { throw new TypeError('The listener must be a function'); } var listener = new EE(fn, context || emitter, once) , evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function EventEmitter() { this._events = new Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ EventEmitter.prototype.eventNames = function eventNames() { var names = [] , events , name; if (this._eventsCount === 0) return names; for (name in (events = this._events)) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ EventEmitter.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event , handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event , listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if ( listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context) ) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Allow `EventEmitter` to be imported as module namespace. // EventEmitter.EventEmitter = EventEmitter; // // Expose the module. // if (true) { module.exports = EventEmitter; } /***/ }), /***/ "./src/extensions/formTypeEx.ts": /*!**************************************!*\ !*** ./src/extensions/formTypeEx.ts ***! \**************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FormTypeEx: () => (/* binding */ FormTypeEx) /* harmony export */ }); var FormTypeEx = /** @class */ (function () { function FormTypeEx() { } FormTypeEx.isItem = function (type) { return type === 42 /* FormType.Ammo */ || type === 26 /* FormType.Armor */ || type === 27 /* FormType.Book */ || type === 30 /* FormType.Ingredient */ || type === 31 /* FormType.Light */ || type === 46 /* FormType.Potion */ || type === 23 /* FormType.ScrollItem */ || type === 52 /* FormType.SoulGem */ || type === 41 /* FormType.Weapon */ || type === 32 /* FormType.Misc */; }; return FormTypeEx; }()); /***/ }), /***/ "./src/extensions/objectReferenceEx.ts": /*!*********************************************!*\ !*** ./src/extensions/objectReferenceEx.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ObjectReferenceEx: () => (/* binding */ ObjectReferenceEx) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _formTypeEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./formTypeEx */ "./src/extensions/formTypeEx.ts"); var ObjectReferenceEx = /** @class */ (function () { function ObjectReferenceEx() { } ObjectReferenceEx.getWorldOrCell = function (self) { var world = self.getWorldSpace(); if (world) { return world.getFormID(); } var cell = self.getParentCell(); if (cell) { return cell.getFormID(); } return 0; }; ObjectReferenceEx.getPos = function (self) { return [self.getPositionX(), self.getPositionY(), self.getPositionZ()]; }; ; ObjectReferenceEx.getDistance = function (a, b) { var deltaX = a[0] - b[0]; var deltaY = a[1] - b[1]; var deltaZ = a[2] - b[2]; return Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); }; ; ObjectReferenceEx.getDistanceNoZ = function (a, b) { var deltaX = a[0] - b[0]; var deltaY = a[1] - b[1]; return Math.sqrt(deltaX * deltaX + deltaY * deltaY); }; ; ObjectReferenceEx.dealWithRef = function (self, base) { var _a, _b; var t = base.getType(); var isItem = _formTypeEx__WEBPACK_IMPORTED_MODULE_1__.FormTypeEx.isItem(t); // BlackFallsBarrow02, door isn't opening via SetOpen so we're hacking it. // Not blocking activation & asking parent to activate until will be in the correct state // See also modelApplyUtils.ts var caveGSecretDoor01 = 0x6f703; // You can also block for t === FormType.Flora || t === FormType.Tree, but I don't think it's necessary. if (t === 40 /* FormType.Furniture */ || t === 24 /* FormType.Activator */ || t === 28 /* FormType.Container */ || isItem || t === 43 /* FormType.NPC */ || (t === 29 /* FormType.Door */ && ((_a = self.getBaseObject()) === null || _a === void 0 ? void 0 : _a.getFormID()) !== caveGSecretDoor01)) { self.blockActivation(true); } else { self.blockActivation(false); } if (self.isLocked()) { self.lock(false, false); } if (isItem) { self.setMotionType(4 /* MotionType.Keyframed */, false); } // https://github.com/skyrim-multiplayer/issue-tracker/issues/36 if (t === 39 /* FormType.Flora */ && ((_b = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Flora.from(base)) === null || _b === void 0 ? void 0 : _b.getIngredient())) { self.setMotionType(4 /* MotionType.Keyframed */, false); } }; return ObjectReferenceEx; }()); /***/ }), /***/ "./src/features/authModel.ts": /*!***********************************!*\ !*** ./src/features/authModel.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ authGameDataStorageKey: () => (/* binding */ authGameDataStorageKey) /* harmony export */ }); ; ; ; var authGameDataStorageKey = "authGameData"; /***/ }), /***/ "./src/lib/errors.ts": /*!***************************!*\ !*** ./src/lib/errors.ts ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ NeverError: () => (/* binding */ NeverError), /* harmony export */ RespawnNeededError: () => (/* binding */ RespawnNeededError) /* harmony export */ }); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var RespawnNeededError = /** @class */ (function (_super) { __extends(RespawnNeededError, _super); function RespawnNeededError(message) { var _this = _super.call(this, message) || this; Object.setPrototypeOf(_this, RespawnNeededError.prototype); return _this; } return RespawnNeededError; }(Error)); var NeverError = /** @class */ (function (_super) { __extends(NeverError, _super); function NeverError(message) { var _this = _super.call(this, "NeverError: ".concat(JSON.stringify(message))) || this; Object.setPrototypeOf(_this, NeverError.prototype); return _this; } return NeverError; }(Error)); /***/ }), /***/ "./src/lib/functionInfo.ts": /*!*********************************!*\ !*** ./src/lib/functionInfo.ts ***! \*********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FunctionInfo: () => (/* binding */ FunctionInfo) /* harmony export */ }); var FunctionInfo = /** @class */ (function () { function FunctionInfo(f) { this.f = f; } Object.defineProperty(FunctionInfo.prototype, "text", { get: function () { // this part is different to functionInfo.ts used in skymp5-functions-lib return this.getTextWithoutErrorHandling(); }, enumerable: false, configurable: true }); FunctionInfo.prototype.getText = function (args) { if (!args) { return this.text; } return "(function(){const {".concat(Object.keys(args).join(','), "} = ").concat(JSON.stringify(args), ";").concat(this.text, "})()"); }; FunctionInfo.prototype.getTextWithoutErrorHandling = function () { var funcString = this.f.toString().substring(0, this.f.toString().length - 1); return funcString.replace(new RegExp('^.+?{', 'm'), '').trim(); }; return FunctionInfo; }()); /***/ }), /***/ "./src/lib/idManager.ts": /*!******************************!*\ !*** ./src/lib/idManager.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ IdManager: () => (/* binding */ IdManager) /* harmony export */ }); var IdManager = /** @class */ (function () { function IdManager() { this.idByValue = new Array(); this.valueById = new Array(); this.minimumUnusedId = 0; } IdManager.prototype.allocateIdFor = function (value) { if (this.idByValue.length <= value) { this.idByValue.length = value + 1; } this.idByValue[value] = this.minimumUnusedId; if (this.valueById.length <= this.minimumUnusedId) { this.valueById.length = this.minimumUnusedId + 1; } this.valueById[this.minimumUnusedId] = value; var res = this.minimumUnusedId; this.minimumUnusedId++; while (this.valueById.length > this.minimumUnusedId && typeof this.valueById[this.minimumUnusedId] === "number") { this.minimumUnusedId++; } return res; }; IdManager.prototype.freeIdFor = function (value) { var id = this.idByValue[value]; if (id < this.minimumUnusedId) { this.minimumUnusedId = id; } this.idByValue[value] = undefined; this.valueById[id] = undefined; return; }; IdManager.prototype.getId = function (value) { var r = this.idByValue[value]; return typeof r === "number" ? r : -1; }; IdManager.prototype.getValueById = function (id) { return this.valueById[id]; }; return IdManager; }()); /***/ }), /***/ "./src/lib/nameof.ts": /*!***************************!*\ !*** ./src/lib/nameof.ts ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ nameof: () => (/* binding */ nameof) /* harmony export */ }); function nameof(key) { return key; } /***/ }), /***/ "./src/logging.ts": /*!************************!*\ !*** ./src/logging.ts ***! \************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ logError: () => (/* binding */ logError), /* harmony export */ logTrace: () => (/* binding */ logTrace) /* harmony export */ }); /* harmony import */ var _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @skyrim-platform/skyrim-platform */ "skyrimPlatform"); /* harmony import */ var _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__); var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; // TODO: redirect this to spdlog function logError(service) { var rest = []; for (var _i = 1; _i < arguments.length; _i++) { rest[_i - 1] = arguments[_i]; } var restProcessed = rest.map(function (item) { if (item instanceof Error) { return item.stack || item.message; } return item; }); _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__.printConsole.apply(void 0, __spreadArray(["Error in ".concat(typeof service !== "string" ? service.constructor.name : service, ":")], restProcessed, false)); } // TODO: redirect this to spdlog function logTrace(service) { var rest = []; for (var _i = 1; _i < arguments.length; _i++) { rest[_i - 1] = arguments[_i]; } var restProcessed = rest.map(function (item) { if (item instanceof Error) { return item.stack || item.message; } return item; }); _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__.printConsole.apply(void 0, __spreadArray(["Trace in ".concat(typeof service !== "string" ? service.constructor.name : service, ":")], restProcessed, false)); } /***/ }), /***/ "./src/messages.ts": /*!*************************!*\ !*** ./src/messages.ts ***! \*************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MsgType: () => (/* binding */ MsgType) /* harmony export */ }); var MsgType; (function (MsgType) { MsgType[MsgType["CustomPacket"] = 1] = "CustomPacket"; MsgType[MsgType["UpdateMovement"] = 2] = "UpdateMovement"; MsgType[MsgType["UpdateAnimation"] = 3] = "UpdateAnimation"; MsgType[MsgType["UpdateAppearance"] = 4] = "UpdateAppearance"; MsgType[MsgType["UpdateEquipment"] = 5] = "UpdateEquipment"; MsgType[MsgType["Activate"] = 6] = "Activate"; MsgType[MsgType["UpdateProperty"] = 7] = "UpdateProperty"; MsgType[MsgType["PutItem"] = 8] = "PutItem"; MsgType[MsgType["TakeItem"] = 9] = "TakeItem"; MsgType[MsgType["FinishSpSnippet"] = 10] = "FinishSpSnippet"; MsgType[MsgType["OnEquip"] = 11] = "OnEquip"; MsgType[MsgType["ConsoleCommand"] = 12] = "ConsoleCommand"; MsgType[MsgType["CraftItem"] = 13] = "CraftItem"; MsgType[MsgType["Host"] = 14] = "Host"; MsgType[MsgType["CustomEvent"] = 15] = "CustomEvent"; MsgType[MsgType["ChangeValues"] = 16] = "ChangeValues"; MsgType[MsgType["OnHit"] = 17] = "OnHit"; MsgType[MsgType["DeathStateContainer"] = 18] = "DeathStateContainer"; MsgType[MsgType["DropItem"] = 19] = "DropItem"; MsgType[MsgType["Teleport"] = 20] = "Teleport"; MsgType[MsgType["OpenContainer"] = 21] = "OpenContainer"; MsgType[MsgType["PlayerBowShot"] = 22] = "PlayerBowShot"; MsgType[MsgType["SpellCast"] = 23] = "SpellCast"; MsgType[MsgType["UpdateAnimVariables"] = 24] = "UpdateAnimVariables"; // ex-strings MsgType[MsgType["DestroyActor"] = 25] = "DestroyActor"; MsgType[MsgType["HostStart"] = 26] = "HostStart"; MsgType[MsgType["HostStop"] = 27] = "HostStop"; MsgType[MsgType["SetInventory"] = 28] = "SetInventory"; MsgType[MsgType["SetRaceMenuOpen"] = 29] = "SetRaceMenuOpen"; MsgType[MsgType["SpSnippet"] = 30] = "SpSnippet"; MsgType[MsgType["Teleport2"] = 31] = "Teleport2"; MsgType[MsgType["UpdateGamemodeData"] = 32] = "UpdateGamemodeData"; MsgType[MsgType["CreateActor"] = 33] = "CreateActor"; })(MsgType || (MsgType = {})); /***/ }), /***/ "./src/services/events/events.ts": /*!***************************************!*\ !*** ./src/services/events/events.ts ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EventEmitterFactory: () => (/* binding */ EventEmitterFactory) /* harmony export */ }); /* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.mjs"); var EventEmitterFactory = /** @class */ (function () { function EventEmitterFactory() { } EventEmitterFactory.makeEventEmitter = function () { return (new eventemitter3__WEBPACK_IMPORTED_MODULE_0__.EventEmitter()); }; return EventEmitterFactory; }()); /***/ }), /***/ "./src/services/services/activationService.ts": /*!****************************************************!*\ !*** ./src/services/services/activationService.ts ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ActivationService: () => (/* binding */ ActivationService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _sync_inventory__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../sync/inventory */ "./src/sync/inventory.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _lastInvService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lastInvService */ "./src/services/services/lastInvService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _extensions_formTypeEx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../extensions/formTypeEx */ "./src/extensions/formTypeEx.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out var ActivationService = /** @class */ (function (_super) { __extends(ActivationService, _super); function ActivationService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.on("activate", function (e) { return _this.onActivate(e); }); return _this; } ActivationService.prototype.onActivate = function (e) { var lastInvService = this.controller.lookupListener(_lastInvService__WEBPACK_IMPORTED_MODULE_4__.LastInvService); lastInvService.lastInv = (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_2__.getInventory)(this.sp.Game.getPlayer()); var caster = e.caster ? e.caster.getFormID() : 0; var target = e.target ? e.target.getFormID() : 0; if (!target || !caster) { return; } // Bloquear el "agarre" de items sueltos del mundo: si el target es // un item (clutter de la ciudad, etc.), no mandamos el Activate al // server, asi nunca pasa al inventario. La activacion vanilla ya // esta bloqueada por ObjectReferenceEx.dealWithRef, asi que apretar // E sobre el item no hace nada. Puertas / contenedores / NPCs no se // ven afectados — solo los FormType de item (FormTypeEx.isItem). var targetBase = e.target ? e.target.getBaseObject() : null; if (targetBase && _extensions_formTypeEx__WEBPACK_IMPORTED_MODULE_6__.FormTypeEx.isItem(targetBase.getType())) { return; } // Actors never have non-ff ids locally in skymp if (caster !== 0x14 && caster < 0xff000000) { return; } target = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_3__.localIdToRemoteId)(target); if (!target) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logError)(this, 'localIdToRemoteId returned 0 (target) in on(\'activate\')'); return; } caster = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_3__.localIdToRemoteId)(caster); if (!caster) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logError)(this, 'localIdToRemoteId returned 0 (caster) in on(\'activate\')'); return; } var openState = e.target.getOpenState(); if (openState === 2 /* OpenState.Opening */ || openState === 4 /* OpenState.Closing */) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Ignoring activation of door because it's already opening or closing"); return; } this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.Activate, data: { caster: caster, target: target, isSecondActivation: false } }, reliability: "reliable" }); (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Sent activation for caster=", caster.toString(16), "and target=", target.toString(16)); }; return ActivationService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); ; /***/ }), /***/ "./src/services/services/animDebugService.ts": /*!***************************************************!*\ !*** ./src/services/services/animDebugService.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnimDebugService: () => (/* binding */ AnimDebugService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (undefined && undefined.__assign) || function () { __assign = Object.assign || function(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); }; var playerId = 0x14; var AnimDebugService = /** @class */ (function (_super) { __extends(AnimDebugService, _super); function AnimDebugService(sp, controller) { var _this = this; var _a; _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.settings = _this.sp.settings["skymp5-client"]["animDebug"]; // clear previous texts in case of hotreload if (_this.sp.storage[AnimQueueCollection.Name] && _this.sp.storage[AnimQueueCollection.Name].clearSPText) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "Destroying old AnimQueueCollection"); try { _this.sp.storage[AnimQueueCollection.Name].clearSPText(); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "Failed to destroy old AnimQueueCollection:", e); } } var self = _this; _this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { }, leave: function (ctx) { self.onSendAnimationEventLeave(ctx); } }, playerId, playerId); if (!_this.settings || !_this.settings.isActive) { return _this; } if ((_a = _this.settings.textOutput) === null || _a === void 0 ? void 0 : _a.isActive) { _this.queue = new AnimQueueCollection(_this.sp, _this.settings); _this.sp.storage[AnimQueueCollection.name] = _this.queue; } return _this; } AnimDebugService.prototype.onSendAnimationEventLeave = function (ctx) { if (this.queue === undefined) { return; } this.queue.push(ctx.animEventName, ctx.animationSucceeded ? animationSucceededTextColor : animationNotSucceededTextColor); }; return AnimDebugService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); var animationSucceededTextColor = [255, 255, 255, 1]; var animationNotSucceededTextColor = [255, 0, 0, 1]; var AnimQueueCollection = /** @class */ (function () { function AnimQueueCollection(sp, settings) { var _a, _b, _c, _d, _e, _f; this.sp = sp; var arrayLength = (_b = (_a = settings === null || settings === void 0 ? void 0 : settings.textOutput) === null || _a === void 0 ? void 0 : _a.itemCount) !== null && _b !== void 0 ? _b : 5; var startPos = (_d = (_c = settings === null || settings === void 0 ? void 0 : settings.textOutput) === null || _c === void 0 ? void 0 : _c.startPos) !== null && _d !== void 0 ? _d : { x: 650, y: 600 }; ; var yPosDelta = (_f = (_e = settings === null || settings === void 0 ? void 0 : settings.textOutput) === null || _e === void 0 ? void 0 : _e.yPosDelta) !== null && _f !== void 0 ? _f : 32; var y = startPos.y; this.list = new Array(arrayLength); for (var idx = 0; idx < arrayLength; ++idx) { this.list[idx] = { name: "", textId: sp.createText(startPos.x, y, "", animationSucceededTextColor), color: animationSucceededTextColor }; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__.setTextSize)(this.list[idx].textId, 0.5); y += yPosDelta; } } AnimQueueCollection.prototype.clearSPText = function () { var _this = this; if (this.list.length === 0) { return; } this.list.forEach(function (item) { return _this.sp.destroyText(item.textId); }); }; AnimQueueCollection.prototype.push = function (animName, color) { var prevItem = null; for (var idx = this.list.length - 1; idx >= 0; --idx) { var item = this.list[idx]; prevItem = __assign({}, item); item.name = animName; item.color = color; this.sp.setTextString(item.textId, item.name); this.sp.setTextColor(item.textId, item.color); animName = prevItem.name; color = prevItem.color; } }; AnimQueueCollection.Name = "AnimQueueCollection"; return AnimQueueCollection; }()); /***/ }), /***/ "./src/services/services/authService.ts": /*!**********************************************!*\ !*** ./src/services/services/authService.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AuthService: () => (/* binding */ AuthService) /* harmony export */ }); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! crypto */ "crypto"); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ "fs"); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _features_authModel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../features/authModel */ "./src/features/authModel.ts"); /* harmony import */ var _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../lib/functionInfo */ "./src/lib/functionInfo.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var _timersService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./timersService */ "./src/services/services/timersService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _networkingService__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./networkingService */ "./src/services/services/networkingService.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _settingsService__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./settingsService */ "./src/services/services/settingsService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // Constants used on both client and browser side (see browsersideWidgetSetter) var events = { openDiscordOauth: 'openDiscordOauth', authAttempt: 'authAttemptEvent', openGithub: 'openGithub', openPatreon: 'openPatreon', clearAuthData: 'clearAuthData', updateRequired: 'updateRequired', backToLogin: 'backToLogin', joinDiscord: 'joinDiscord' }; // Vaiables used on both client and browser side (see browsersideWidgetSetter) var browserState = { comment: '', failCount: 9000, loginFailedReason: '', }; var authData = null; var translations = { "ru": { loginViaDiscord: 'войдите через discord', joinDiscordServer: 'вступите в discord сервер', banned: 'вы забанены', whatWasThat: 'что это было?', openingBrowser: 'открываем браузер...', loginFirst: 'сначала войдите', linkedSuccessfully: 'привязан успешно', connecting: 'подключение', technicalIssues: 'технические шоколадки\nпопробуйте еще раз\nпожалуйста\nили напишите нам в discord', authorization: 'Авторизация', notAuthorized: 'не авторизирован', changeAccount: 'сменить аккаунт', loginViaSkymp: 'войти через skymp', play: 'Играть', loginOrChangeHint: 'Вы можете войти или поменять аккаунт', connectToServer: 'Подключиться к игровому серверу', updateCaption: 'новинка', updateAvailable: 'ура! вышло обновление', downloadAt: 'спешите скачать на', openSkympNet: 'открыть skymp.net', updateDownloadHint: 'Перейти на страницу скачивания обновления', oops: 'упс', join: 'вступить', back: 'назад', }, "en": { loginViaDiscord: 'log in via Discord', joinDiscordServer: 'join the Discord server', banned: 'you are banned', whatWasThat: 'what was that?', openingBrowser: 'opening browser...', loginFirst: 'log in first', linkedSuccessfully: 'linked successfully', connecting: 'connecting', technicalIssues: 'technical difficulties\nplease try again\nor contact us on Discord', authorization: 'Authorization', notAuthorized: 'not authorized', changeAccount: 'change account', loginViaSkymp: 'log in via skymp', play: 'Play', loginOrChangeHint: 'You can log in or change your account', connectToServer: 'Connect to game server', updateCaption: 'Update', updateAvailable: 'a new update is available!', downloadAt: 'download it at', openSkympNet: 'open skymp.net', updateDownloadHint: 'Go to the update download page', oops: 'oops', join: 'join', back: 'back', }, }; var strings = translations['en']; try { var lang = fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync('./Data/Platform/Distribution/locale', 'utf8').trim(); if (lang in translations) { strings = translations[lang]; var src = "window.setLanguage(".concat(lang, ")"); skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__.browser.executeJavaScript(src); } } catch (_a) { // locale file not found or unreadable, default to 'en' } var AuthService = /** @class */ (function (_super) { __extends(AuthService, _super); function AuthService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.deniedWidgetSetter = function () { var widget = { type: "form", id: 2, caption: strings.updateCaption, elements: [ { type: "text", text: strings.updateAvailable, tags: [] }, { type: "text", text: strings.downloadAt, tags: [] }, { type: "text", text: "skymp.net", tags: [] }, { type: "button", text: strings.openSkympNet, tags: ["ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.updateRequired); }, hint: strings.updateDownloadHint, } ] }; window.skyrimPlatform.widgets.set([widget]); // Make sure gamemode will not be able to update widgets anymore window.skyrimPlatform.widgets = null; }; _this.loginFailedWidgetSetter = function () { var splitParts = browserState.loginFailedReason.split('\n'); var textElements = splitParts.map(function (part) { return ({ type: "text", text: part, tags: [], }); }); var widget = { type: "form", id: 2, caption: strings.oops, elements: new Array() }; textElements.forEach(function (element) { return widget.elements.push(element); }); if (browserState.loginFailedReason === strings.joinDiscordServer) { widget.elements.push({ type: "button", text: strings.join, tags: ["ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.joinDiscord); }, hint: null }); } widget.elements.push({ type: "button", text: strings.back, tags: ["ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.backToLogin); }, hint: undefined }); window.skyrimPlatform.widgets.set([widget]); }; _this.browsersideWidgetSetter = function () { var loginWidget = { type: "form", id: 1, caption: strings.authorization, elements: [ // { // type: "button", // tags: ["BUTTON_STYLE_GITHUB"], // hint: "get a colored nickname and mention in news", // click: () => window.skyrimPlatform.sendMessage(events.openGithub), // }, // { // type: "button", // tags: ["BUTTON_STYLE_PATREON", "ELEMENT_SAME_LINE", "HINT_STYLE_RIGHT"], // hint: "get a colored nickname and other bonuses for patrons", // click: () => window.skyrimPlatform.sendMessage(events.openPatreon), // }, // { // type: "icon", // text: "username", // tags: ["ICON_STYLE_SKYMP"], // }, // { // type: "icon", // text: "", // tags: ["ICON_STYLE_DISCORD"], // }, { type: "text", text: (authData ? (authData.discordUsername ? "".concat(authData.discordUsername) : "id: ".concat(authData.masterApiId)) : strings.notAuthorized), tags: [ /*"ELEMENT_SAME_LINE", "ELEMENT_STYLE_MARGIN_EXTENDED"*/], }, // { // type: "icon", // text: "discord", // tags: ["ICON_STYLE_DISCORD"], // }, { type: "button", text: authData ? strings.changeAccount : strings.loginViaSkymp, tags: [ /*"ELEMENT_SAME_LINE"*/], click: function () { return window.skyrimPlatform.sendMessage(events.openDiscordOauth); }, hint: strings.loginOrChangeHint, }, { type: "button", text: strings.play, tags: ["BUTTON_STYLE_FRAME", "ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.authAttempt); }, hint: strings.connectToServer, }, { type: "text", text: browserState.comment, tags: [], }, ] }; window.skyrimPlatform.widgets.set([loginWidget]); }; _this._isListenBrowserMessage = false; _this.trigger = { authNeededFired: false, browserWindowLoadedFired: false, get conditionMet() { return this.authNeededFired && this.browserWindowLoadedFired; } }; _this.discordAuthState = crypto__WEBPACK_IMPORTED_MODULE_0__.randomBytes(32).toString('hex'); _this.authDialogOpen = false; _this.loggingStartMoment = 0; _this.authAttemptProgressIndicator = false; _this.authAttemptProgressIndicatorCounter = 0; _this.playerEverSawActualGameplay = false; _this.githubUrl = "https://github.com/skyrim-multiplayer/skymp"; _this.patreonUrl = "https://www.patreon.com/skymp"; _this.pluginAuthDataName = "auth-data-no-load"; _this.controller.emitter.on("authNeeded", function (e) { return _this.onAuthNeeded(e); }); _this.controller.emitter.on("browserWindowLoaded", function (e) { return _this.onBrowserWindowLoaded(e); }); _this.controller.emitter.on("createActorMessage", function (e) { return _this.onCreateActorMessage(e); }); _this.controller.emitter.on("connectionAccepted", function () { return _this.handleConnectionAccepted(); }); _this.controller.emitter.on("connectionDenied", function (e) { return _this.handleConnectionDenied(e); }); _this.controller.emitter.on("customPacketMessage", function (e) { return _this.onCustomPacketMessage(e); }); _this.controller.on("browserMessage", function (e) { return _this.onBrowserMessage(e); }); _this.controller.on("tick", function () { return _this.onTick(); }); _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } AuthService.prototype.onAuthNeeded = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received authNeeded event"); var settingsGameData = this.sp.settings["skymp5-client"]["gameData"]; var isOfflineMode = Number.isInteger(settingsGameData === null || settingsGameData === void 0 ? void 0 : settingsGameData.profileId); if (isOfflineMode) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Offline mode detected in settings, emitting auth event with authGameData.local"); this.controller.emitter.emit("authAttempt", { authGameData: { local: { profileId: settingsGameData.profileId } } }); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "No offline mode detectted in settings, regular auth needed"); this.setListenBrowserMessage(true, 'authNeeded event received'); this.trigger.authNeededFired = true; if (this.trigger.conditionMet) { this.onBrowserWindowLoadedAndOnlineAuthNeeded(); } } }; AuthService.prototype.onBrowserWindowLoaded = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received browserWindowLoaded event"); this.trigger.browserWindowLoadedFired = true; if (this.trigger.conditionMet) { this.onBrowserWindowLoadedAndOnlineAuthNeeded(); } }; AuthService.prototype.onCreateActorMessage = function (e) { if (e.message.isMe) { if (this.authDialogOpen) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received createActorMessage for self, resetting widgets"); this.sp.browser.executeJavaScript('window.skyrimPlatform.widgets.set([]);'); this.authDialogOpen = false; } else { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received createActorMessage for self, but auth dialog was not open so not resetting widgets"); } } this.loggingStartMoment = 0; this.authAttemptProgressIndicator = false; }; AuthService.prototype.onCustomPacketMessage = function (event) { var msg = event.message; var msgContent = {}; try { msgContent = JSON.parse(msg.contentJsonDump); } catch (e) { if (e instanceof SyntaxError) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "onCustomPacketMessage failed to parse JSON", e.message, "json:", msg.contentJsonDump); return; } else { throw e; } } switch (msgContent["customPacketType"]) { // case 'loginRequired': // logTrace(this, 'loginRequired received'); // this.loginWithSkympIoCredentials(); // break; case 'loginFailedNotLoggedViaDiscord': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedNotLoggedViaDiscord received'); browserState.loginFailedReason = strings.loginViaDiscord; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedNotLoggedViaDiscord received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case 'loginFailedNotInTheDiscordServer': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedNotInTheDiscordServer received'); browserState.loginFailedReason = strings.joinDiscordServer; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedNotInTheDiscordServer received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case 'loginFailedBanned': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedBanned received'); browserState.loginFailedReason = strings.banned; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedBanned received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case 'loginFailedIpMismatch': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedIpMismatch received'); browserState.loginFailedReason = strings.whatWasThat; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedIpMismatch received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; } }; AuthService.prototype.onBrowserWindowLoadedAndOnlineAuthNeeded = function () { var _this = this; if (!this.isListenBrowserMessage) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "isListenBrowserMessage was false for some reason, aborting auth"); return; } (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Showing widgets and starting loop"); authData = this.readAuthDataFromDisk(); this.refreshWidgets(); this.sp.browser.setVisible(true); this.sp.browser.setFocused(true); var timersService = this.controller.lookupListener(_timersService__WEBPACK_IMPORTED_MODULE_6__.TimersService); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Calling setTimeout for testing"); try { timersService.setTimeout(function () { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(_this, "Test timeout fired"); }, 1); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "Failed to call setTimeout"); } }; AuthService.prototype.onBrowserMessage = function (e) { if (!this.isListenBrowserMessage) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "onBrowserMessage: isListenBrowserMessage was false, ignoring message", JSON.stringify(e.arguments)); return; } var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_10__.SettingsService); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "onBrowserMessage:", JSON.stringify(e.arguments)); var eventKey = e.arguments[0]; switch (eventKey) { case events.openDiscordOauth: browserState.comment = strings.openingBrowser; this.refreshWidgets(); this.sp.win32.loadUrl("".concat(settingsService.getMasterUrl(), "/api/users/login-discord?state=").concat(this.discordAuthState)); // Launch checkLoginState loop this.checkLoginState(); break; case events.authAttempt: if (authData === null) { browserState.comment = strings.loginFirst; this.refreshWidgets(); break; } this.writeAuthDataToDisk(authData); this.controller.emitter.emit("authAttempt", { authGameData: { remote: authData } }); this.authAttemptProgressIndicator = true; break; case events.clearAuthData: // Doesn't seem to be used this.writeAuthDataToDisk(null); break; case events.openGithub: this.sp.win32.loadUrl(this.githubUrl); break; case events.openPatreon: this.sp.win32.loadUrl(this.patreonUrl); break; case events.updateRequired: this.sp.win32.loadUrl("https://skymp.net/UpdInstall"); break; case events.backToLogin: this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.browsersideWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case events.joinDiscord: this.sp.win32.loadUrl("https://discord.gg/9KhSZ6zjGT"); break; default: break; } }; AuthService.prototype.createPlaySession = function (token, callback) { var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_10__.SettingsService); var client = new this.sp.HttpClient(settingsService.getMasterUrl()); var route = "/api/users/me/play/".concat(settingsService.getServerMasterKey()); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Creating play session ".concat(route)); client.post(route, { body: '{}', contentType: 'application/json', headers: { 'authorization': token, }, // @ts-ignore }, function (res) { if (res.status != 200) { callback('', 'status code ' + res.status); } else { // TODO: handle JSON.parse failure? callback(JSON.parse(res.body).session, ''); } }); }; AuthService.prototype.checkLoginState = function () { var _this = this; if (!this.isListenBrowserMessage) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "checkLoginState: isListenBrowserMessage was false, aborting check"); return; } var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_10__.SettingsService); var timersService = this.controller.lookupListener(_timersService__WEBPACK_IMPORTED_MODULE_6__.TimersService); // Social engineering protection, don't show the full state var halfDiscordAuthState = this.discordAuthState.slice(0, 16); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Checking login state", halfDiscordAuthState, '...'); new this.sp.HttpClient(settingsService.getMasterUrl()) .get("/api/users/login-discord/status?state=" + this.discordAuthState, undefined, // @ts-ignore function (response) { switch (response.status) { case 200: var _a = JSON.parse(response.body), token = _a.token, masterApiId_1 = _a.masterApiId, discordUsername_1 = _a.discordUsername, discordDiscriminator_1 = _a.discordDiscriminator, discordAvatar_1 = _a.discordAvatar; browserState.failCount = 0; _this.createPlaySession(token, function (playSession, error) { if (error) { browserState.failCount = 0; browserState.comment = (error); timersService.setTimeout(function () { return _this.checkLoginState(); }, Math.floor((1.5 + Math.random() * 2) * 1000)); _this.refreshWidgets(); return; } authData = { session: playSession, masterApiId: masterApiId_1, discordUsername: discordUsername_1, discordDiscriminator: discordDiscriminator_1, discordAvatar: discordAvatar_1, }; browserState.comment = strings.linkedSuccessfully; _this.refreshWidgets(); }); break; case 401: // Unauthorized browserState.failCount = 0; browserState.comment = ''; //(`Still waiting...`); timersService.setTimeout(function () { return _this.checkLoginState(); }, Math.floor((1.5 + Math.random() * 2) * 1000)); break; case 403: // Forbidden case 404: // Not found browserState.failCount = 9000; browserState.comment = ("Fail: ".concat(response.body)); break; default: ++browserState.failCount; browserState.comment = "Server returned ".concat(response.status.toString() || "???", " \"").concat(response.body || response.error, "\""); timersService.setTimeout(function () { return _this.checkLoginState(); }, Math.floor((1.5 + Math.random() * 2) * 1000)); } }); }; ; AuthService.prototype.refreshWidgets = function () { this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.browsersideWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); this.authDialogOpen = true; }; ; AuthService.prototype.readAuthDataFromDisk = function () { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Reading", this.pluginAuthDataName, "from disk"); try { // @ts-expect-error (TODO: Remove in 2.10.0) var data = this.sp.getPluginSourceCode(this.pluginAuthDataName, "PluginsNoLoad"); if (!data) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Read empty", this.pluginAuthDataName, "returning null"); return null; } return JSON.parse(data.slice(2)) || null; } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "Error reading", this.pluginAuthDataName, "from disk:", e, ", falling back to null"); return null; } }; AuthService.prototype.writeAuthDataToDisk = function (data) { var content = "//" + (data ? JSON.stringify(data) : "null"); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Writing", this.pluginAuthDataName, "to disk:", content); try { this.sp.writePlugin(this.pluginAuthDataName, content, // @ts-expect-error (TODO: Remove in 2.10.0) "PluginsNoLoad"); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "Error writing", this.pluginAuthDataName, "to disk:", e, ", will not remember user"); } }; ; AuthService.prototype.handleConnectionDenied = function (e) { var _this = this; this.authAttemptProgressIndicator = false; if (e.error.toLowerCase().includes("invalid password")) { this.controller.once("tick", function () { _this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); }); this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.deniedWidgetSetter).getText({ events: events, strings: strings })); this.sp.browser.setVisible(true); this.sp.browser.setFocused(true); this.controller.once("update", function () { _this.sp.Game.disablePlayerControls(true, true, true, true, true, true, true, true, 0); }); this.setListenBrowserMessage(true, 'connectionDenied event received'); } }; AuthService.prototype.handleConnectionAccepted = function () { this.setListenBrowserMessage(false, 'connectionAccepted event received'); this.loggingStartMoment = Date.now(); var authData = this.sp.storage[_features_authModel__WEBPACK_IMPORTED_MODULE_2__.authGameDataStorageKey]; if (authData === null || authData === void 0 ? void 0 : authData.local) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Logging in offline mode, profileId =", authData.local.profileId); var message = { t: _messages__WEBPACK_IMPORTED_MODULE_9__.MsgType.CustomPacket, contentJsonDump: JSON.stringify({ customPacketType: 'loginWithSkympIo', gameData: { profileId: authData.local.profileId, }, }), }; this.controller.emitter.emit("sendMessage", { message: message, reliability: "reliable" }); return; } if (authData === null || authData === void 0 ? void 0 : authData.remote) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'Logging in as a master API user'); var message = { t: _messages__WEBPACK_IMPORTED_MODULE_9__.MsgType.CustomPacket, contentJsonDump: JSON.stringify({ customPacketType: 'loginWithSkympIo', gameData: { session: authData.remote.session, }, }), }; this.controller.emitter.emit("sendMessage", { message: message, reliability: "reliable" }); return; } (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, 'Not found authentication method'); }; ; AuthService.prototype.onTick = function () { // TODO: Should be no hardcoded/magic-number limit // TODO: Busy waiting is bad. Should be replaced with some kind of event var maxLoggingDelay = 15000; if (this.loggingStartMoment && Date.now() - this.loggingStartMoment > maxLoggingDelay) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'Max logging delay reached received'); if (this.playerEverSawActualGameplay) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'Player saw actual gameplay, reconnecting'); this.loggingStartMoment = 0; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).reconnect(); // TODO: should we prompt user to relogin? } else { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'Player never saw actual gameplay, showing login dialog'); this.loggingStartMoment = 0; this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); browserState.comment = ""; browserState.loginFailedReason = strings.technicalIssues; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); authData = null; this.writeAuthDataToDisk(null); } } if (this.authAttemptProgressIndicator) { this.authAttemptProgressIndicatorCounter++; if (this.authAttemptProgressIndicatorCounter === 1000000) { this.authAttemptProgressIndicatorCounter = 0; } var slowCounter = Math.floor(this.authAttemptProgressIndicatorCounter / 15); var dot = slowCounter % 3 === 0 ? '.' : slowCounter % 3 === 1 ? '..' : '...'; browserState.comment = strings.connecting + dot; this.refreshWidgets(); } }; AuthService.prototype.onceUpdate = function () { this.playerEverSawActualGameplay = true; }; AuthService.prototype.isListenBrowserMessage = function () { return this._isListenBrowserMessage; }; AuthService.prototype.setListenBrowserMessage = function (value, reason) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "setListenBrowserMessage:", value, "reason:", reason); this._isListenBrowserMessage = value; }; return AuthService; }(_clientListener__WEBPACK_IMPORTED_MODULE_4__.ClientListener)); /***/ }), /***/ "./src/services/services/blockPapyrusEventsService.ts": /*!************************************************************!*\ !*** ./src/services/services/blockPapyrusEventsService.ts ***! \************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ BlockPapyrusEventsService: () => (/* binding */ BlockPapyrusEventsService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var BlockPapyrusEventsService = /** @class */ (function (_super) { __extends(BlockPapyrusEventsService, _super); function BlockPapyrusEventsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.once("tick", function () { return _this.onceTick(); }); _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } BlockPapyrusEventsService.prototype.onceTick = function () { // @ts-ignore this.sp.blockPapyrusEvents(true); }; BlockPapyrusEventsService.prototype.onceUpdate = function () { this.sp.TESModPlatform.blockPapyrusEvents(true); }; return BlockPapyrusEventsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); ; /***/ }), /***/ "./src/services/services/blockedAnimationsService.ts": /*!***********************************************************!*\ !*** ./src/services/services/blockedAnimationsService.ts ***! \***********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ BlockedAnimationsService: () => (/* binding */ BlockedAnimationsService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var BlockedAnimationsService = /** @class */ (function (_super) { __extends(BlockedAnimationsService, _super); function BlockedAnimationsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; var blockedAnims = []; var self = _this; blockedAnims.forEach(function (blockedAnim) { _this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(self, "blocking animation event", ctx.animEventName); ctx.animEventName = ""; }, leave: function () { } }, 0x14, 0x14, blockedAnim); }); return _this; } return BlockedAnimationsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); ; /***/ }), /***/ "./src/services/services/browserService.ts": /*!*************************************************!*\ !*** ./src/services/services/browserService.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ BrowserService: () => (/* binding */ BrowserService) /* harmony export */ }); /* harmony import */ var _view_formView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../view/formView */ "./src/view/formView.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: send event instead of direct dependency on FormView class var unfocusEventString = "window.dispatchEvent(new CustomEvent('skymp5-client:browserUnfocused', {}))"; var focusEventString = "window.dispatchEvent(new CustomEvent('skymp5-client:browserFocused', {}))"; var BrowserService = /** @class */ (function (_super) { __extends(BrowserService, _super); function BrowserService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.badMenusOpen = new Set(); _this.badMenus = [ "BarterMenu" /* Menu.Barter */, "Book Menu" /* Menu.Book */, "ContainerMenu" /* Menu.Container */, "Crafting Menu" /* Menu.Crafting */, "GiftMenu" /* Menu.Gift */, "InventoryMenu" /* Menu.Inventory */, "Journal Menu" /* Menu.Journal */, "Lockpicking Menu" /* Menu.Lockpicking */, "Loading Menu" /* Menu.Loading */, "MapMenu" /* Menu.Map */, "RaceSex Menu" /* Menu.RaceSex */, "StatsMenu" /* Menu.Stats */, "TweenMenu" /* Menu.Tween */, "Console" /* Menu.Console */, "Main Menu" /* Menu.Main */, ]; _this.sp.browser.setVisible(false); _this.controller.emitter.on("queryKeyCodeBindings", function (e) { return _this.onQueryKeyCodeBindings(e); }); _this.controller.once("update", function () { return _this.onceUpdate(); }); _this.controller.on("browserMessage", function (e) { return _this.onBrowserMessage(e); }); _this.controller.on("menuOpen", function (e) { return _this.onMenuOpen(e); }); _this.controller.on("menuClose", function (e) { return _this.onMenuClose(e); }); return _this; } // TODO: keycodes should be configurable BrowserService.prototype.onQueryKeyCodeBindings = function (e) { if (e.isDown([59 /* DxScanCode.F1 */])) { _view_formView__WEBPACK_IMPORTED_MODULE_0__.FormView.isDisplayingNicknames = !_view_formView__WEBPACK_IMPORTED_MODULE_0__.FormView.isDisplayingNicknames; } if (e.isDown([60 /* DxScanCode.F2 */])) { this.sp.browser.setVisible(!this.sp.browser.isVisible()); } if (this.badMenusOpen.size === 0 && e.isDown([64 /* DxScanCode.F6 */])) { var newState = !this.sp.browser.isFocused(); this.sp.browser.setFocused(newState); if (newState) { this.sp.browser.executeJavaScript(focusEventString); } else { this.sp.browser.executeJavaScript(unfocusEventString); } } if (this.badMenusOpen.size === 0 && e.isDown([28 /* DxScanCode.Enter */])) { this.sp.browser.setFocused(true); this.sp.browser.executeJavaScript(focusEventString); } if (e.isDown([1 /* DxScanCode.Escape */])) { if (this.sp.browser.isFocused()) { this.sp.browser.setFocused(false); this.sp.browser.executeJavaScript(unfocusEventString); } } }; BrowserService.prototype.onceUpdate = function () { this.sp.browser.setVisible(true); }; BrowserService.prototype.onBrowserMessage = function (e) { var onFrontLoadedEventKey = "front-loaded"; if (e.arguments[0] === onFrontLoadedEventKey) { this.controller.emitter.emit("browserWindowLoaded", {}); } }; BrowserService.prototype.onMenuOpen = function (e) { if (this.isBadMenu(e.name)) { this.sp.browser.setVisible(false); this.badMenusOpen.add(e.name); } else if (e.name === "HUD Menu" /* Menu.HUD */) { this.sp.browser.setVisible(true); } }; BrowserService.prototype.onMenuClose = function (e) { if (this.badMenusOpen.delete(e.name)) { if (this.badMenusOpen.size === 0) { this.sp.browser.setVisible(true); } } if (e.name === "HUD Menu" /* Menu.HUD */) { this.sp.browser.setVisible(false); } }; BrowserService.prototype.isBadMenu = function (menu) { return this.badMenus.includes(menu); }; return BrowserService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/clientListener.ts": /*!*************************************************!*\ !*** ./src/services/services/clientListener.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ClientListener: () => (/* binding */ ClientListener) /* harmony export */ }); ; var ClientListener = /** @class */ (function () { function ClientListener() { // Don't let TypeScript treat this class as empty this._nonEmptyClassMark = ''; } return ClientListener; }()); /***/ }), /***/ "./src/services/services/consoleCommandsService.ts": /*!*********************************************************!*\ !*** ./src/services/services/consoleCommandsService.ts ***! \*********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ConsoleCommandsService: () => (/* binding */ ConsoleCommandsService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out var CmdArgument; (function (CmdArgument) { CmdArgument[CmdArgument["ObjectReference"] = 0] = "ObjectReference"; CmdArgument[CmdArgument["BaseForm"] = 1] = "BaseForm"; CmdArgument[CmdArgument["Int"] = 2] = "Int"; CmdArgument[CmdArgument["String"] = 3] = "String"; })(CmdArgument || (CmdArgument = {})); var ConsoleCommandsService = /** @class */ (function (_super) { __extends(ConsoleCommandsService, _super); function ConsoleCommandsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.immuneSchema = ["mp"]; _this.nonVanilaCommands = ["mp"]; _this.schemas = ConsoleCommandsService.createSchemas(); _this.setupMpCommand(); _this.setupVanilaCommands(); return _this; } ConsoleCommandsService.createSchemas = function () { var schemas = new Map(); schemas.set("additem", [CmdArgument.ObjectReference, CmdArgument.BaseForm, CmdArgument.Int]); schemas.set("equipitem", [CmdArgument.ObjectReference, CmdArgument.BaseForm]); schemas.set("placeatme", [CmdArgument.ObjectReference, CmdArgument.BaseForm]); schemas.set("disable", [CmdArgument.ObjectReference]); schemas.set("mp", [CmdArgument.ObjectReference, CmdArgument.String]); return schemas; }; ConsoleCommandsService.prototype.setupMpCommand = function () { var command = this.sp.findConsoleCommand(" ConfigureUM") || this.sp.findConsoleCommand("test"); if (command === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "command was null in setupMpCommand"); return; } command.shortName = "mp"; command.execute = this.getCommandExecutor("mp"); }; ConsoleCommandsService.prototype.setupVanilaCommands = function () { var _this = this; (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(this, "Setting up vanila commands"); this.schemas.forEach(function (_, commandName) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "Setting up command", commandName); var command = _this.sp.findConsoleCommand(commandName); if (command === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "command", commandName, "was null in setupVanilaCommands"); return; } if (_this.nonVanilaCommands.includes(commandName)) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "command", commandName, " is non-vanila command"); return; } command.execute = _this.getCommandExecutor(commandName); }); (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(this, "Vanila commands set up"); }; ConsoleCommandsService.prototype.getCommandExecutor = function (commandName) { var _this = this; return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } // TODO: handle possible exceptions in this function var schema = _this.schemas.get(commandName); if (schema === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "Schema not found for command", commandName); return false; } if (args.length !== schema.length && !_this.immuneSchema.includes(commandName)) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "Mismatch found in the schema of", commandName, "command"); return false; } for (var i = 0; i < args.length; ++i) { switch (schema[i]) { case CmdArgument.ObjectReference: args[i] = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.localIdToRemoteId)(parseInt("".concat(args[i]))); break; } } for (var i = 0; i < args.length; ++i) { if (typeof args[i] !== "string" && typeof args[i] !== "number") { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "Bad argument type in command", commandName, "argument index", i); return false; } } _this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.ConsoleCommand, data: { commandName: commandName, args: args } }, reliability: "reliable" }); // Meant to be shown to user, not for logging _this.sp.printConsole("sent"); return false; }; }; return ConsoleCommandsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_3__.ClientListener)); /***/ }), /***/ "./src/services/services/containersService.ts": /*!****************************************************!*\ !*** ./src/services/services/containersService.ts ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ContainersService: () => (/* binding */ ContainersService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _remoteServer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./remoteServer */ "./src/services/services/remoteServer.ts"); /* harmony import */ var _sync_inventory__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../sync/inventory */ "./src/sync/inventory.ts"); /* harmony import */ var _lastInvService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lastInvService */ "./src/services/services/lastInvService.ts"); /* harmony import */ var _sweetTaffySweetCantDropService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./sweetTaffySweetCantDropService */ "./src/services/services/sweetTaffySweetCantDropService.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (undefined && undefined.__assign) || function () { __assign = Object.assign || function(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); }; var ContainersService = /** @class */ (function (_super) { __extends(ContainersService, _super); function ContainersService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; controller.on('containerChanged', function (e) { return _this.onContainerChanged(e); }); return _this; } ContainersService.prototype.onContainerChanged = function (e) { var _this = this; var sweetCantDropService = this.controller.lookupListener(_sweetTaffySweetCantDropService__WEBPACK_IMPORTED_MODULE_6__.SweetTaffySweetCantDropService); if (e.oldContainer && e.newContainer) { if (e.oldContainer.getFormID() === 0x14 || e.newContainer.getFormID() === 0x14) { var lastInvService_1 = this.controller.lookupListener(_lastInvService__WEBPACK_IMPORTED_MODULE_5__.LastInvService); if (!lastInvService_1.lastInv) { lastInvService_1.lastInv = (0,_remoteServer__WEBPACK_IMPORTED_MODULE_3__.getPcInventory)(); } if (lastInvService_1.lastInv) { var newInv = (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_4__.getInventory)(this.sp.Game.getPlayer()); // It seems that 'ignoreWorn = false' fixes this: // https://github.com/skyrim-multiplayer/issue-tracker/issues/43 // For some reason excess diff is produced when 'ignoreWorn = true' // I thought that it would be vice versa but that's how it works var ignoreWorn = false; var diff = (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_4__.getDiff)(lastInvService_1.lastInv, newInv, ignoreWorn); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)('diff:'); for (var i = 0; i < diff.entries.length; ++i) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("[".concat(i, "] ").concat(JSON.stringify(diff.entries[i]))); } var msgs = diff.entries .filter(function (entry) { // TODO: review this condition, seems to be incorrect return entry.count > 0 ? sweetCantDropService.canDropOrPutItem(entry.baseId) : true; }) .filter(function (entry) { return entry.count !== 0; }) .map(function (entry) { var _a; var entryCopy = JSON.parse(JSON.stringify(entry)); var msg = __assign(__assign({}, entryCopy), { t: entry.count > 0 ? _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.PutItem : _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.TakeItem, target: e.oldContainer.getFormID() === 0x14 ? (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_7__.localIdToRemoteId)(e.newContainer.getFormID()) : (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_7__.localIdToRemoteId)(e.oldContainer.getFormID()) }); msg.count = Math.abs(msg.count); if (((_a = _this.sp.Game.getFormEx(entry.baseId)) === null || _a === void 0 ? void 0 : _a.getName()) === msg.name) { delete msg.name; } return msg; }); msgs.forEach(function (msg) { return _this.controller.emitter.emit("sendMessage", { message: msg, reliability: "reliable" }); }); // Prevent emitting 1,2,3,4,5 changes when taking/putting 5 potions one by one // This code makes it 1,1,1,1,1 but works only for extra-less items // At the moment of writing this I think it's not needed for items with extras diff.entries.forEach(function (entry) { if (lastInvService_1.lastInv && !(0,_sync_inventory__WEBPACK_IMPORTED_MODULE_4__.hasExtras)(entry)) { var put = entry.count > 0; var take = entry.count < 0; if (put) { lastInvService_1.lastInv = (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_4__.removeSimpleItemsAsManyAsPossible)(lastInvService_1.lastInv, entry.baseId, entry.count); } else if (take) { var add = { entries: [entry] }; add.entries[0].count *= -1; lastInvService_1.lastInv = (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_4__.sumInventories)(lastInvService_1.lastInv, add); } } }); } } } }; return ContainersService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/craftService.ts": /*!***********************************************!*\ !*** ./src/services/services/craftService.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CraftService: () => (/* binding */ CraftService) /* harmony export */ }); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out var CraftService = /** @class */ (function (_super) { __extends(CraftService, _super); function CraftService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.furnitureStreak = new Map(); controller.on('containerChanged', function (e) { return _this.onContainerChanged(e); }); return _this; } CraftService.prototype.onContainerChanged = function (e) { var oldContainerId = e.oldContainer ? e.oldContainer.getFormID() : 0; var newContainerId = e.newContainer ? e.newContainer.getFormID() : 0; var baseObjId = e.baseObj ? e.baseObj.getFormID() : 0; if (oldContainerId !== 0x14 && newContainerId !== 0x14) { return; } var furnitureRef = this.sp.Game.getPlayer().getFurnitureReference(); if (!furnitureRef) { return; } var furnitureId = furnitureRef.getFormID(); if (oldContainerId === 0x14 && newContainerId === 0) { var craftInputObjects = this.furnitureStreak.get(furnitureId); if (!craftInputObjects) { craftInputObjects = { entries: [] }; } craftInputObjects.entries.push({ baseId: baseObjId, count: e.numItems, }); this.furnitureStreak.set(furnitureId, craftInputObjects); (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Adding baseObjId", baseObjId.toString(16), "numItems", e.numItems, "to craft"); } else if (oldContainerId === 0 && newContainerId === 0x14) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, 'Finishing craft'); var craftInputObjects = this.furnitureStreak.get(furnitureId); if (craftInputObjects && craftInputObjects.entries.length) { this.furnitureStreak.delete(furnitureId); var workbench = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(furnitureId); if (!workbench) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(this, "localIdToRemoteId returned 0 for furnitureId", furnitureId); return; } var resultObjectId = baseObjId; (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Sending craft workbench", workbench, "resultObjectId", resultObjectId, "craftInputObjects", JSON.stringify(craftInputObjects.entries)); this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.CraftItem, data: { workbench: workbench, craftInputObjects: craftInputObjects, resultObjectId: resultObjectId }, }, reliability: "reliable" }); } } }; return CraftService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/deathService.ts": /*!***********************************************!*\ !*** ./src/services/services/deathService.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DeathService: () => (/* binding */ DeathService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _lib_errors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../lib/errors */ "./src/lib/errors.ts"); /* harmony import */ var _sync_animation__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../sync/animation */ "./src/sync/animation.ts"); /* harmony import */ var _ragdollService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ragdollService */ "./src/services/services/ragdollService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var DeathService = /** @class */ (function (_super) { __extends(DeathService, _super); function DeathService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.applyDeathState = function (actor, isDead) { if (actor.isDead() === isDead && _this.isPlayer(actor) === false) { return; } if (isDead === true) { _this.killActor(actor, null); } else { _this.resurrectActor(actor); } }; _this.killActor = function (actor, killer) { if (killer === void 0) { killer = null; } if (_this.isPlayer(actor) === true) { _this.playerDead = true; _this.busyForOtherReasonsCounter++; _this.sp.Utility.wait(7.5).then(function () { return _this.busyForOtherReasonsCounter--; }); _this.allowedPlayerAnimations = []; actor.setDontMove(true); _this.killWithPush(actor); } else { actor.endDeferredKill(); actor.kill(killer); } }; _this.resurrectActor = function (actor) { if (_this.isPlayer(actor) === true) { _this.playerDead = false; _this.busyForOtherReasonsCounter++; _this.sp.Utility.wait(7.5).then(function () { return _this.busyForOtherReasonsCounter--; }); _this.allowedPlayerAnimations = null; actor.setDontMove(false); _this.ressurectWithPushKill(actor); } else { throw new _lib_errors__WEBPACK_IMPORTED_MODULE_2__.RespawnNeededError("needs to be respawned"); } }; _this.killWithPush = function (actor) { var _a; (_a = _this.allowedPlayerAnimations) === null || _a === void 0 ? void 0 : _a.push(_sync_animation__WEBPACK_IMPORTED_MODULE_3__.AnimationEventName.Ragdoll); actor.pushActorAway(actor, 0); }; _this.ressurectWithPushKill = function (act) { var formId = act.getFormID(); var ragdollService = _this.controller.lookupListener(_ragdollService__WEBPACK_IMPORTED_MODULE_4__.RagdollService); ragdollService.safeRemoveRagdollFromWorld(act, function () { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(_this.sp.Game.getFormEx(formId)); if (!actor) { return; } // TODO: should use actor variable instead of getPlayer? // TODO: use different iGetUpType if ressurecting under water _this.sp.Game.getPlayer().setAnimationVariableInt("iGetUpType", 1); _this.sp.Debug.sendAnimationEvent(actor, _sync_animation__WEBPACK_IMPORTED_MODULE_3__.AnimationEventName.GetUpBegin); }); }; _this.isPlayer = function (actor) { return actor.getFormID() === _this.playerActorId; }; // Null to allow all animations. Empty array to disallow all _this.allowedPlayerAnimations = null; _this.playerActorId = 0x14; _this.playerDead = false; _this.busyForOtherReasonsCounter = 0; controller.once("update", function () { return _this.onceUpdate(); }); controller.emitter.on("applyDeathStateEvent", function (e) { return _this.onApplyDeathState(e); }); _this.hookDisableKillMoves(); _this.hookDisableStagger(); _this.hookDisableBlockedAnims(); return _this; } DeathService.prototype.isBusy = function () { return this.playerDead || this.busyForOtherReasonsCounter > 0; }; DeathService.prototype.onceUpdate = function () { var player = this.sp.Game.getPlayer(); player === null || player === void 0 ? void 0 : player.startDeferredKill(); }; DeathService.prototype.onApplyDeathState = function (e) { this.applyDeathState(e.actor, e.isDead); }; DeathService.prototype.hookDisableKillMoves = function () { this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { ctx.animEventName = ""; }, leave: function () { }, }, 0xff000000, 0xffffffff, "KillMove*"); }; DeathService.prototype.hookDisableStagger = function () { this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { ctx.animEventName = ""; }, leave: function () { }, }, 0xff000000, 0xffffffff, "staggerStart"); }; DeathService.prototype.hookDisableBlockedAnims = function () { var _this = this; this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { if (_this.allowedPlayerAnimations === null) { return; } if (!_this.allowedPlayerAnimations.includes(ctx.animEventName)) { ctx.animEventName = ""; } }, leave: function () { }, }, this.playerActorId, this.playerActorId); }; return DeathService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/disableDifficultySelectionService.ts": /*!********************************************************************!*\ !*** ./src/services/services/disableDifficultySelectionService.ts ***! \********************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DisableDifficultySelectionService: () => (/* binding */ DisableDifficultySelectionService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var DisableDifficultySelectionService = /** @class */ (function (_super) { __extends(DisableDifficultySelectionService, _super); function DisableDifficultySelectionService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.difficulty = 5; _this.counter = 0; _this.controller.on("update", function () { return _this.onUpdate(); }); return _this; } DisableDifficultySelectionService.prototype.onUpdate = function () { this.counter++; if (this.counter >= 60) { this.counter = 0; this.sp.Utility.setINIInt("iDifficulty:GamePlay", this.difficulty); } }; return DisableDifficultySelectionService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/disableFastTravelService.ts": /*!***********************************************************!*\ !*** ./src/services/services/disableFastTravelService.ts ***! \***********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DisableFastTravelService: () => (/* binding */ DisableFastTravelService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var DisableFastTravelService = /** @class */ (function (_super) { __extends(DisableFastTravelService, _super); function DisableFastTravelService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.on("update", function () { return _this.onUpdate(); }); return _this; } DisableFastTravelService.prototype.onUpdate = function () { this.sp.Game.enableFastTravel(false); }; return DisableFastTravelService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/disableSkillAdvanceService.ts": /*!*************************************************************!*\ !*** ./src/services/services/disableSkillAdvanceService.ts ***! \*************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DisableSkillAdvanceService: () => (/* binding */ DisableSkillAdvanceService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var DisableSkillAdvanceService = /** @class */ (function (_super) { __extends(DisableSkillAdvanceService, _super); function DisableSkillAdvanceService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } DisableSkillAdvanceService.prototype.onceUpdate = function () { // turn off player level exp this.sp.Game.setGameSettingFloat("fXPPerSkillRank", 0); // turn off skill exp this.turnOffSkillLocalExp(18 /* ActorValue.Alteration */); this.turnOffSkillLocalExp(19 /* ActorValue.Conjuration */); this.turnOffSkillLocalExp(20 /* ActorValue.Destruction */); this.turnOffSkillLocalExp(21 /* ActorValue.Illusion */); this.turnOffSkillLocalExp(22 /* ActorValue.Restoration */); this.turnOffSkillLocalExp(23 /* ActorValue.Enchanting */); this.turnOffSkillLocalExp(6 /* ActorValue.OneHanded */); this.turnOffSkillLocalExp(7 /* ActorValue.TwoHanded */); this.turnOffSkillLocalExp(8 /* ActorValue.Archery */); this.turnOffSkillLocalExp(9 /* ActorValue.Block */); this.turnOffSkillLocalExp(10 /* ActorValue.Smithing */); this.turnOffSkillLocalExp(11 /* ActorValue.HeavyArmor */); this.turnOffSkillLocalExp(12 /* ActorValue.LightArmor */); this.turnOffSkillLocalExp(13 /* ActorValue.Pickpocket */); this.turnOffSkillLocalExp(14 /* ActorValue.Lockpicking */); this.turnOffSkillLocalExp(15 /* ActorValue.Sneak */); this.turnOffSkillLocalExp(16 /* ActorValue.Alchemy */); this.turnOffSkillLocalExp(17 /* ActorValue.Speech */); }; DisableSkillAdvanceService.prototype.turnOffSkillLocalExp = function (av) { var avi = this.sp.ActorValueInfo.getActorValueInfoByID(av); if (avi === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "Not found ActorValueInfo for actor value", av); return; } avi.setSkillUseMult(0); avi.setSkillOffsetMult(0); }; ; return DisableSkillAdvanceService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/dropItemService.ts": /*!**************************************************!*\ !*** ./src/services/services/dropItemService.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DropItemService: () => (/* binding */ DropItemService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _sweetTaffySweetCantDropService__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sweetTaffySweetCantDropService */ "./src/services/services/sweetTaffySweetCantDropService.ts"); /* harmony import */ var _worldCleanerService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./worldCleanerService */ "./src/services/services/worldCleanerService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var DropItemService = /** @class */ (function (_super) { __extends(DropItemService, _super); function DropItemService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; controller.on('containerChanged', function (e) { return _this.onContainerChanged(e); }); return _this; } DropItemService.prototype.onContainerChanged = function (e) { var _this = this; var _a; var sweetCantDropService = this.controller.lookupListener(_sweetTaffySweetCantDropService__WEBPACK_IMPORTED_MODULE_2__.SweetTaffySweetCantDropService); var pl = this.sp.Game.getPlayer(); var isPlayer = pl && e.oldContainer && pl.getFormID() === e.oldContainer.getFormID(); var noContainer = e.newContainer === null || e.newContainer === undefined; var isReference = e.reference !== null; if (e.newContainer && e.newContainer.getFormID() === pl.getFormID()) return; if (!this.sp.Ui.isMenuOpen("InventoryMenu")) return; if (isPlayer && isReference && noContainer && sweetCantDropService.canDropOrPutItem(e.baseObj.getFormID())) { var radius = 2000; var baseId = e.baseObj.getFormID(); var player = this.sp.Game.getPlayer(); var set = new Set(); for (var i = 0; i < 200; i++) { var refrId = (_a = this.sp.Game.findRandomReferenceOfType(this.sp.Game.getFormEx(baseId), player.getPositionX(), player.getPositionY(), player.getPositionZ(), radius)) === null || _a === void 0 ? void 0 : _a.getFormID(); if (refrId) { set.add(refrId); } else { break; } } var numFound_1 = 0; var worldCleanerService_1 = this.controller.lookupListener(_worldCleanerService__WEBPACK_IMPORTED_MODULE_3__.WorldCleanerService); set.forEach(function (refrId) { var ref = _this.sp.ObjectReference.from(_this.sp.Game.getFormEx(refrId)); if (ref !== null && ref.isDeleted() === false) { var refrId_1 = ref.getFormID(); if (worldCleanerService_1.getWcProtection(refrId_1) === 0) { ref.delete(); ++numFound_1; (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "Found and deleted reference " + refrId_1.toString(16)); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "Found reference " + refrId_1.toString(16) + " but it's protected"); } } }); if (!numFound_1) { return (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Ignoring item drop as false positive"); } var t = _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.DropItem; var count = e.numItems; this.controller.emitter.emit("sendMessage", { message: { t: t, baseId: baseId, count: count, }, reliability: "reliable" }); } }; return DropItemService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/enforceLimitationsService.ts": /*!************************************************************!*\ !*** ./src/services/services/enforceLimitationsService.ts ***! \************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EnforceLimitationsService: () => (/* binding */ EnforceLimitationsService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var EnforceLimitationsService = /** @class */ (function (_super) { __extends(EnforceLimitationsService, _super); function EnforceLimitationsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; controller.once("update", function () { return _this.onceUpdate(); }); controller.emitter.on("gameLoad", function (e) { return _this.onGameLoad(e); }); return _this; } EnforceLimitationsService.prototype.onceUpdate = function () { this.sp.Game.setInChargen(true, true, false); }; EnforceLimitationsService.prototype.onGameLoad = function (event) { this.sp.Game.setInChargen(true, true, false); }; return EnforceLimitationsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/frontHotReloadService.ts": /*!********************************************************!*\ !*** ./src/services/services/frontHotReloadService.ts ***! \********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FrontHotReloadService: () => (/* binding */ FrontHotReloadService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _features_authModel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../features/authModel */ "./src/features/authModel.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var FrontHotReloadService = /** @class */ (function (_super) { __extends(FrontHotReloadService, _super); function FrontHotReloadService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; var enable = !!_this.sp.settings["skymp5-client"]["enable-front-hotreload"]; (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "enable-front-hotreload is", enable); if (!enable) { return _this; } // TODO: refactor out very similar code in skympClient.ts var authGameData = _this.sp.storage[_features_authModel__WEBPACK_IMPORTED_MODULE_1__.authGameDataStorageKey]; var storageHasValidAuthGameData = (authGameData === null || authGameData === void 0 ? void 0 : authGameData.local) || (authGameData === null || authGameData === void 0 ? void 0 : authGameData.remote); if (storageHasValidAuthGameData) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "Recovered AuthGameData from storage, starting FrontHotReloadService"); _this.connectToFrontHotReload(); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "Unable to recover AuthGameData from storage, waiting for auth"); _this.controller.emitter.on("authAttempt", function (e) { return _this.onAuthAttempt(e); }); } return _this; } FrontHotReloadService.prototype.onAuthAttempt = function (e) { this.connectToFrontHotReload(); }; FrontHotReloadService.prototype.connectToFrontHotReload = function () { var _this = this; this.controller.once("update", function () { var url = "localhost:1234"; (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "Loading url", url); _this.sp.browser.loadUrl(url); }); }; return FrontHotReloadService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/gamemodeEventSourceService.ts": /*!*************************************************************!*\ !*** ./src/services/services/gamemodeEventSourceService.ts ***! \*************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GamemodeEventSourceService: () => (/* binding */ GamemodeEventSourceService) /* harmony export */ }); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _serverJsVerificationService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./serverJsVerificationService */ "./src/services/services/serverJsVerificationService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // The reason we use global skyrimPlatform is that this.sp may be limited, and gamemode api needs unlimited access to skyrimPlatform // Sligthly different types var GamemodeEventSourceService = /** @class */ (function (_super) { __extends(GamemodeEventSourceService, _super); function GamemodeEventSourceService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.setupEventSource = function (ctx) { _this.controller.once('update', function () { try { ctx._fn(ctx); (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "'eventSources", ctx._eventName, "- Added"); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(_this, "'eventSources", ctx._eventName, "-", e); } }); }; if (Array.isArray(_this.sp.storage['eventSourceContexts'])) { _this.sp.storage['eventSourceContexts'] = _this.sp.storage['eventSourceContexts'].filter(function (ctx) { return !ctx._expired; }); _this.sp.storage['eventSourceContexts'].forEach(function (ctx) { _this.setupEventSource(ctx); }); } _this.controller.emitter.on("updateGamemodeDataMessage", function (e) { return _this.onUpdateGamemodeDataMessage(e); }); return _this; } GamemodeEventSourceService.prototype.onUpdateGamemodeDataMessage = function (event) { var _this = this; if (this.sp.settings["skymp5-client"]["disable-gamemode-updates"]) { if (this.sp.storage['GamemodeEventSourceService_sawEventSources'] === true) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Gamemode updates are disabled by settings"); return; } (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Gamemode updates are disabled by settings - processing first update only"); this.sp.storage['GamemodeEventSourceService_sawEventSources'] = true; } if (!Array.isArray(this.sp.storage['eventSourceContexts'])) { this.sp.storage['eventSourceContexts'] = []; } else { this.sp.storage['eventSourceContexts'].forEach(function (ctx) { ctx.sendEvent = function () { }; ctx._expired = true; }); } var eventSourcesRecord = {}; event.message.eventSources.forEach(function (pair) { return eventSourcesRecord[pair.name] = pair.content; }); var eventNames = Object.keys(eventSourcesRecord); var blockedEventSources = this.sp.settings["skymp5-client"]["blockedEventSources"]; if (Array.isArray(blockedEventSources)) { blockedEventSources.forEach(function (blockedEventSource) { eventNames = eventNames.filter(function (eventName) { return eventName !== blockedEventSource; }); (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "'eventSources", blockedEventSource, "- Blocked by the client"); }); } var serverJsVerificationService = this.controller.lookupListener(_serverJsVerificationService__WEBPACK_IMPORTED_MODULE_5__.ServerJsVerificationService); eventNames.forEach(function (eventName) { var result = serverJsVerificationService.verifyServerJs(eventSourcesRecord[eventName]); if (result.src === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(_this, "'eventSources", eventName, 'Verification failed:', result.error); return; } try { var fn = new Function('ctx', result.src); var ctx = { refr: undefined, value: undefined, _model: undefined, _view: undefined, i: -1, get: function (_propName) { throw new Error("ctx.get can't be used in event source"); }, respawn: function () { throw new Error("ctx.respawn can't be used in event source"); }, sp: skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__, sendEvent: function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var message = { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.CustomEvent, argsJsonDumps: args.map(function (arg) { return JSON.stringify(arg); }), eventName: eventName }; _this.controller.emitter.emit("sendMessage", { message: message, reliability: "reliable" }); }, getFormIdInServerFormat: function (clientsideFormId) { return (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(clientsideFormId); }, getFormIdInClientFormat: function (serversideFormId) { return (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.remoteIdToLocalId)(serversideFormId); }, _fn: fn, _eventName: eventName, state: {}, }; _this.sp.storage['eventSourceContexts'].push(ctx); _this.setupEventSource(ctx); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(_this, "'eventSources", eventName, "-", e); } }); }; return GamemodeEventSourceService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); ; /***/ }), /***/ "./src/services/services/gamemodeUpdateService.ts": /*!********************************************************!*\ !*** ./src/services/services/gamemodeUpdateService.ts ***! \********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GamemodeUpdateService: () => (/* binding */ GamemodeUpdateService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _remoteServer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./remoteServer */ "./src/services/services/remoteServer.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _serverJsVerificationService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./serverJsVerificationService */ "./src/services/services/serverJsVerificationService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor // The reason we use global skyrimPlatform is that this.sp may be limited, and gamemode api needs unlimited access to skyrimPlatform // Sligthly different types var GamemodeUpdateService = /** @class */ (function (_super) { __extends(GamemodeUpdateService, _super); function GamemodeUpdateService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.emitter.on("updateGamemodeDataMessage", function (e) { return _this.onUpdateGamemodeDataMessage(e); }); _this.controller.emitter.on("createActorMessage", function (e) { return _this.onCreateActorMessage(e); }); _this.controller.on("tick", function () { return _this.onTick(); }); _this.controller.on("update", function () { return _this.onUpdate(); }); _this.updateOwnerCtx = { sp: skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__, refr: undefined, value: undefined, _model: undefined, getFormIdInServerFormat: function (clientsideFormId) { return (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.localIdToRemoteId)(clientsideFormId); }, getFormIdInClientFormat: function (serversideFormId) { return (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.remoteIdToLocalId)(serversideFormId); }, get: function (propName) { return this._model[propName]; }, state: {}, _view: undefined, i: -1, respawn: function () { throw new Error("ctx.respawn is not available for updateOwner"); } }; _this.updateNeighborCtx = { refr: undefined, value: undefined, _model: undefined, sp: skyrimPlatform__WEBPACK_IMPORTED_MODULE_3__, state: undefined, _view: undefined, i: -1, getFormIdInServerFormat: function (clientsideFormId) { return (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.localIdToRemoteId)(clientsideFormId); }, getFormIdInClientFormat: function (serversideFormId) { return (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.remoteIdToLocalId)(serversideFormId); }, get: function (propName) { return this._model[propName]; }, respawn: function () { this._view.destroyForm(this.i); } }; _this.updateNeighborFunctionsKeys = []; _this.updateNeighborFunctions = {}; return _this; } GamemodeUpdateService.prototype.setFormViewArray = function (formViewArray) { this.updateNeighborCtx._view = formViewArray; }; GamemodeUpdateService.prototype.setI = function (i) { this.updateNeighborCtx.i = i; }; GamemodeUpdateService.prototype.updateNeighbor = function (refr, model, state) { for (var _i = 0, _a = this.updateNeighborFunctionsKeys; _i < _a.length; _i++) { var key = _a[_i]; var v = model[key]; // According to docs: // In `updateOwner`/`updateNeighbor` equals to a value of a currently processed property. // Can't be `undefined` here, since updates are not received for `undefined` property values. // In other contexts is always `undefined`. if (v !== undefined) { this.updateNeighborCtx.refr = refr; this.updateNeighborCtx.value = v; this.updateNeighborCtx._model = model; this.updateNeighborCtx.state = state; var f = this.updateNeighborFunctions[key]; // Actually, 'f' should always be a valid function, but who knows try { if (f) { f(this.updateNeighborCtx); } } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "updateNeighbor", key, '-', e); } } } }; GamemodeUpdateService.prototype.onUpdateGamemodeDataMessage = function (event) { if (this.sp.settings["skymp5-client"]["disable-gamemode-updates"]) { if (this.sp.storage['GamemodeUpdateService_sawUpdateFunctions'] === true) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Gamemode updates are disabled by settings"); return; } (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Gamemode updates are disabled by settings - processing first update only"); this.sp.storage['GamemodeUpdateService_sawUpdateFunctions'] = true; } this.sp.storage['updateNeighborFunctions'] = undefined; this.sp.storage['updateOwnerFunctions'] = undefined; this.updateGamemodeUpdateFunctions('updateNeighborFunctions', event.message.updateNeighborFunctions); this.updateGamemodeUpdateFunctions('updateOwnerFunctions', event.message.updateOwnerFunctions); }; GamemodeUpdateService.prototype.onCreateActorMessage = function (event) { var _this = this; if (!event.message.isMe) { return; } // Otherwise worldModel.playerCharacterFormIdx may be unassigned this.controller.once("tick", function () { var remoteServer = _this.controller.lookupListener(_remoteServer__WEBPACK_IMPORTED_MODULE_1__.RemoteServer); var worldModel = remoteServer.getWorldModel(); var myFormModel = worldModel.forms[worldModel.playerCharacterFormIdx]; if (!myFormModel) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(_this, "Unable to find formModel with index", worldModel.playerCharacterFormIdx); return; } _this.setOwnerModel(myFormModel); }); }; GamemodeUpdateService.prototype.onTick = function () { var keys = this.sp.storage["updateNeighborFunctions_keys"]; if (keys && Array.isArray(keys)) { this.updateNeighborFunctionsKeys = keys; } else { this.updateNeighborFunctionsKeys = []; } // TODO: Shouldn't we check storage value before assignment? this.updateNeighborFunctions = this.sp.storage["updateNeighborFunctions"]; }; GamemodeUpdateService.prototype.onUpdate = function () { var playerRef = this.sp.ObjectReference.from(this.sp.Game.getPlayer()); var keys = this.sp.storage["updateOwnerFunctions_keys"]; if (!keys || !Array.isArray(keys)) { keys = []; } var funcs = this.sp.storage["updateOwnerFunctions"]; if (this.sp.storage["ownerModelSet"] !== true) { return; } var ownerModel = this.sp.storage["ownerModel"]; for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var propName = keys_1[_i]; var f = funcs[propName]; // Actually, must always be a valid funciton, but who knows if (!f) { continue; } this.updateOwnerCtx._model = ownerModel; if (!this.updateOwnerCtx._model) { continue; } this.updateOwnerCtx.value = this.updateOwnerCtx._model[propName]; if (this.updateOwnerCtx.value === undefined) { continue; } this.updateOwnerCtx.refr = playerRef; this.updateOwnerCtx._model = ownerModel; try { if (f) { f(this.updateOwnerCtx); } } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "updateOwner", propName, '-', e); } } }; GamemodeUpdateService.prototype.setOwnerModel = function (ownerModel) { this.sp.storage["ownerModel"] = ownerModel; this.sp.storage["ownerModelSet"] = true; }; ; GamemodeUpdateService.prototype.updateGamemodeUpdateFunctions = function (storageVar, functionSources) { var serverJsVerificationService = this.controller.lookupListener(_serverJsVerificationService__WEBPACK_IMPORTED_MODULE_5__.ServerJsVerificationService); var functionSourcesRecord = {}; functionSources.forEach(function (pair) { return functionSourcesRecord[pair.name] = pair.content; }); this.sp.storage[storageVar] = functionSourcesRecord; for (var _i = 0, _a = Object.keys(functionSourcesRecord); _i < _a.length; _i++) { var propName = _a[_i]; var result = serverJsVerificationService.verifyServerJs(this.sp.storage[storageVar][propName]); if (result.src === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(this, storageVar, propName, 'Verification failed:', result.error); delete this.sp.storage[storageVar][propName]; continue; } try { this.sp.storage[storageVar][propName] = new Function('ctx', result.src); var emptyFunction = functionSourcesRecord[propName] === ''; if (emptyFunction) { delete this.sp.storage[storageVar][propName]; (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, storageVar, propName, 'Added empty'); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, storageVar, propName, 'Added'); } } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(this, storageVar, propName, e); } } this.sp.storage["".concat(storageVar, "_keys")] = Object.keys(this.sp.storage[storageVar]); }; return GamemodeUpdateService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); ; /***/ }), /***/ "./src/services/services/hitService.ts": /*!*********************************************!*\ !*** ./src/services/services/hitService.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ HitService: () => (/* binding */ HitService) /* harmony export */ }); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out var HitService = /** @class */ (function (_super) { __extends(HitService, _super); function HitService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.recentMagicHits = new Map(); controller.on('hit', function (e) { return _this.onHit(e); }); return _this; } HitService.prototype.onHit = function (e) { // TODO: add more logging in case of 'return' // TODO: allow non-weapon sources var aggressor = e.aggressor.getFormID(); if (aggressor < 0xff000000 && aggressor !== 0x14) return; // all skymp npcs are FF+ if (aggressor >= 0xff000000) { // TODO: make host service var hosted = skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.storage['hosted']; var alreadyHosted = false; if (Array.isArray(hosted)) { var remoteId = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(aggressor); if (hosted.includes(remoteId) || hosted.includes(remoteId + 0x100000000)) { alreadyHosted = true; } } if (!alreadyHosted) { return; } } var base = e.target.getBaseObject(); var type = base === null || base === void 0 ? void 0 : base.getType(); if (type === 34 /* FormType.Static */ || type === 36 /* FormType.MovableStatic */) { return; } var isWeapon = this.sp.Weapon.from(e.source); var isSpell = !isWeapon && this.sp.Spell.from(e.source); var isScroll = !isWeapon && !isSpell && this.sp.Scroll.from(e.source); if (!isWeapon && !isSpell && !isScroll) { return; } // prevent double hit that happens for some reason with magic projectiles if (isSpell || isScroll) { var aggressorId = e.aggressor.getFormID(); var now = Date.now(); var lastHitTime = this.recentMagicHits.get(aggressorId); if (lastHitTime && now - lastHitTime < 100) { return; } this.recentMagicHits.set(aggressorId, now); } this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_3__.MsgType.OnHit, data: this.getHitData(e) }, reliability: "reliable" }); }; HitService.prototype.getHitData = function (e) { var hitData = { aggressor: (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(e.aggressor.getFormID()), isBashAttack: e.isBashAttack, isHitBlocked: e.isHitBlocked, isPowerAttack: e.isPowerAttack, isSneakAttack: e.isSneakAttack, projectile: e.projectile ? e.projectile.getFormID() : 0, source: e.source ? e.source.getFormID() : 0, target: (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(e.target.getFormID()) }; return hitData; }; return HitService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/keyboardEventsService.ts": /*!********************************************************!*\ !*** ./src/services/services/keyboardEventsService.ts ***! \********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KeyboardEventsService: () => (/* binding */ KeyboardEventsService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var KeyboardEventsService = /** @class */ (function (_super) { __extends(KeyboardEventsService, _super); function KeyboardEventsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.lastNumKeys = 0; controller.on("update", function () { return _this.onUpdate(); }); return _this; } KeyboardEventsService.prototype.onUpdate = function () { var _this = this; var numKeys = this.sp.Input.getNumKeysPressed(); if (this.lastNumKeys !== numKeys) { this.lastNumKeys = numKeys; this.controller.emitter.emit("queryKeyCodeBindings", { isDown: function (binding) { if (binding.every(function (key) { return _this.sp.Input.isKeyPressed(key); })) { return true; } return false; } }); } }; return KeyboardEventsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); ; /***/ }), /***/ "./src/services/services/lastInvService.ts": /*!*************************************************!*\ !*** ./src/services/services/lastInvService.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LastInvService: () => (/* binding */ LastInvService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var LastInvService = /** @class */ (function (_super) { __extends(LastInvService, _super); function LastInvService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; return _this; } Object.defineProperty(LastInvService.prototype, "lastInv", { get: function () { return this._lastInv; }, set: function (newValue) { this._lastInv = newValue; }, enumerable: false, configurable: true }); return LastInvService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/loadGameService.ts": /*!**************************************************!*\ !*** ./src/services/services/loadGameService.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LoadGameService: () => (/* binding */ LoadGameService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var LoadGameService = /** @class */ (function (_super) { __extends(LoadGameService, _super); function LoadGameService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this._isCausedBySkyrimPlatform = false; _this.controller.on("loadGame", function () { return _this.onLoadGame(); }); return _this; } LoadGameService.prototype.loadGame = function (pos, rot, worldOrCell, changeFormNpc, loadOrder, time) { try { // @ts-ignore this.sp.loadGame(pos, rot, worldOrCell, changeFormNpc, loadOrder, time); } catch (e) { // Hotfix non-vanilla headparts bug // @ts-ignore this.sp.loadGame(pos, rot, worldOrCell, undefined, loadOrder, time); } this._isCausedBySkyrimPlatform = true; }; LoadGameService.prototype.onLoadGame = function () { var _this = this; try { var gameLoadEvent = { isCausedBySkyrimPlatform: this._isCausedBySkyrimPlatform }; this.controller.emitter.emit("gameLoad", gameLoadEvent); } catch (e) { this.controller.once("tick", function () { _this._isCausedBySkyrimPlatform = false; }); throw e; } this.controller.once("tick", function () { _this._isCausedBySkyrimPlatform = false; }); }; return LoadGameService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/loadOrderVerificationService.ts": /*!***************************************************************!*\ !*** ./src/services/services/loadOrderVerificationService.ts ***! \***************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LoadOrderVerificationService: () => (/* binding */ LoadOrderVerificationService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _view_formView__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../view/formView */ "./src/view/formView.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _settingsService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./settingsService */ "./src/services/services/settingsService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var STATE_KEY = 'loadOrderCheckState'; ; var LoadOrderVerificationService = /** @class */ (function (_super) { __extends(LoadOrderVerificationService, _super); function LoadOrderVerificationService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } LoadOrderVerificationService.prototype.onceUpdate = function () { this.verifyLoadOrder(); }; LoadOrderVerificationService.prototype.verifyLoadOrder = function () { var _this = this; var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_4__.SettingsService); this.resetText(); var clientMods = this.getClientMods(); this.printModOrder('Client load order:', clientMods); return settingsService.getServerMods() .then(function (serverMods) { _this.printModOrder('Server load order:', serverMods); if (clientMods.length < serverMods.length) { throw new Error("Missing some server mods. Server has ".concat(serverMods.length, ", we have ").concat(clientMods.length)); } if (clientMods.length > serverMods.length) { _this.updateText('LOAD ORDER WARNING: you have more mods than server!\n(or could not receive server mod list)\nCheck console for details.', [255, 255, 0, 1], 5); } var fail = []; for (var i = 0; i < serverMods.length; ++i) { // Need case-insensitive check for 1.6+ if (clientMods[i].filename.toLowerCase() !== serverMods[i].filename.toLowerCase() || clientMods[i].size !== serverMods[i].size || clientMods[i].crc32 !== serverMods[i].crc32) { fail.push(i); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("".concat(i, "-th mod (numbered from 0) does not match.")); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Server has ".concat(JSON.stringify(serverMods[i]))); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("We have ".concat(JSON.stringify(clientMods[i]))); } } if (fail.length !== 0) { throw new Error('Load order check failed! Indices: ' + JSON.stringify(fail)); } }) .catch(function (err) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)(err); if (_this.sp.settings['skymp5-client']['ignoreLoadOrderMismatch']) { _this.updateText('LOAD ORDER ERROR!\nHowever, ignoring it because of ignoreLoadOrderMismatch being set.' + '\nExpect EVERYTHING BREAK, unless you know what you are doing.\nCheck console for details.' + '\nThis message will disappear after 30 seconds.', [255, 0, 0, 1], 30); return; } _this.updateText('LOAD ORDER ERROR!\nCheck console for details.', [255, 0, 0, 1]); }); }; ; LoadOrderVerificationService.prototype.getState = function () { if (typeof this.sp.storage[STATE_KEY] !== 'object') { return {}; } return this.sp.storage[STATE_KEY]; }; ; LoadOrderVerificationService.prototype.setState = function (replacement) { var oldState = this.sp.storage[STATE_KEY] = this.getState(); for (var _i = 0, _a = Object.entries(replacement); _i < _a.length; _i++) { var _b = _a[_i], k = _b[0], v = _b[1]; oldState[k] = v; } }; ; LoadOrderVerificationService.prototype.resetText = function () { var statusTextId = this.getState().statusTextId; if (statusTextId) { this.sp.destroyText(statusTextId); statusTextId = undefined; this.setState({ statusTextId: statusTextId }); } }; ; LoadOrderVerificationService.prototype.updateText = function (text, color, clearDelay) { var _this = this; var _a = (0,_view_formView__WEBPACK_IMPORTED_MODULE_1__.getScreenResolution)(), width = _a.width, height = _a.height; this.resetText(); var statusTextId = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.createText)(width / 2, height / 2, text, color); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(statusTextId, 0.5); this.setState({ statusTextId: statusTextId }); if (clearDelay) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(clearDelay).then(function () { return _this.resetText(); }); } }; LoadOrderVerificationService.prototype.enumerateClientMods = function (getCount, getAt) { var result = []; for (var i = 0; i < getCount(); ++i) { var filename = getAt(i); var _a = this.getFileInfoSafe(filename), crc32 = _a.crc32, size = _a.size; result.push({ filename: filename, crc32: crc32, size: size }); } return result; }; LoadOrderVerificationService.prototype.getClientMods = function () { return this.enumerateClientMods(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getModCount, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getModName); }; ; LoadOrderVerificationService.prototype.printModOrder = function (header, order) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)(header); for (var _i = 0, _a = Object.entries(order); _i < _a.length; _i++) { var _b = _a[_i], i = _b[0], mod = _b[1]; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("#".concat(i, " ").concat(JSON.stringify(mod))); } }; ; LoadOrderVerificationService.prototype.getFileInfoSafe = function (filename) { try { return this.sp.getFileInfo(filename); } catch (e) { var message = e.message; if (typeof message === "string" && message.includes('is not a valid argument')) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Failed to get file info for", filename); return { crc32: 0, size: 0 }; } else { throw e; } } }; return LoadOrderVerificationService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/magicSyncService.ts": /*!***************************************************!*\ !*** ./src/services/services/magicSyncService.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MagicSyncService: () => (/* binding */ MagicSyncService) /* harmony export */ }); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out // @ts-expect-error (TODO: Remove in 2.10.0) var MagicSyncService = /** @class */ (function (_super) { __extends(MagicSyncService, _super); function MagicSyncService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.playerId = 0x14; _this.sendUpdateAnimationVariablesRateMs = 500; _this.lastSpellCastEventMsg = null; _this.lastSendUpdateAnimationVariables = 0; _this.controller.on("update", function () { return _this.onUpdate(); }); _this.controller.on("spellCast", function (e) { return _this.onSpellCast(e); }); var self = _this; _this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { }, leave: function (ctx) { self.onSendAnimationEventLeave(ctx); } }, _this.playerId, _this.playerId); return _this; } MagicSyncService.prototype.onUpdate = function () { var _this = this; if (this.isAnyMagicStuffEquiped() === false) { return; } if (Date.now() - this.lastSendUpdateAnimationVariables <= this.sendUpdateAnimationVariablesRateMs) { return; } this.lastSendUpdateAnimationVariables = Date.now(); this.controller.once('update', function () { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.Game.getPlayer(); if (!ac) { return; } var animVariables = _this.getAnimationVariablesFromActorConverted(ac.getFormID()); _this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_3__.MsgType.UpdateAnimVariables, data: _this.getUpdateAnimVariablesEventData(ac, animVariables) }, reliability: "reliable" }); }); }; MagicSyncService.prototype.onSpellCast = function (event) { var isInterruptCast = false; var msg = this.getSpellCastEventData(event, isInterruptCast); this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_3__.MsgType.SpellCast, data: msg }, reliability: "reliable" }); this.lastSpellCastEventMsg = msg; }; MagicSyncService.prototype.onSendAnimationEventLeave = function (ctx) { var _this = this; if (!this.lastSpellCastEventMsg || !this.isInteraptSpellCastAnim(ctx.animEventName)) { return; } this.controller.once('update', function () { if (!_this.lastSpellCastEventMsg || _this.lastSpellCastEventMsg.interruptCast) { return; } var msg = _this.lastSpellCastEventMsg; msg.interruptCast = true; msg.actorAnimationVariables = _this.getAnimationVariablesFromActorConverted((0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.remoteIdToLocalId)(_this.lastSpellCastEventMsg.caster)); _this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_3__.MsgType.SpellCast, data: msg }, reliability: "reliable" }); }); }; MagicSyncService.prototype.getSpellCastEventData = function (e, isInterruptCast) { var spellCastData = { caster: (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(e.caster.getFormID(), true), // @ts-expect-error (TODO: Remove in 2.10.0) target: e.target ? (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(e.target.getFormID(), true) : 0, spell: e.spell ? e.spell.getFormID() : 0, interruptCast: isInterruptCast, // @ts-expect-error (TODO: Remove in 2.10.0) isDualCasting: e.isDualCasting, // @ts-expect-error (TODO: Remove in 2.10.0) castingSource: e.castingSource, // @ts-expect-error (TODO: Remove in 2.10.0) aimAngle: e.aimAngle, // @ts-expect-error (TODO: Remove in 2.10.0) aimHeading: e.aimHeading, actorAnimationVariables: this.getAnimationVariablesFromActorConverted(e.caster.getFormID()), }; return spellCastData; }; MagicSyncService.prototype.getAnimationVariablesFromActorConverted = function (actorId) { var animVars = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.getAnimationVariablesFromActor)(actorId); var booleans = animVars.booleans; var floats = animVars.floats; var integers = animVars.integers; return { booleans: Array.from(new Uint8Array(booleans)), floats: Array.from(new Uint8Array(floats)), integers: Array.from(new Uint8Array(integers)), }; }; MagicSyncService.prototype.getUpdateAnimVariablesEventData = function (ac, animVariables) { var animVarsData = { actorRemoteId: (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId)(ac.getFormID(), true), actorAnimationVariables: animVariables, }; return animVarsData; }; MagicSyncService.prototype.isInteraptSpellCastAnim = function (animEventName) { var eventName = animEventName.toLowerCase(); return eventName === "mlh_equipped_event" || eventName === "mrh_equipped_event"; }; ; MagicSyncService.prototype.isSpellCastAnim = function (animEventName) { var eventName = animEventName.toLowerCase(); var isSpellCastAnimForLeftHand = eventName === "mlh_spellaimedconcentrationstart" || eventName === "mlh_spellaimedstart" || eventName === "mlh_spellready_event" || eventName === "mlh_spellrelease_event" || eventName === "mlh_equipped_event"; var isSpellCastAnimForRightHand = eventName === "mrh_spellaimedconcentrationstart" || eventName === "mrh_spellaimedstart" || eventName === "mrh_spellready_event" || eventName === "mrh_spellrelease_event" || eventName === "mrh_equipped_event"; return isSpellCastAnimForLeftHand || isSpellCastAnimForRightHand; }; ; MagicSyncService.prototype.isAnyMagicStuffEquiped = function () { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.Game.getPlayer(); if (!ac) { return false; } if (ac.getEquippedSpell(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.SpellType.Left) || ac.getEquippedSpell(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.SpellType.Right)) { return true; } if (ac.getEquippedSpell(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.SpellType.Voise) || ac.getEquippedSpell(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.SpellType.Instant)) { return true; } var leftHandEquipmentType = ac.getEquippedItemType(1 /* SlotType.Left */); var rightHandEquipmentType = ac.getEquippedItemType(2 /* SlotType.Right */); if (leftHandEquipmentType === 9 || leftHandEquipmentType === 8 /* EquippedItemType.Staff */ || rightHandEquipmentType === 9 || rightHandEquipmentType === 8 /* EquippedItemType.Staff */) { return true; } return false; }; return MagicSyncService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/netInfoService.ts": /*!*************************************************!*\ !*** ./src/services/services/netInfoService.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ NetInfoService: () => (/* binding */ NetInfoService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var NetInfoService = /** @class */ (function (_super) { __extends(NetInfoService, _super); function NetInfoService(sp, controller) { var _this = this; var _a; _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.receivedPacketCount = 0; _this.sentPacketCount = 0; _this.localLagUnits = 0; _this.delayMs = 1000; _this.lastDt = 0; _this.dt = 0; _this.greenARGB = [0, 128, 0, 1]; _this.redARGB = [255, 0, 0, 1]; // clear previous texts in case of hotreload if (_this.sp.storage[NetInfoTexts.Name] && _this.sp.storage[NetInfoTexts.Name].clear) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "Destroying old NetInfoTexts"); try { (_a = _this.sp.storage[NetInfoTexts.Name]) === null || _a === void 0 ? void 0 : _a.clear(); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(_this, "Failed to destroy old NetInfoTexts:", e); } } if (!_this.isEnabled()) { return _this; } _this.textIds = new NetInfoTexts(_this.sp); _this.sp.storage[NetInfoTexts.Name] = _this.textIds; _this.lastDt = Date.now(); _this.controller.emitter.on("sendMessage", function (e) { return _this.onSendMessage(e); }); _this.controller.emitter.on("sendMessageWithRefrId", function (e) { return _this.onSendMessageWithRefrId(e); }); _this.controller.emitter.on("anyMessage", function (e) { return _this.onAnyMessage(e); }); _this.controller.emitter.on("newLocalLagValueCalculated", function (e) { return _this.onNewLocalLagValueCalculated(e); }); _this.controller.on("update", function () { return _this.onUpdate(); }); return _this; } NetInfoService.prototype.onSendMessage = function (e) { this.addSentPacketCount(1); }; NetInfoService.prototype.onSendMessageWithRefrId = function (e) { this.addSentPacketCount(1); }; NetInfoService.prototype.onAnyMessage = function (e) { this.addReceivedPacketCount(1); }; NetInfoService.prototype.onNewLocalLagValueCalculated = function (e) { this.setLocalLagUnits(e.lagUnitsNoZ); }; NetInfoService.prototype.onUpdate = function () { if (this.textIds === undefined) { return; } this.dt += Date.now() - this.lastDt; this.lastDt = Date.now(); var isConnected = this.sp.mpClientPlugin.isConnected(); this.sp.setTextString(this.textIds.connectionStateTextId, "".concat(isConnected ? "ON" : "OFF")); this.sp.setTextColor(this.textIds.connectionStateTextId, isConnected ? this.greenARGB : this.redARGB); // https://www.creationkit.com/index.php?title=Unit var units = this.getLocalLagUnits(); var unitsInMeter = 70.0218818381; var meters = Math.round(units / unitsInMeter * 10) / 10; this.sp.setTextString(this.textIds.localPositionLagAmountTextId, "".concat(units, " units (~").concat(meters, " m)")); if (this.delayMs > this.dt) { return; } this.sp.setTextString(this.textIds.receivedPacketAmountTextId, "".concat(Math.round(this.getAndClearReceivedPacketCount()))); this.sp.setTextString(this.textIds.sentPacketAmountTextId, "".concat(Math.round(this.getAndClearSentPacketCount()))); this.dt = 0; }; NetInfoService.prototype.addReceivedPacketCount = function (count) { this.receivedPacketCount += count; }; NetInfoService.prototype.getAndClearReceivedPacketCount = function () { var value = this.receivedPacketCount; this.receivedPacketCount = 0; return value; }; NetInfoService.prototype.addSentPacketCount = function (count) { this.sentPacketCount += count; }; NetInfoService.prototype.getAndClearSentPacketCount = function () { var value = this.sentPacketCount; this.sentPacketCount = 0; return value; }; NetInfoService.prototype.setLocalLagUnits = function (distance) { this.localLagUnits = distance; }; NetInfoService.prototype.getLocalLagUnits = function () { return this.localLagUnits; }; NetInfoService.prototype.isEnabled = function () { return !!this.sp.settings["skymp5-client"]["show-net-info"]; }; return NetInfoService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); var NetInfoTexts = /** @class */ (function () { function NetInfoTexts(sp, connectionStaticTextId, connectionStateTextId, receivedPacketStaticTextId, receivedPacketAmountTextId, sentPacketStaticTextId, sentPacketAmountTextId, localPositionLagStaticTextId, localPositionLagAmountTextId) { if (connectionStaticTextId === void 0) { connectionStaticTextId = sp.createText(100, 350, "connection:", [255, 255, 255, 1]); } if (connectionStateTextId === void 0) { connectionStateTextId = sp.createText(220, 350, "", [255, 255, 255, 1]); } if (receivedPacketStaticTextId === void 0) { receivedPacketStaticTextId = sp.createText(120, 390, "incoming (p/s):", [255, 255, 255, 1]); } if (receivedPacketAmountTextId === void 0) { receivedPacketAmountTextId = sp.createText(250, 390, "", [255, 255, 255, 1]); } if (sentPacketStaticTextId === void 0) { sentPacketStaticTextId = sp.createText(120, 430, "outgoing (p/s):", [255, 255, 255, 1]); } if (sentPacketAmountTextId === void 0) { sentPacketAmountTextId = sp.createText(250, 430, "", [255, 255, 255, 1]); } if (localPositionLagStaticTextId === void 0) { localPositionLagStaticTextId = sp.createText(90, 470, "local lag:", [255, 255, 255, 1]); } if (localPositionLagAmountTextId === void 0) { localPositionLagAmountTextId = sp.createText(250, 470, "", [255, 255, 255, 1]); } this.sp = sp; this.connectionStaticTextId = connectionStaticTextId; this.connectionStateTextId = connectionStateTextId; this.receivedPacketStaticTextId = receivedPacketStaticTextId; this.receivedPacketAmountTextId = receivedPacketAmountTextId; this.sentPacketStaticTextId = sentPacketStaticTextId; this.sentPacketAmountTextId = sentPacketAmountTextId; this.localPositionLagStaticTextId = localPositionLagStaticTextId; this.localPositionLagAmountTextId = localPositionLagAmountTextId; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.connectionStaticTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.connectionStateTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.receivedPacketStaticTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.receivedPacketAmountTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.sentPacketStaticTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.sentPacketAmountTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.localPositionLagStaticTextId, 0.5); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.localPositionLagAmountTextId, 0.5); } NetInfoTexts.prototype.clear = function () { this.sp.destroyText(this.connectionStaticTextId); this.sp.destroyText(this.connectionStateTextId); this.sp.destroyText(this.receivedPacketStaticTextId); this.sp.destroyText(this.receivedPacketAmountTextId); this.sp.destroyText(this.sentPacketStaticTextId); this.sp.destroyText(this.sentPacketAmountTextId); this.sp.destroyText(this.localPositionLagStaticTextId); this.sp.destroyText(this.localPositionLagAmountTextId); }; NetInfoTexts.Name = "netInfoTexts"; return NetInfoTexts; }()); /***/ }), /***/ "./src/services/services/networkingService.ts": /*!****************************************************!*\ !*** ./src/services/services/networkingService.ts ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ NetworkingService: () => (/* binding */ NetworkingService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _lib_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../lib/errors */ "./src/lib/errors.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _remoteServer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./remoteServer */ "./src/services/services/remoteServer.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var NetworkingService = /** @class */ (function (_super) { __extends(NetworkingService, _super); function NetworkingService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.on("tick", function () { return _this.onTick(); }); _this.controller.emitter.on("sendMessage", function (e) { return _this.onSendMessage(e); }); _this.controller.emitter.on("sendRawMessage", function (e) { return _this.onSendRawMessage(e); }); _this.controller.emitter.on("sendMessageWithRefrId", function (e) { return _this.onSendMessageWithRefrId(e); }); return _this; } NetworkingService.prototype.onSendMessage = function (e) { this.sp.mpClientPlugin.send(JSON.stringify(e.message), this.isReliable(e.reliability)); }; NetworkingService.prototype.onSendRawMessage = function (e) { // @ts-expect-error this.sp.mpClientPlugin.sendRaw(e.rawMessage, e.rawMessage.byteLength, this.isReliable(e.reliability)); }; NetworkingService.prototype.onSendMessageWithRefrId = function (e) { var refrId = e.message._refrId; var remoteServer = this.controller.lookupListener(_remoteServer__WEBPACK_IMPORTED_MODULE_4__.RemoteServer); var idxInModel = refrId ? remoteServer.getWorldModel().forms.findIndex(function (f) { return f && f.refrId === refrId; }) : remoteServer.getWorldModel().playerCharacterFormIdx; // fixes "can't get property idx of null or undefined" if (!remoteServer.getWorldModel().forms[idxInModel]) { return; } // @ts-ignore e.message.idx = remoteServer.getWorldModel().forms[idxInModel].idx; delete e.message._refrId; this.sp.mpClientPlugin.send(JSON.stringify(e.message), this.isReliable(e.reliability)); }; NetworkingService.prototype.connect = function (hostName, port) { this.serverAddress = { hostName: hostName, port: port }; this.createClientSafe(); }; NetworkingService.prototype.reconnect = function () { this.createClientSafe(); }; NetworkingService.prototype.close = function () { this.sp.mpClientPlugin.destroyClient(); }; NetworkingService.prototype.isConnected = function () { return this.sp.mpClientPlugin.isConnected(); }; NetworkingService.prototype.onTick = function () { var _this = this; this.sp.mpClientPlugin.tick(function (packetType, rawContent, error) { switch (packetType) { case "connectionAccepted": _this.controller.emitter.emit("connectionAccepted", {}); break; case "connectionDenied": _this.controller.emitter.emit("connectionDenied", { error: error }); _this.reconnect(); break; case "connectionFailed": _this.controller.emitter.emit("connectionFailed", {}); _this.reconnect(); break; case "disconnect": _this.controller.emitter.emit("connectionDisconnect", {}); _this.reconnect(); break; case "message": // TODO: in theory can be empty jsonContent and non-empty error var msgAny = void 0; if (rawContent === null) { msgAny = {}; (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "null rawContent"); } else if ((new Uint8Array(rawContent)[0]) === 0x7b) { // assume json msgAny = JSON.parse(_this.sp.decodeUtf8(rawContent)); } else { // assume raw var event = { rawContent: rawContent }; return _this.controller.emitter.emit("anyRawMessage", event); } if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.OpenContainer) { var event = { message: msgAny }; _this.controller.emitter.emit("openContainerMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateMovement) { var event = { message: msgAny }; _this.controller.emitter.emit("updateMovementMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateAnimation) { var event = { message: msgAny }; _this.controller.emitter.emit("updateAnimationMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateEquipment) { var event = { message: msgAny }; _this.controller.emitter.emit("updateEquipmentMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.ChangeValues) { var event = { message: msgAny }; _this.controller.emitter.emit("changeValuesMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.SpellCast) { var event = { message: msgAny }; _this.controller.emitter.emit("spellCastMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateAnimVariables) { var event = { message: msgAny }; _this.controller.emitter.emit("updateAnimVariablesMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateAppearance) { var event = { message: msgAny }; _this.controller.emitter.emit("updateAppearanceMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.Teleport) { var event = { message: msgAny }; _this.controller.emitter.emit("teleportMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateProperty) { var event = { message: msgAny }; _this.controller.emitter.emit("updatePropertyMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.DeathStateContainer) { var event = { message: msgAny }; _this.controller.emitter.emit("deathStateContainerMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.CreateActor) { var event = { message: msgAny }; _this.controller.emitter.emit("createActorMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.CustomPacket) { var event = { message: msgAny }; _this.controller.emitter.emit("customPacketMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.DestroyActor) { var event = { message: msgAny }; _this.controller.emitter.emit("destroyActorMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.HostStart) { var event = { message: msgAny }; _this.controller.emitter.emit("hostStartMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.HostStop) { var event = { message: msgAny }; _this.controller.emitter.emit("hostStopMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.SetInventory) { var event = { message: msgAny }; _this.controller.emitter.emit("setInventoryMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.SetRaceMenuOpen) { var event = { message: msgAny }; _this.controller.emitter.emit("setRaceMenuOpenMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.SpSnippet) { var event = { message: msgAny }; _this.controller.emitter.emit("spSnippetMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateGamemodeData) { var event = { message: msgAny }; _this.controller.emitter.emit("updateGamemodeDataMessage", event); _this.controller.emitter.emit("anyMessage", event); } else if (msgAny.t === _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.Teleport2) { var event = { message: msgAny }; _this.controller.emitter.emit("teleportMessage2", event); _this.controller.emitter.emit("anyMessage", event); } else { // throw new NeverError(msgAny); throw new Error("Unhandled MsgType " + msgAny.t); } break; } }); }; NetworkingService.prototype.createClientSafe = function () { var _a = this.serverAddress, hostName = _a.hostName, port = _a.port; (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(this, "createClientSafe " + hostName + ":" + port); if (this.serverAddress.hostName !== "" && this.serverAddress.port !== 0) { this.sp.mpClientPlugin.createClient(hostName, port); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "createClientSafe failed"); } }; Object.defineProperty(NetworkingService.prototype, "serverAddress", { get: function () { var res = this.sp.storage["serverAddress"]; if (typeof res === "object") { var result = res; if (typeof result.hostName === "string" && typeof result.port === "number") { return result; } } return { hostName: "", port: 0 }; }, set: function (newValue) { this.sp.storage["serverAddress"] = newValue; }, enumerable: false, configurable: true }); NetworkingService.prototype.isReliable = function (reliability) { switch (reliability) { case "reliable": return true; case "unreliable": return false; default: throw new _lib_errors__WEBPACK_IMPORTED_MODULE_1__.NeverError(reliability); } }; return NetworkingService; }(_clientListener__WEBPACK_IMPORTED_MODULE_3__.ClientListener)); ; /***/ }), /***/ "./src/services/services/playerBowShotService.ts": /*!*******************************************************!*\ !*** ./src/services/services/playerBowShotService.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PlayerBowShotService: () => (/* binding */ PlayerBowShotService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _sync_equipment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../sync/equipment */ "./src/sync/equipment.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var PlayerBowShotService = /** @class */ (function (_super) { __extends(PlayerBowShotService, _super); function PlayerBowShotService(sp, controller) { var _this_1 = _super.call(this) || this; _this_1.sp = sp; _this_1.controller = controller; _this_1.score = 0; _this_1.inventoryUnblockMoment = 0; _this_1.controller.emitter.on("queryBlockSetInventoryEvent", function (e) { return _this_1.onQueryBlockSetInventoryEvent(e); }); _this_1.controller.on("playerBowShot", function (e) { return _this_1.onPlayerBowShot(e); }); var _this = _this_1; var eventPatterns = ["attackRelease", "crossbowAttackStart"]; eventPatterns.forEach(function (eventPattern) { _this_1.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { }, leave: function (ctx) { if (!ctx.animationSucceeded) { return; } if (ctx.animEventName === "crossbowAttackStart") { _this.score = 1; } else if (ctx.animEventName === "attackRelease") { if (_this.score === 1) { _this.controller.once("update", function () { _this.onPlayerCrossbowShot(); }); _this.score = 0; } } else { _this.score = 0; } } }, 0x14, 0x14, eventPattern); }); return _this_1; } PlayerBowShotService.prototype.onQueryBlockSetInventoryEvent = function (e) { if (Date.now() < this.inventoryUnblockMoment) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Blocked inventory operation"); e.block(); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Not blocked inventory operation"); } }; PlayerBowShotService.prototype.onPlayerBowShot = function (e) { this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.PlayerBowShot, weaponId: e.weapon.getFormID(), ammoId: e.ammo.getFormID(), power: e.power, isSunGazing: e.isSunGazing || false }, reliability: "unreliable" }); }; PlayerBowShotService.prototype.onPlayerCrossbowShot = function () { var actor = this.sp.Game.getPlayer(); if (actor === null) { return; } var crossbow = actor.getEquippedWeapon(false); if (crossbow === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(this, "Couldn't get equipped weapon"); return; } var weaponType = crossbow.getWeaponType(); if (weaponType !== 9 /* WeaponType.Crossbow */) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(this, "Expected weapon to be crossbow, but got WeaponType", weaponType); return; } var equippedAmmoEntries = (0,_sync_equipment__WEBPACK_IMPORTED_MODULE_3__.getEquipment)(actor, 0).inv.entries.filter(function (entry) { return entry.worn && skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ammo.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(entry.baseId)); }); if (equippedAmmoEntries.length === 0) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(this, "Ammo not found"); return; } if (equippedAmmoEntries.length > 1) { var equippedAmmoIds = equippedAmmoEntries.map(function (entry) { return entry.baseId; }); (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logError)(this, "Found more than 1 ammos:", equippedAmmoIds); return; } this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.PlayerBowShot, weaponId: crossbow.getFormID(), ammoId: equippedAmmoEntries[0].baseId, isSunGazing: false, power: 1.0 }, reliability: "unreliable" }); // Fixes race condition when the server removes an item faster than local crossbow does that: -1 total // Then crossbow removes one more item: -2 total // The item is being added back: -1 total (which is correct but looks ugly in process) this.inventoryUnblockMoment = Date.now() + 5 * 1000; (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(this, "Sent crossbow shot"); }; return PlayerBowShotService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); ; /***/ }), /***/ "./src/services/services/profilingService.ts": /*!***************************************************!*\ !*** ./src/services/services/profilingService.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProfilingService: () => (/* binding */ ProfilingService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var inspector__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! inspector */ "inspector"); /* harmony import */ var inspector__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(inspector__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! fs */ "fs"); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (undefined && undefined.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var ProfilingService = /** @class */ (function (_super) { __extends(ProfilingService, _super); function ProfilingService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; var settings = sp.settings["skymp5-client"]; if (!settings["enableProfiling"]) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "ProfilingService: disabled"); return _this; } var profilingDurationMs = _this.getInteger(settings["profilingDurationMs"]) || 10000; var session = new inspector__WEBPACK_IMPORTED_MODULE_2__.Session(); session.connect(); (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "ProfilingService: start"); _this.startProfiling(session, profilingDurationMs); return _this; } ProfilingService.prototype.startProfiling = function (session, profilingDurationMs) { return __awaiter(this, void 0, void 0, function () { var profile, fileNameSuffix; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, new Promise(function (resolve, reject) { session.post('Profiler.enable', function (err) { if (err) { reject(err); } else { resolve(undefined); } }); })]; case 1: _a.sent(); return [4 /*yield*/, new Promise(function (resolve, reject) { session.post('Profiler.start', function (err) { if (err) { reject(err); } else { resolve(undefined); } }); })]; case 2: _a.sent(); return [4 /*yield*/, new Promise(function (resolve) { setTimeout(resolve, profilingDurationMs); })]; case 3: _a.sent(); (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(this, "ProfilingService: stop"); return [4 /*yield*/, new Promise(function (resolve, reject) { session.post('Profiler.stop', function (err, res) { if (err) { reject(err); } else { resolve(res); } }); })]; case 4: profile = (_a.sent()).profile; fileNameSuffix = Math.random().toString().replace(".0", ""); fs__WEBPACK_IMPORTED_MODULE_3__.writeFileSync("./profile".concat(fileNameSuffix, ".cpuprofile"), JSON.stringify(profile)); return [2 /*return*/]; } }); }); }; ProfilingService.prototype.getInteger = function (value) { if (typeof value === 'number') { if (Number.isInteger(value)) { return value; } } return undefined; }; return ProfilingService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/ragdollService.ts": /*!*************************************************!*\ !*** ./src/services/services/ragdollService.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RagdollService: () => (/* binding */ RagdollService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var RagdollService = /** @class */ (function (_super) { __extends(RagdollService, _super); function RagdollService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; // TODO: think about tracking ragdoll state of player _this.safeRemoveRagdollFromWorld = function (actor, afterRemoveCallback) { _this.setLocalDamageMult(0); actor.forceRemoveRagdollFromWorld().then(function () { _this.controller.once("update", function () { _this.setLocalDamageMult(_this.defaultLocalDamageMult); afterRemoveCallback(); }); }); }; _this.defaultLocalDamageMult = 1; _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } RagdollService.prototype.onceUpdate = function () { this.setLocalDamageMult(this.defaultLocalDamageMult); }; RagdollService.prototype.setLocalDamageMult = function (damageMult) { this.sp.Game.setGameSettingFloat("fDiffMultHPToPCE", damageMult); this.sp.Game.setGameSettingFloat("fDiffMultHPToPCH", damageMult); this.sp.Game.setGameSettingFloat("fDiffMultHPToPCL", damageMult); this.sp.Game.setGameSettingFloat("fDiffMultHPToPCN", damageMult); this.sp.Game.setGameSettingFloat("fDiffMultHPToPCVE", damageMult); this.sp.Game.setGameSettingFloat("fDiffMultHPToPCVH", damageMult); }; return RagdollService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/remoteServer.ts": /*!***********************************************!*\ !*** ./src/services/services/remoteServer.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RemoteServer: () => (/* binding */ RemoteServer), /* harmony export */ getPcInventory: () => (/* binding */ getPcInventory) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); /* harmony import */ var _lib_idManager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../lib/idManager */ "./src/lib/idManager.ts"); /* harmony import */ var _lib_nameof__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../lib/nameof */ "./src/lib/nameof.ts"); /* harmony import */ var _sync_actorvalues__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../sync/actorvalues */ "./src/sync/actorvalues.ts"); /* harmony import */ var _sync_appearance__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../sync/appearance */ "./src/sync/appearance.ts"); /* harmony import */ var _sync_equipment__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../sync/equipment */ "./src/sync/equipment.ts"); /* harmony import */ var _sync_inventory__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../sync/inventory */ "./src/sync/inventory.ts"); /* harmony import */ var _sync_spell__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../sync/spell */ "./src/sync/spell.ts"); /* harmony import */ var _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../view/modelApplyUtils */ "./src/view/modelApplyUtils.ts"); /* harmony import */ var _loadGameService__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./loadGameService */ "./src/services/services/loadGameService.ts"); /* harmony import */ var _ragdollService__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./ragdollService */ "./src/services/services/ragdollService.ts"); /* harmony import */ var _lib_errors__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../lib/errors */ "./src/lib/errors.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _timeService__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./timeService */ "./src/services/services/timeService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (undefined && undefined.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; // @ts-expect-error (TODO: Remove in 2.10.0) /* eslint-disable @typescript-eslint/no-empty-function */ // TODO: refactor worldViewMisc into service var getPcInventory = function () { var res = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['pcInv']; if (typeof res === 'object' && res['entries']) { return res; } return undefined; }; var setPcInventory = function (inv) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['pcInv'] = inv; }; var pcInvLastApply = 0; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.on)('update', function () { if ((0,_sync_equipment__WEBPACK_IMPORTED_MODULE_7__.isBadMenuShown)()) { return; } if (Date.now() - pcInvLastApply > 5000) { pcInvLastApply = Date.now(); var pcInv = getPcInventory(); if (pcInv) { (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_8__.applyInventory)(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(), pcInv, false, true); } } }); var unequipIronHelmet = function () { var ironHelment = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Armor.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(0x00012e4d)); var pl = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); if (pl) { pl.unequipItem(ironHelment, false, true); } }; var RemoteServer = /** @class */ (function (_super) { __extends(RemoteServer, _super); function RemoteServer(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.numSetInventory = 0; _this.controller.emitter.on("hostStartMessage", function (e) { return _this.onHostStartMessage(e); }); _this.controller.emitter.on("hostStopMessage", function (e) { return _this.onHostStopMessage(e); }); _this.controller.emitter.on("setInventoryMessage", function (e) { return _this.onSetInventoryMessage(e); }); _this.controller.emitter.on("openContainerMessage", function (e) { return _this.onOpenContainerMessage(e); }); _this.controller.emitter.on("updateMovementMessage", function (e) { return _this.onUpdateMovementMessage(e); }); _this.controller.emitter.on("updateAnimationMessage", function (e) { return _this.onUpdateAnimationMessage(e); }); _this.controller.emitter.on("updateEquipmentMessage", function (e) { return _this.onUpdateEquipmentMessage(e); }); _this.controller.emitter.on("changeValuesMessage", function (e) { return _this.onChangeValuesMessage(e); }); _this.controller.emitter.on("updateAppearanceMessage", function (e) { return _this.onUpdateAppearanceMessage(e); }); _this.controller.emitter.on("teleportMessage", function (e) { return _this.onTeleportMessage(e); }); _this.controller.emitter.on("teleportMessage2", function (e) { return _this.onTeleportMessage(e); }); _this.controller.emitter.on("createActorMessage", function (e) { return _this.onCreateActorMessage(e); }); _this.controller.emitter.on("destroyActorMessage", function (e) { return _this.onDestroyActorMessage(e); }); _this.controller.emitter.on("setRaceMenuOpenMessage", function (e) { return _this.onSetRaceMenuOpenMessage(e); }); _this.controller.emitter.on("updatePropertyMessage", function (e) { return _this.onUpdatePropertyMessage(e); }); _this.controller.emitter.on("deathStateContainerMessage", function (e) { return _this.onDeathStateContainerMessage(e); }); _this.controller.emitter.on("connectionAccepted", function () { return _this.handleConnectionAccepted(); }); _this.controller.emitter.on("spellCastMessage", function (e) { return _this.onSpellCastMessage(e); }); _this.controller.emitter.on("updateAnimVariablesMessage", function (e) { return _this.onUpdateAnimVariablesMessage(e); }); return _this; } RemoteServer.prototype.onHostStartMessage = function (event) { var msg = event.message; var target = msg.target; var hosted = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['hosted']; if (typeof hosted !== typeof []) { // if you try to switch to Set please checkout .concat usage. // concat compiles but doesn't work as expected hosted = new Array(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['hosted'] = hosted; } if (!hosted.includes(target)) { hosted.push(target); } }; RemoteServer.prototype.onHostStopMessage = function (event) { var msg = event.message; var target = msg.target; (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, 'hostStop ' + target.toString(16)); var hosted = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['hosted']; if (typeof hosted === typeof []) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['hosted'] = hosted.filter(function (x) { return x !== target; }); } }; RemoteServer.prototype.onSetInventoryMessage = function (event) { var _this = this; this.numSetInventory++; var msg = event.message; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { setPcInventory(msg.inventory); var blocked = false; _this.controller.emitter.emit('queryBlockSetInventoryEvent', { block: function () { return blocked = true; } }); if (!blocked) { pcInvLastApply = 0; } }); }; RemoteServer.prototype.onOpenContainerMessage = function (event) { var _this = this; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { return __awaiter(_this, void 0, void 0, function () { var remoteId, localId, refr, baseObject, baseType, functionChecker, factName, delaySeconds; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.1)]; case 1: _a.sent(); // Give a chance to update inventory remoteId = event.message.target; localId = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.remoteIdToLocalId)(remoteId); refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(localId)); if (refr === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, 'onOpenContainerMessage - refr not found', 'remoteId', remoteId.toString(16), 'localId', localId.toString(16)); return [2 /*return*/]; } refr.activate(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(), true); baseObject = refr.getBaseObject(); baseType = baseObject === null || baseObject === void 0 ? void 0 : baseObject.getType(); functionChecker = null; factName = ""; delaySeconds = -1.0; if (baseType === 28 /* FormType.Container */) { functionChecker = function () { return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen("ContainerMenu"); }; factName = "'ContainerMenu open'"; delaySeconds = 0.0; } else if (baseType === 40 /* FormType.Furniture */) { functionChecker = function () { var _a; return !!((_a = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer()) === null || _a === void 0 ? void 0 : _a.getFurnitureReference()); }; factName = "'getFurnitureReference not null'"; delaySeconds = 1.0; } if (functionChecker === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "onOpenContainerMesage - not a container or furniture", baseType); return [2 /*return*/]; } // In SkyMP containers have 2-nd, closing activation under the hood. // This differs from Skyrim's behavior, where it's just one activation. (function () { return __awaiter(_this, void 0, void 0, function () { var message; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "onOpenContainerMesage - waiting for", factName, "to be true"); _a.label = 1; case 1: if (!!functionChecker()) return [3 /*break*/, 3]; return [4 /*yield*/, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.1)]; case 2: _a.sent(); return [3 /*break*/, 1]; case 3: (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "onOpenContainerMesage - waiting for", factName, "to be false"); _a.label = 4; case 4: if (!functionChecker()) return [3 /*break*/, 6]; return [4 /*yield*/, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.1)]; case 5: _a.sent(); return [3 /*break*/, 4]; case 6: (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "onOpenContainerMesage - menu closed", factName); message = { t: _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.Activate, data: { caster: 0x14, target: event.message.target, isSecondActivation: true } }; (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "onOpenContainerMesage - waiting", delaySeconds, "seconds before sending ActivateMessage"); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.waitMenuMode(delaySeconds).then(function () { _this.controller.emitter.emit("sendMessage", { message: message, reliability: "reliable" }); (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, "onOpenContainerMesage - sent ActivateMessage", message); }); return [2 /*return*/]; } }); }); })(); return [2 /*return*/]; } }); }); }); }; RemoteServer.prototype.onTeleportMessage = function (event) { var _this = this; var msg = event.message; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var id = ("idx" in msg && typeof msg.idx === "number") ? _this.getIdManager().getId(msg.idx) : _this.getMyActorIndex(); var refr = id === _this.getMyActorIndex() ? skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer() : (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.getObjectReference)(id); (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, "Teleporting id", id, "refrId", refr === null || refr === void 0 ? void 0 : refr.getFormID().toString(16), "...", msg.pos, 'cell/world is', msg.worldOrCell.toString(16)); var ragdollService = _this.controller.lookupListener(_ragdollService__WEBPACK_IMPORTED_MODULE_12__.RagdollService); var refrId = refr === null || refr === void 0 ? void 0 : refr.getFormID(); var removeRagdollCallback = function () { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.moveRefrToPosition(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId || 0)), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Cell.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(msg.worldOrCell)), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.WorldSpace.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(msg.worldOrCell)), msg.pos[0], msg.pos[1], msg.pos[2], msg.rot[0], msg.rot[1], msg.rot[2]); }; var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (actor /*&& actor.getFormID() === 0x14*/) { ragdollService.safeRemoveRagdollFromWorld(actor, removeRagdollCallback); } else { removeRagdollCallback(); } }); }; RemoteServer.prototype.onCreateActorMessage = function (event) { var _this = this; var _a; var msg = event.message; if (this.skipFormViewCreation(msg)) { var refrId_1 = msg.refrId; this.onceLoad(refrId_1, function (refr) { var _a; if (refr) { _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.dealWithRef(refr, refr.getBaseObject()); if (msg.props) { if (msg.props.inventory) { _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelInventory(refr, msg.props.inventory); } _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelIsOpen(refr, !!msg.props['isOpen']); _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelIsHarvested(refr, !!msg.props['isHarvested']); _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelNodeScale(refr, msg.props.setNodeScale); _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelNodeTextureSet(refr, msg.props.setNodeTextureSet); _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelIsDisabled(refr, !!msg.props['disabled']); // TODO: move to a separate module var animation_1 = msg.props.lastAnimation; if (typeof animation_1 === "string") { var refrid_1 = refr.getFormID(); (function () { return __awaiter(_this, void 0, void 0, function () { var i_1, res2; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: i_1 = 0; _b.label = 1; case 1: if (!(i_1 < 5)) return [3 /*break*/, 4]; res2 = (_a = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrid_1))) === null || _a === void 0 ? void 0 : _a.playAnimation(animation_1); if (res2) { return [3 /*break*/, 4]; } return [4 /*yield*/, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(2)]; case 2: _b.sent(); _b.label = 3; case 3: i_1++; return [3 /*break*/, 1]; case 4: return [2 /*return*/]; } }); }); })(); } var displayName = msg.props.displayName; // keep in sync with spSnippetService.ts if (typeof displayName === "string") { var replaceValue = (_a = refr.getBaseObject()) === null || _a === void 0 ? void 0 : _a.getName(); if (replaceValue !== undefined) { displayName = displayName.replace(/%original_name%/g, replaceValue); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(_this, "Couldn't get a replaceValue for SetDisplayName, refr.getFormID() was", refr.getFormID().toString(16)); } refr.setDisplayName(displayName, true); (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, "calling setDisplayName", displayName, "for", refr.getFormID().toString(16)); } } } else { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(_this, 'Failed to apply model to', refrId_1.toString(16)); } }); return; } (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "Create actor"); var i = this.getIdManager().allocateIdFor(msg.idx); if (this.worldModel.forms.length <= i) { this.worldModel.forms.length = i + 1; } var movement = undefined; // TODO: better check if it is an npc (not an object reference) if (msg.refrId !== undefined && msg.refrId >= 0xff000000) { movement = { pos: msg.transform.pos, rot: msg.transform.rot, worldOrCell: msg.transform.worldOrCell, runMode: 'Standing', direction: 0, isInJumpState: false, isSneaking: false, isBlocking: false, isWeapDrawn: false, isDead: false, healthPercentage: 1.0, speed: 0, }; } var form = { idx: msg.idx, movement: movement, numMovementChanges: 0, numAppearanceChanges: 0, baseId: msg.baseId, refrId: msg.refrId, isMyClone: msg.isMe, }; this.worldModel.forms[i] = form; if (msg.appearance) { form.appearance = msg.appearance; } if (msg.equipment) { form.equipment = msg.equipment; } if (msg.isDead) { form.isDead = msg.isDead; } if (msg.animation) { form.animation = msg.animation; } if (msg.props) { for (var propName in msg.props) { form[propName] = msg.props[propName]; } } msg.customPropsJsonDumps.forEach(function (element) { var _a; var parsed; try { parsed = JSON.parse(element.propValueJsonDump); } catch (e) { if (e instanceof SyntaxError) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(_this, "createActor", (_a = msg.refrId) === null || _a === void 0 ? void 0 : _a.toString(16), "failed to parse custom prop", element.propName, element.propValueJsonDump, e.message); } else { throw e; } } form[element.propName] = parsed; }); if (msg.isMe) { this.worldModel.playerCharacterFormIdx = i; this.worldModel.playerCharacterRefrId = msg.refrId || 0; } // TODO: move to a separate module if (msg.props && !msg.props.isHostedByOther) { } if (msg.props && msg.props.isRaceMenuOpen && msg.isMe) { this.onSetRaceMenuOpenMessage({ message: { t: _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.SetRaceMenuOpen, open: true } }); } var numSetInventory = this.numSetInventory; var applyPcInv = function () { if (msg.equipment) { (0,_sync_equipment__WEBPACK_IMPORTED_MODULE_7__.applyEquipment)(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(), msg.equipment); } if (numSetInventory !== _this.numSetInventory) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, 'Skipping inventory apply due to newer setInventory message'); return; } if (msg.props && msg.props.inventory) { _this.onSetInventoryMessage({ message: { t: _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.SetInventory, inventory: msg.props.inventory } }); } }; if (msg.isMe && msg.props && msg.props.learnedSpells) { var learnedSpells_1 = msg.props.learnedSpells; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(1).then(function () { var player = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); if (player) { (0,_sync_spell__WEBPACK_IMPORTED_MODULE_9__.removeAllSpells)(player); (0,_sync_spell__WEBPACK_IMPORTED_MODULE_9__.learnSpells)(player, learnedSpells_1); (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, "player learnedSpells:", JSON.stringify(learnedSpells_1)); } }); }); } if (msg.isMe) { if ((_a = msg.props) === null || _a === void 0 ? void 0 : _a.isDead) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)("update", function () { _this.controller.emitter.emit("applyDeathStateEvent", { actor: skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(), isDead: true }); }); } } if (msg.isMe) { var spawnTask_1 = { running: false }; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { // Use MoveRefrToPosition to spawn if possible (not in main menu) // In case of connection lost this is essential if (!spawnTask_1.running) { spawnTask_1.running = true; (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, 'Using moveRefrToPosition to spawn player'); (function () { return __awaiter(_this, void 0, void 0, function () { var pl, pos, sqr, distance; return __generator(this, function (_a) { switch (_a.label) { case 0: if (false) {} (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, 'Spawning...'); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.moveRefrToPosition(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Cell.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(msg.transform.worldOrCell)), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.WorldSpace.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(msg.transform.worldOrCell)), msg.transform.pos[0], msg.transform.pos[1], msg.transform.pos[2], msg.transform.rot[0], msg.transform.rot[1], msg.transform.rot[2]); return [4 /*yield*/, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(1)]; case 1: _a.sent(); pl = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); if (!pl) { return [3 /*break*/, 2]; } pos = [ pl.getPositionX(), pl.getPositionY(), pl.getPositionZ(), ]; sqr = function (x) { return x * x; }; distance = Math.sqrt(sqr(pos[0] - msg.transform.pos[0]) + sqr(pos[1] - msg.transform.pos[1])); if (distance < 256) { return [3 /*break*/, 2]; } return [3 /*break*/, 0]; case 2: return [2 /*return*/]; } }); }); })(); // Unfortunatelly it requires two calls to work skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(1).then(applyPcInv); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(1.3).then(applyPcInv); // Note: appearance part was copy-pasted if (msg.appearance) { (0,_sync_appearance__WEBPACK_IMPORTED_MODULE_6__.applyAppearanceToPlayer)(msg.appearance); } } if (msg.props) { var baseActorValues_1 = new Map([ ['healRate', msg.props.healRate], ['healRateMult', msg.props.healRateMult], ['health', msg.props.health], ['magickaRate', msg.props.magickaRate], ['magickaRateMult', msg.props.magickaRateMult], ['magicka', msg.props.magicka], ['staminaRate', msg.props.staminaRate], ['staminaRateMult', msg.props.staminaRateMult], ['stamina', msg.props.stamina], ['healthPercentage', msg.props.healthPercentage], ['staminaPercentage', msg.props.staminaPercentage], ['magickaPercentage', msg.props.magickaPercentage], ]); var player_1 = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); if (player_1) { baseActorValues_1.forEach(function (value, key) { if (typeof value === 'number') { if (key.includes('Percentage')) { var subKey = key.replace('Percentage', ''); var subValue = baseActorValues_1.get(subKey); if (typeof subValue === 'number') { (0,_sync_actorvalues__WEBPACK_IMPORTED_MODULE_5__.setActorValuePercentage)(player_1, subKey, value); } } else { player_1.setActorValue(key, value); } } }); } } }); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('tick', function () { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('tick', function () { if (!spawnTask_1.running) { spawnTask_1.running = true; var loadOrder = new Array(); for (var i_2 = 0; i_2 < _this.sp.Game.getModCount(); ++i_2) { loadOrder.push(_this.sp.Game.getModName(i_2)); } (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, "loading game in world/cell", msg.transform.worldOrCell.toString(16)); var loadGameService = _this.controller.lookupListener(_loadGameService__WEBPACK_IMPORTED_MODULE_11__.LoadGameService); loadGameService.loadGame(msg.transform.pos, msg.transform.rot, msg.transform.worldOrCell, msg.appearance ? { name: msg.appearance.name, raceId: msg.appearance.raceId, // TODO: In types, isFemale is under face, but in the reality SP expects it here. Fix required. // @ts-expect-error isFemale: msg.appearance.isFemale, face: { hairColor: msg.appearance.hairColor, bodySkinColor: msg.appearance.skinColor, headTextureSetId: msg.appearance.headTextureSetId, headPartIds: msg.appearance.headpartIds, presets: msg.appearance.presets }, } : undefined, loadOrder, { minutes: 0, seconds: 0, hours: _this.controller.lookupListener(_timeService__WEBPACK_IMPORTED_MODULE_16__.TimeService).getTime().newGameHourValue }); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { applyPcInv(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.3).then(applyPcInv); // Note: appearance part was copy-pasted if (msg.appearance) { (0,_sync_appearance__WEBPACK_IMPORTED_MODULE_6__.applyAppearanceToPlayer)(msg.appearance); } }); } }); }); } }; RemoteServer.prototype.onDestroyActorMessage = function (event) { var _a; var msg = event.message; var i = this.getIdManager().getId(msg.idx); this.worldModel.forms[i] = undefined; (_a = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.getViewFromStorage)()) === null || _a === void 0 ? void 0 : _a.syncFormArray(this.worldModel); // Shrink to fit while (1) { var length = this.worldModel.forms.length; if (!length) { break; } if (this.worldModel.forms[length - 1]) { break; } this.worldModel.forms.length = length - 1; } if (this.worldModel.playerCharacterFormIdx === i) { this.worldModel.playerCharacterFormIdx = -1; this.worldModel.playerCharacterRefrId = 0; // TODO: move to a separate module (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.quitToMainMenu(); }); } this.getIdManager().freeIdFor(msg.idx); }; RemoteServer.prototype.onUpdateMovementMessage = function (event) { var msg = event.message; var i = this.getIdManager().getId(msg.idx); var form = this.worldModel.forms[i]; if (form === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onUpdateMovementMessage - Form with idx", msg.idx, "not found"); return; } form.movement = msg.data; if (!form.numMovementChanges) { form.numMovementChanges = 0; } form.numMovementChanges++; }; RemoteServer.prototype.onUpdateAnimationMessage = function (event) { var msg = event.message; var i = this.getIdManager().getId(msg.idx); var form = this.worldModel.forms[i]; if (form === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onUpdateAnimationMessage - Form with idx", msg.idx, "not found"); return; } form.animation = msg.data; }; RemoteServer.prototype.onUpdateAppearanceMessage = function (event) { var _this = this; var msg = event.message; var i = this.getIdManager().getId(msg.idx); var form = this.worldModel.forms[i]; if (form === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onUpdateAppearanceMessage - Form with idx", msg.idx, "not found"); return; } form.appearance = msg.data || undefined; if (!form.numAppearanceChanges) { form.numAppearanceChanges = 0; } form.numAppearanceChanges++; var newAppearance = msg.data; if (i === this.getMyActorIndex() && newAppearance) { this.controller.once("update", function () { (0,_sync_appearance__WEBPACK_IMPORTED_MODULE_6__.applyAppearanceToPlayer)(newAppearance); (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(_this, "Applied appearance to the player"); }); } }; RemoteServer.prototype.onUpdateEquipmentMessage = function (event) { var msg = event.message; var i = this.getIdManager().getId(msg.idx); var form = this.worldModel.forms[i]; if (form === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onUpdateEquipmentMessage - Form with idx", msg.idx, "not found"); return; } form.equipment = msg.data; }; RemoteServer.prototype.onUpdatePropertyMessage = function (event) { var _this = this; var msg = event.message; var msgData = this.extractUpdatePropertyMessageData(msg); if (this.skipFormViewCreation(msg)) { var refrId_2 = msg.refrId; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId_2)); if (!refr) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(_this, 'UpdateProperty: refr not found'); return; } if (msg.propName === 'inventory') { _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelInventory(refr, msgData); } else if (msg.propName === 'isOpen') { _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelIsOpen(refr, !!msgData); } else if (msg.propName === 'isHarvested') { _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelIsHarvested(refr, !!msgData); } else if (msg.propName === 'disabled') { _view_modelApplyUtils__WEBPACK_IMPORTED_MODULE_10__.ModelApplyUtils.applyModelIsDisabled(refr, !!msgData); } }); return; } var i = this.getIdManager().getId(msg.idx); var form = this.worldModel.forms[i]; form[msg.propName] = msgData; }; RemoteServer.prototype.onDeathStateContainerMessage = function (event) { var _this = this; var msg = event.message; (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "Received death state:", JSON.stringify(msg.tIsDead)); var id = this.getIdManager().getId(msg.tIsDead.idx); var form = this.worldModel.forms[id]; if (form === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onDeathStateContainerMessage - Form with idx", msg.tIsDead.idx, "not found"); return; } if (msg.tIsDead.propName !== (0,_lib_nameof__WEBPACK_IMPORTED_MODULE_4__.nameof)('isDead')) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onDeathStateContainerMessage - Invalid propName", msg.tIsDead.propName); return; } var msgData = this.extractUpdatePropertyMessageData(msg.tIsDead); if (typeof msgData !== 'boolean') { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, "onDeathStateContainerMessage - Invalid data", msgData); return; } if (msg.tChangeValues) { this.onChangeValuesMessage({ message: msg.tChangeValues }); } (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { return _this.onUpdatePropertyMessage({ message: msg.tIsDead }); }); if (msg.tTeleport) { this.onTeleportMessage({ message: msg.tTeleport }); } (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var _a; var actor = id === _this.getWorldModel().playerCharacterFormIdx ? skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer() : skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx((0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.remoteIdToLocalId)((_a = form.refrId) !== null && _a !== void 0 ? _a : 0))); if (actor) { try { _this.controller.emitter.emit("applyDeathStateEvent", { actor: actor, isDead: msgData }); } catch (e) { if (e instanceof _lib_errors__WEBPACK_IMPORTED_MODULE_13__.RespawnNeededError) { actor.disableNoWait(false); actor.delete(); } else { throw e; } } } }); }; RemoteServer.prototype.handleConnectionAccepted = function () { this.worldModel.forms = []; this.worldModel.playerCharacterFormIdx = -1; this.worldModel.playerCharacterRefrId = 0; (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logTrace)(this, "Handle connection accepted"); }; RemoteServer.prototype.onChangeValuesMessage = function (event) { var _this = this; var msg = event.message; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var id = _this.getIdManager().getId(msg.idx); var refr = id === _this.getMyActorIndex() ? skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer() : (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.getObjectReference)(id); var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (!ac) { return; } var _a = msg.data, health = _a.health, stamina = _a.stamina, magicka = _a.magicka; if (typeof health === "number") { (0,_sync_actorvalues__WEBPACK_IMPORTED_MODULE_5__.setActorValuePercentage)(ac, 'health', health); } if (typeof stamina === "number") { (0,_sync_actorvalues__WEBPACK_IMPORTED_MODULE_5__.setActorValuePercentage)(ac, 'stamina', stamina); } if (typeof magicka === "number") { (0,_sync_actorvalues__WEBPACK_IMPORTED_MODULE_5__.setActorValuePercentage)(ac, 'magicka', magicka); } }); }; RemoteServer.prototype.onSetRaceMenuOpenMessage = function (event) { var msg = event.message; if (msg.open) { // wait 0.3s cause we can see visual bugs when teleporting // and showing this menu at the same time in onConnect (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.3).then(function () { unequipIronHelmet(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.showRaceMenu(); }); }); } else { // TODO: Implement closeMenu in SkyrimPlatform } }; /** Packet handlers end **/ RemoteServer.prototype.getWorldModel = function () { return this.worldModel; }; RemoteServer.prototype.getMyActorIndex = function () { return this.worldModel.playerCharacterFormIdx; }; RemoteServer.prototype.getMyRemoteRefrId = function () { return this.worldModel.playerCharacterRefrId; }; RemoteServer.prototype.getIdManager = function () { return this.idManager_; }; Object.defineProperty(RemoteServer.prototype, "worldModel", { get: function () { if (typeof skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["worldModel"] === "function") { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["worldModel"] = { forms: [], playerCharacterFormIdx: -1, playerCharacterRefrId: 0 }; } return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["worldModel"]; }, enumerable: false, configurable: true }); Object.defineProperty(RemoteServer.prototype, "idManager_", { get: function () { if (typeof skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["idManager"] === "function") { // Note: full IdManager object preserved across hot-reloads, including methods. skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["idManager"] = new _lib_idManager__WEBPACK_IMPORTED_MODULE_3__.IdManager(); } return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["idManager"]; }, enumerable: false, configurable: true }); RemoteServer.prototype.onceLoad = function (refrId, callback, maxAttempts) { var _this = this; if (maxAttempts === void 0) { maxAttempts = 120; } (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId)); if (refr) { callback(refr); } else { maxAttempts--; if (maxAttempts > 0) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { return _this.onceLoad(refrId, callback, maxAttempts); }); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(_this, 'Failed to load object reference ' + refrId.toString(16)); } } }); }; ; RemoteServer.prototype.skipFormViewCreation = function (msg) { // Optimization added in #1186, however it doesn't work for doors for some reason return msg.refrId && msg.refrId < 0xff000000 && msg.baseRecordType !== 'DOOR'; }; ; RemoteServer.prototype.extractUpdatePropertyMessageData = function (updatePropertyMessage) { var msgData = updatePropertyMessage.data; if (updatePropertyMessage.dataDump !== undefined) { try { msgData = JSON.parse(updatePropertyMessage.dataDump); } catch (e) { if (e instanceof SyntaxError) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(this, 'extractUpdatePropertyMessageData - Failed to parse dataDump', updatePropertyMessage.dataDump); return; } else { throw e; } } } return msgData; }; RemoteServer.prototype.onSpellCastMessage = function (event) { var msg = event.message; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx((0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.remoteIdToLocalId)(msg.data.caster))); if (!ac) { return; } var actorAnimationVariables = { booleans: new Uint8Array(msg.data.actorAnimationVariables.booleans), floats: new Uint8Array(msg.data.actorAnimationVariables.floats), integers: new Uint8Array(msg.data.actorAnimationVariables.integers) }; if (msg.data.interruptCast) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.interruptCast)(ac.getFormID(), msg.data.castingSource, actorAnimationVariables); return; } var spell = ac.getEquippedSpell(msg.data.castingSource); if (spell) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.castSpellImmediate)(ac.getFormID(), msg.data.castingSource, spell.getFormID(), (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.remoteIdToLocalId)(msg.data.target), msg.data.aimAngle, msg.data.aimHeading, actorAnimationVariables); } }); }; RemoteServer.prototype.onUpdateAnimVariablesMessage = function (event) { var _this = this; var msg = event.message; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)('update', function () { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx((0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_15__.remoteIdToLocalId)(msg.data.actorRemoteId))); if (!ac) { return; } var actorAnimationVariables = { booleans: new Uint8Array(msg.data.actorAnimationVariables.booleans), floats: new Uint8Array(msg.data.actorAnimationVariables.floats), integers: new Uint8Array(msg.data.actorAnimationVariables.integers) }; var isApplyed = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.applyAnimationVariablesToActor)(ac.getFormID(), actorAnimationVariables); if (!isApplyed) { (0,_logging__WEBPACK_IMPORTED_MODULE_17__.logError)(_this, 'Failed apply AnimationVariables to actor with id: ' + ac.getFormID().toString(16)); } }); }; return RemoteServer; }(_clientListener__WEBPACK_IMPORTED_MODULE_14__.ClientListener)); /***/ }), /***/ "./src/services/services/sendInputsService.ts": /*!****************************************************!*\ !*** ./src/services/services/sendInputsService.ts ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SendInputsService: () => (/* binding */ SendInputsService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _singlePlayerService__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./singlePlayerService */ "./src/services/services/singlePlayerService.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _sync_movementGet__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../sync/movementGet */ "./src/sync/movementGet.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _sync_animation__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../sync/animation */ "./src/sync/animation.ts"); /* harmony import */ var _sync_appearance__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../sync/appearance */ "./src/sync/appearance.ts"); /* harmony import */ var _sync_actorvalues__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../sync/actorvalues */ "./src/sync/actorvalues.ts"); /* harmony import */ var _sync_equipment__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../sync/equipment */ "./src/sync/equipment.ts"); /* harmony import */ var _view_hostAttempts__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../view/hostAttempts */ "./src/view/hostAttempts.ts"); /* harmony import */ var _remoteServer__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./remoteServer */ "./src/services/services/remoteServer.ts"); /* harmony import */ var _deathService__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./deathService */ "./src/services/services/deathService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out var playerFormId = 0x14; // TODO: split this service into EquipmentService, MovementService, AnimationService, ActorValueService, HostAttemptsService var SendInputsService = /** @class */ (function (_super) { __extends(SendInputsService, _super); function SendInputsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.lastSendMovementMoment = new Map(); _this.playerAnimSource = new Map(); // TODO: make service _this.lastAnimationSent = new Map(); _this.actorValuesNeedUpdate = false; _this.isRaceSexMenuShown = false; _this.equipmentChanged = false; _this.numEquipmentChanges = 0; _this.prevValues = { health: 0, stamina: 0, magicka: 0 }; _this.prevActorValuesUpdateTime = 0; _this.prevCastingDetectedTime = 0; _this.controller.on("update", function () { return _this.onUpdate(); }); _this.controller.on("equip", function (e) { return _this.onEquip(e); }); _this.controller.on("unequip", function (e) { return _this.onUnequip(e); }); _this.controller.on("loadGame", function () { return _this.onLoadGame(); }); return _this; } SendInputsService.prototype.onUpdate = function () { if (!this.singlePlayerService.isSinglePlayer) { this.sendInputs(); var player = this.sp.Game.getPlayer(); var isPlayerCasting = player.getAnimationVariableBool("IsCastingRight") || player.getAnimationVariableBool("IsCastingLeft") || player.getAnimationVariableBool("IsCastingDual"); if (isPlayerCasting) { this.prevCastingDetectedTime = Date.now(); } } }; SendInputsService.prototype.onEquip = function (event) { if (!event.actor || !event.baseObj) { return; } if (event.actor.getFormID() !== playerFormId) { return; } var type = event.baseObj.getType(); if (type !== 27 /* FormType.Book */ && type !== 46 /* FormType.Potion */ && type !== 30 /* FormType.Ingredient */) { // Trigger UpdateEquipment only for equips that are not spell tomes, potions, ingredients this.equipmentChanged = true; } // Send OnEquip for any equips including spell tomes, potions, ingredients // Otherwise, the server won't trigger spell learn, potion drink, ingredient eat and Papyrus scripts this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.OnEquip, baseId: event.baseObj.getFormID() }, reliability: "unreliable" }); }; SendInputsService.prototype.onUnequip = function (event) { if (!event.actor || !event.baseObj) { return; } if (event.actor.getFormID() === playerFormId) { this.equipmentChanged = true; } }; SendInputsService.prototype.onLoadGame = function () { var _this = this; // Currently only armor is equipped after relogging (see remoteServer.ts) // This hack forces sending /equipment without weapons/ back to the server this.sp.Utility.wait(3).then(function () { return (_this.equipmentChanged = true); }); }; SendInputsService.prototype.sendInputs = function () { var _this = this; var hosted = typeof this.sp.storage['hosted'] === typeof [] ? this.sp.storage['hosted'] : []; var targets = [undefined].concat(hosted); var modelSource = this.controller.lookupListener(_remoteServer__WEBPACK_IMPORTED_MODULE_10__.RemoteServer); var world = modelSource.getWorldModel(); targets.forEach(function (target) { var targetFormModel = target ? _this.getForm(target, world) : _this.getForm(undefined, world); _this.sendMovement(target, targetFormModel); _this.sendAnimation(target); _this.sendAppearance(target); _this.sendEquipment(target); _this.sendActorValuePercentage(target, targetFormModel); }); this.sendHostAttempts(); }; SendInputsService.prototype.sendMovement = function (_refrId, form) { var owner = this.getInputOwner(_refrId); if (!owner) { return; } var refrIdStr = "".concat(_refrId); var sendMovementRateMs = 130; var now = Date.now(); var last = this.lastSendMovementMoment.get(refrIdStr); if (!last || now - last > sendMovementRateMs) { var message = { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateMovement, data: (0,_sync_movementGet__WEBPACK_IMPORTED_MODULE_3__.getMovement)(owner, form), _refrId: _refrId }; this.controller.emitter.emit("sendMessageWithRefrId", { message: message, reliability: "unreliable" }); this.lastSendMovementMoment.set(refrIdStr, now); } }; SendInputsService.prototype.sendActorValuePercentage = function (_refrId, form) { var _a; var canSend = form && ((_a = form.isDead) !== null && _a !== void 0 ? _a : false) === false; if (!canSend) { return; } var owner = this.getInputOwner(_refrId); if (!owner) { return; } var av = (0,_sync_actorvalues__WEBPACK_IMPORTED_MODULE_7__.getActorValues)(this.sp.Game.getPlayer()); var currentTime = Date.now(); if (this.actorValuesNeedUpdate === false && this.prevValues.health === av.health && this.prevValues.stamina === av.stamina && this.prevValues.magicka === av.magicka) { return; } if (currentTime - this.prevActorValuesUpdateTime < 2000 && this.actorValuesNeedUpdate === false) { return; } // Delaying actor values update due to casting // TODO: use partial updates for actor values once server finally supports it // i.e. keep sending health and stamina during casting, but delay magicka update if (currentTime - this.prevCastingDetectedTime < 500 && av.health > 0 // don't delay death actor value update ) { return; } var deathService = this.controller.lookupListener(_deathService__WEBPACK_IMPORTED_MODULE_11__.DeathService); if (deathService.isBusy()) { (0,_logging__WEBPACK_IMPORTED_MODULE_12__.logTrace)(this, "Not sending actor values, death service is busy"); return; } var message = { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.ChangeValues, data: av, _refrId: _refrId }; this.controller.emitter.emit("sendMessageWithRefrId", { message: message, reliability: "unreliable" }); this.actorValuesNeedUpdate = false; this.prevValues = av; this.prevActorValuesUpdateTime = currentTime; }; SendInputsService.prototype.sendAnimation = function (_refrId) { var owner = this.getInputOwner(_refrId); if (!owner) { return; } // Extermly important that it's a local id since AnimationSource depends on it var refrIdStr = owner.getFormID().toString(16); var animSource = this.playerAnimSource.get(refrIdStr); if (!animSource) { animSource = new _sync_animation__WEBPACK_IMPORTED_MODULE_5__.AnimationSource(owner); this.playerAnimSource.set(refrIdStr, animSource); } var anim = animSource.getAnimation(); var lastAnimationSent = this.lastAnimationSent.get(refrIdStr); if (!lastAnimationSent || anim.numChanges !== lastAnimationSent.numChanges) { // Drink potion anim from this mod https://www.nexusmods.com/skyrimspecialedition/mods/97660 if (anim.animEventName !== '' && !anim.animEventName.startsWith("DrinkPotion_")) { this.lastAnimationSent.set(refrIdStr, anim); this.updateActorValuesAfterAnimation(anim.animEventName); var message = { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateAnimation, data: anim, _refrId: _refrId }; this.controller.emitter.emit("sendMessageWithRefrId", { message: message, reliability: "unreliable" }); } } }; SendInputsService.prototype.sendAppearance = function (_refrId) { if (_refrId) { return; } var shown = this.sp.Ui.isMenuOpen('RaceSex Menu'); if (shown != this.isRaceSexMenuShown) { this.isRaceSexMenuShown = shown; if (!shown) { this.sp.printConsole('Exited from race menu'); var appearance = (0,_sync_appearance__WEBPACK_IMPORTED_MODULE_6__.getAppearance)(this.sp.Game.getPlayer()); // TODO: log appearance contents to debug appearance issues? var message = { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateAppearance, data: appearance, _refrId: _refrId }; this.controller.emitter.emit("sendMessageWithRefrId", { message: message, reliability: "reliable" }); } } }; SendInputsService.prototype.sendEquipment = function (_refrId) { if (_refrId) { return; } if (this.equipmentChanged) { this.equipmentChanged = false; ++this.numEquipmentChanges; var eq = (0,_sync_equipment__WEBPACK_IMPORTED_MODULE_8__.getEquipment)(this.sp.Game.getPlayer(), this.numEquipmentChanges); var message = { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.UpdateEquipment, data: eq, _refrId: _refrId }; this.controller.emitter.emit("sendMessageWithRefrId", { message: message, reliability: "reliable" }); } }; SendInputsService.prototype.sendHostAttempts = function () { var remoteId = (0,_view_hostAttempts__WEBPACK_IMPORTED_MODULE_9__.nextHostAttempt)(); if (!remoteId) { return; } this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_2__.MsgType.Host, remoteId: remoteId }, reliability: "unreliable" }); }; SendInputsService.prototype.getInputOwner = function (_refrId) { return _refrId ? this.sp.Actor.from(this.sp.Game.getFormEx(_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_4__.remoteIdToLocalId(_refrId))) : this.sp.Game.getPlayer(); }; SendInputsService.prototype.getForm = function (refrId, world) { var form = refrId ? world === null || world === void 0 ? void 0 : world.forms.find(function (f) { return (f === null || f === void 0 ? void 0 : f.refrId) === refrId; }) : world.forms[world.playerCharacterFormIdx]; return form; }; SendInputsService.prototype.updateActorValuesAfterAnimation = function (animName) { if (animName === 'JumpLand' || animName === 'JumpLandDirectional' || animName === 'DeathAnim') { this.actorValuesNeedUpdate = true; } }; Object.defineProperty(SendInputsService.prototype, "singlePlayerService", { get: function () { return this.controller.lookupListener(_singlePlayerService__WEBPACK_IMPORTED_MODULE_1__.SinglePlayerService); }, enumerable: false, configurable: true }); return SendInputsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/serverJsVerificationService.ts": /*!**************************************************************!*\ !*** ./src/services/services/serverJsVerificationService.ts ***! \**************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ServerJsVerificationService: () => (/* binding */ ServerJsVerificationService) /* harmony export */ }); /* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! node:crypto */ "node:crypto"); /* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_crypto__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _settingsService__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./settingsService */ "./src/services/services/settingsService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var ServerJsVerificationService = /** @class */ (function (_super) { __extends(ServerJsVerificationService, _super); function ServerJsVerificationService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; return _this; } ServerJsVerificationService.prototype.verifyServerJs = function (src, customPrefix) { if (!src) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, 'Empty server JS, skipping verification'); return { src: src, error: null }; } var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_2__.SettingsService); var getTargetPeerResult = settingsService.getTargetPeer(); if (!getTargetPeerResult.targetPeerCached) { return { src: null, error: 'target peer not ready' }; } var publicKeys = getTargetPeerResult.targetPeerCached.publicKeys; if (!publicKeys) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, 'No public keys configured, skipping server JS verification'); return { src: src, error: null }; } var lastLineStart = src.lastIndexOf('\n') + 1; var sigPrefix = customPrefix || '// skymp:sig:y:'; if (lastLineStart === 0 || !src.substring(lastLineStart).startsWith(sigPrefix)) { return { src: null, error: 'no signature found' }; } var _a = src.substring(lastLineStart + sigPrefix.length).split(':'), keyId = _a[0], sig = _a[1]; if (!this.isAlphaNumeric(keyId)) { return { src: null, error: 'malformed key id' }; } var key = publicKeys[keyId]; if (!key) { return { src: null, error: 'unknown key ' + keyId }; } var toVerify = this.toArrayBufferView(src.substring(0, lastLineStart - 1), 'utf8'); if (!(0,node_crypto__WEBPACK_IMPORTED_MODULE_0__.verify)(null, toVerify, key, this.toArrayBufferView(sig, 'base64'))) { return { src: null, error: 'bad signature' }; } (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Server JS verified with key ".concat(keyId)); return { src: src, error: null }; }; ServerJsVerificationService.prototype.isAlphaNumeric = function (str) { for (var i = 0; i < str.length; ++i) { var code = str.charCodeAt(i); if (!((97 <= code && code <= 122) || (65 <= code && code <= 90) || (48 <= code && code <= 57))) { return false; } } return true; }; ServerJsVerificationService.prototype.toArrayBufferView = function (str, enc) { var buf = Buffer.from(str, enc); return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); }; return ServerJsVerificationService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/settingsService.ts": /*!**************************************************!*\ !*** ./src/services/services/settingsService.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SettingsService: () => (/* binding */ SettingsService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _authService__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./authService */ "./src/services/services/authService.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _timersService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./timersService */ "./src/services/services/timersService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (undefined && undefined.__assign) || function () { __assign = Object.assign || function(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); }; var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (undefined && undefined.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var SettingsService = /** @class */ (function (_super) { __extends(SettingsService, _super); function SettingsService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.targetPeerCache = null; return _this; } SettingsService.prototype.getServerMasterKey = function () { var masterKey = this.sp.settings["skymp5-client"]["server-master-key"]; if (!masterKey) { masterKey = this.sp.settings["skymp5-client"]["master-key"]; } if (!masterKey) { masterKey = this.sp.settings["skymp5-client"]["server-ip"] + ":" + this.sp.settings["skymp5-client"]["server-port"]; } return masterKey; }; SettingsService.prototype.getMasterUrl = function () { return this.normalizeUrl(this.sp.settings["skymp5-client"]["master"] || "https://gateway.skymp.net"); }; SettingsService.prototype.makeMasterApiClient = function () { var masterApiBaseUrl = this.getMasterUrl(); return new skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.HttpClient(masterApiBaseUrl); }; SettingsService.prototype.getTargetPeer = function (callback) { var _this = this; if (this.targetPeerCache) { callback === null || callback === void 0 ? void 0 : callback(this.targetPeerCache); return { targetPeerCached: this.targetPeerCache }; } this.getTargetPeerImpl(function (targetPeer) { _this.targetPeerCache = targetPeer; callback === null || callback === void 0 ? void 0 : callback(targetPeer); }); return { targetPeerCached: null }; }; // have to use callbacks here: promises don't work in the main menu SettingsService.prototype.getTargetPeerImpl = function (callback) { var _this = this; var masterApiClient = this.makeMasterApiClient(); var masterKey = this.getServerMasterKey(); var serverInfoRequestTimeoutMs = 5000; var defaultPeer = { host: this.sp.settings['skymp5-client']['server-ip'], port: this.sp.settings['skymp5-client']['server-port'], publicKeys: this.sp.settings['skymp5-client']['server-public-keys'], }; var resolved = false; var states = { start: function () { var _a; try { if (_this.sp.settings['skymp5-client']['server-info-ignore']) { (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, 'Skipping serverinfo request due to server-info-ignore in config'); states.resolve(defaultPeer); return; } _this.controller.lookupListener(_timersService__WEBPACK_IMPORTED_MODULE_3__.TimersService).setTimeout(function () { return states.reject(new Error('getTargetPeer: serverinfo request timed out')); }, serverInfoRequestTimeoutMs); var headers = {}; var session = (_a = _this.controller.lookupListener(_authService__WEBPACK_IMPORTED_MODULE_1__.AuthService).readAuthDataFromDisk()) === null || _a === void 0 ? void 0 : _a.session; if (session) { headers['X-Session'] = session; } masterApiClient.get("/api/servers/".concat(masterKey, "/serverinfo"), { headers: headers }, states.handleResponse); } catch (e) { states.reject(e); } }, handleResponse: function (res) { try { if (res.status !== 200) { throw new Error("status ".concat(res.status)); } states.resolve(JSON.parse(res.body)); } catch (e) { states.reject(e); } }, resolve: function (targetPeer) { if (resolved) { return; } resolved = true; (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "Resolved target peer", targetPeer); var enrichedTargetPeer = __assign({}, targetPeer); enrichedTargetPeer.publicKeys = __assign(__assign({}, defaultPeer.publicKeys), targetPeer.publicKeys); (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "Enriched target peer", enrichedTargetPeer); callback(enrichedTargetPeer); }, reject: function (err) { if (resolved) { return; } resolved = true; (0,_logging__WEBPACK_IMPORTED_MODULE_4__.logTrace)(_this, "Server info request failed, falling back to", defaultPeer, "; error:", err); callback(defaultPeer); }, }; states.start(); }; SettingsService.prototype.getServerMods = function () { return __awaiter(this, void 0, void 0, function () { var masterApiClient, masterKey, attempt, res, manifest, e_1; return __generator(this, function (_a) { switch (_a.label) { case 0: masterApiClient = this.makeMasterApiClient(); masterKey = this.getServerMasterKey(); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)(masterKey); attempt = 0; _a.label = 1; case 1: if (!(attempt < 5)) return [3 /*break*/, 7]; _a.label = 2; case 2: _a.trys.push([2, 4, , 6]); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Trying to get server mods, attempt ".concat(attempt)); return [4 /*yield*/, masterApiClient.get("/api/servers/".concat(masterKey, "/manifest.json"))]; case 3: res = _a.sent(); if (res.status != 200) { throw new Error("status code ".concat(res.status, ", error ").concat(res.error)); } manifest = JSON.parse(res.body); if (manifest.versionMajor !== 1) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("server manifest version is ".concat(manifest.versionMajor, ", we expect 1")); return [2 /*return*/, []]; } return [2 /*return*/, manifest.mods]; case 4: e_1 = _a.sent(); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Request/parse error: ".concat(e_1)); return [4 /*yield*/, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.1 + Math.random())]; case 5: _a.sent(); return [3 /*break*/, 6]; case 6: ++attempt; return [3 /*break*/, 1]; case 7: return [2 /*return*/, []]; } }); }); }; ; SettingsService.prototype.normalizeUrl = function (url) { if (url.endsWith('/')) { return url.slice(0, url.length - 1); } return url; }; ; return SettingsService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/singlePlayerService.ts": /*!******************************************************!*\ !*** ./src/services/services/singlePlayerService.ts ***! \******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SinglePlayerService: () => (/* binding */ SinglePlayerService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _networkingService__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./networkingService */ "./src/services/services/networkingService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var SinglePlayerService = /** @class */ (function (_super) { __extends(SinglePlayerService, _super); function SinglePlayerService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this._isSinglePlayer = false; _this.controller.emitter.on("gameLoad", function (e) { return _this.onGameLoad(e); }); return _this; } Object.defineProperty(SinglePlayerService.prototype, "isSinglePlayer", { get: function () { return this._isSinglePlayer; }, enumerable: false, configurable: true }); SinglePlayerService.prototype.onGameLoad = function (event) { if (!event.isCausedBySkyrimPlatform && !this._isSinglePlayer) { this.sp.Debug.messageBox('Save has been loaded in multiplayer, switching to the single-player mode'); this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_1__.NetworkingService).close(); this._isSinglePlayer = true; this.sp.Game.setInChargen(false, false, false); } }; return SinglePlayerService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/skympClient.ts": /*!**********************************************!*\ !*** ./src/services/services/skympClient.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SkympClient: () => (/* binding */ SkympClient) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _networkingService__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./networkingService */ "./src/services/services/networkingService.ts"); /* harmony import */ var _sync_animation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../sync/animation */ "./src/sync/animation.ts"); /* harmony import */ var _features_authModel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../features/authModel */ "./src/features/authModel.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _settingsService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./settingsService */ "./src/services/services/settingsService.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)('Hello Multiplayer!'); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)('settings:', skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.settings['skymp5-client']); var SkympClient = /** @class */ (function (_super) { __extends(SkympClient, _super); function SkympClient(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.emitter.on("connectionFailed", function (e) { return _this.onConnectionFailed(e); }); _this.controller.emitter.on("connectionDenied", function (e) { return _this.onConnectionDenied(e); }); _this.controller.emitter.on("createActorMessage", function (e) { return _this.onActorCreateMessage(e); }); // TODO: refactor out very similar code in frontHotReloadService.ts var authGameData = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage[_features_authModel__WEBPACK_IMPORTED_MODULE_3__.authGameDataStorageKey]; var storageHasValidAuthGameData = (authGameData === null || authGameData === void 0 ? void 0 : authGameData.local) || (authGameData === null || authGameData === void 0 ? void 0 : authGameData.remote); if (storageHasValidAuthGameData) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(_this, "Recovered AuthGameData from storage, starting client"); _this.startClient(); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(_this, "Unable to recover AuthGameData from storage, requesting auth"); // Next tick because we're in constructor of the service, AuthService may not be listening events yet _this.controller.once("tick", function () { _this.controller.emitter.emit("authNeeded", {}); }); _this.controller.emitter.on("authAttempt", function (e) { return _this.onAuthAttempt(e); }); } return _this; } SkympClient.prototype.onAuthAttempt = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Caught auth event"); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage[_features_authModel__WEBPACK_IMPORTED_MODULE_3__.authGameDataStorageKey] = e.authGameData; this.startClient(); // TODO: remove this when you will be able to see errors without console // this.sp.browser.setFocused(false); }; SkympClient.prototype.onActorCreateMessage = function (e) { if (e.message.isMe) { this.sp.browser.setFocused(false); } }; SkympClient.prototype.onConnectionFailed = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Connection failed"); }; SkympClient.prototype.onConnectionDenied = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Connection denied: " + e.error); }; SkympClient.prototype.startClient = function () { var _this = this; // once("tick", ...) is needed to ensure networking service initialized this.controller.once("tick", function () { return _this.establishConnectionConditional(); }); this.ctor(); }; SkympClient.prototype.ctor = function () { // TODO: refactor into service (0,_sync_animation__WEBPACK_IMPORTED_MODULE_2__.setupHooks)(); this.sp.printConsole('SkympClient ctor'); }; SkympClient.prototype.establishConnectionConditional = function () { var _this = this; var isConnected = this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_1__.NetworkingService).isConnected(); if (isConnected) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, 'Reconnect is not required'); return; } this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_6__.SettingsService).getTargetPeer(function (_a) { var host = _a.host, port = _a.port; skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage.targetIp = host; skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage.targetPort = port; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Connecting to ".concat(host, ":").concat(port)); _this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_1__.NetworkingService).connect(host, port); }); }; return SkympClient; }(_clientListener__WEBPACK_IMPORTED_MODULE_4__.ClientListener)); /***/ }), /***/ "./src/services/services/spSnippetService.ts": /*!***************************************************!*\ !*** ./src/services/services/spSnippetService.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SpSnippetService: () => (/* binding */ SpSnippetService) /* harmony export */ }); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _view_worldView__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../view/worldView */ "./src/view/worldView.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (undefined && undefined.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; // TODO: refactor worldViewMisc into service var SpSnippetService = /** @class */ (function (_super) { __extends(SpSnippetService, _super); function SpSnippetService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.emitter.on("spSnippetMessage", function (e) { return _this.onSpSnippetMessage(e); }); _this.spAny = sp; return _this; } SpSnippetService.prototype.onSpSnippetMessage = function (event) { var _this = this; var msg = event.message; this.controller.once('update', function () { return __awaiter(_this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { this.run(msg) .then(function (res) { var isNoResultSnippet = msg.snippetIdx === 0xffffffff; if (isNoResultSnippet) { return; } if (res === undefined) { res = null; } if (res !== null && typeof res !== "number" && typeof res !== "string" && typeof res !== "boolean") { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(_this, "Unsupported SpSnippet result type '".concat(typeof res, "'")); return; } var message = res === null ? { t: _messages__WEBPACK_IMPORTED_MODULE_0__.MsgType.FinishSpSnippet, snippetIdx: msg.snippetIdx } : { t: _messages__WEBPACK_IMPORTED_MODULE_0__.MsgType.FinishSpSnippet, returnValue: res, snippetIdx: msg.snippetIdx, }; _this.controller.emitter.emit("sendMessage", { message: message, reliability: "reliable" }); }) .catch(function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(_this, 'SpSnippet ' + msg.class + ' ' + msg.function + ' failed ' + e); }); return [2 /*return*/]; }); }); }); }; SpSnippetService.prototype.run = function (snippet) { var _a; return __awaiter(this, void 0, void 0, function () { var functionLowerCase, classLowerCase, newName, selfId, self, replaceValue, worldView_1, form, sign, count, soundId, sound, name, name; var _this = this; return __generator(this, function (_b) { functionLowerCase = snippet.function.toLowerCase(); classLowerCase = snippet.class.toLowerCase(); // keep in sync with remoteServer.ts if (classLowerCase === "objectreference") { if (functionLowerCase === "setdisplayname") { newName = snippet.arguments[0]; if (typeof newName === "string") { selfId = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.remoteIdToLocalId)(snippet.selfId); self = this.sp.ObjectReference.from(this.sp.Game.getFormEx(selfId)); replaceValue = (_a = self === null || self === void 0 ? void 0 : self.getBaseObject()) === null || _a === void 0 ? void 0 : _a.getName(); if (replaceValue !== undefined) { newName = newName.replace(/%original_name%/g, replaceValue); snippet.arguments[0] = newName; } else { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(this, "Couldn't get a replaceValue for SetDisplayName, snippet.selfId was", snippet.selfId.toString(16)); } } else { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(this, "Encountered SetDisplayName with non-string argument", newName); } } } if (classLowerCase === "game") { if (functionLowerCase === "showracemenu" || functionLowerCase === "showlimitedracemenu") { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "showracemenu called"); worldView_1 = this.controller.lookupListener(_view_worldView__WEBPACK_IMPORTED_MODULE_4__.WorldView); worldView_1.setFormViewUpdateAllowed(false); (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Waiting 1.0s before calling showracemenu"); this.sp.Utility.wait(1.0).then(function () { _this.runStatic(snippet); worldView_1.waitGameTimeAndAllowFormViewUpdate(1.0); }); return [2 /*return*/]; } } if (classLowerCase === "skymphacks") { if (functionLowerCase === "additem" || functionLowerCase === "removeitem") { form = this.sp.Form.from(this.deserializeArg(snippet.arguments[0])); if (form === null) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(this, "Unable to find form with id " + snippet.arguments[0].formId.toString(16)); return [2 /*return*/]; } sign = snippet.function === "AddItem" ? "+" : "-"; count = snippet.arguments[1]; soundId = 0x334ab; if (form.getFormID() !== 0xf) { soundId = 0x14115; } sound = this.sp.Sound.from(this.sp.Game.getFormEx(soundId)); if (sound !== null) { name = form.getName(); if (name.trim() === "") { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Sound will not be played because item has no name"); } else { sound.play(this.sp.Game.getPlayer()); } } else { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(this, "Unable to find sound with id " + soundId.toString(16)); } if (count <= 0) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logError)(this, "Positive count expected, got " + count.toString()); } else { name = form.getName(); if (name.trim() === "") { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Notification will not be shown because item has no name"); } else { this.sp.Debug.notification(sign + " " + name + " (" + count + ")"); } (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, sign + " " + name + " (" + count + ")"); } } else throw new Error("Unknown SkympHack - " + snippet.function); return [2 /*return*/]; } return [2 /*return*/, snippet.selfId ? this.runMethod(snippet) : this.runStatic(snippet)]; }); }); }; ; SpSnippetService.prototype.deserializeArg = function (arg) { if (typeof arg === "object") { var formId = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.remoteIdToLocalId)(arg.formId); var form = this.sp.Game.getFormEx(formId); var cl = this.spAny[arg.type]; if (!cl) { var matchingKey = Object.keys(this.spAny).find(function (key) { return key.toLowerCase() === arg.type.toLowerCase(); }); if (matchingKey) { cl = this.spAny[matchingKey]; } } if (!cl) { throw new Error("deserializeArg - Class ".concat(arg.type, " not found")); } var gameObject = cl.from(form); return gameObject; } return arg; }; ; SpSnippetService.prototype.runMethod = function (snippet) { return __awaiter(this, void 0, void 0, function () { var selfId, self, cl, matchingKey, selfCasted, f; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: selfId = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_2__.remoteIdToLocalId)(snippet.selfId); self = this.sp.Game.getFormEx(selfId); if (!self) throw new Error("Unable to find form with id ".concat(selfId.toString(16))); cl = this.spAny[snippet.class]; if (!cl) { matchingKey = Object.keys(this.spAny).find(function (key) { return key.toLowerCase() === snippet.class.toLowerCase(); }); if (matchingKey) { cl = this.spAny[matchingKey]; } } if (!cl) { throw new Error("runMethod - Class ".concat(snippet.class, " not found, found")); } selfCasted = cl.from(self); if (!selfCasted) throw new Error("Form ".concat(selfId.toString(16), " is not instance of ").concat(snippet.class, ", form type is ").concat(self.getType())); f = selfCasted[snippet.function]; return [4 /*yield*/, f.apply(selfCasted, snippet.arguments.map(function (arg) { return _this.deserializeArg(arg); }))]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; ; SpSnippetService.prototype.runStatic = function (snippet) { return __awaiter(this, void 0, void 0, function () { var papyrusClass; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: papyrusClass = this.spAny[snippet.class]; return [4 /*yield*/, papyrusClass[snippet.function].apply(papyrusClass, snippet.arguments.map(function (arg) { return _this.deserializeArg(arg); }))]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; ; return SpSnippetService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); ; /***/ }), /***/ "./src/services/services/spVersionCheckService.ts": /*!********************************************************!*\ !*** ./src/services/services/spVersionCheckService.ts ***! \********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SpVersionCheckService: () => (/* binding */ SpVersionCheckService) /* harmony export */ }); /* harmony import */ var _version__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../version */ "./src/version.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var SpVersionCheckService = /** @class */ (function (_super) { __extends(SpVersionCheckService, _super); function SpVersionCheckService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; controller.once("update", function () { return _this.onceUpdate(); }); return _this; } SpVersionCheckService.prototype.onceUpdate = function () { var _this = this; var realVersion = this.sp.getPlatformVersion(); if (!_version__WEBPACK_IMPORTED_MODULE_0__.requiredVersion.includes(realVersion)) { this.sp.Debug.messageBox("You need to have on of those SkyrimPlatform versions ".concat(JSON.stringify(_version__WEBPACK_IMPORTED_MODULE_0__.requiredVersion), " to join this server. Your current version is ").concat(realVersion)); this.sp.Utility.waitMenuMode(0.5).then(function () { _this.controller.on('update', function () { if (!_this.sp.Ui.isMenuOpen('MessageBoxMenu')) { _this.sp.Game.quitToMainMenu(); } }); }); } }; return SpVersionCheckService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetCameraEnforcementService.ts": /*!****************************************************************!*\ !*** ./src/services/services/sweetCameraEnforcementService.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetCameraEnforcementService: () => (/* binding */ SweetCameraEnforcementService) /* harmony export */ }); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! fs */ "fs"); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var playerId = 0x14; var translations = { "ru": { pressSpace: 'Пробел, чтобы выйти из анимации' }, "en": { pressSpace: 'Space to exit animation' }, }; var strings = translations['en']; try { var lang = fs__WEBPACK_IMPORTED_MODULE_3__.readFileSync('./Data/Platform/Distribution/locale', 'utf8').trim(); if (lang in translations) { strings = translations[lang]; } } catch (_a) { // locale file not found or unreadable, default to 'en' } // ex AnimDebugService part var SweetCameraEnforcementService = /** @class */ (function (_super) { __extends(SweetCameraEnforcementService, _super); function SweetCameraEnforcementService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.currentAnim = null; _this.stopAnimInProgress = false; _this.exitAnimName = null; _this.interruptAnimName = null; _this.tryInvokeAnimCount = 0; _this.lastNotificationMoment = 0; _this.tryInvokeAnimCountMax = 1000000000; _this.exitAnimEvent = undefined; _this.optionsCache = undefined; _this.optionCb = undefined; _this.usePlayerControlsDelayMs = true; var hasSweetPie = _this.hasSweetPie(); if (!hasSweetPie) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "SweetTaffy features disabled"); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "SweetTaffy features enabled"); } _this.settings = _this.sp.settings["skymp5-client"]["animDebug"]; if (hasSweetPie) { var self_1 = _this; _this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { }, leave: function (ctx) { self_1.onSendAnimationEventLeave(ctx); self_1.onSendExitAnimationEventLeave(ctx); // Tracking the successful launch of the exit animation }, }, playerId, playerId); _this.controller.on("buttonEvent", function (e) { return _this.onButtonEvent(e); }); _this.controller.emitter.on("customPacketMessage", function (e) { return _this.onCustomPacketMessage2(e); }); } return _this; } SweetCameraEnforcementService.prototype.onCustomPacketMessage2 = function (e) { var _this = this; var content = {}; try { content = JSON.parse(e.message.contentJsonDump); } catch (err) { if (err instanceof SyntaxError) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "Failed to parse custom packet contentJsonDump:", e.message.contentJsonDump, "Error:", err); return; } throw err; } if (content["customPacketType"] !== "invokeAnim") { return; } (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Received custom packet with customPacketType invokeAnim"); var name = content["animEventName"]; var requestId = content["requestId"]; var weaponDrawnAllowed = content["weaponDrawnAllowed"]; var furnitureAllowed = content["furnitureAllowed"]; var exitAnimName = content["exitAnimName"]; var interruptAnimName = content["interruptAnimName"]; var timeMs = content["timeMs"]; var isPlayExitAnimAfterwardsEnabled = content["isPlayExitAnimAfterwardsEnabled"]; var parentAnimEventName = content["parentAnimEventName"]; var enablePlayerControlsDelayMs = content["enablePlayerControlsDelayMs"]; var preferInterruptAnimAsExitAnimTimeMs = content["preferInterruptAnimAsExitAnimTimeMs"]; var preventManualInterrupt = content["preventManualInterrupt"]; if (typeof name !== "string") { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "Expected animEventName to be string"); return; } if (typeof requestId !== "string" && typeof requestId !== "number" && typeof requestId !== "undefined") { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "Expected requestId to be string or number or undefined"); return; } this.controller.once("update", function () { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "Trying to invoke anim", name, "with weaponDrawnAllowed=", weaponDrawnAllowed, ", furnitureAllowed=", furnitureAllowed, ", exitAnimName=", exitAnimName, ", interruptAnimName=", interruptAnimName, ", timeMs=", timeMs, ", isPlayExitAnimAfterwardsEnabled=", isPlayExitAnimAfterwardsEnabled, ", parentAnimEventName=", parentAnimEventName, ", enablePlayerControlsDelayMs=", enablePlayerControlsDelayMs, ", preferInterruptAnimAsExitAnimTimeMs=", preferInterruptAnimAsExitAnimTimeMs, ", preventManualInterrupt=", preventManualInterrupt); var result = _this.tryInvokeAnim(name, { weaponDrawnAllowed: weaponDrawnAllowed, furnitureAllowed: furnitureAllowed, exitAnimName: exitAnimName, interruptAnimName: interruptAnimName, timeMs: timeMs, isPlayExitAnimAfterwardsEnabled: isPlayExitAnimAfterwardsEnabled, parentAnimEventName: parentAnimEventName, enablePlayerControlsDelayMs: enablePlayerControlsDelayMs, preferInterruptAnimAsExitAnimTimeMs: preferInterruptAnimAsExitAnimTimeMs, preventManualInterrupt: preventManualInterrupt }); var message = { t: _messages__WEBPACK_IMPORTED_MODULE_0__.MsgType.CustomPacket, contentJsonDump: JSON.stringify({ customPacketType: "invokeAnimResult", result: result, requestId: requestId, }) }; _this.controller.emitter.emit("sendMessage", { message: message, reliability: "reliable", }); }); }; SweetCameraEnforcementService.prototype.onSendAnimationEventLeave = function (ctx) { var _this = this; var animLowerCase = ctx.animEventName.toLowerCase(); if (animLowerCase.startsWith("idle") && !animLowerCase.startsWith("idleforcedefaultstate")) { this.controller.once("update", function () { var _a; // This is only for player.playidle if (!_this.sp.Ui.isMenuOpen("Console" /* Menu.Console */)) { return; } if ((_a = _this.sp.Game.getPlayer()) === null || _a === void 0 ? void 0 : _a.getFurnitureReference()) { return; } (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "Forcing third person and disabling player controls"); _this.sp.Game.forceThirdPerson(); _this.sp.Game.disablePlayerControls(true, false, true, false, false, false, false, false, 0); _this.currentAnim = { name: ctx.animEventName, options: null, preferInterruptAnimState: null }; _this.startAntiExploitPolling(); }); } }; SweetCameraEnforcementService.prototype.exitAnim = function (options) { var _this = this; var _a, _b; // TODO(1): See another TODO(1) in this file if (options.playExitAnim) { var useInterruptAnimAsExitAnim = false; if (options.useInterruptAnimAsExitAnim) { useInterruptAnimAsExitAnim = true; this.usePlayerControlsDelayMs = false; (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Using interrupt anim as exit anim: ".concat(this.interruptAnimName, ". Reason: useInterruptAnimAsExitAnim is true")); } if ((_b = (_a = this.currentAnim) === null || _a === void 0 ? void 0 : _a.preferInterruptAnimState) === null || _b === void 0 ? void 0 : _b.prefer) { useInterruptAnimAsExitAnim = true; this.usePlayerControlsDelayMs = false; (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Using interrupt anim as exit anim: ".concat(this.interruptAnimName, ". Reason: preferInterruptAnimState.prefer is true")); } var animEventToSend = useInterruptAnimAsExitAnim ? (this.interruptAnimName || "IdleStop") : (this.exitAnimName || "IdleForceDefaultState"); this.sp.Debug.sendAnimationEvent(this.sp.Game.getPlayer(), animEventToSend); this.exitAnimEvent = animEventToSend; this.optionsCache = options; (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Sent animation event:", animEventToSend); } else { this.currentAnim = null; var enablePlayerControlsDelaySeconds = (typeof options.enablePlayerControlsDelayMs === "number" && options.enablePlayerControlsDelayMs > 0 && Number.isFinite(options.enablePlayerControlsDelayMs) && this.usePlayerControlsDelayMs) ? options.enablePlayerControlsDelayMs / 1000 : 0.5; var stopAnimDelaySeconds = enablePlayerControlsDelaySeconds + 0.5; this.stopAnimInProgress = true; this.sp.Utility.wait(enablePlayerControlsDelaySeconds).then(function () { _this.sp.Game.enablePlayerControls(true, false, true, false, false, false, false, false, 0); }); this.sp.Utility.wait(stopAnimDelaySeconds).then(function () { _this.stopAnimInProgress = false; if (_this.optionCb) { _this.optionCb(); _this.optionCb = undefined; } }); } }; SweetCameraEnforcementService.prototype.onSendExitAnimationEventLeave = function (ctx) { var _this = this; if (ctx.animationSucceeded && this.exitAnimEvent && this.optionsCache && ctx.animEventName === this.exitAnimEvent) { this.currentAnim = null; var enablePlayerControlsDelaySeconds = (typeof this.optionsCache.enablePlayerControlsDelayMs === "number" && this.optionsCache.enablePlayerControlsDelayMs > 0 && Number.isFinite(this.optionsCache.enablePlayerControlsDelayMs) && this.usePlayerControlsDelayMs) ? this.optionsCache.enablePlayerControlsDelayMs / 1000 : 0.5; var stopAnimDelaySeconds = enablePlayerControlsDelaySeconds + 0.5; this.stopAnimInProgress = true; this.optionsCache = undefined; this.exitAnimEvent = undefined; this.usePlayerControlsDelayMs = true; this.sp.Utility.wait(enablePlayerControlsDelaySeconds).then(function () { _this.sp.Game.enablePlayerControls(true, false, true, false, false, false, false, false, 0); }); this.sp.Utility.wait(stopAnimDelaySeconds).then(function () { _this.stopAnimInProgress = false; if (_this.optionCb) { _this.optionCb(); _this.optionCb = undefined; } }); } else { this.optionsCache = undefined; this.exitAnimEvent = undefined; if (this.optionCb) { this.optionCb = undefined; } } }; SweetCameraEnforcementService.prototype.startAntiExploitPolling = function (mode) { // Fixes https://github.com/skyrim-multiplayer/skymp5-gamemode/issues/240 // P.S. There is a very similar code in skymp5-gamemode // See disableCheats.ts, skymp5-gamemode for comments var _this = this; if (mode === void 0) { mode = "death"; } var _callNative = this.sp.callNative; var cameraState = -1; var needsExitingAnim = false; var f = function (i) { var _a; if (i >= 10 * 60) { return; } cameraState = _callNative("Game", "getCameraState", undefined); needsExitingAnim = _this.needsExitingAnim; if (!needsExitingAnim) { return f(Infinity); } if (cameraState === 0) { // 1-st person _callNative("Game", "forceThirdPerson", undefined); _this.exitAnim({ playExitAnim: true, enablePlayerControlsDelayMs: undefined }); if (mode === "death") { (_a = _this.sp.Game.getPlayer()) === null || _a === void 0 ? void 0 : _a.damageActorValue("Health", 10000); } return f(Infinity); } _this.controller.once("update", function () { return f(i + 1); }); }; f(0); }; SweetCameraEnforcementService.prototype.onButtonEvent = function (e) { var _a, _b, _c, _d, _e, _f; // TODO: de-hardcode controls if (e.isPressed) { return; } if (e.code === 57 /* DxScanCode.Spacebar */ || e.code === 17 /* DxScanCode.W */ || e.code === 30 /* DxScanCode.A */ || e.code === 31 /* DxScanCode.S */ || e.code === 32 /* DxScanCode.D */) { if (this.needsExitingAnim) { // Checking whether manual interruption is prohibited if ((_b = (_a = this.currentAnim) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.preventManualInterrupt) { return; } if ((_c = this.currentAnim) === null || _c === void 0 ? void 0 : _c.options) { this.exitAnim({ playExitAnim: true, enablePlayerControlsDelayMs: this.currentAnim.options.enablePlayerControlsDelayMs }); } else { this.exitAnim({ playExitAnim: true, enablePlayerControlsDelayMs: undefined }); } } } else { if (this.needsExitingAnim) { if ((_e = (_d = this.currentAnim) === null || _d === void 0 ? void 0 : _d.options) === null || _e === void 0 ? void 0 : _e.preventManualInterrupt) { return; } var intervalMs = (_f = this.settings) === null || _f === void 0 ? void 0 : _f.exitAnimNotificationIntervalMs; if (!intervalMs || (Date.now() - this.lastNotificationMoment) >= intervalMs) { this.lastNotificationMoment = Date.now(); this.sp.Debug.notification(strings.pressSpace); } } } if (!e.isUp) { return; } if (!this.settings || !this.settings.animKeys) { return; } var animEvent = this.settings.animKeys[e.code]; if (!animEvent) { return; } (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Starting anims from keyboard is disabled in this version"); // this.tryInvokeAnim(animEvent, { // weaponDrawnAllowed: false, // furnitureAllowed: false, // exitAnimName: null, // interruptAnimName: null, // timeMs: 0, // isPlayExitAnimAfterwardsEnabled: true, // parentAnimEventName: null, // enablePlayerControlsDelayMs: null, // preferInterruptAnimAsExitAnimTimeMs: null, // }); }; SweetCameraEnforcementService.prototype.tryInvokeAnim = function (animEvent, options) { var _this = this; this.tryInvokeAnimCount++; if (this.tryInvokeAnimCount >= this.tryInvokeAnimCountMax) { this.tryInvokeAnimCount = 0; } var currentInvokeAnimCount = this.tryInvokeAnimCount; if (typeof options.exitAnimName === "string") { this.exitAnimName = options.exitAnimName; } else { this.exitAnimName = null; } if (typeof options.preventManualInterrupt !== "boolean") { options.preventManualInterrupt = false; } if (typeof options.interruptAnimName === "string") { this.interruptAnimName = options.interruptAnimName; } else { this.interruptAnimName = null; } if (typeof options.timeMs === "number" && options.timeMs > 0 && Number.isFinite(options.timeMs)) { var timeSeconds = options.timeMs / 1000; // Using Utility.wait makes sense because it waits game time, not simply real time. this.sp.Utility.wait(timeSeconds).then(function () { if (_this.tryInvokeAnimCount !== currentInvokeAnimCount) { return; } if (!_this.needsExitingAnim) { return; } var isPlayExitAnimAfterwardsEnabled = typeof options.isPlayExitAnimAfterwardsEnabled === "boolean" ? options.isPlayExitAnimAfterwardsEnabled : true; _this.exitAnim({ playExitAnim: isPlayExitAnimAfterwardsEnabled, enablePlayerControlsDelayMs: options.enablePlayerControlsDelayMs }); }); } var player = this.sp.Game.getPlayer(); if (!player) { return { success: false, reason: "player_not_found" }; } if (player.isWeaponDrawn() && !options.weaponDrawnAllowed) { return { success: false, reason: "weapon_drawn" }; } if (player.getAnimationVariableBool("bInJumpState")) { return { success: false, reason: "jump_state" }; } if (this.sp.Ui.isMenuOpen("FavoritesMenu" /* Menu.Favorites */)) { return { success: false, reason: "favorites_menu_open" }; } if (this.sp.Ui.isMenuOpen("Console" /* Menu.Console */)) { return { success: false, reason: "console_menu_open" }; } if (this.stopAnimInProgress) { return { success: false, reason: "busy_stopping_anim" }; } if (player.getFurnitureReference() && !options.furnitureAllowed) { return { success: false, reason: "player_in_furniture" }; } if (player.isSneaking()) { return { success: false, reason: "player_sneaking" }; } if (player.isSwimming()) { return { success: false, reason: "player_swimming" }; } if (animEvent.toLowerCase() === "idleforcedefaultstate") { if (this.needsExitingAnim) { this.exitAnim({ playExitAnim: true, enablePlayerControlsDelayMs: undefined }); } } else { var doInvoke = function () { _this.sp.Game.forceThirdPerson(); _this.sp.Game.disablePlayerControls(true, false, true, false, false, false, false, false, 0); _this.sp.Debug.sendAnimationEvent(_this.sp.Game.getPlayer(), animEvent); var preferInterruptAnimState = null; if (typeof options.preferInterruptAnimAsExitAnimTimeMs === "number" && options.preferInterruptAnimAsExitAnimTimeMs > 0 && Number.isFinite(options.preferInterruptAnimAsExitAnimTimeMs)) { var state_1 = { prefer: true }; (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "Prefer interrupt anim as exit anim for ".concat(options.preferInterruptAnimAsExitAnimTimeMs, " ms")); _this.sp.Utility.wait(options.preferInterruptAnimAsExitAnimTimeMs / 1000).then(function () { state_1.prefer = false; (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "Prefer interrupt anim as exit anim state changed to false"); }); preferInterruptAnimState = state_1; } _this.currentAnim = { name: animEvent, options: options, preferInterruptAnimState: preferInterruptAnimState }; _this.startAntiExploitPolling("no_death"); }; if (typeof options.parentAnimEventName === "string" && this.currentAnimName === options.parentAnimEventName) { doInvoke(); } else if (Array.isArray(options.parentAnimEventName) && options.parentAnimEventName.includes(this.currentAnimName)) { doInvoke(); } else if (this.needsExitingAnim) { // TODO (1): consider not using enablePlayerControlsDelayMs here, because useInterruptAnimAsExitAnim doesn't need it this.optionCb = doInvoke; this.exitAnim({ playExitAnim: true, useInterruptAnimAsExitAnim: true, enablePlayerControlsDelayMs: options.enablePlayerControlsDelayMs }); } else { doInvoke(); } (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Sent animation event: ".concat(animEvent)); } return { success: true }; }; SweetCameraEnforcementService.prototype.hasSweetPie = function () { var modCount = this.sp.Game.getModCount(); for (var i = 0; i < modCount; ++i) { if (this.sp.Game.getModName(i).toLowerCase().includes('sweetpie')) { return true; } } return false; }; Object.defineProperty(SweetCameraEnforcementService.prototype, "needsExitingAnim", { get: function () { return this.currentAnimName !== null; }, enumerable: false, configurable: true }); Object.defineProperty(SweetCameraEnforcementService.prototype, "currentAnimName", { get: function () { return this.currentAnim ? this.currentAnim.name : null; }, enumerable: false, configurable: true }); return SweetCameraEnforcementService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetTaffyDynamicPerksService.ts": /*!****************************************************************!*\ !*** ./src/services/services/sweetTaffyDynamicPerksService.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffyDynamicPerksService: () => (/* binding */ SweetTaffyDynamicPerksService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var SweetTaffyDynamicPerksService = /** @class */ (function (_super) { __extends(SweetTaffyDynamicPerksService, _super); function SweetTaffyDynamicPerksService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.requestAddPerksToActors = function (actorIds, perkIds) { _this.controller.once("update", function () { var actors = actorIds.map(function (actorId) { return _this.sp.Actor.from(_this.sp.Game.getFormEx(actorId)); }).filter(function (actor) { return actor !== null; }); var perks = perkIds.map(function (perkId) { return _this.sp.Perk.from(_this.sp.Game.getFormEx(perkId)); }).filter(function (perk) { return perk !== null; }); actors.forEach(function (actor) { return perks.forEach(function (perk) { return actor === null || actor === void 0 ? void 0 : actor.addPerk(perk); }); }); }); }; if (!_this.hasSweetPie()) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "SweetTaffy features disabled"); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(_this, "SweetTaffy features enabled"); } controller.on('containerChanged', function (e) { return _this.onContainerChanged(e); }); controller.emitter.on("setInventoryMessage", function (e) { return _this.onSetInventoryMessage(e); }); controller.emitter.on("createActorMessage", function (e) { return _this.onCreateActorMessage(e); }); return _this; } SweetTaffyDynamicPerksService.prototype.onContainerChanged = function (e) { if (!this.hasSweetPie()) { return; } if (e.oldContainer && e.newContainer) { if (e.newContainer.getFormID() === 0x14 && e.numItems > 0) { this.handlePlayerInventoryChanged({ baseId: e.baseObj.getFormID(), count: e.numItems, }); } } }; SweetTaffyDynamicPerksService.prototype.onSetInventoryMessage = function (e) { var _this = this; if (!this.hasSweetPie()) { return; } var entries = e.message.inventory.entries; if (entries.length === 0) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Received SetInventoryMessage with empty inventory"); return; } this.controller.once("update", function () { entries.forEach(function (entry) { return _this.handlePlayerInventoryChanged(entry); }); }); }; SweetTaffyDynamicPerksService.prototype.onCreateActorMessage = function (e) { var _this = this; var _a, _b; if (!this.hasSweetPie()) { return; } if (!e.message.isMe) { return; } var entries = (_b = (_a = e.message.props) === null || _a === void 0 ? void 0 : _a.inventory) === null || _b === void 0 ? void 0 : _b.entries; if (entries === undefined) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Received CreateActorMessage without inventory"); return; } if (entries.length === 0) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logTrace)(this, "Received CreateActorMessage with empty inventory"); return; } this.controller.once("update", function () { entries.forEach(function (entry) { return _this.handlePlayerInventoryChanged(entry); }); }); }; SweetTaffyDynamicPerksService.prototype.handlePlayerInventoryChanged = function (entry) { if (!this.hasSweetPie()) { return; } var item = this.sp.Game.getFormEx(entry.baseId); if (!item) { return; } if (entry.count <= 0) { return; } var perkIds = this.getPerkIdsByKeyword(item); if (perkIds) { var playerId = 0x14; this.requestAddPerksToActors([playerId], perkIds); } }; SweetTaffyDynamicPerksService.prototype.getPerkIdsByKeyword = function (item) { var _this = this; var result = new Array(); this.getKeywordPerkMap().forEach(function (v, k) { var keyWord = _this.sp.Keyword.getKeyword(k); if (item.hasKeyword(keyWord)) { result.push(v); } }); return result.length > 0 ? result : null; }; // TODO: move this to config SweetTaffyDynamicPerksService.prototype.getKeywordPerkMap = function () { return new Map([ // Стрелец ["SweetPerkBow1", 0x1036F0], ["SweetPerkBow2", 0x58F61], ["SweetPerkBow3", 0x105F19], ["SweetPerkBow4", 0x58F63], // Убийца ["SweetPerkSneak1", 0x58210], ["SweetPerkSneak2", 0x105F23], ["SweetPerkSneak3", 0x58208], ["SweetPerkSneak4", 0x58211], // Пехотинец ["SweetPerkArmorLight1", 0x105F22], ["SweetPerkArmorLight2", 0x51B1C], // Зачарователь ["SweetPerkEnchant2", 0x108A44], ["SweetPerkEnchant1", 0x58F7C], // Латник ["SweetPerkArmorHeavy1", 0xBCD2B], ["SweetPerkArmorHeavy2", 0x58F6D], // Щитоносец ["SweetPerkBlock1", 0x58F67], ["SweetPerkBlock2", 0x106253], ["SweetPerkBlock3", 0x58F6A], ["SweetPerkBlock4", 0x58F69], // Мечник, клинок, рубака, крушитель, монах, копейщик, стражник (двуручное оружие) ["SweetPerk1Hand2Hand1", 0x58F6F], ["SweetPerk2Hand2", 0xCB407], ["SweetPerk2Hand3", 0x96590], ["SweetPerk2Hand4", 0x52D51], // Ассасин, разведчик, шпион, предшественник, рыцарь, разбойник, берсерк, громила (одноручное оружие) ["SweetPerk1Hand2Hand1", 0x58F6F], ["SweetPerk1Hand2", 0xCB406], ["SweetPerk1Hand3", 0x106256], ["SweetPerk1Hand4", 0x52D50], ]); }; SweetTaffyDynamicPerksService.prototype.hasSweetPie = function () { var modCount = this.sp.Game.getModCount(); for (var i = 0; i < modCount; ++i) { if (this.sp.Game.getModName(i).toLowerCase().includes('sweetpie')) { return true; } } return false; }; return SweetTaffyDynamicPerksService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetTaffyEvalService.ts": /*!********************************************************!*\ !*** ./src/services/services/sweetTaffyEvalService.ts ***! \********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffyEvalService: () => (/* binding */ SweetTaffyEvalService) /* harmony export */ }); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _remoteServer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./remoteServer */ "./src/services/services/remoteServer.ts"); /* harmony import */ var _serverJsVerificationService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./serverJsVerificationService */ "./src/services/services/serverJsVerificationService.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var SweetTaffyEvalService = /** @class */ (function (_super) { __extends(SweetTaffyEvalService, _super); function SweetTaffyEvalService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.emitter.on("customPacketMessage", function (e) { return _this.onCustomPacketMessage(e); }); return _this; } SweetTaffyEvalService.prototype.onCustomPacketMessage = function (event) { var msg = event.message; var msgContent = {}; try { msgContent = JSON.parse(msg.contentJsonDump); } catch (e) { if (e instanceof SyntaxError) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "onCustomPacketMessage failed to parse JSON", e.message, "json:", msg.contentJsonDump); return; } else { throw e; } } switch (msgContent["customPacketType"]) { case 'eval': var code = msgContent["code"]; if (typeof code !== "string") { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "onCustomPacketMessage expected 'code' to be a string", "code:", code); break; } this.processEval(code); break; } }; SweetTaffyEvalService.prototype.processEval = function (code) { var _this = this; // Consider removing try catch try { var src = code; var serverJsVerificationService = this.controller.lookupListener(_serverJsVerificationService__WEBPACK_IMPORTED_MODULE_4__.ServerJsVerificationService); var prefix = "// skymp:sig:y:GM"; var result_1 = serverJsVerificationService.verifyServerJs(src, prefix); if (result_1.src && !result_1.error) { this.controller.once("update", function () { var remoteServer = _this.controller.lookupListener(_remoteServer__WEBPACK_IMPORTED_MODULE_3__.RemoteServer); var worldModel = remoteServer.getWorldModel(); var myFormModel = worldModel.forms[worldModel.playerCharacterFormIdx]; var ctx = { sp: skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__, _model: myFormModel, getFormIdInServerFormat: _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.localIdToRemoteId, getFormIdInClientFormat: _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_0__.remoteIdToLocalId, get: function (propName) { var _a; return (_a = this._model) === null || _a === void 0 ? void 0 : _a[propName]; } }; (new Function('ctx', result_1.src))(ctx); }); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__.printConsole)("Eval executed successfully"); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "processEval failed server JS verification", "error:", result_1.error, "src:", src); } } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_1__.logError)(this, "processEval error", e); } }; return SweetTaffyEvalService; }(_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetTaffyNicknamesService.ts": /*!*************************************************************!*\ !*** ./src/services/services/sweetTaffyNicknamesService.ts ***! \*************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffyNicknamesService: () => (/* binding */ SweetTaffyNicknamesService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var SweetTaffyNicknamesService = /** @class */ (function (_super) { __extends(SweetTaffyNicknamesService, _super); function SweetTaffyNicknamesService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; controller.emitter.on("nicknameCreate", function (e) { return _this.onNicknameCreate(e); }); controller.emitter.on("nicknameDestroy", function (e) { return _this.onNicknameDestroy(e); }); return _this; } SweetTaffyNicknamesService.prototype.onNicknameCreate = function (e) { var _a; var storageNickname = typeof this.sp.storage["idTextNickname"] === 'object' ? this.sp.storage["idTextNickname"] : null; if (storageNickname === null && e.remoteRefrId) { this.sp.storage["idTextNickname"] = (_a = {}, _a[e.remoteRefrId] = e.textId, _a); } else if (storageNickname !== null && e.remoteRefrId) { storageNickname[e.remoteRefrId] = e.textId; this.sp.storage["idTextNickname"] = storageNickname; } }; SweetTaffyNicknamesService.prototype.onNicknameDestroy = function (e) { var storageNickname = typeof this.sp.storage["idTextNickname"] === 'object' ? this.sp.storage["idTextNickname"] : null; if (storageNickname !== null && e.remoteRefrId) { delete storageNickname[e.remoteRefrId]; this.sp.storage["idTextNickname"] = storageNickname; } }; return SweetTaffyNicknamesService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); ; /***/ }), /***/ "./src/services/services/sweetTaffyPlayerCombatService.ts": /*!****************************************************************!*\ !*** ./src/services/services/sweetTaffyPlayerCombatService.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffyPlayerCombatService: () => (/* binding */ SweetTaffyPlayerCombatService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: move to service var playerLastStaminaValue = 0; var playerLastIsSprintingValue = false; var blockPlayerControlTimeStamp = 0; var isPlayerControlDisabled = true; var playerAttackTimeout = 0; var activeTimers = new Set(); // TODO: move to config var staminaAttackMap = new Map([ ["Std", 7], ["Power", 35], ["Jump", 15], ["Bow", 25], ["Crossbow", 30], ]); // TODO: consider splitting this service (separate stamina and timer management) // TODO: subscribe events/hooks in constructor var SweetTaffyPlayerCombatService = /** @class */ (function (_super) { __extends(SweetTaffyPlayerCombatService, _super); function SweetTaffyPlayerCombatService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; if (!_this.hasSweetPie()) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "SweetTaffy features disabled"); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "SweetTaffy features enabled"); } _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } SweetTaffyPlayerCombatService.prototype.onceUpdate = function () { this.setAttackStaminaRestriction(); this.registerHandlersIfNeeded(); }; SweetTaffyPlayerCombatService.prototype.setAttackStaminaRestriction = function () { var _this = this; if (!this.hasSweetPie()) { return; } this.controller.on("update", function () { var player = _this.sp.Game.getPlayer(); playerLastStaminaValue = player.getActorValue("Stamina"); playerLastIsSprintingValue = player.isSprinting(); }); for (var _i = 0, _a = ['SprintStart']; _i < _a.length; _i++) { var pattern = _a[_i]; var sp = this.sp; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { if (playerLastStaminaValue < 7.5) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } for (var _b = 0, _c = ['blockStart']; _b < _c.length; _b++) { var pattern = _c[_b]; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { if (playerLastIsSprintingValue) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } for (var _d = 0, _e = ['attackStart*', 'AttackStart*']; _d < _e.length; _d++) { var pattern = _e[_d]; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { var _a; if (playerLastStaminaValue < ((_a = staminaAttackMap.get("Std")) !== null && _a !== void 0 ? _a : 0)) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } for (var _f = 0, _g = ['attackPowerStart*', 'AttackPowerStart*']; _f < _g.length; _f++) { var pattern = _g[_f]; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { var _a; if (playerLastStaminaValue < ((_a = staminaAttackMap.get("Power")) !== null && _a !== void 0 ? _a : 0)) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } for (var _h = 0, _j = ['JumpDirectionalStart*', 'JumpStandingStart*']; _h < _j.length; _h++) { var pattern = _j[_h]; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { var _a; if (playerLastStaminaValue < ((_a = staminaAttackMap.get("Jump")) !== null && _a !== void 0 ? _a : 0)) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } for (var _k = 0, _l = ['bowAttackStart*']; _k < _l.length; _k++) { var pattern = _l[_k]; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { var _a; if (playerLastStaminaValue < ((_a = staminaAttackMap.get("Bow")) !== null && _a !== void 0 ? _a : 0)) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } for (var _m = 0, _o = ['crossbowAttackStart*']; _m < _o.length; _m++) { var pattern = _o[_m]; this.sp.hooks.sendAnimationEvent.add({ enter: (function (ctx) { var _a; if (playerLastStaminaValue < ((_a = staminaAttackMap.get("Crossbow")) !== null && _a !== void 0 ? _a : 0)) { ctx.animEventName = ""; } }), leave: (function () { }), }, 0x14, 0x14, pattern); } }; SweetTaffyPlayerCombatService.prototype.registerHandlersIfNeeded = function () { var _this = this; var self = this; if (!this.hasSweetPie()) { return; } for (var _i = 0, _a = ['attackStart*', 'AttackStart*']; _i < _a.length; _i++) { var pattern = _a[_i]; this.sp.hooks.sendAnimationEvent.add({ enter: (function () { }), leave: (function (ctx) { return self.blockPlayerAttack(ctx.animEventName.toLowerCase().includes('lefthand')); }), }, 0x14, 0x14, pattern); } for (var _b = 0, _c = ['attackPowerStart*', 'AttackPowerStart*', 'Jump*']; _b < _c.length; _b++) { var pattern = _c[_b]; this.sp.hooks.sendAnimationEvent.add({ enter: (function () { }), leave: (function () { playerAttackTimeout = 0; activeTimers.clear(); }), }, 0x14, 0x14, pattern); } this.controller.on("update", function () { if (isPlayerControlDisabled === true && Date.now() - blockPlayerControlTimeStamp >= playerAttackTimeout) { _this.sp.Game.getPlayer().setDontMove(false); isPlayerControlDisabled = false; } }); }; SweetTaffyPlayerCombatService.prototype.blockPlayerAttack = function (isLeftHand) { var _this = this; this.controller.once("update", function () { var _a; var player = _this.sp.Game.getPlayer(); if (player.getAnimationVariableBool("bInJumpState")) { return; } var _b = _this.getTimings((_a = player.getEquippedWeapon(isLeftHand)) === null || _a === void 0 ? void 0 : _a.getWeaponType()), delay = _b[0], timeout = _b[1]; var rnd = Math.random().toString(); activeTimers.add(rnd); _this.sp.Utility.wait(delay / 1000).then(function () { if (!activeTimers.delete(rnd)) { return; } _this.controller.once("update", function () { isPlayerControlDisabled = true; blockPlayerControlTimeStamp = Date.now(); _this.sp.Game.getPlayer().setDontMove(true); playerAttackTimeout = timeout; }); }); }); }; SweetTaffyPlayerCombatService.prototype.getAndValidateTimingsConfigKey = function (key, weaponTimings) { var value = weaponTimings[key]; if (value && Array.isArray(value) && value.length === 2) { var element0 = value[0]; if (typeof element0 !== "number") { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "Invalid timings config for weapon type", key, value); return [0, 0]; } var element1 = value[1]; if (typeof element1 !== "number") { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "Invalid timings config for weapon type", key, value); return [0, 0]; } return [element0, element1]; } return [0, 0]; }; ; SweetTaffyPlayerCombatService.prototype.getSettingsFromFile = function () { var sweetTaffyPlayerCombatService = this.sp.settings["skymp5-client"]["sweetTaffyPlayerCombatService"]; if (!sweetTaffyPlayerCombatService || typeof sweetTaffyPlayerCombatService !== "object") { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "No sweetTaffyPlayerCombatService settings found"); return null; } var weaponTimings = sweetTaffyPlayerCombatService.weaponTimings; if (!weaponTimings || typeof weaponTimings !== "object") { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "No weaponTimings settings found"); return null; } return weaponTimings; }; SweetTaffyPlayerCombatService.prototype.getSettingsDefault = function () { return { fist: [0, 30], sword: [0, 30], dagger: [0, 60], warAxe: [0, 60], mace: [0, 65], greatsword: [0, 65], // Note: both of Battleaxe and Warhammer weapon types correspond to id=6. battleaxe: [0, 70], warhammer: [0, 70], bow: [0, 70], staff: [0, 70], crossbow: [0, 70], }; }; SweetTaffyPlayerCombatService.prototype.getTimingsFromConfig = function (weapon) { if (!weapon) { weapon = 0 /* WeaponType.Fist */; } // skymp5-client-settings.txt is perfectly editable by users, so we don't use it for now. // It's well-tested though, so we can enable it once we have a protection mechanism. // const weaponTimings = this.getSettingsFromFile(); var weaponTimings = this.getSettingsDefault(); if (!weaponTimings) { return null; } var weaponTimingsResult = { fist: [0, 0], sword: [0, 0], dagger: [0, 0], warAxe: [0, 0], mace: [0, 0], greatsword: [0, 0], battleaxe: [0, 0], warhammer: [0, 0], bow: [0, 0], staff: [0, 0], crossbow: [0, 0], }; weaponTimingsResult.fist = this.getAndValidateTimingsConfigKey("fist", weaponTimings); weaponTimingsResult.sword = this.getAndValidateTimingsConfigKey("sword", weaponTimings); weaponTimingsResult.dagger = this.getAndValidateTimingsConfigKey("dagger", weaponTimings); weaponTimingsResult.warAxe = this.getAndValidateTimingsConfigKey("warAxe", weaponTimings); weaponTimingsResult.mace = this.getAndValidateTimingsConfigKey("mace", weaponTimings); weaponTimingsResult.greatsword = this.getAndValidateTimingsConfigKey("greatsword", weaponTimings); weaponTimingsResult.battleaxe = this.getAndValidateTimingsConfigKey("battleaxe", weaponTimings); weaponTimingsResult.warhammer = this.getAndValidateTimingsConfigKey("warhammer", weaponTimings); weaponTimingsResult.bow = this.getAndValidateTimingsConfigKey("bow", weaponTimings); weaponTimingsResult.staff = this.getAndValidateTimingsConfigKey("staff", weaponTimings); weaponTimingsResult.crossbow = this.getAndValidateTimingsConfigKey("crossbow", weaponTimings); switch (weapon) { case 0 /* WeaponType.Fist */: return weaponTimingsResult.fist; case 1 /* WeaponType.Sword */: return weaponTimingsResult.sword; case 2 /* WeaponType.Dagger */: return weaponTimingsResult.dagger; case 3 /* WeaponType.WarAxe */: return weaponTimingsResult.warAxe; case 4 /* WeaponType.Mace */: return weaponTimingsResult.mace; case 5 /* WeaponType.Greatsword */: return weaponTimingsResult.greatsword; case 6 /* WeaponType.Battleaxe */: return weaponTimingsResult.battleaxe; case 6 /* WeaponType.Warhammer */: return weaponTimingsResult.warhammer; case 7 /* WeaponType.Bow */: return weaponTimingsResult.bow; case 8 /* WeaponType.Staff */: return weaponTimingsResult.staff; case 9 /* WeaponType.Crossbow */: return weaponTimingsResult.crossbow; default: (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "No timings found for weapon type", weapon); return null; } }; SweetTaffyPlayerCombatService.prototype.getTimings = function (weapon) { var timingsFromConfig = this.getTimingsFromConfig(weapon); if (!weapon || !timingsFromConfig) { weapon = 0 /* WeaponType.Fist */; timingsFromConfig = this.getTimingsFromConfig(weapon); } if (!timingsFromConfig) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(this, "No timings found for weapon type", weapon); return [0, 0]; } return timingsFromConfig; }; ; SweetTaffyPlayerCombatService.prototype.hasSweetPie = function () { var modCount = this.sp.Game.getModCount(); for (var i = 0; i < modCount; ++i) { if (this.sp.Game.getModName(i).toLowerCase().includes('sweetpie')) { return true; } } return false; }; return SweetTaffyPlayerCombatService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetTaffySkillMenuService.ts": /*!*************************************************************!*\ !*** ./src/services/services/sweetTaffySkillMenuService.ts ***! \*************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffySkillMenuService: () => (/* binding */ SweetTaffySkillMenuService) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: move to server/gamemode var SweetTaffySkillMenuService = /** @class */ (function (_super) { __extends(SweetTaffySkillMenuService, _super); function SweetTaffySkillMenuService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.altars = [ 0x00100780, 0x000D9883, 0x000D987B, 0x000D9881, 0x000D9887, 0x000FB997, 0x000D9885, 0x000D987D, 0x00071854, 0x07187500, 0x0200c86b, 0x000d987f, 0x07058d4e, 0x07058d53, 0x070A6912, 0x07058d51, 0x07058d50, 0x07058d4f, 0x07058d4d, 0x07058d4c, 0x07058d4b, 0x0705e2fa, 0x07058d4a, 0x07058d49, 0x0705e367, 0x07058d48, 0x07058d55, 0x07058d46, 0x07058d47, 0x0705e2b0, 0x07058d45 ]; if (!_this.hasSweetPie()) { (0,_logging__WEBPACK_IMPORTED_MODULE_2__.logTrace)(_this, "SweetTaffy features disabled"); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_2__.logTrace)(_this, "SweetTaffy features enabled"); } _this.controller.once("activate", function (e) { return _this.onActivate(e); }); return _this; } SweetTaffySkillMenuService.prototype.onActivate = function (event) { var _a; if (!this.hasSweetPie()) { return; } if (!this.altars.includes(((_a = event.target.getBaseObject()) === null || _a === void 0 ? void 0 : _a.getFormID()) || -1)) { return; } skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.browser.setFocused(true); var src = "window.dispatchEvent(new CustomEvent('initSkillMenu'))"; skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.browser.executeJavaScript(src); }; SweetTaffySkillMenuService.prototype.hasSweetPie = function () { var modCount = this.sp.Game.getModCount(); for (var i = 0; i < modCount; ++i) { if (this.sp.Game.getModName(i).toLowerCase().includes('sweetpie')) { return true; } } return false; }; return SweetTaffySkillMenuService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetTaffyStaticPerksService.ts": /*!***************************************************************!*\ !*** ./src/services/services/sweetTaffyStaticPerksService.ts ***! \***************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffyStaticPerksService: () => (/* binding */ SweetTaffyStaticPerksService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var SweetTaffyStaticPerksService = /** @class */ (function (_super) { __extends(SweetTaffyStaticPerksService, _super); function SweetTaffyStaticPerksService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; // TODO: move this to config _this.stealth = [0xBE126, 0xC07C6, 0xC07C7, 0xC07C8, 0xC07C9]; _this.magic = [0x58213, 0x105F24, 0x58214]; _this.warrior = [0xCB40D, 0xCB40F, 0xCB414, 0xCB411, 0xCB412, 0xCB410, 0xCB40E]; if (!_this.hasSweetPie()) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "SweetTaffy features disabled"); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "SweetTaffy features enabled"); } _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } SweetTaffyStaticPerksService.prototype.onceUpdate = function () { if (!this.hasSweetPie()) { return; } this.addStaticPerksToThePlayer(); }; SweetTaffyStaticPerksService.prototype.addStaticPerksToThePlayer = function () { var _this = this; var player = this.sp.Game.getPlayer(); var allStaticPerkIds = this.stealth.concat(this.magic).concat(this.warrior); allStaticPerkIds.forEach(function (perkId) { player.addPerk(_this.sp.Perk.from(_this.sp.Game.getFormEx(perkId))); }); }; SweetTaffyStaticPerksService.prototype.hasSweetPie = function () { var modCount = this.sp.Game.getModCount(); for (var i = 0; i < modCount; ++i) { if (this.sp.Game.getModName(i).toLowerCase().includes('sweetpie')) { return true; } } return false; }; return SweetTaffyStaticPerksService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); /***/ }), /***/ "./src/services/services/sweetTaffySweetCantDropService.ts": /*!*****************************************************************!*\ !*** ./src/services/services/sweetTaffySweetCantDropService.ts ***! \*****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SweetTaffySweetCantDropService: () => (/* binding */ SweetTaffySweetCantDropService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: move to the server/gamemode var SweetTaffySweetCantDropService = /** @class */ (function (_super) { __extends(SweetTaffySweetCantDropService, _super); function SweetTaffySweetCantDropService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.cantDropKeyword = "SweetCantDrop"; return _this; } SweetTaffySweetCantDropService.prototype.canDropOrPutItem = function (itemId) { var item = this.sp.Game.getFormEx(itemId); if (item !== null) { if (item.hasKeyword(this.sp.Keyword.getKeyword(this.cantDropKeyword))) { return false; } } return true; }; return SweetTaffySweetCantDropService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/timeService.ts": /*!**********************************************!*\ !*** ./src/services/services/timeService.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TimeService: () => (/* binding */ TimeService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var TimeService = /** @class */ (function (_super) { __extends(TimeService, _super); function TimeService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.lastTimeUpd = 0; controller.on("update", function () { return _this.onUpdate(); }); return _this; } TimeService.prototype.getTime = function () { var hoursOffsetSetting = this.sp.settings["skymp5-client"]["hoursOffset"]; var hoursOffset = typeof hoursOffsetSetting === "number" ? hoursOffsetSetting : 0; var hoursOffsetMs = hoursOffset * 60 * 60 * 1000; var d = new Date(Date.now() + hoursOffsetMs); var newGameHourValue = 0; newGameHourValue += d.getUTCHours(); newGameHourValue += d.getUTCMinutes() / 60; newGameHourValue += d.getUTCSeconds() / 60 / 60; newGameHourValue += d.getUTCMilliseconds() / 60 / 60 / 1000; return { newGameHourValue: newGameHourValue, date: d }; }; TimeService.prototype.every2seconds = function () { var gameHourId = 0x38; var gameMonthId = 0x36; var gameDayId = 0x37; var gameYearId = 0x35; var timeScaleId = 0x3a; var gameHour = this.sp.GlobalVariable.from(this.sp.Game.getFormEx(gameHourId)); var gameDay = this.sp.GlobalVariable.from(this.sp.Game.getFormEx(gameDayId)); var gameMonth = this.sp.GlobalVariable.from(this.sp.Game.getFormEx(gameMonthId)); var gameYear = this.sp.GlobalVariable.from(this.sp.Game.getFormEx(gameYearId)); var timeScale = this.sp.GlobalVariable.from(this.sp.Game.getFormEx(timeScaleId)); if (!gameHour || !gameDay || !gameMonth || !gameYear || !timeScale) { return; } var _a = this.getTime(), newGameHourValue = _a.newGameHourValue, date = _a.date; var diff = Math.abs(gameHour.getValue() - newGameHourValue); if (diff >= 1 / 60) { gameHour.setValue(newGameHourValue); gameDay.setValue(date.getUTCDate()); gameMonth.setValue(date.getUTCMonth()); gameYear.setValue(date.getUTCFullYear() - 2020 + 199); } timeScale.setValue(gameHour.getValue() > newGameHourValue ? 0.6 : 1.2); }; TimeService.prototype.onUpdate = function () { if (Date.now() - this.lastTimeUpd <= 2000) { return; } this.lastTimeUpd = Date.now(); this.every2seconds(); }; return TimeService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/timersService.ts": /*!************************************************!*\ !*** ./src/services/services/timersService.ts ***! \************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TimersService: () => (/* binding */ TimersService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var ProcessMethodType; (function (ProcessMethodType) { ProcessMethodType["update"] = "update"; ProcessMethodType["tick"] = "tick"; })(ProcessMethodType || (ProcessMethodType = {})); var TimersService = /** @class */ (function (_super) { __extends(TimersService, _super); function TimersService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.timersArr = new Array(); _this.intervalsArr = new Array(); _this.lastCallTime = Date.now(); _this.processMethodTypeStorageKey = "updateTypeStorageKey"; var storageProcessMethod = sp.storage[_this.processMethodTypeStorageKey]; if (typeof storageProcessMethod !== "function") { _this.setProcessMethod(storageProcessMethod); } else { _this.setProcessMethod(ProcessMethodType.tick); } _this.controller.on("menuOpen", function (e) { return _this.onMenuOpen(e); }); _this.controller.on("preLoadGame", function () { return _this.onPreLoadGame(); }); return _this; } TimersService.prototype.setTimeout = function (handler, timeout) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } var timer = { handler: handler, args: args, delayMs: timeout !== null && timeout !== void 0 ? timeout : 0, passedMs: 0 }; for (var i = 0; i < this.timersArr.length; ++i) { if (!this.timersArr[i]) { this.timersArr[i] = timer; return i + 1; } } return this.timersArr.push(timer); }; TimersService.prototype.clearTimeout = function (id) { if (id === undefined) { this.timersArr = new Array(); return; } if (id <= 0 || id > this.timersArr.length) { return; } this.timersArr[id - 1] = null; return; }; TimersService.prototype.setInterval = function (handler, timeout) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } var timer = { handler: handler, args: args, delayMs: timeout !== null && timeout !== void 0 ? timeout : 0, passedMs: 0 }; for (var i = 0; i < this.intervalsArr.length; ++i) { if (!this.intervalsArr[i]) { this.intervalsArr[i] = timer; return i + 1; } } return this.intervalsArr.push(timer); }; TimersService.prototype.clearInterval = function (id) { if (id === undefined) { this.intervalsArr = new Array(); return; } if (id <= 0 || id > this.intervalsArr.length) { return; } this.intervalsArr[id - 1] = null; return; }; TimersService.prototype.setProcessMethod = function (method) { var _this = this; switch (method) { case ProcessMethodType.tick: this.sp.storage[this.processMethodTypeStorageKey] = ProcessMethodType.tick; this.updateEventHandle = this.controller.on(ProcessMethodType.tick, function () { return _this.processTimers(); }); return; case ProcessMethodType.update: this.sp.storage[this.processMethodTypeStorageKey] = ProcessMethodType.update; this.updateEventHandle = this.controller.on(ProcessMethodType.update, function () { return _this.processTimers(); }); return; default: break; } try { if (this.sp.Game.getPlayer()) { // FIXME(GM-1008) } this.setProcessMethod(ProcessMethodType.update); } catch (_a) { this.setProcessMethod(ProcessMethodType.tick); } }; TimersService.prototype.processTimers = function () { var dt = Date.now() - this.lastCallTime; this.lastCallTime = Date.now(); // process timers for (var i = 0; i < this.timersArr.length; ++i) { var timer = this.timersArr[i]; if (timer) { timer.passedMs += dt; if (timer.passedMs >= timer.delayMs) { this.timersArr[i] = null; if (typeof timer.handler === "function") { timer.handler.call(this, timer.args); } else { eval(timer.handler); } } } else if (i === this.timersArr.length - 1) { // remove last unused element this.timersArr.length -= 1; } } // process intervals for (var i = 0; i < this.intervalsArr.length; ++i) { var interval = this.intervalsArr[i]; if (interval) { interval.passedMs += dt; if (interval.passedMs >= interval.delayMs) { interval.passedMs = 0; if (typeof interval.handler === "function") { interval.handler.call(this, interval.args); } else { eval(interval.handler); } } } else if (i === this.intervalsArr.length - 1) { // remove last unused element this.intervalsArr.length -= 1; } } }; TimersService.prototype.onMenuOpen = function (e) { if (e.name === "Main Menu" /* Menu.Main */) { if (this.updateEventHandle) { this.sp.unsubscribe(this.updateEventHandle); } this.setProcessMethod(ProcessMethodType.tick); } }; TimersService.prototype.onPreLoadGame = function () { if (this.updateEventHandle) { this.sp.unsubscribe(this.updateEventHandle); } this.setProcessMethod(ProcessMethodType.update); }; return TimersService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/services/worldCleanerService.ts": /*!******************************************************!*\ !*** ./src/services/services/worldCleanerService.ts ***! \******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorldCleanerService: () => (/* binding */ WorldCleanerService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var WorldCleanerService = /** @class */ (function (_super) { __extends(WorldCleanerService, _super); function WorldCleanerService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.protection = new Map(); _this.controller.on("update", function () { return _this.onUpdate(); }); _this.controller.emitter.on("gameLoad", function () { return _this.onGameLoad(); }); return _this; } WorldCleanerService.prototype.modWcProtection = function (actorId, mod) { var currentProtection = this.protection.get(actorId); this.protection.set(actorId, currentProtection ? currentProtection + mod : mod); }; WorldCleanerService.prototype.getWcProtection = function (actorId) { return this.protection.get(actorId) || 0; }; WorldCleanerService.prototype.onGameLoad = function () { var player = this.sp.Game.getPlayer(); if (!player) { return; } this.initialPos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getPos(player); this.initialCellOrWorld = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getWorldOrCell(player); }; WorldCleanerService.prototype.onUpdate = function () { this.processOneActor(); }; WorldCleanerService.prototype.processOneActor = function () { var _this = this; var _a; var pc = this.sp.Game.getPlayer(); if (pc === null) { return; } var actor = this.sp.Game.findRandomActor(pc.getPositionX(), pc.getPositionY(), pc.getPositionZ(), 8192); if (actor === null) { return; } var actorId = actor.getFormID(); var currentProtection = this.protection.get(actorId) || 0; if (currentProtection > 0) { return; } // Eldervale: allowlist de actores CLIENT-LOCAL (caballos via placeAtMe en el gamemode) que // no estan en el modelo del server y por eso no tienen proteccion via FormView. El gamemode // marca su formId en el mismo storage global (ctx.sp.storage['eldHorseProtect']). Sin esto el // WorldCleaner los borra a los pocos frames. var eldProtect = skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__.storage["eldHorseProtect"]; if (eldProtect && typeof eldProtect === "object" && eldProtect[actorId]) { return; } if (actorId === 0x14 || actor.isDisabled() || actor.isDeleted()) { return; } if (this.isActorInDialogue(actor)) { // Deleting actor in dialogue crashes Skyrim // https://github.com/skyrim-multiplayer/issue-tracker/issues/13 actor.setPosition(0, 0, 0); actor.disableNoWait(true); // Seems to not crash return; } // Keep vanila pre-placed bodies, but delete player bodies if (actor.isDead() && actorId < 0xff000000) { actor.blockActivation(true); return; } var pos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getPos(actor); var cellOrWorld = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getWorldOrCell(actor); var chickenRace = 0xa919d; // We discovered anomaly chickens that fail to Disable if we load game near to them // Refs: 106C22, 106C23 if (actorId < 0xff000000 && ((_a = actor.getRace()) === null || _a === void 0 ? void 0 : _a.getFormID()) === chickenRace) { if (this.initialPos && _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getDistanceNoZ(pos, this.initialPos) < 4096) { if (cellOrWorld === this.initialCellOrWorld) { if (this.isActorInDialogue(actor)) { return; } (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, "Deleting chicken anomaly", actorId.toString(16)); actor.killSilent(null); actor.blockActivation(true); actor.disableNoWait(false); actor.setAlpha(0, false); return; } } } actor.disable(false).then(function () { var ac = _this.sp.Actor.from(_this.sp.Game.getFormEx(actorId)); if (!ac || _this.isActorInDialogue(ac)) { return; } ac.delete(); }); }; WorldCleanerService.prototype.isActorInDialogue = function (ac) { return ac.isInDialogueWithPlayer() || ac.getDialogueTarget() !== null; }; return WorldCleanerService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); /***/ }), /***/ "./src/services/spApiInteractor.ts": /*!*****************************************!*\ !*** ./src/services/spApiInteractor.ts ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SpApiInteractor: () => (/* binding */ SpApiInteractor) /* harmony export */ }); /* harmony import */ var _events_events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./events/events */ "./src/services/events/events.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__); var SpApiInteractor = /** @class */ (function () { function SpApiInteractor() { } SpApiInteractor.setup = function (listeners) { listeners.forEach(function (listener) { return SpApiInteractor.registerListenerForLookup(listener.constructor, listener); }); }; SpApiInteractor.getControllerInstance = function () { if (SpApiInteractor.controller) { return SpApiInteractor.controller; } SpApiInteractor.controller = { // TODO: handle errors in event handlers. will output to game console by default on: skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.on, once: skyrimPlatform__WEBPACK_IMPORTED_MODULE_1__.once, emitter: _events_events__WEBPACK_IMPORTED_MODULE_0__.EventEmitterFactory.makeEventEmitter(), lookupListener: function (constructor) { var listener = SpApiInteractor.listenersForLookupByName.get(constructor); if (listener === undefined) { throw new Error("listener not found for name '".concat(constructor.name, "'")); } if (!(listener instanceof constructor)) { throw new Error("listener class mismatch for name '".concat(constructor.name, "'")); } return listener; }, }; return SpApiInteractor.controller; }; SpApiInteractor.registerListenerForLookup = function (constructor, listener) { if (SpApiInteractor.listenersForLookupByName.has(constructor)) { throw new Error("listener re-registration for name '".concat(constructor, "'")); } SpApiInteractor.listenersForLookupByName.set(constructor, listener); }; SpApiInteractor.listenersForLookupByName = new Map(); return SpApiInteractor; }()); /***/ }), /***/ "./src/sync/actorvalues.ts": /*!*********************************!*\ !*** ./src/sync/actorvalues.ts ***! \*********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getActorValues: () => (/* binding */ getActorValues), /* harmony export */ getMaximumActorValue: () => (/* binding */ getMaximumActorValue), /* harmony export */ setActorValuePercentage: () => (/* binding */ setActorValuePercentage) /* harmony export */ }); var getActorValues = function (ac) { if (!ac) { return { health: 0, stamina: 0, magicka: 0 }; } var healthPercentage = (ac.isDead()) ? 0 : ac.getActorValuePercentage("health"); var staminaPercentage = ac.getActorValuePercentage("stamina"); var magickaPercentage = ac.getActorValuePercentage("magicka"); var resultActorValue = { health: healthPercentage, stamina: staminaPercentage, magicka: magickaPercentage, }; return resultActorValue; }; var getMaximumActorValue = function (ac, avName) { var currentPercentage = ac.getActorValuePercentage(avName); return currentPercentage === 0 ? ac.getBaseActorValue(avName) : Math.ceil(ac.getActorValue(avName) / currentPercentage); }; var setActorValuePercentage = function (ac, avName, percentage) { // Actor value percentage for health may be below zero (-1.8 for example, it means u have -180% health) var currentPercentage = ac.getActorValuePercentage(avName); if (currentPercentage === percentage) { return; } var currentMaxValue = getMaximumActorValue(ac, avName); var deltaPercentage = percentage - currentPercentage; if (deltaPercentage > 0) { ac.restoreActorValue(avName, deltaPercentage * currentMaxValue); } else if (deltaPercentage < 0) { ac.damageActorValue(avName, deltaPercentage * currentMaxValue); } }; /***/ }), /***/ "./src/sync/animation.ts": /*!*******************************!*\ !*** ./src/sync/animation.ts ***! \*******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnimationEventName: () => (/* binding */ AnimationEventName), /* harmony export */ AnimationSource: () => (/* binding */ AnimationSource), /* harmony export */ applyAnimation: () => (/* binding */ applyAnimation), /* harmony export */ setDefaultAnimsDisabled: () => (/* binding */ setDefaultAnimsDisabled), /* harmony export */ setupHooks: () => (/* binding */ setupHooks) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _movementApply__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./movementApply */ "./src/sync/movementApply.ts"); /* eslint-disable @typescript-eslint/no-empty-function */ var AnimationEventName; (function (AnimationEventName) { AnimationEventName["Ragdoll"] = "Ragdoll"; AnimationEventName["GetUpBegin"] = "GetUpBegin"; })(AnimationEventName || (AnimationEventName = {})); ; var allowedIdles = new Array(); var refsWithDefaultAnimsDisabled = new Set(); var allowedAnims = new Set(); var actorSitAnimsLowerCase = [ 'idlestoolenterplayer', 'idlestoolenter', 'idlestoolenterinstant', 'idlechairrightenter', 'idlechairleftenter', 'idlechairfrontenter', 'idlechairenterinstant', 'idlejarlchairenter', 'idlejarlchairenterinstant', 'idlesnowelfprincechairdialogue', 'idlesnowelfprincechairenter', 'idlesnowelfprincechairenterinstant', 'idlechairchildenterinstant', 'idlechairchildfrontenter', 'idlechairchildleftenter', 'idlechairchildrightenter', ]; var actorGetUpAnimsLowerCase = [ 'idlestoolbackexit', 'idlechairrightexit', 'idlechairrightquickexit', 'idlechairleftexit', 'idlechairleftquickexit', 'idlechairfrontexit', 'idlechairfrontquickexit', 'idlechairchildfrontexit', 'idlechairchildleftexit', 'idlechairchildrightexit' ]; // It's critical for values to be the correct case, not just lowercase, otherwise 'allowedIdles' check will break // We don't want to modify the check itself, because it'll be slower var animOverridesLowerCase = { 'idlechairbook_onepage': 'IdleChairEnterInstant', 'idlechairshoulderflex': 'IdleChairEnterInstant', 'idlechairwrite': 'IdleChairEnterInstant', 'idlechairarmscrossedvar1': 'IdleChairEnterInstant', 'chaireatingstart_vampiremeat': 'IdleChairEnterInstant', 'chairreadingstart': 'IdleChairEnterInstant', 'chairvampireeatingstart': 'IdleChairEnterInstant', 'chairdrinkingstart': 'IdleChairEnterInstant', 'chaireatingstart': 'IdleChairEnterInstant', // The only triple animation we know for now. One base anim to sit, then two to eat 'chaireatingsoupstart': 'IdleChairEnterInstant', 'idleeatsoup': 'IdleChairEnterInstant', // No need to re-play the animation, use instant variant for spawning actors // This is not essential, but makes the sync feel more smooth. The list is not complete. 'idlechairrightenter': 'IdleChairEnterInstant', 'idlechairleftenter': 'IdleChairEnterInstant', 'idlechairfrontenter': 'IdleChairEnterInstant', // Untested yet looks correct 'idlesnowelfprincefireandforget': 'IdleSnowElfPrinceChairEnterInstant', 'idletablemugenter': 'IdleTableEnterInstant', 'idletabledrinkenter': 'IdleTableEnterInstant', 'idletabledrinkandmugenter': 'IdleTableEnterInstant' }; // unclassified: // IdleChairEnterInstant // IdleChairEnterStart // IdleChairEnterStop // IdleChairEnterToSit // IdleChairExitStart // IdleChairExitToStand // IdleChairSitting // IdleLeftChairEnterStart // ChairIdle // IdleRightChairEnterStart // IdleLeftChairEnterStart var isIdle = function (animEventName) { var animEventNameLowerCase = animEventName.toLowerCase(); return (animEventNameLowerCase === "motiondrivenidle" || (animEventNameLowerCase.startsWith("idle") && animEventNameLowerCase !== "idlestop" && animEventNameLowerCase !== "idleforcedefaultstate")); }; var applyAnimation = function (refr, anim, state) { if (state.lastNumChanges === anim.numChanges) { return; } state.lastNumChanges = anim.numChanges; if (state.useAnimOverrides) { var animOverride = animOverridesLowerCase[anim.animEventName.toLowerCase()]; if (animOverride !== undefined) { anim.animEventName = animOverride; } } var animEventNameLowerCase = anim.animEventName.toLowerCase(); if (isIdle(anim.animEventName)) { allowedIdles.push([refr.getFormID(), anim.animEventName]); } var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (anim.animEventName === "SkympFakeEquip") { if (ac) { (0,_movementApply__WEBPACK_IMPORTED_MODULE_1__.applyWeapDrawn)(ac, true); } return; } if (anim.animEventName === "SkympFakeUnequip") { if (ac) { (0,_movementApply__WEBPACK_IMPORTED_MODULE_1__.applyWeapDrawn)(ac, false); } return; } if (anim.animEventName === "Ragdoll") { if (ac) { if (skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["animationFunc1Set"] === true) { // @ts-ignore skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["animationFunc1"](ac); } else { ac.pushActorAway(ac, 0); ac.setActorValue("Variable10", -1000); } } return; } if (refsWithDefaultAnimsDisabled.has(refr.getFormID())) { if (animEventNameLowerCase.includes("attack")) { allowedAnims.add(refr.getFormID() + ":" + anim.animEventName); } } skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Debug.sendAnimationEvent(refr, anim.animEventName); if (anim.animEventName === "GetUpBegin") { var refrId_1 = refr.getFormID(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(1).then(function () { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId_1)); if (ac) { ac.setActorValue("Variable10", 1000); } }); } if (actorSitAnimsLowerCase.find(function (x) { return x === animEventNameLowerCase; }) !== undefined) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setCollision)(refr.getFormID(), false); } if (actorGetUpAnimsLowerCase.find(function (x) { return x === animEventNameLowerCase; }) !== undefined) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setCollision)(refr.getFormID(), true); } }; var setDefaultAnimsDisabled = function (refrId, disabled) { if (disabled) { refsWithDefaultAnimsDisabled.add(refrId); } else { refsWithDefaultAnimsDisabled.delete(refrId); } }; var AnimationSource = /** @class */ (function () { function AnimationSource(refr) { var _this = this; this.refrId = 0; this.numChanges = 0; this.animEventName = ""; this.weapNonDrawnBlocker = 0; this.weapDrawnBlocker = 0; this.sneakBlocker = null; this.refrId = refr.getFormID(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.hooks.sendAnimationEvent.add({ enter: function () { }, leave: function (ctx) { if (ctx.selfId !== _this.refrId) { return; } if (!ctx.animationSucceeded) { // Workaround, see carryAnimSystem.ts in gamemode // Case-sensetive check here for better performance if (ctx.animEventName !== "OffsetCarryBasketStart") { return; } } _this.onSendAnimationEvent(ctx.animEventName); }, }); } AnimationSource.prototype.filterMovement = function (mov) { if (this.weapDrawnBlocker >= Date.now()) { mov.isWeapDrawn = true; } if (this.weapNonDrawnBlocker >= Date.now()) { mov.isWeapDrawn = false; } if (this.sneakBlocker === mov.isSneaking) { this.sneakBlocker = null; } else if (this.sneakBlocker === true) { mov.isSneaking = true; } else if (this.sneakBlocker === false) { mov.isSneaking = false; } return mov; }; AnimationSource.prototype.getAnimation = function () { var _a = this, numChanges = _a.numChanges, animEventName = _a.animEventName; return { numChanges: numChanges, animEventName: animEventName }; }; AnimationSource.prototype.onSendAnimationEvent = function (animEventName) { if (ignoredAnims.has(animEventName)) { return; } var lower = animEventName.toLowerCase(); var isTorchEvent = lower.includes("torch"); if (animEventName.toLowerCase().includes("unequip") && !isTorchEvent) { this.weapNonDrawnBlocker = Date.now() + 300; animEventName = "SkympFakeUnequip"; } else if (animEventName.toLowerCase().includes("equip") && !isTorchEvent) { this.weapDrawnBlocker = Date.now() + 300; animEventName = "SkympFakeEquip"; } if (animEventName === "SneakStart") { this.sneakBlocker = true; return; } if (animEventName === "SneakStop") { this.sneakBlocker = false; return; } this.numChanges++; this.animEventName = animEventName; }; return AnimationSource; }()); var ignoredAnims = new Set([ "moveStart", "moveStop", "turnStop", "CyclicCrossBlend", "CyclicFreeze", "TurnLeft", "TurnRight", ]); var setupHooks = function () { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.hooks.sendAnimationEvent.add({ enter: function (ctx) { if (refsWithDefaultAnimsDisabled.has(ctx.selfId)) { if (ctx.animEventName.toLowerCase().includes("attack")) { var animKey = ctx.selfId + ":" + ctx.animEventName; if (allowedAnims.has(animKey)) { allowedAnims.delete(animKey); } else { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("block anim " + ctx.animEventName); return (ctx.animEventName = ""); } } } // ShowRaceMenu forces this anim if (ctx.animEventName === "OffsetBoundStandingPlayerInstant") { return (ctx.animEventName = ""); } // Disable idle animations for 0xff actors if (ctx.selfId < 0xff000000) { return; } if (isIdle(ctx.animEventName)) { var i = allowedIdles.findIndex(function (pair) { return pair[0] === ctx.selfId && pair[1] === ctx.animEventName; }); i === -1 ? (ctx.animEventName = "") : allowedIdles.splice(i, 1); } }, leave: function () { }, }); }; /***/ }), /***/ "./src/sync/appearance.ts": /*!********************************!*\ !*** ./src/sync/appearance.ts ***! \********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ applyAppearance: () => (/* binding */ applyAppearance), /* harmony export */ applyAppearanceToPlayer: () => (/* binding */ applyAppearanceToPlayer), /* harmony export */ applyTints: () => (/* binding */ applyTints), /* harmony export */ getAppearance: () => (/* binding */ getAppearance), /* harmony export */ silentVoiceTypeId: () => (/* binding */ silentVoiceTypeId) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); var getAppearance = function (actor) { var base = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ActorBase.from(actor.getBaseObject()); var hairColor = base.getHairColor(); var skinColor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.getSkinColor(base); var newAppearance = { isFemale: base.getSex() === 1, raceId: base.getRace() ? base.getRace().getFormID() : 0, weight: base.getWeight(), hairColor: hairColor ? hairColor.getColor() : 0, headpartIds: [], headTextureSetId: base.getFaceTextureSet() ? base.getFaceTextureSet().getFormID() : 0, options: new Array(19), presets: new Array(4), tints: [], skinColor: skinColor ? skinColor.getColor() : 0, name: actor.getBaseObject().getName(), }; var numHeadparts = base.getNumHeadParts(); for (var i = 0; i < numHeadparts; ++i) { var part = base.getNthHeadPart(i); if (part) { newAppearance.headpartIds.push(part.getFormID()); } } for (var i = 0; i < newAppearance.options.length; ++i) { newAppearance.options[i] = base.getFaceMorph(i); } for (var i = 0; i < newAppearance.presets.length; ++i) { newAppearance.presets[i] = base.getFacePreset(i); } var numTints = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer().getFormID() === actor.getFormID() ? skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getNumTintMasks() : 0; for (var i = 0; i < numTints; ++i) { var tint = { texturePath: skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getNthTintMaskTexturePath(i), type: skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getNthTintMaskType(i), argb: skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getNthTintMaskColor(i), }; newAppearance.tints.push(tint); } return newAppearance; }; var isVisible = function (argb) { return argb > 0x00ffffff || argb < 0; }; var applyTints = function (actor, appearance) { if (!appearance) { throw new Error("null appearance has been passed to applyTints"); } var tints = appearance.tints.filter(function (t) { return isVisible(t.argb); }); var raceWarPaintRegex = /.*Head.+WarPaint.*/; var uniWarPaintRegex = /.*HeadWarPaint.*/; var raceSpecificWarPaint = tints.filter(function (t) { return isVisible(t.argb) && t.texturePath.match(raceWarPaintRegex); }).length; // MaleHeadNordWarPaint var uniWarPaint = tints.filter(function (t) { return isVisible(t.argb) && t.texturePath.match(uniWarPaintRegex); }).length; // MaleHeadWarPaint if (raceSpecificWarPaint + uniWarPaint > 1) { // If visible war paints of these two types present, then Skyrim crashes (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("bad warpaint!", raceSpecificWarPaint, uniWarPaint); return; } skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.clearTintMasks(actor); tints.forEach(function (tint) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.pushTintMask(actor, tint.type, tint.argb, tint.texturePath); }); var playerBaseId = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer().getBaseObject().getFormID(); if (actor) skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setFormIdUnsafe(actor.getBaseObject(), playerBaseId); }; var silentVoiceTypeId = 0x0002f7c3; var applyAppearanceCommon = function (appearance, npc) { var race = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Race.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(appearance.raceId)); var headparts = appearance.headpartIds .map(function (id) { return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.HeadPart.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(id)); }) .filter(function (headpart) { return !!headpart; }); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setNpcSex(npc, appearance.isFemale ? 1 : 0); if (race) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setNpcRace(npc, race); } npc.setWeight(appearance.weight); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setNpcSkinColor(npc, appearance.skinColor); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setNpcHairColor(npc, appearance.hairColor); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.resizeHeadpartsArray(npc, headparts.length); headparts.forEach(function (v, i) { return npc.setNthHeadPart(v, i); }); npc.setFaceTextureSet(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TextureSet.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(appearance.headTextureSetId))); // setFaceTextureSet supports null argument npc.setVoiceType(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.VoiceType.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(silentVoiceTypeId))); appearance.options.forEach(function (v, i) { return npc.setFaceMorph(v, i); }); appearance.presets.forEach(function (v, i) { return npc.setFacePreset(v, i); }); if (appearance.name) { npc.setName(appearance.name); } else { // for undefined or empty name npc.setName(" "); } }; var applyAppearance = function (appearance) { var npc = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.createNpc(); if (!npc) { throw new Error("createNpc returned null"); } applyAppearanceCommon(appearance, npc); return npc; }; var applyAppearanceToPlayer = function (appearance) { applyAppearanceCommon(appearance, skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ActorBase.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer().getBaseObject())); applyTints(null, appearance); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer().queueNiNodeUpdate(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.wait(0.0625).then(function () { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)("update", function () { var _a; (_a = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer()) === null || _a === void 0 ? void 0 : _a.startDeferredKill(); }); }); }; /***/ }), /***/ "./src/sync/equipment.ts": /*!*******************************!*\ !*** ./src/sync/equipment.ts ***! \*******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ applyEquipment: () => (/* binding */ applyEquipment), /* harmony export */ getEquipedSpell: () => (/* binding */ getEquipedSpell), /* harmony export */ getEquipment: () => (/* binding */ getEquipment), /* harmony export */ isBadMenuShown: () => (/* binding */ isBadMenuShown), /* harmony export */ syncSpellEquipment: () => (/* binding */ syncSpellEquipment) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _inventory__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./inventory */ "./src/sync/inventory.ts"); var getEquipedSpell = function (refr, spellType) { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (!actor) { return 0; } switch (spellType) { case 0 /* SpellType.Left */: { var spell = actor.getEquippedSpell(0 /* SpellType.Left */); return spell ? spell.getFormID() : 0; } case 1 /* SpellType.Right */: { var spell = actor.getEquippedSpell(1 /* SpellType.Right */); return spell ? spell.getFormID() : 0; } case 2 /* SpellType.Voice */: { var spell = actor.getEquippedSpell(2 /* SpellType.Voice */); return spell ? spell.getFormID() : 0; } case 3 /* SpellType.Instant */: { var spell = actor.getEquippedSpell(3 /* SpellType.Instant */); return spell ? spell.getFormID() : 0; } default: { return 0; } } }; var filterWorn = function (inv) { return { entries: inv.entries.filter(function (x) { return x.worn || x.wornLeft; }) }; }; var removeUnnecessaryExtra = function (inv, ignoreAmmo) { return { entries: inv.entries.map(function (x) { var r = JSON.parse(JSON.stringify(x)); r.chargePercent = r.maxCharge; if (ignoreAmmo) { r.count = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ammo.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(x.baseId)) ? r.count : 1; } else { r.count = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ammo.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(x.baseId)) ? 1000 : 1; } delete r.name; return r; }), }; }; var getEquipment = function (ac, numChanges) { return { inv: (0,_inventory__WEBPACK_IMPORTED_MODULE_1__.getInventory)(ac), leftSpell: getEquipedSpell(ac, 0 /* SpellType.Left */), rightSpell: getEquipedSpell(ac, 1 /* SpellType.Right */), voiceSpell: getEquipedSpell(ac, 2 /* SpellType.Voice */), instantSpell: getEquipedSpell(ac, 3 /* SpellType.Instant */), numChanges: numChanges, }; }; var syncSpellEquipment = function (ac, spellBaseId, spellType) { if (spellBaseId !== undefined && spellBaseId > 0) { ac.equipSpell(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Spell.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(spellBaseId)), spellType); } else { var equipedSpell = ac.getEquippedSpell(spellType); if (equipedSpell) { ac.unequipSpell(equipedSpell, spellType); } } }; var applyEquipment = function (ac, eq) { ac.removeAllItems(null, false, true); ac.unequipAll(); ac.removeAllItems(null, false, true); var newInventory = removeUnnecessaryExtra(filterWorn(eq.inv), ac.getFormID() === 0x14); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setInventory)(ac.getFormID(), newInventory); syncSpellEquipment(ac, eq.leftSpell, 0 /* SpellType.Left */); syncSpellEquipment(ac, eq.rightSpell, 1 /* SpellType.Right */); syncSpellEquipment(ac, eq.voiceSpell, 2 /* SpellType.Voice */); syncSpellEquipment(ac, eq.instantSpell, 3 /* SpellType.Instant */); return true; }; var isBadMenuShown = function () { return (skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen('InventoryMenu') || skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen('FavoritesMenu') || skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen('MagicMenu') || skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen('ContainerMenu') || skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen('Crafting Menu') // Actually I don't think it causes crashes ); }; /***/ }), /***/ "./src/sync/inventory.ts": /*!*******************************!*\ !*** ./src/sync/inventory.ts ***! \*******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ applyInventory: () => (/* binding */ applyInventory), /* harmony export */ getDiff: () => (/* binding */ getDiff), /* harmony export */ getInventory: () => (/* binding */ getInventory), /* harmony export */ hasExtras: () => (/* binding */ hasExtras), /* harmony export */ removeSimpleItemsAsManyAsPossible: () => (/* binding */ removeSimpleItemsAsManyAsPossible), /* harmony export */ sumInventories: () => (/* binding */ sumInventories) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); // 'loxsword (Legendary)' => 'loxsword' var getRealName = function (s) { if (!s) { return s; } var arr = s.split(" "); if (arr.length && arr[arr.length - 1].match(/^\(.*\)$/)) { arr.pop(); } return arr.join(" "); }; // 'aaaaaaaaaaaaaaaa' => 'aaa...' var cropName = function (s) { if (!s) { return s; } var max = 128; return s.length >= max ? s .split("") .filter(function (x, i) { return i < max; }) .join("") .concat("...") : s; }; var checkIfNameIsGeneratedByGame = function (aStr, bStr, formName) { if (!aStr.length && bStr.startsWith(formName)) { var bEnding = bStr.substr(formName.length); if (bEnding.match(/^\s\(.*\)$/)) { return true; } } return false; }; var namesEqual = function (a, b) { var aStr = a.name || ""; var bStr = b.name || ""; if (cropName(getRealName(aStr)) === cropName(getRealName(bStr))) { return true; } if (a.baseId === b.baseId) { var form = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(a.baseId); if (form) { var formName = form.getName(); if (checkIfNameIsGeneratedByGame(aStr, bStr, formName) || checkIfNameIsGeneratedByGame(bStr, aStr, formName)) return true; } } return false; }; var extrasEqual = function (a, b, ignoreWorn) { if (ignoreWorn === void 0) { ignoreWorn = false; } return (a.health === b.health && a.enchantmentId === b.enchantmentId && a.maxCharge === b.maxCharge && !!a.removeEnchantmentOnUnequip === !!b.removeEnchantmentOnUnequip && //a.chargePercent === b.chargePercent && //namesEqual(a, b) && a.soul === b.soul && a.poisonId === b.poisonId && a.poisonCount === b.poisonCount && ((!!a.worn === !!b.worn && !!a.wornLeft === !!b.wornLeft) || ignoreWorn)); }; var hasExtras = function (e) { return !extrasEqual(e, { baseId: 0, count: 0 }); }; var extractExtraData = function (refr, extraList, out) { // I see that ExtraWorn is not emitted for 0xFF actors when arrows are equipped. Fixing var item = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(out.baseId); if (skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ammo.from(item)) { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (actor && actor.isEquipped(item)) { out.worn = true; } } (extraList || []).forEach(function (extra) { switch (extra.type) { case "Health": out.health = Math.round(extra.health * 10) / 10; // TESModPlatform::AddItemEx makes all items at least 1.01 health if (out.health === 1) { delete out.health; } break; case "Count": out.count = extra.count; break; case "Enchantment": out.enchantmentId = extra.enchantmentId; out.maxCharge = extra.maxCharge; out.removeEnchantmentOnUnequip = extra.removeOnUnequip; break; case "Charge": out.chargePercent = extra.charge; break; case "Poison": out.poisonId = extra.poisonId; out.poisonCount = extra.count; break; case "Soul": out.soul = extra.soul; break; case "TextDisplayData": out.name = extra.name; break; case "Worn": out.worn = true; break; case "WornLeft": out.wornLeft = true; break; } }); }; var squash = function (inv) { var res = new Array(); inv.entries.forEach(function (e) { var same = res.find(function (x) { return e.baseId === x.baseId && extrasEqual(x, e); }); if (same) { same.count += e.count; } else { res.push(JSON.parse(JSON.stringify(e))); } }); return { entries: res.filter(function (x) { return x.count !== 0; }) }; }; var getExtraContainerChangesAsInventory = function (refr) { var extraContainerChanges = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.getExtraContainerChanges)(refr.getFormID()); var entries = new Array(); (extraContainerChanges || []).forEach(function (changesEntry) { var entry = { baseId: changesEntry.baseId, count: changesEntry.countDelta, }; (changesEntry.extendDataList || []).forEach(function (extraList) { var e = { baseId: entry.baseId, count: 1, }; extractExtraData(refr, extraList, e); entries.push(e); entry.count -= e.count; }); if (entry.count !== 0) { entries.push(entry); } }); var res = { entries: entries }; res = squash(res); return res; }; var getBaseContainerAsInventory = function (refr) { return { entries: (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.getContainer)(refr.getBaseObject().getFormID()), }; }; var sumInventories = function (lhs, rhs) { var leftEntriesWithExtras = lhs.entries.filter(function (e) { return hasExtras(e); }); var rightEntriesWithExtras = rhs.entries.filter(function (e) { return hasExtras(e); }); var leftEntriesSimple = lhs.entries.filter(function (e) { return !hasExtras(e); }); var rightEntriesSimple = rhs.entries.filter(function (e) { return !hasExtras(e); }); leftEntriesSimple.forEach(function (e) { var matching = rightEntriesSimple.find(function (x) { return x.baseId === e.baseId; }); if (matching) { e.count += matching.count; matching.count = 0; } }); return { entries: leftEntriesWithExtras .concat(rightEntriesWithExtras) .concat(leftEntriesSimple) .concat(rightEntriesSimple) .filter(function (e) { return e.count !== 0; }), }; }; var removeSimpleItemsAsManyAsPossible = function (inv, baseId, count) { var res = { entries: [] }; res.entries = JSON.parse(JSON.stringify(inv.entries)); var entry = res.entries.find(function (e) { return !hasExtras(e) && e.baseId === baseId; }); if (entry) { entry.count -= count; } res.entries = res.entries.filter(function (e) { return e.count > 0; }); return res; }; var getDiff = function (lhs, rhs, ignoreWorn) { var lhsCopy = JSON.parse(JSON.stringify(lhs)); var rhsCopy = JSON.parse(JSON.stringify(rhs)); rhsCopy.entries.forEach(function (e) { var sameFromLeft = lhsCopy.entries.find(function (x) { return x.baseId === e.baseId && extrasEqual(x, e, ignoreWorn); }); if (sameFromLeft) { sameFromLeft.count -= e.count; } else { lhsCopy.entries.push(e); lhsCopy.entries[lhsCopy.entries.length - 1].count *= -1; } }); return { entries: lhsCopy.entries.filter(function (x) { return x.count !== 0; }) }; }; var getInventory = function (refr) { return squash(sumInventories(getBaseContainerAsInventory(refr), getExtraContainerChangesAsInventory(refr))); }; var basesReset = function () { if (skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["basesResetExists"] !== true) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["basesResetExists"] = true; skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["basesReset"] = new Set(); } return skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["basesReset"]; }; var resetBase = function (refr) { var base = refr.getBaseObject(); var baseId = base ? base.getFormID() : 0; if (!basesReset().has(baseId)) { basesReset().add(baseId); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.resetContainer(base); refr.removeAllItems(null, false, true); } }; var applyInventory = function (refr, newInventory, enableCrashProtection, ignoreWorn) { if (ignoreWorn === void 0) { ignoreWorn = false; } resetBase(refr); var diff = getDiff(newInventory, getInventory(refr), ignoreWorn).entries; var res = true; diff.sort(function (a, b) { return (a.count < b.count ? -1 : 1); }); diff.forEach(function (e, i) { if (i > 0 && enableCrashProtection) { res = false; return; } var absCount = Math.abs(e.count); var queueNiNodeUpdateNeeded = false; var worn = !!e.worn; var wornLeft = !!e.wornLeft; var oneStepCount = e.count / absCount; var f = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(e.baseId); if (!f) { return (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Bad form ID ".concat(e.baseId.toString(16))); } var type = f.getType(); // For misc items, potions and ingredients we don't want to split them into multiple items // This was made to fix a performance issue with users having 10000+ of misc items (i.e. gold) if (type === 32 /* FormType.Misc */ || type === 46 /* FormType.Potion */ || type === 30 /* FormType.Ingredient */) { absCount = 1; oneStepCount = e.count; } else { if (absCount > 1000) { absCount = 1; oneStepCount = 1; // Also for arrows with strange count if (worn && e.count < 0) { absCount = 0; } } if (e.count > 1 && skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ammo.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(e.baseId))) { absCount = 1; oneStepCount = e.count; if (e.count > 60000) { // Why would actor have 60k arrows? e.count = 1; } } } for (var i_1 = 0; i_1 < absCount; ++i_1) { if (worn || wornLeft) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.pushWornState(!!worn, !!wornLeft); queueNiNodeUpdateNeeded = true; } var addItemExArgs = void 0; addItemExArgs = [ refr, f, oneStepCount, e.health ? e.health : 1, e.enchantmentId ? skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Enchantment.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(e.enchantmentId)) : null, e.maxCharge ? e.maxCharge : 0, !!e.removeEnchantmentOnUnequip, e.chargePercent ? e.chargePercent : 0, e.name ? cropName(e.name) : f.getName(), e.soul ? e.soul : 0, e.poisonId ? skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Potion.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(e.poisonId)) : null, e.poisonCount ? e.poisonCount : 0 ]; // Log debug removido: en server con muchos items por player (starter // inventory + drops) este printConsole spammeaba la consola de SP // varias veces por segundo. Si necesitas debug, descomenta esto. // const argsToPrint = addItemExArgs.map((arg) => { // if (arg instanceof ObjectReference) return `ObjectReference(${arg.getFormID().toString(16)})`; // if (arg instanceof Form) return `Form(${arg.getFormID().toString(16)})`; // return JSON.stringify(arg); // }); // printConsole(`TESModPlatform.addItemEx(${argsToPrint.join(", ")})`); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.addItemEx.apply(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform, addItemExArgs); } if (queueNiNodeUpdateNeeded) { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (ac) { ac.queueNiNodeUpdate(); } } }); return res; }; /***/ }), /***/ "./src/sync/movementApply.ts": /*!***********************************!*\ !*** ./src/sync/movementApply.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ applyMovement: () => (/* binding */ applyMovement), /* harmony export */ applyWeapDrawn: () => (/* binding */ applyWeapDrawn), /* harmony export */ destroyProxyMountForRider: () => (/* binding */ destroyProxyMountForRider) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _lib_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lib/errors */ "./src/lib/errors.ts"); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); /* harmony import */ var _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../services/spApiInteractor */ "./src/services/spApiInteractor.ts"); var sqr = function (x) { return x * x; }; var proxyMounts = new Map(); // riderRemoteFormId -> proxy local // m.vehicleFormId viene de la RED (no confiable). Solo spawneamos proxies de bases de CABALLO // conocidas, para que un cliente modificado no fuerce a los observadores a instanciar/proteger // forms arbitrarios. PROTOTIPO: hardcode de las bases del catálogo (68cfa/68d04); el lifecycle // final las recibirá del gamemode (catálogo /caballos) vía storage. var ALLOWED_HORSE_BASES = new Set([0x68cfa, 0x68d04]); var setHorseProtect = function (id, on) { // Misma allowlist que respeta el WorldCleanerService (si no, borra el proxy en pocos frames). try { var pr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["eldHorseProtect"]; if (!pr || typeof pr !== "object") pr = {}; if (on) pr[id] = 1; else delete pr[id]; skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["eldHorseProtect"] = pr; } catch (e) { /* ignore */ } }; var destroyProxyMount = function (riderId) { var pm = proxyMounts.get(riderId); if (!pm) return; proxyMounts.delete(riderId); try { setHorseProtect(pm.proxyId, false); // SIEMPRE desproteger antes de borrar (evita huérfano protegido) var ref = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(pm.proxyId)); if (ref) { ref.disable(false); ref.delete(); } } catch (e) { /* ignore */ } }; var PROXY_GRACE_MS = 700; var PROXY_TTL_MS = 4000; // jinete que deja de mandar movimiento > TTL -> su proxy se barre var lastProxySweep = 0; // Limpieza inmediata por jinete; la llama FormView.destroy() al remover al actor remoto (cubre // salir del worldView / cambio de celda / desconexión sin un paquete final de desmontaje). var destroyProxyMountForRider = function (riderId) { destroyProxyMount(riderId); }; // Barrido throttled de proxies huérfanos: catch-all si el jinete desaparece sin desmontar y sin // que FormView.destroy lo limpie. Se dispara desde cualquier applyMovement (hay movimiento siempre // que haya algún remoto en escena). var sweepStaleProxies = function () { var now = Date.now(); if (now - lastProxySweep < 1000) return; lastProxySweep = now; proxyMounts.forEach(function (pm, riderId) { if (now - pm.lastSeenMs > PROXY_TTL_MS) destroyProxyMount(riderId); }); }; var applyMovement = function (refr, m, isMyClone) { sweepStaleProxies(); if (teleportIfNeed(refr, m)) { return; } var mountAc = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (mountAc) { var riderId = refr.getFormID(); var reqBase = (m.vehicleFormId !== undefined && m.vehicleFormId !== null) ? (m.vehicleFormId >>> 0) : 0; if (reqBase > 0 && ALLOWED_HORSE_BASES.has(reqBase)) { var baseId = reqBase; var pm = proxyMounts.get(riderId); // Cambio de montura -> desmontar al jinete del proxy viejo, descartarlo y crear uno nuevo. if (pm && pm.baseId !== baseId) { try { if (mountAc.isOnMount()) mountAc.dismount(); } catch (e) { /* ignore */ } destroyProxyMount(riderId); pm = undefined; } if (!pm) { try { var base = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(baseId); var proxy = base ? mountAc.placeAtMe(base, 1, true, false) : null; if (proxy) { var proxyId = proxy.getFormID() >>> 0; setHorseProtect(proxyId, true); // que el WorldCleaner del observador no lo borre pm = { proxyId: proxyId, baseId: baseId, lastSeenMs: Date.now() }; proxyMounts.set(riderId, pm); } } catch (e) { /* reintentar el próximo frame */ } } if (pm) { var proxyRef = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(pm.proxyId)); if (!proxyRef) { // El proxy se perdió (borrado por cleanup/celda/race). El estado de monta del engine puede // sobrevivir al ref borrado -> desmontar al jinete e invalidar (destroyProxyMount quita // eldHorseProtect + Map; NO se refrescó lastSeenMs). El próximo paquete crea uno nuevo. try { if (mountAc.isOnMount()) mountAc.dismount(); } catch (e) { /* ignore */ } destroyProxyMount(riderId); } else { pm.lastSeenMs = Date.now(); // solo refrescar con proxy VÁLIDO (si no, el TTL nunca barrería) // ¿Montado en ESTE proxy (no en uno viejo/borrado)? El estado de monta del engine puede // sobrevivir al Map; verificamos con la furniture ACTUAL y RE-BINDeamos si no coincide. var cur = mountAc.getFurnitureReference(); var onThisProxy = !!cur && (cur.getFormID() >>> 0) === pm.proxyId; if (!onThisProxy) { try { mountAc.setVehicle(proxyRef); } catch (e) { /* ignore */ } } translateTo(proxyRef, m); // pegar el proxy a la pos (fluida) del jinete var after = mountAc.getFurnitureReference(); var confirmed = !!after && (after.getFormID() >>> 0) === pm.proxyId; if (confirmed) { // Montado en el proxy ACTUAL: aplicar solo lo no-posicional (al jinete lo lleva el proxy) y salir. applyWeapDrawn(mountAc, m.isWeapDrawn); applyHealthPercentage(mountAc, m.healthPercentage); _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_3__.SpApiInteractor.getControllerInstance().emitter.emit("applyDeathStateEvent", { actor: mountAc, isDead: m.isDead }); return; // NO seguir al path normal de movimiento } // Aún no enganchó en el proxy actual (3D no listo / reseat en curso): NO return -> mover al // jinete por el path normal este frame y reintentar el próximo. Evita congelarlo. } } // Proxy aún no listo (race spawn): NO congelar -> caer al movimiento normal del jinete y reintentar. } else { // Sin montura ESTE paquete: ventana de gracia para no desmontar por 1 paquete perdido/reordenado. var pm = proxyMounts.get(riderId); if (pm) { if (Date.now() - pm.lastSeenMs <= PROXY_GRACE_MS) { var proxyRef = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(pm.proxyId)); if (proxyRef && mountAc.isOnMount()) { translateTo(proxyRef, m); applyWeapDrawn(mountAc, m.isWeapDrawn); applyHealthPercentage(mountAc, m.healthPercentage); _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_3__.SpApiInteractor.getControllerInstance().emitter.emit("applyDeathStateEvent", { actor: mountAc, isDead: m.isDead }); return; // dentro de la gracia y aún montado: bridge del paquete faltante (sin flicker) } // si ya no está montado, caer al movimiento normal (no congelar); se limpia al expirar la gracia } // Gracia expirada -> desmontar y limpiar el proxy. try { if (mountAc.isOnMount()) mountAc.dismount(); } catch (e) { /* ignore */ } destroyProxyMount(riderId); } } } // Z axis isn't useful here var acX = refr.getPositionX(); var acY = refr.getPositionY(); var lagUnitsNoZ = Math.round(Math.sqrt(sqr(m.pos[0] - acX) + sqr(m.pos[1] - acY))); if (isMyClone === true) { _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_3__.SpApiInteractor.getControllerInstance().emitter.emit("newLocalLagValueCalculated", { lagUnitsNoZ: lagUnitsNoZ }); } translateTo(refr, m); var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (!ac) { return; } var lookAt = null; if (m.lookAt) { try { lookAt = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.findClosestActor(m.lookAt[0], m.lookAt[1], m.lookAt[2], 128); } catch (e) { lookAt = null; } } if (lookAt) { ac.setHeadTracking(true); ac.setLookAt(lookAt, false); } else { ac.setHeadTracking(false); } // ac.stopCombat(); ac.blockActivation(true); keepOffsetFromActor(ac, m); applySprinting(ac, m.runMode === "Sprinting"); applyBlocking(ac, m); applySneaking(ac, m.isSneaking); applyWeapDrawn(ac, m.isWeapDrawn); applyHealthPercentage(ac, m.healthPercentage); _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_3__.SpApiInteractor.getControllerInstance().emitter.emit("applyDeathStateEvent", { actor: ac, isDead: m.isDead }); }; var keepOffsetFromActor = function (ac, m) { var offsetAngle = m.rot[2] - ac.getAngleZ(); if (Math.abs(offsetAngle) < 5) { offsetAngle = 0; } if (m.runMode === "Standing") { return ac.keepOffsetFromActor(ac, 0, 0, 0, 0, 0, offsetAngle, 1, 1); } var offset = [ 3 * Math.sin((m.direction / 180) * Math.PI), 3 * Math.cos((m.direction / 180) * Math.PI), getOffsetZ(m.runMode), ]; ac.keepOffsetFromActor(ac, offset[0], offset[1], offset[2], 0, 0, offsetAngle, m.runMode === "Walking" ? 2048 : 1, 1); }; var getOffsetZ = function (runMode) { switch (runMode) { case "Walking": return -512; case "Running": return -1024; } return 0; }; var applySprinting = function (ac, isSprinting) { if (ac.isSprinting() != isSprinting) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Debug.sendAnimationEvent(ac, isSprinting ? "SprintStart" : "SprintStop"); } }; var applyBlocking = function (ac, m) { if (ac.getAnimationVariableBool("IsBlocking") != m.isBlocking) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Debug.sendAnimationEvent(ac, m.isBlocking ? "BlockStart" : "BlockStop"); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Debug.sendAnimationEvent(ac, m.isSneaking ? "SneakStart" : "SneakStop"); } }; var applySneaking = function (ac, isSneaking) { var currentIsSneaking = ac.isSneaking() || ac.getAnimationVariableBool("IsSneaking"); if (currentIsSneaking != isSneaking) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Debug.sendAnimationEvent(ac, isSneaking ? "SneakStart" : "SneakStop"); } }; var applyWeapDrawn = function (ac, isWeapDrawn) { if (ac.isWeaponDrawn() !== isWeapDrawn) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setWeaponDrawnMode(ac, isWeapDrawn ? 1 : 0); } }; var applyHealthPercentage = function (ac, healthPercentage) { var currentPercentage = ac.getActorValuePercentage('health'); if (currentPercentage === healthPercentage) { return; } var currentMax = ac.getBaseActorValue('health'); var deltaPercentage = healthPercentage - currentPercentage; var k = 0.25; if (deltaPercentage > 0) { ac.restoreActorValue('health', deltaPercentage * currentMax * k); } else if (deltaPercentage < 0) { ac.damageActorValue('health', deltaPercentage * currentMax * k); } }; // Use global temp var to avoid allocation of an array on each translateTo var gTempTargetPos = [0, 0, 0]; var translateTo = function (refr, m) { var _a; var time = 0.2; if (m.isInJumpState || m.runMode !== "Standing") { time = 0.2; } // Local lag compensation // TODO: Remove "|| 0" hack (added to support old MpClientPlugin) var distanceAdd = (m.speed || 0) * time; var direction = m.rot[2] + m.direction; gTempTargetPos[0] = m.pos[0]; gTempTargetPos[1] = m.pos[1]; gTempTargetPos[2] = m.pos[2]; // We do not want to add pos in case of standing-jumping if (m.runMode !== "Standing") { gTempTargetPos[0] += Math.sin(direction / 180 * Math.PI) * distanceAdd; gTempTargetPos[1] += Math.cos(direction / 180 * Math.PI) * distanceAdd; } var refrRealPos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getPos(refr); var distance = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getDistance(refrRealPos, gTempTargetPos); var speed = distance / time; var angleDiff = Math.abs(m.rot[2] - refr.getAngleZ()); if (m.runMode !== "Standing" || m.isInJumpState || _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getDistanceNoZ(refrRealPos, gTempTargetPos) > 8 || angleDiff > 80 || ((_a = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr)) === null || _a === void 0 ? void 0 : _a.getSitState()) === 3) { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (actor && actor.getActorValue("Variable10") < -999) { return; } if (!actor || !actor.isDead()) { refr.translateTo(gTempTargetPos[0], gTempTargetPos[1], gTempTargetPos[2], m.rot[0], m.rot[1], m.rot[2], speed, 0); } } }; var teleportIfNeed = function (refr, m) { if (isInDifferentWorldOrCell(refr, m.worldOrCell) || (!refr.is3DLoaded() && isInDifferentExteriorCell(refr, m.pos))) { throw new _lib_errors__WEBPACK_IMPORTED_MODULE_1__.RespawnNeededError("needs to be respawned"); } return false; }; var cellWidth = 4096; var isInDifferentExteriorCell = function (refr, pos) { var currentPos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getPos(refr); var playerPos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getPos(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer()); var targetDistanceToPlayer = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getDistance(playerPos, pos); var currentDistanceToPlayer = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getDistance(playerPos, currentPos); return currentDistanceToPlayer > cellWidth && targetDistanceToPlayer <= cellWidth; }; var isInDifferentWorldOrCell = function (refr, worldOrCell) { return worldOrCell !== _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.getWorldOrCell(refr); }; /***/ }), /***/ "./src/sync/movementGet.ts": /*!*********************************!*\ !*** ./src/sync/movementGet.ts ***! \*********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getMovement: () => (/* binding */ getMovement) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); var PlayerCharacterSpeedCalculator = /** @class */ (function () { function PlayerCharacterSpeedCalculator() { } PlayerCharacterSpeedCalculator.savePosition = function (pos, worldOrCell) { this.lastPcPos = pos; this.lastPcPosCheck = Date.now(); this.lastPcWorldOrCell = worldOrCell; }; PlayerCharacterSpeedCalculator.getSpeed = function (currentPos, worldOrCell) { if (this.lastPcPosCheck === -1) { return 0; } var timeDeltaSec = (Date.now() - this.lastPcPosCheck) / 1000; if (timeDeltaSec > 5) return 0; // Too inaccurate if (timeDeltaSec === 0) return 0; // Division by zero if (worldOrCell !== this.lastPcWorldOrCell) { return 0; } var distance = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getDistance(currentPos, this.lastPcPos); return distance / timeDeltaSec; }; PlayerCharacterSpeedCalculator.lastPcPos = [0, 0, 0]; PlayerCharacterSpeedCalculator.lastPcPosCheck = -1; PlayerCharacterSpeedCalculator.lastPcWorldOrCell = 0; return PlayerCharacterSpeedCalculator; }()); var getMovement = function (refr, form) { var _a; var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); // It is running for ObjectReferences because Standing // Doesn't lead to translateTo call var runMode = ac ? getRunMode(ac) : "Running"; var healthPercentage = ac && ac.getActorValuePercentage("health"); if (ac && ac.isDead()) { healthPercentage = 0; } var lookAt = undefined; if (refr.getFormID() !== 0x14) { var combatTarget = ac === null || ac === void 0 ? void 0 : ac.getCombatTarget(); if (combatTarget) { lookAt = [ combatTarget.getPositionX(), combatTarget.getPositionY(), combatTarget.getPositionZ(), ]; } } var pos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getPos(refr); var speed; if (refr.getFormID() !== 0x14) { speed = refr.getAnimationVariableFloat("SpeedSampled"); } else { // Real players often run into the wall. // We need to have zero speed in this case. SpeedSampled doesn't help var w = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getWorldOrCell(refr); speed = PlayerCharacterSpeedCalculator.getSpeed(pos, w); PlayerCharacterSpeedCalculator.savePosition(pos, w); // It's unrealistic speed. It still may happen due to teleports if (speed > 2000) { speed = 0; } } var worldOrCell = refr.getWorldSpace() || refr.getParentCell(); // Eldervale Parte 2 (Opción D, PROTOTIPO): si ESTE jugador local está montado (su caballo // CLIENT-LOCAL de la Parte 1), reportamos el BASE id del caballo (formid base, universal en // todos los clientes). Cada observador spawnea su PROPIO caballo local con ese base y nos sienta // encima. Reusamos el campo vehicleFormId como "baseId" SOLO en el prototipo; el consumidor en // movementApply lo interpreta así. (El diseño final usará un campo mountedBaseId propio.) var vehicleFormId = undefined; if (ac && refr.getFormID() === 0x14 && ac.isOnMount()) { try { // La montura ACTUAL (el caballo cuenta como furniture) -> más fiable que // getPlayersLastRiddenHorse (que puede quedar stale tras cambiar de montura). var mount = ac.getFurnitureReference(); var base = mount ? mount.getBaseObject() : null; if (base) { var baseId = base.getFormID() >>> 0; if (baseId > 0) vehicleFormId = baseId; } } catch (e) { vehicleFormId = undefined; } } return { worldOrCell: (worldOrCell === null || worldOrCell === void 0 ? void 0 : worldOrCell.getFormID()) || 0, pos: pos, rot: [refr.getAngleX(), refr.getAngleY(), refr.getAngleZ()], runMode: runMode, direction: runMode !== "Standing" ? 360 * refr.getAnimationVariableFloat("Direction") : 0, isInJumpState: !!(ac && ac.getAnimationVariableBool("bInJumpState")), isSneaking: !!(ac && isSneaking(ac)), isBlocking: !!(ac && ac.getAnimationVariableBool("IsBlocking")), isWeapDrawn: !!(ac && ac.isWeaponDrawn()), isDead: ((_a = form === null || form === void 0 ? void 0 : form.isDead) !== null && _a !== void 0 ? _a : false) || !!(ac && ac.isDead()), healthPercentage: healthPercentage || 0, lookAt: lookAt, speed: speed, vehicleFormId: vehicleFormId }; }; var isSneaking = function (ac) { return ac.isSneaking() || ac.getAnimationVariableBool("IsSneaking"); }; var getRunMode = function (ac) { if (ac.isSprinting()) { return "Sprinting"; } var speed = ac.getAnimationVariableFloat("SpeedSampled"); if (!speed) { return "Standing"; } var furniture = ac.getFurnitureReference(); if (furniture !== null) return "Standing"; // TODO: Sitting? var isRunning = true; if (ac.getFormID() == 0x14) { if (!skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.isPlayerRunningEnabled() || speed < 150) isRunning = false; } else { if (!ac.isRunning() || speed < 150) { isRunning = false; } } if (ac.getAnimationVariableFloat("IsBlocking")) { isRunning = isSneaking(ac); } var carryWeight = ac.getActorValue("CarryWeight"); var totalItemWeight = ac.getTotalItemWeight(); if (carryWeight < totalItemWeight) { isRunning = false; } return isRunning ? "Running" : "Walking"; }; /***/ }), /***/ "./src/sync/spell.ts": /*!***************************!*\ !*** ./src/sync/spell.ts ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ learnSpells: () => (/* binding */ learnSpells), /* harmony export */ removeAllSpells: () => (/* binding */ removeAllSpells) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); var removeAllSpells = function (actor) { var spellToRemove = new Array(); for (var i = 0; i < actor.getSpellCount(); i++) { var spell = actor.getNthSpell(i); if (spell) { spellToRemove.push(spell); } } for (var _i = 0, spellToRemove_1 = spellToRemove; _i < spellToRemove_1.length; _i++) { var spell = spellToRemove_1[_i]; var removeResult = actor.removeSpell(spell); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("removeResult: ".concat(removeResult, ", spellIdToRemove: ").concat(spell .getFormID() .toString(16), ", spellName: ").concat(spell.getName())); } }; var learnSpells = function (actor, spellsIds) { for (var _i = 0, spellsIds_1 = spellsIds; _i < spellsIds_1.length; _i++) { var spellId = spellsIds_1[_i]; var spell = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Spell.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(spellId)); if (spell) { var addResult = actor.addSpell(spell, false); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("addResult: ".concat(addResult, ", spellIdToLearn: ").concat(spell .getFormID() .toString(16), ", spellName: ").concat(spell.getName())); } } }; /***/ }), /***/ "./src/version.ts": /*!************************!*\ !*** ./src/version.ts ***! \************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ requiredVersion: () => (/* binding */ requiredVersion), /* harmony export */ verifyVersion: () => (/* binding */ verifyVersion) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); var requiredVersion = '2.9.0'; var realVersion = typeof skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.getPlatformVersion === 'function' ? (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.getPlatformVersion)() : 'unknown'; // TODO: no one actually calls this function. make a service var verifyVersion = function () { if (!requiredVersion.includes(realVersion)) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Debug.messageBox("You need to have on of those SkyrimPlatform versions ".concat(JSON.stringify(requiredVersion), " to join this server. Your current version is ").concat(realVersion)); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.waitMenuMode(0.5).then(function () { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.on)('update', function () { if (!skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Ui.isMenuOpen('MessageBoxMenu')) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.quitToMainMenu(); } }); }); } }; /***/ }), /***/ "./src/view/formView.ts": /*!******************************!*\ !*** ./src/view/formView.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FormView: () => (/* binding */ FormView), /* harmony export */ getScreenResolution: () => (/* binding */ getScreenResolution) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _sync_animation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../sync/animation */ "./src/sync/animation.ts"); /* harmony import */ var _sync_appearance__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../sync/appearance */ "./src/sync/appearance.ts"); /* harmony import */ var _sync_equipment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../sync/equipment */ "./src/sync/equipment.ts"); /* harmony import */ var _lib_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../lib/errors */ "./src/lib/errors.ts"); /* harmony import */ var _sync_movementApply__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../sync/movementApply */ "./src/sync/movementApply.ts"); /* harmony import */ var _spawnProcess__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./spawnProcess */ "./src/view/spawnProcess.ts"); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); /* harmony import */ var _playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./playerCharacterDataHolder */ "./src/view/playerCharacterDataHolder.ts"); /* harmony import */ var _sync_movementGet__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../sync/movementGet */ "./src/sync/movementGet.ts"); /* harmony import */ var _hostAttempts__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./hostAttempts */ "./src/view/hostAttempts.ts"); /* harmony import */ var _modelApplyUtils__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./modelApplyUtils */ "./src/view/modelApplyUtils.ts"); /* harmony import */ var _worldViewMisc__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../services/spApiInteractor */ "./src/services/spApiInteractor.ts"); /* harmony import */ var _services_services_worldCleanerService__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../services/services/worldCleanerService */ "./src/services/services/worldCleanerService.ts"); /* harmony import */ var _services_services_gamemodeUpdateService__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../services/services/gamemodeUpdateService */ "./src/services/services/gamemodeUpdateService.ts"); var _screenResolution; var getScreenResolution = function () { if (!_screenResolution) { _screenResolution = { width: skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.getINIInt("iSize W:Display"), height: skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.getINIInt("iSize H:Display"), }; } return _screenResolution; }; var FormView = /** @class */ (function () { function FormView(remoteRefrId) { this.remoteRefrId = remoteRefrId; this.lastHarvestedApply = 0; this.lastOpenApply = 0; this.isSetNodeTextureSetApplied = false; this.isSetNodeScaleApplied = false; this.refrId = 0; this.ready = false; this.animState = this.getDefaultAnimState(); this.movState = { lastNumChanges: 0, lastApply: 0, lastRehost: 0, everApplied: false, }; this.appearanceState = this.getDefaultAppearanceState(); this.eqState = this.getDefaultEquipState(); this.appearanceBasedBaseId = 0; this.leveledBaseId = 0; this.isOnScreen = false; this.lastPcWorldOrCell = 0; this.lastWorldOrCell = 0; this.spawnMoment = 0; this.wasHostedByOther = undefined; this.state = {}; this.localImmortal = false; this.textNameId = undefined; } FormView.prototype.update = function (model) { var _this = this; var _a, _b, _c, _d, _e, _f, _g, _h; // Other players mutate into PC clones when moving to another location if (model.movement) { if (!this.lastWorldOrCell) this.lastWorldOrCell = model.movement.worldOrCell; if (this.lastWorldOrCell !== model.movement.worldOrCell) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("[1] worldOrCell changed, destroying FormView ".concat(this.lastWorldOrCell.toString(16), " => ").concat(model.movement.worldOrCell.toString(16))); this.lastWorldOrCell = model.movement.worldOrCell; this.destroy(); this.refrId = 0; this.appearanceBasedBaseId = 0; return; } } // Don't spawn dead actors if not already if (model.isDead) { if (this.refrId === 0) { return; } } // Players with different worldOrCell should be invisible if (model.movement) { var worldOrCell = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_7__.ObjectReferenceEx.getWorldOrCell(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer()); if (worldOrCell !== 0 && model.movement.worldOrCell !== worldOrCell) { this.destroy(); this.refrId = 0; return; } } // Apply appearance before base form selection to prevent double-spawn if (model.appearance || (!model.appearance && this.appearanceState.appearance)) { if (!this.appearanceState.appearance || model.numAppearanceChanges !== this.appearanceState.lastNumChanges) { // Both non-null if (model.appearance && this.appearanceState.appearance) { var modelAppearanceCopy = JSON.parse(JSON.stringify(model.appearance)); var stateAppearanceCopy = JSON.parse(JSON.stringify(this.appearanceState.appearance)); modelAppearanceCopy.name = ""; stateAppearanceCopy.name = ""; var equalWithoutNames = JSON.stringify(modelAppearanceCopy) === JSON.stringify(stateAppearanceCopy); if (equalWithoutNames) { // Change name inplace var refr_1 = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(this.refrId)); (_a = refr_1 === null || refr_1 === void 0 ? void 0 : refr_1.getBaseObject()) === null || _a === void 0 ? void 0 : _a.setName(model.appearance.name); refr_1 === null || refr_1 === void 0 ? void 0 : refr_1.setDisplayName(model.appearance.name, true); //printConsole("Appearance updated, changing name inplace"); } else { // Force re-apply appearance on the next getAppearanceBasedBase call this.appearanceBasedBaseId = 0; //printConsole("Appearance updated"); } } else { // Force re-apply appearance on the next getAppearanceBasedBase call this.appearanceBasedBaseId = 0; //printConsole("Appearance updated"); } this.appearanceState.appearance = model.appearance || null; this.appearanceState.lastNumChanges = model.numAppearanceChanges; } } var refId = model.refrId && model.refrId < 0xff000000 ? model.refrId : undefined; if (refId) { if (this.refrId !== refId) { this.destroy(); this.refrId = model.refrId; this.ready = true; var refr_2 = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(this.refrId)); if (refr_2) { var base = refr_2.getBaseObject(); if (base) { _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_7__.ObjectReferenceEx.dealWithRef(refr_2, base); } } } } else { var templateChain = model.templateChain; // There is no place for random/leveling in 1-sized chain // Just spawn an NPC, do not generate a temporary TESNPC form if ((templateChain === null || templateChain === void 0 ? void 0 : templateChain.length) === 1) { templateChain = undefined; } // TODO: getLeveledBase crashes too often ATM var base = null; //Game.getFormEx(this.getLeveledBase(templateChain)); if (base === null) { base = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(model.baseId || NaN); } if (base === null) { base = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(this.getAppearanceBasedBase()); } if (base === null) { return; } var refr_3 = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(this.refrId)); var respawnRequired = false; if (!refr_3) { respawnRequired = true; } else if (!refr_3.getBaseObject()) { respawnRequired = true; } else if (refr_3.getBaseObject().getFormID() !== base.getFormID()) { respawnRequired = true; } if (respawnRequired) { this.destroy(); var player_1 = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); var spawnMethodOriginal = { spawn: function (baseForm, _spawnPosition, _spawnRotation) { return player_1.placeAtMe(baseForm, 1, true, true); }, triggerSpawnProcess: function (spawningRefr, spawnPosition, appearance, callback) { new _spawnProcess__WEBPACK_IMPORTED_MODULE_6__.SpawnProcess(appearance, spawnPosition, spawningRefr.getFormID(), callback); } }; var spawnMethodStub = { spawn: function (baseForm, spawnPosition, spawnRotation) { var f = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["formViewFunc1"]; var ref = f(baseForm, spawnPosition, spawnRotation); return ref; }, triggerSpawnProcess: function (spawningRefr, spawnPosition, appearance, callback) { var f = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["formViewFunc2"]; f(spawningRefr, spawnPosition, appearance, callback); } }; var spawnUsingStubMethod = base.getType() === 43 /* FormType.NPC */ && !this.appearanceState.appearance && skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["formViewFunc1Set"] === true && skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["formViewFunc2Set"] === true; var spawnMethod = spawnUsingStubMethod ? spawnMethodStub : spawnMethodOriginal; if (model.movement) { refr_3 = spawnMethod.spawn(base, model.movement.pos, model.movement.rot); } else { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("model.movement was " + model.movement); } this.state = {}; delete this.wasHostedByOther; if (base.getType() !== 43 /* FormType.NPC */) { refr_3 === null || refr_3 === void 0 ? void 0 : refr_3.setAngle(((_b = model.movement) === null || _b === void 0 ? void 0 : _b.rot[0]) || 0, ((_c = model.movement) === null || _c === void 0 ? void 0 : _c.rot[1]) || 0, ((_d = model.movement) === null || _d === void 0 ? void 0 : _d.rot[2]) || 0); } else { var race = (_f = (_e = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr_3)) === null || _e === void 0 ? void 0 : _e.getRace()) === null || _f === void 0 ? void 0 : _f.getFormID(); var draugrRace = 0xd53; var falmerRace = 0x131f4; var chaurusRace = 0x131eb; var frostbiteSpiderRaceGiant = 0x4e507; var frostbiteSpiderRaceLarge = 0x53477; var dwarvenCenturionRace = 0x131f1; var dwarvenSphereRace = 0x131f2; var dwarvenSpiderRace = 0x131f3; var sprigganRace = 0x2013b77; var sprigganRace2 = 0xf3903; var sprigganRace3 = 0x13204; var sprigganRace4 = 0x401b644; var sprigganRace5 = 0x9aa44; var wolfRace = 0x1320a; // potential masterambushscript if (race === draugrRace || race === falmerRace || race === chaurusRace || race === frostbiteSpiderRaceGiant || race === frostbiteSpiderRaceLarge || race === dwarvenCenturionRace || race === dwarvenSphereRace || race === dwarvenSpiderRace || race === sprigganRace || race === sprigganRace2 || race === sprigganRace3 || race === sprigganRace4 || race === sprigganRace5 || race === wolfRace) { (_g = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr_3)) === null || _g === void 0 ? void 0 : _g.setActorValue("Aggression", 2); } } if (refr_3 !== null) { _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_13__.SpApiInteractor.getControllerInstance().lookupListener(_services_services_worldCleanerService__WEBPACK_IMPORTED_MODULE_14__.WorldCleanerService).modWcProtection(refr_3.getFormID(), 1); } // TODO: reset all states? this.eqState = this.getDefaultEquipState(); this.animState = this.getDefaultAnimState(); this.ready = false; var spawnPos = void 0; if (model.movement) { spawnPos = model.movement.pos; // printConsole("Spawn NPC at movement.pos"); } else { spawnPos = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_7__.ObjectReferenceEx.getPos(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer()); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Spawn NPC at player pos"); } if (refr_3) { spawnMethod.triggerSpawnProcess(refr_3, spawnPos, model.appearance || null, function () { _this.ready = true; _this.spawnMoment = Date.now(); }); } else { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Unable to triggerSpawnProcess for null refr"); } if (model.appearance && model.appearance.name) { refr_3 === null || refr_3 === void 0 ? void 0 : refr_3.setDisplayName("" + model.appearance.name, true); } (_h = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr_3)) === null || _h === void 0 ? void 0 : _h.setActorValue("attackDamageMult", 0); } this.refrId = refr_3.getFormID(); } if (!this.ready) { return; } var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(this.refrId)); if (refr) { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (actor && !this.localImmortal) { actor.startDeferredKill(); actor.setActorValue("health", 1000000); actor.setActorValue("magicka", 1000000); this.localImmortal = true; } this.applyAll(refr, model); var gamemodeUpdateService = _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_13__.SpApiInteractor.getControllerInstance().lookupListener(_services_services_gamemodeUpdateService__WEBPACK_IMPORTED_MODULE_15__.GamemodeUpdateService); gamemodeUpdateService.updateNeighbor(refr, model, this.state); } }; FormView.prototype.destroy = function () { this.isOnScreen = false; this.spawnMoment = 0; var refrId = this.refrId; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)("update", function () { (0,_sync_movementApply__WEBPACK_IMPORTED_MODULE_5__.destroyProxyMountForRider)(refrId); // Eldervale P2: limpiar el caballo-proxy local de este jinete if (refrId >= 0xff000000) { var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId)); if (refr) { refr.delete(); } _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_13__.SpApiInteractor.getControllerInstance().lookupListener(_services_services_worldCleanerService__WEBPACK_IMPORTED_MODULE_14__.WorldCleanerService).modWcProtection(refrId, -1); var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (ac) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setWeaponDrawnMode(ac, -1); } } }); this.localImmortal = false; this.removeNickname(); }; FormView.prototype.applyAll = function (refr, model) { var _a, _b, _c; var forcedWeapDrawn = null; if (_playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__.PlayerCharacterDataHolder.getCrosshairRefId() === this.refrId) { this.lastHarvestedApply = 0; this.lastOpenApply = 0; } var now = Date.now(); if (now - this.lastHarvestedApply > 666) { this.lastHarvestedApply = now; _modelApplyUtils__WEBPACK_IMPORTED_MODULE_11__.ModelApplyUtils.applyModelIsHarvested(refr, !!model.isHarvested); } if (now - this.lastOpenApply > 133) { this.lastOpenApply = now; _modelApplyUtils__WEBPACK_IMPORTED_MODULE_11__.ModelApplyUtils.applyModelIsOpen(refr, !!model.isOpen); } if (!this.isSetNodeScaleApplied) { this.isSetNodeScaleApplied = true; _modelApplyUtils__WEBPACK_IMPORTED_MODULE_11__.ModelApplyUtils.applyModelNodeScale(refr, model.setNodeScale); } if (!this.isSetNodeTextureSetApplied) { this.isSetNodeTextureSetApplied = true; _modelApplyUtils__WEBPACK_IMPORTED_MODULE_11__.ModelApplyUtils.applyModelNodeTextureSet(refr, model.setNodeTextureSet); } if (model.inventory && _playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__.PlayerCharacterDataHolder.getCrosshairRefId() == this.refrId && !(0,_sync_equipment__WEBPACK_IMPORTED_MODULE_3__.isBadMenuShown)()) { // Do not let actors breaking their equipment via inventory apply // However, actually, actors do not have inventory in their models // Except your clone. if (!skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr)) { _modelApplyUtils__WEBPACK_IMPORTED_MODULE_11__.ModelApplyUtils.applyModelInventory(refr, model.inventory); model.inventory = undefined; } } if (model.animation) { if (model.animation.animEventName === "SkympFakeUnequip") { forcedWeapDrawn = false; } else if (model.animation.animEventName === "SkympFakeEquip") { forcedWeapDrawn = true; } } // TODO: make host service var hosted = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['hosted']; var alreadyHosted = false; if (Array.isArray(hosted)) { var remoteId = (0,_worldViewMisc__WEBPACK_IMPORTED_MODULE_12__.localIdToRemoteId)(this.refrId); if (hosted.includes(remoteId) || hosted.includes(remoteId + 0x100000000)) { alreadyHosted = true; } } (0,_sync_animation__WEBPACK_IMPORTED_MODULE_1__.setDefaultAnimsDisabled)(this.refrId, alreadyHosted ? false : true); if (alreadyHosted) { (_a = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr)) === null || _a === void 0 ? void 0 : _a.clearKeepOffsetFromActor(); } if (model.movement) { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (this.movState.lastApply && Date.now() - this.movState.lastApply > 1500) { if (Date.now() - this.movState.lastRehost > 1000) { this.movState.lastRehost = Date.now(); var remoteId = this.remoteRefrId; if (ac && ac.is3DLoaded()) { this.tryHostIfNeed(ac, remoteId); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("tryHostIfNeed - reason: not seeing movement for long time"); } } } if (+model.numMovementChanges !== this.movState.lastNumChanges || Date.now() - this.movState.lastApply > 2000) { this.movState.lastApply = Date.now(); if (model.isHostedByOther || !this.movState.everApplied) { var backup = model.movement.isWeapDrawn; if (forcedWeapDrawn === true || forcedWeapDrawn === false) { model.movement.isWeapDrawn = forcedWeapDrawn; } try { (0,_sync_movementApply__WEBPACK_IMPORTED_MODULE_5__.applyMovement)(refr, model.movement, !!model.isMyClone); } catch (e) { if (e instanceof _lib_errors__WEBPACK_IMPORTED_MODULE_4__.RespawnNeededError) { this.lastWorldOrCell = model.movement.worldOrCell; this.destroy(); this.refrId = 0; this.appearanceBasedBaseId = 0; return; } else { throw e; } } model.movement.isWeapDrawn = backup; this.movState.lastNumChanges = +model.numMovementChanges; this.movState.everApplied = true; } else { var remoteId = this.remoteRefrId; if (ac && remoteId && ac.is3DLoaded()) { ac.clearKeepOffsetFromActor(); // TODO: make host service var hosted_1 = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage['hosted']; var alreadyHosted_1 = false; if (Array.isArray(hosted_1)) { var remoteId_1 = (0,_worldViewMisc__WEBPACK_IMPORTED_MODULE_12__.localIdToRemoteId)(ac.getFormID()); if (hosted_1.includes(remoteId_1) || hosted_1.includes(remoteId_1 + 0x100000000)) { alreadyHosted_1 = true; } } if (!alreadyHosted_1) { if (this.tryHostIfNeed(ac, remoteId)) { // previously, we did this cleanup on each update // but I guess it's too expensive and can possibly hurt FPS skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.setWeaponDrawnMode(ac, -1); } } } } } } if (refr.is3DLoaded()) { if (model.animation) { (0,_sync_animation__WEBPACK_IMPORTED_MODULE_1__.applyAnimation)(refr, model.animation, this.animState); } // Use them only once, for spawning actors with correct animations this.animState.useAnimOverrides = false; } if (model.appearance) { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (actor && !_playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__.PlayerCharacterDataHolder.isInJumpState()) { if (_playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__.PlayerCharacterDataHolder.getWorldOrCell()) { if (this.lastPcWorldOrCell && _playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__.PlayerCharacterDataHolder.getWorldOrCell() !== this.lastPcWorldOrCell) { // Redraw tints if PC world/cell changed this.isOnScreen = false; } this.lastPcWorldOrCell = _playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_8__.PlayerCharacterDataHolder.getWorldOrCell(); } var headPos = [ skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.getNodeWorldPositionX(actor, "NPC Head [Head]", false), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.getNodeWorldPositionY(actor, "NPC Head [Head]", false), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.getNodeWorldPositionZ(actor, "NPC Head [Head]", false), ]; var screenPoint = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.worldPointToScreenPoint)(headPos)[0]; var isOnScreen = screenPoint[0] > 0 && screenPoint[1] > 0 && screenPoint[2] > 0 && screenPoint[0] < 1 && screenPoint[1] < 1 && screenPoint[2] < 1; if (isOnScreen != this.isOnScreen) { this.isOnScreen = isOnScreen; if (isOnScreen) { actor.queueNiNodeUpdate(); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer().queueNiNodeUpdate(); } } } } if (model.equipment) { if (this.eqState.lastNumChanges !== model.equipment.numChanges) { var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); // If we do not block inventory here, we will be able to reproduce the bug: // 1. Place ~90 bots and force them to reequip iron swords to the left hand (rate should be ~50ms) // 2. Open your inventory and reequip different items fast // 3. After 1-2 minutes close your inventory and see that HUD disappeared if (ac && !(0,_sync_equipment__WEBPACK_IMPORTED_MODULE_3__.isBadMenuShown)() && Date.now() - this.eqState.lastEqMoment > 500 && Date.now() - this.spawnMoment > -1 && this.spawnMoment > 0) { //if (this.spawnMoment > 0 && Date.now() - this.spawnMoment > 5000) { if ((0,_sync_equipment__WEBPACK_IMPORTED_MODULE_3__.applyEquipment)(ac, model.equipment)) { this.eqState.lastNumChanges = model.equipment.numChanges; } this.eqState.lastEqMoment = Date.now(); //} //const res: boolean = applyEquipment(ac, model.equipment); //if (res) this.eqState.lastNumChanges = model.equipment.numChanges; } } } if (FormView.isDisplayingNicknames && this.refrId && ((_b = model.appearance) === null || _b === void 0 ? void 0 : _b.name)) { var headPart = "NPC Head [Head]"; var maxNicknameDrawDistance = 1000; var playerActor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); var isVisibleByPlayer = !((_c = model.movement) === null || _c === void 0 ? void 0 : _c.isSneaking) && playerActor.getDistance(refr) <= maxNicknameDrawDistance && playerActor.hasLOS(refr) && !this.isSweetHidePerson(refr); if (isVisibleByPlayer) { var headScreenPos = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.worldPointToScreenPoint)([ skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.getNodeWorldPositionX(refr, headPart, false), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.getNodeWorldPositionY(refr, headPart, false), skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.getNodeWorldPositionZ(refr, headPart, false) + 32 ])[0]; var resolution = getScreenResolution(); var textXPos = Math.round(headScreenPos[0] * resolution.width); var textYPos = Math.round((1 - headScreenPos[1]) * resolution.height); if (!this.textNameId && headScreenPos[2] > 0) { this.textNameId = (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.createText)(textXPos, textYPos, refr.getDisplayName(), [1, 1, 1, 0.8]); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextSize)(this.textNameId, 0.5); _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_13__.SpApiInteractor.getControllerInstance().emitter.emit("nicknameCreate", { remoteRefrId: this.getRemoteRefrId(), textId: this.textNameId }); } else { var deleteNickname = headScreenPos[2] < 0; if (deleteNickname) { this.removeNickname(); } if (this.textNameId) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.setTextPos)(this.textNameId, textXPos, textYPos); } } } else { this.removeNickname(); } } else { this.removeNickname(); } }; FormView.prototype.isSweetHidePerson = function (refr) { var actor = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (!actor) { return false; } var keyword = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Keyword.getKeyword('SweetHidePerson'); return actor.wornHasKeyword(keyword); }; FormView.prototype.removeNickname = function () { if (this.textNameId) { _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_13__.SpApiInteractor.getControllerInstance().emitter.emit("nicknameDestroy", { remoteRefrId: this.getRemoteRefrId(), textId: this.textNameId }); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.destroyText)(this.textNameId); this.textNameId = undefined; } }; FormView.prototype.getAppearanceBasedBase = function () { var base = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ActorBase.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(this.appearanceBasedBaseId)); if (!base && this.appearanceState.appearance) { this.appearanceBasedBaseId = (0,_sync_appearance__WEBPACK_IMPORTED_MODULE_2__.applyAppearance)(this.appearanceState.appearance).getFormID(); } return this.appearanceBasedBaseId; }; FormView.prototype.getLeveledBase = function (templateChain) { if (templateChain === undefined) { return 0; } var str = templateChain.join(','); if (this.leveledBaseId === 0) { // @ts-ignore var leveledBase = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TESModPlatform.evaluateLeveledNpc(str); if (!leveledBase) { (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.printConsole)("Failed to evaluate leveled npc", str); } this.leveledBaseId = (leveledBase === null || leveledBase === void 0 ? void 0 : leveledBase.getFormID()) || 0; } return this.leveledBaseId; }; FormView.prototype.getDefaultEquipState = function () { return { lastNumChanges: 0, lastEqMoment: 0 }; }; ; FormView.prototype.getDefaultAppearanceState = function () { return { lastNumChanges: 0, appearance: null }; }; ; FormView.prototype.getDefaultAnimState = function () { return { lastNumChanges: 0, useAnimOverrides: true }; }; ; FormView.prototype.tryHostIfNeed = function (ac, remoteId) { var last = _hostAttempts__WEBPACK_IMPORTED_MODULE_10__.lastTryHost[remoteId]; if (!last || Date.now() - last >= 1000) { _hostAttempts__WEBPACK_IMPORTED_MODULE_10__.lastTryHost[remoteId] = Date.now(); if ((0,_sync_movementGet__WEBPACK_IMPORTED_MODULE_9__.getMovement)(ac).worldOrCell === (0,_sync_movementGet__WEBPACK_IMPORTED_MODULE_9__.getMovement)(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer()).worldOrCell) { (0,_hostAttempts__WEBPACK_IMPORTED_MODULE_10__.tryHost)(remoteId); return true; } } return false; }; ; FormView.prototype.getLocalRefrId = function () { return this.refrId; }; FormView.prototype.getRemoteRefrId = function () { return this.remoteRefrId; }; FormView.isDisplayingNicknames = true; return FormView; }()); /***/ }), /***/ "./src/view/formViewArray.ts": /*!***********************************!*\ !*** ./src/view/formViewArray.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FormViewArray: () => (/* binding */ FormViewArray) /* harmony export */ }); /* harmony import */ var _formView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./formView */ "./src/view/formView.ts"); /* harmony import */ var _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../services/spApiInteractor */ "./src/services/spApiInteractor.ts"); /* harmony import */ var _services_services_gamemodeUpdateService__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../services/services/gamemodeUpdateService */ "./src/services/services/gamemodeUpdateService.ts"); var FormViewArray = /** @class */ (function () { function FormViewArray() { this.formViews = new Array(); } FormViewArray.prototype.updateForm = function (form, i) { var view = this.formViews[i]; if (!view) { this.formViews[i] = new _formView__WEBPACK_IMPORTED_MODULE_0__.FormView(form.refrId); } else { view.update(form); } }; FormViewArray.prototype.destroyForm = function (i) { var formView = this.formViews[i]; if (formView === undefined) { return; } formView.destroy(); this.formViews[i] = undefined; }; FormViewArray.prototype.resize = function (newSize) { if (this.formViews.length > newSize) { this.formViews.slice(newSize).forEach(function (v) { return v && v.destroy(); }); } this.formViews.length = newSize; }; FormViewArray.prototype.updateAll = function (model, showMe, isCloneView) { var gamemodeUpdateService = _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_1__.SpApiInteractor.getControllerInstance().lookupListener(_services_services_gamemodeUpdateService__WEBPACK_IMPORTED_MODULE_2__.GamemodeUpdateService); gamemodeUpdateService.setFormViewArray(this); var forms = model.forms; var n = forms.length; for (var i = 0; i < n; ++i) { var form = forms[i]; if (!form || (model.playerCharacterFormIdx === i && !showMe)) { this.destroyForm(i); continue; } var realPos = undefined; var offset = model.playerCharacterFormIdx === i || isCloneView; if (offset && form.movement) { realPos = form.movement.pos; form.movement.pos = [ realPos[0] + 128, realPos[1] + 128, realPos[2], ]; } if (isCloneView) { // Prevent using the same refr by normal and clone views if (!form.refrId || form.refrId >= 0xff000000) { var backup = form.isHostedByOther; form.isHostedByOther = true; // TODO: Explain why do not GamemodeApiSupport.setI(i); here this.updateForm(form, i); form.isHostedByOther = backup; } } else { gamemodeUpdateService.setI(i); this.updateForm(form, i); } if (offset && form.movement && realPos) { form.movement.pos = realPos; } } }; FormViewArray.prototype.syncFormView = function (model, showMe) { for (var i = 0; i < model.forms.length; ++i) { if (!model.forms[i] || (model.playerCharacterFormIdx === i && !showMe)) { this.destroyForm(i); continue; } } }; FormViewArray.prototype.getRemoteRefrId = function (clientsideRefrId) { if (clientsideRefrId < 0xff000000) throw new Error("This function is only for 0xff forms"); var formView = this.formViews.find(function (formView) { return formView && formView.getLocalRefrId() === clientsideRefrId; }); return formView ? formView.getRemoteRefrId() : 0; }; FormViewArray.prototype.getLocalRefrId = function (remoteRefrId) { if (remoteRefrId < 0xff000000) throw new Error("This function is only for 0xff forms"); var formView = this.formViews.find(function (formView) { return formView && formView.getRemoteRefrId() === remoteRefrId; }); return formView ? formView.getLocalRefrId() : 0; }; FormViewArray.prototype.getNthFormView = function (i) { return this.formViews[i]; }; FormViewArray.prototype.getFormViewsArrayLength = function () { return this.formViews.length; }; return FormViewArray; }()); /***/ }), /***/ "./src/view/hostAttempts.ts": /*!**********************************!*\ !*** ./src/view/hostAttempts.ts ***! \**********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ lastTryHost: () => (/* binding */ lastTryHost), /* harmony export */ nextHostAttempt: () => (/* binding */ nextHostAttempt), /* harmony export */ tryHost: () => (/* binding */ tryHost) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["hostAttempts"] = []; var tryHost = function (targetRemoteId) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["hostAttempts"].push(targetRemoteId); }; var nextHostAttempt = function () { var arr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["hostAttempts"]; if (arr.length === 0) { return undefined; } return arr.shift(); }; var lastTryHost = {}; /***/ }), /***/ "./src/view/modelApplyUtils.ts": /*!*************************************!*\ !*** ./src/view/modelApplyUtils.ts ***! \*************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ModelApplyUtils: () => (/* binding */ ModelApplyUtils) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _sync_inventory__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../sync/inventory */ "./src/sync/inventory.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../logging */ "./src/logging.ts"); // For 0xff000000+ used from FormView // For objects from master files used directly from remoteServer.ts var ModelApplyUtils = /** @class */ (function () { function ModelApplyUtils() { } ModelApplyUtils.applyModelInventory = function (refr, inventory) { (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_1__.applyInventory)(refr, inventory, false, true); }; ModelApplyUtils.applyModelIsOpen = function (refr, isOpen) { var _a; refr.setOpen(isOpen); // See also objectReferenceEx.ts var caveGSecretDoor01 = 0x6f703; // TODO: add more activators to support more cells var parentActivatorId = 0x460ca; if (((_a = refr.getBaseObject()) === null || _a === void 0 ? void 0 : _a.getFormID()) === caveGSecretDoor01) { var openOrOpening = [1, 2].includes(refr.getOpenState()); if (openOrOpening) { if (!isOpen) { refr.activate(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getForm(parentActivatorId)), false); } } if (!openOrOpening) { if (isOpen) { refr.activate(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getForm(parentActivatorId)), false); } } } }; ModelApplyUtils.applyModelIsDisabled = function (refr, disabled) { var wasDisabled = refr.isDisabled(); if (wasDisabled == disabled) { return; } if (disabled) { refr.disable(false); } else { refr.enable(true); } }; ModelApplyUtils.applyModelIsHarvested = function (refr, isHarvested) { var base = refr.getBaseObject(); if (base) { var t = base.getType(); if (t == 38 /* FormType.Tree */ || t == 39 /* FormType.Flora */) { var wasHarvested = refr.isHarvested(); if (isHarvested != wasHarvested) { var ac = null; if (isHarvested) { for (var i = 0; i < 20; ++i) { ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.findRandomActor(refr.getPositionX(), refr.getPositionY(), refr.getPositionZ(), 10000); if (ac && ac.getFormID() !== 0x14) { break; } } } if (isHarvested && ac && ac.getFormID() !== 0x14) { refr.activate(ac, true); } else { refr.setHarvested(isHarvested); var id_1 = refr.getFormID(); refr.disable(false).then(function () { var restoredRefr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(id_1)); if (restoredRefr) { restoredRefr.enable(false); } }); } } } else { var wasHarvested = refr.isDisabled(); if (isHarvested != wasHarvested) { if (isHarvested) { var id_2 = refr.getFormID(); refr.disable(false).then(function () { var restoredRefr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(id_2)); if (restoredRefr && !restoredRefr.isDisabled()) { restoredRefr.delete(); // Deletion takes time, so in practice this would be called a lot of times } }); } else { refr.enable(true); } } } } }; ModelApplyUtils.applyModelNodeTextureSet = function (refr, setNodeTextureSet) { if (setNodeTextureSet) { setNodeTextureSet.forEach(function (element) { var firstPerson = false; var textureSet = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.TextureSet.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(element.textureSetId)); if (textureSet !== null) { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.setNodeTextureSet(refr, element.nodeName, textureSet, firstPerson); (0,_logging__WEBPACK_IMPORTED_MODULE_2__.logTrace)("ModelApplyUtils", refr.getFormID().toString(16), "Applied texture set", element.textureSetId.toString(16), "to", element.nodeName); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_2__.logError)("ModelApplyUtils", refr.getFormID().toString(16), "Failed to apply texture set", element.textureSetId.toString(16), "to", element.nodeName); } }); } }; ModelApplyUtils.applyModelNodeScale = function (refr, setNodeScale) { if (setNodeScale) { setNodeScale.forEach(function (element) { var firstPerson = false; skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.NetImmerse.setNodeScale(refr, element.nodeName, element.scale, firstPerson); (0,_logging__WEBPACK_IMPORTED_MODULE_2__.logTrace)("ModelApplyUtils", refr.getFormID().toString(16), "Applied node scale", element.scale, "to", element.nodeName); }); } }; return ModelApplyUtils; }()); /***/ }), /***/ "./src/view/playerCharacterDataHolder.ts": /*!***********************************************!*\ !*** ./src/view/playerCharacterDataHolder.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PlayerCharacterDataHolder: () => (/* binding */ PlayerCharacterDataHolder) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); var PlayerCharacterDataHolder = /** @class */ (function () { function PlayerCharacterDataHolder() { } PlayerCharacterDataHolder.updateData = function () { var _a; var player = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getPlayer(); if (!player) { return; } this.inJumpState = player.getAnimationVariableBool("bInJumpState"); this.worldOrCell = _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_1__.ObjectReferenceEx.getWorldOrCell(player); this.crosshairRefId = ((_a = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getCurrentCrosshairRef()) === null || _a === void 0 ? void 0 : _a.getFormID()) || 0; }; PlayerCharacterDataHolder.isInJumpState = function () { return this.inJumpState; }; PlayerCharacterDataHolder.getWorldOrCell = function () { return this.worldOrCell; }; PlayerCharacterDataHolder.getCrosshairRefId = function () { return this.crosshairRefId; }; PlayerCharacterDataHolder.inJumpState = false; PlayerCharacterDataHolder.worldOrCell = 0; PlayerCharacterDataHolder.crosshairRefId = 0; return PlayerCharacterDataHolder; }()); /***/ }), /***/ "./src/view/spawnProcess.ts": /*!**********************************!*\ !*** ./src/view/spawnProcess.ts ***! \**********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SpawnProcess: () => (/* binding */ SpawnProcess) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _sync_appearance__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../sync/appearance */ "./src/sync/appearance.ts"); /* harmony import */ var _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../extensions/objectReferenceEx */ "./src/extensions/objectReferenceEx.ts"); var SpawnProcess = /** @class */ (function () { function SpawnProcess(appearance, pos, refrId, callback) { var _this = this; this.callback = callback; var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId)); if (!refr || refr.getFormID() !== refrId) { return; } refr.setPosition.apply(refr, pos).then(function () { return _this.enable(appearance, refrId); }); } SpawnProcess.prototype.enable = function (appearance, refrId) { var _this = this; var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId)); if (!refr || refr.getFormID() !== refrId) { return; } var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (ac && appearance) { (0,_sync_appearance__WEBPACK_IMPORTED_MODULE_1__.applyTints)(ac, appearance); } refr.enable(false).then(function () { return _this.resurrect(refrId); }); }; SpawnProcess.prototype.resurrect = function (refrId) { var _this = this; var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId)); if (!refr || refr.getFormID() !== refrId) { return; } var ac = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Actor.from(refr); if (ac) { return ac.resurrect().then(function () { _this.callback(); }); } _extensions_objectReferenceEx__WEBPACK_IMPORTED_MODULE_2__.ObjectReferenceEx.dealWithRef(refr, refr.getBaseObject()); return refr.setMotionType(4 /* MotionType.Keyframed */, true).then(this.callback); }; return SpawnProcess; }()); /***/ }), /***/ "./src/view/worldView.ts": /*!*******************************!*\ !*** ./src/view/worldView.ts ***! \*******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorldView: () => (/* binding */ WorldView) /* harmony export */ }); /* harmony import */ var _formViewArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./formViewArray */ "./src/view/formViewArray.ts"); /* harmony import */ var _playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./playerCharacterDataHolder */ "./src/view/playerCharacterDataHolder.ts"); /* harmony import */ var _services_services_clientListener__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../services/services/clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../logging */ "./src/logging.ts"); /* harmony import */ var _services_services_singlePlayerService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../services/services/singlePlayerService */ "./src/services/services/singlePlayerService.ts"); /* harmony import */ var _services_services_remoteServer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../services/services/remoteServer */ "./src/services/services/remoteServer.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var WorldView = /** @class */ (function (_super) { __extends(WorldView, _super); function WorldView(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; controller.on("update", function () { return _this.onUpdate(); }); controller.once("update", function () { return _this.onceUpdate(); }); _this.state = _this.makeEmptyState(); var oldView = _this.sp.storage["view"]; // can't use instanceof here because each hot reload creates a new class _this.oldView = typeof oldView === "object" ? oldView : undefined; _this.sp.storage["view"] = _this; return _this; } WorldView.prototype.getRemoteRefrId = function (clientsideRefrId) { return this.state.formViews.getRemoteRefrId(clientsideRefrId); }; WorldView.prototype.getLocalRefrId = function (remoteRefrId) { return this.state.formViews.getLocalRefrId(remoteRefrId); }; WorldView.prototype.syncFormArray = function (model) { var settings = this.sp.settings; var showMe = settings['skymp5-client']['show-me']; this.state.formViews.syncFormView(model, !!showMe); }; WorldView.prototype.destroy = function () { this.state.formViews.resize(0); this.state.cloneFormViews.resize(0); // Recenrly added, not tested if it's needed this.state = this.makeEmptyState(); }; WorldView.prototype.getFormViews = function () { return this.state.formViews; }; WorldView.prototype.onUpdate = function () { this.resetAllFormViewsIfPlayerChangedWorld(); var singlePlayerService = this.controller.lookupListener(_services_services_singlePlayerService__WEBPACK_IMPORTED_MODULE_4__.SinglePlayerService); if (!singlePlayerService.isSinglePlayer) { var modelSource = this.controller.lookupListener(_services_services_remoteServer__WEBPACK_IMPORTED_MODULE_5__.RemoteServer); this.updateWorld(modelSource.getWorldModel()); } }; WorldView.prototype.onceUpdate = function () { if (this.oldView) { this.oldView.destroy(); this.oldView = undefined; (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, 'Previous View destroyed'); } this.waitGameTimeAndAllowFormViewUpdate(1.0); }; WorldView.prototype.resetAllFormViewsIfPlayerChangedWorld = function () { var state = this.state; var pc = this.sp.Game.getPlayer(); var pcWorldOrCell = (pc.getWorldSpace() || pc.getParentCell()).getFormID(); if (state.pcWorldOrCell !== pcWorldOrCell) { if (state.pcWorldOrCell) { (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, 'Reset all form views'); state.formViews.resize(0); state.cloneFormViews.resize(0); } state.pcWorldOrCell = pcWorldOrCell; } }; // Work around showRaceMenu issue // Default nord in Race Menu will have very ugly face // If other players are spawning when we show this menu // TODO: separate listener WorldView.prototype.waitGameTimeAndAllowFormViewUpdate = function (seconds) { var _this = this; // Wait 1s game time (time spent in Race Menu isn't counted) this.sp.Utility.wait(seconds).then(function () { _this.state.allowUpdate = true; (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(_this, 'Update is now allowed'); }); }; WorldView.prototype.setFormViewUpdateAllowed = function (allowed) { this.state.allowUpdate = allowed; (0,_logging__WEBPACK_IMPORTED_MODULE_3__.logTrace)(this, 'Update is now', allowed ? 'allowed' : 'disallowed'); }; WorldView.prototype.updateWorld = function (model) { var settings = this.sp.settings; var state = this.state; if (!state.allowUpdate) { model = { forms: [], playerCharacterFormIdx: model.playerCharacterFormIdx, playerCharacterRefrId: model.playerCharacterRefrId }; } var skipUpdates = settings['skymp5-client']['skipUpdates']; // skip 50% of updates if specified in the settings state.counter = !state.counter; if (state.counter && skipUpdates) { return; } state.formViews.resize(model.forms.length); var showMe = settings['skymp5-client']['show-me']; var showClones = settings['skymp5-client']['show-clones']; _playerCharacterDataHolder__WEBPACK_IMPORTED_MODULE_1__.PlayerCharacterDataHolder.updateData(); state.formViews.updateAll(model, !!showMe, false); if (showClones) { state.cloneFormViews.updateAll(model, false, true); } else { state.cloneFormViews.resize(0); } }; WorldView.prototype.makeEmptyState = function () { return { formViews: new _formViewArray__WEBPACK_IMPORTED_MODULE_0__.FormViewArray(), cloneFormViews: new _formViewArray__WEBPACK_IMPORTED_MODULE_0__.FormViewArray(), allowUpdate: false, pcWorldOrCell: 0, counter: false, }; }; return WorldView; }(_services_services_clientListener__WEBPACK_IMPORTED_MODULE_2__.ClientListener)); /***/ }), /***/ "./src/view/worldViewMisc.ts": /*!***********************************!*\ !*** ./src/view/worldViewMisc.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getObjectReference: () => (/* binding */ getObjectReference), /* harmony export */ getViewFromStorage: () => (/* binding */ getViewFromStorage), /* harmony export */ localIdToRemoteId: () => (/* binding */ localIdToRemoteId), /* harmony export */ remoteIdToLocalId: () => (/* binding */ remoteIdToLocalId) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../services/spApiInteractor */ "./src/services/spApiInteractor.ts"); /* harmony import */ var _services_services_remoteServer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../services/services/remoteServer */ "./src/services/services/remoteServer.ts"); var getViewFromStorage = function () { var res = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.storage["view"]; // can't use instanceof here because each hot reload creates a new class if (typeof res === "object") { return res; } return undefined; }; var localIdToRemoteId = function (localFormId, newCast) { if (newCast === void 0) { newCast = false; } if (newCast && localFormId == 0x14) { return _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_1__.SpApiInteractor.getControllerInstance().lookupListener(_services_services_remoteServer__WEBPACK_IMPORTED_MODULE_2__.RemoteServer).getMyRemoteRefrId(); } if (localFormId >= 0xff000000) { var view = getViewFromStorage(); if (!view) { return 0; } localFormId = view.getRemoteRefrId(localFormId); if (!localFormId) { return 0; } // serverside ids are 64bit if (localFormId >= 0x100000000) { localFormId -= 0x100000000; } } return localFormId; }; var remoteIdToLocalId = function (remoteFormId) { if (remoteFormId >= 0xff000000) { var view = getViewFromStorage(); if (!view) { return 0; } remoteFormId = view.getLocalRefrId(remoteFormId); if (!remoteFormId) { return 0; } } return remoteFormId; }; var getObjectReference = function (i) { var view = getViewFromStorage(); if (view) { var formView = view.getFormViews().getNthFormView(i); if (formView) { var refrId = formView.getLocalRefrId(); if (refrId > 0) { var refr = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.ObjectReference.from(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.getFormEx(refrId)); if (refr !== null) { return refr; } } } } return null; }; /***/ }), /***/ "crypto": /*!*************************!*\ !*** external "crypto" ***! \*************************/ /***/ ((module) => { module.exports = require("crypto"); /***/ }), /***/ "fs": /*!*********************!*\ !*** external "fs" ***! \*********************/ /***/ ((module) => { module.exports = require("fs"); /***/ }), /***/ "inspector": /*!****************************!*\ !*** external "inspector" ***! \****************************/ /***/ ((module) => { module.exports = require("inspector"); /***/ }), /***/ "node:crypto": /*!******************************!*\ !*** external "node:crypto" ***! \******************************/ /***/ ((module) => { module.exports = require("node:crypto"); /***/ }), /***/ "skyrimPlatform": /*!***********************************!*\ !*** external ["skyrimPlatform"] ***! \***********************************/ /***/ ((module) => { module.exports = skyrimPlatform; /***/ }), /***/ "./node_modules/eventemitter3/index.mjs": /*!**********************************************!*\ !*** ./node_modules/eventemitter3/index.mjs ***! \**********************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EventEmitter: () => (/* reexport default export from named module */ _index_js__WEBPACK_IMPORTED_MODULE_0__), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./index.js */ "./node_modules/eventemitter3/index.js"); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_index_js__WEBPACK_IMPORTED_MODULE_0__); /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; /*!**********************!*\ !*** ./src/index.ts ***! \**********************/ __webpack_require__.r(__webpack_exports__); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _services_services_skympClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./services/services/skympClient */ "./src/services/services/skympClient.ts"); /* harmony import */ var _services_services_blockPapyrusEventsService__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./services/services/blockPapyrusEventsService */ "./src/services/services/blockPapyrusEventsService.ts"); /* harmony import */ var _services_services_enforceLimitationsService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./services/services/enforceLimitationsService */ "./src/services/services/enforceLimitationsService.ts"); /* harmony import */ var _services_services_loadGameService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./services/services/loadGameService */ "./src/services/services/loadGameService.ts"); /* harmony import */ var _services_services_sendInputsService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./services/services/sendInputsService */ "./src/services/services/sendInputsService.ts"); /* harmony import */ var _services_services_singlePlayerService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./services/services/singlePlayerService */ "./src/services/services/singlePlayerService.ts"); /* harmony import */ var _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./services/spApiInteractor */ "./src/services/spApiInteractor.ts"); /* harmony import */ var _services_services_timeService__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./services/services/timeService */ "./src/services/services/timeService.ts"); /* harmony import */ var _services_services_spVersionCheckService__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./services/services/spVersionCheckService */ "./src/services/services/spVersionCheckService.ts"); /* harmony import */ var _services_services_consoleCommandsService__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./services/services/consoleCommandsService */ "./src/services/services/consoleCommandsService.ts"); /* harmony import */ var _services_services_lastInvService__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./services/services/lastInvService */ "./src/services/services/lastInvService.ts"); /* harmony import */ var _services_services_activationService__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./services/services/activationService */ "./src/services/services/activationService.ts"); /* harmony import */ var _services_services_craftService__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./services/services/craftService */ "./src/services/services/craftService.ts"); /* harmony import */ var _services_services_dropItemService__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./services/services/dropItemService */ "./src/services/services/dropItemService.ts"); /* harmony import */ var _services_services_hitService__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./services/services/hitService */ "./src/services/services/hitService.ts"); /* harmony import */ var _services_services_ragdollService__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./services/services/ragdollService */ "./src/services/services/ragdollService.ts"); /* harmony import */ var _services_services_deathService__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./services/services/deathService */ "./src/services/services/deathService.ts"); /* harmony import */ var _services_services_containersService__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./services/services/containersService */ "./src/services/services/containersService.ts"); /* harmony import */ var _services_services_networkingService__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./services/services/networkingService */ "./src/services/services/networkingService.ts"); /* harmony import */ var _services_services_remoteServer__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./services/services/remoteServer */ "./src/services/services/remoteServer.ts"); /* harmony import */ var _services_services_spSnippetService__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./services/services/spSnippetService */ "./src/services/services/spSnippetService.ts"); /* harmony import */ var _services_services_sweetTaffyDynamicPerksService__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./services/services/sweetTaffyDynamicPerksService */ "./src/services/services/sweetTaffyDynamicPerksService.ts"); /* harmony import */ var _services_services_sweetTaffySweetCantDropService__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./services/services/sweetTaffySweetCantDropService */ "./src/services/services/sweetTaffySweetCantDropService.ts"); /* harmony import */ var _services_services_sweetTaffyStaticPerksService__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./services/services/sweetTaffyStaticPerksService */ "./src/services/services/sweetTaffyStaticPerksService.ts"); /* harmony import */ var _services_services_disableSkillAdvanceService__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./services/services/disableSkillAdvanceService */ "./src/services/services/disableSkillAdvanceService.ts"); /* harmony import */ var _services_services_disableFastTravelService__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./services/services/disableFastTravelService */ "./src/services/services/disableFastTravelService.ts"); /* harmony import */ var _services_services_disableDifficultySelectionService__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./services/services/disableDifficultySelectionService */ "./src/services/services/disableDifficultySelectionService.ts"); /* harmony import */ var _services_services_sweetTaffyPlayerCombatService__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./services/services/sweetTaffyPlayerCombatService */ "./src/services/services/sweetTaffyPlayerCombatService.ts"); /* harmony import */ var _services_services_worldCleanerService__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./services/services/worldCleanerService */ "./src/services/services/worldCleanerService.ts"); /* harmony import */ var _services_services_sweetTaffySkillMenuService__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./services/services/sweetTaffySkillMenuService */ "./src/services/services/sweetTaffySkillMenuService.ts"); /* harmony import */ var _services_services_loadOrderVerificationService__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./services/services/loadOrderVerificationService */ "./src/services/services/loadOrderVerificationService.ts"); /* harmony import */ var _services_services_browserService__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./services/services/browserService */ "./src/services/services/browserService.ts"); /* harmony import */ var _services_services_authService__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./services/services/authService */ "./src/services/services/authService.ts"); /* harmony import */ var _services_services_netInfoService__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./services/services/netInfoService */ "./src/services/services/netInfoService.ts"); /* harmony import */ var _services_services_animDebugService__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./services/services/animDebugService */ "./src/services/services/animDebugService.ts"); /* harmony import */ var _services_services_timersService__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./services/services/timersService */ "./src/services/services/timersService.ts"); /* harmony import */ var _services_services_playerBowShotService__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./services/services/playerBowShotService */ "./src/services/services/playerBowShotService.ts"); /* harmony import */ var _services_services_gamemodeEventSourceService__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./services/services/gamemodeEventSourceService */ "./src/services/services/gamemodeEventSourceService.ts"); /* harmony import */ var _services_services_gamemodeUpdateService__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./services/services/gamemodeUpdateService */ "./src/services/services/gamemodeUpdateService.ts"); /* harmony import */ var _services_services_frontHotReloadService__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./services/services/frontHotReloadService */ "./src/services/services/frontHotReloadService.ts"); /* harmony import */ var _services_services_blockedAnimationsService__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./services/services/blockedAnimationsService */ "./src/services/services/blockedAnimationsService.ts"); /* harmony import */ var _view_worldView__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./view/worldView */ "./src/view/worldView.ts"); /* harmony import */ var _services_services_keyboardEventsService__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./services/services/keyboardEventsService */ "./src/services/services/keyboardEventsService.ts"); /* harmony import */ var _services_services_magicSyncService__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./services/services/magicSyncService */ "./src/services/services/magicSyncService.ts"); /* harmony import */ var _services_services_profilingService__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./services/services/profilingService */ "./src/services/services/profilingService.ts"); /* harmony import */ var _services_services_settingsService__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./services/services/settingsService */ "./src/services/services/settingsService.ts"); /* harmony import */ var _services_services_sweetCameraEnforcementService__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./services/services/sweetCameraEnforcementService */ "./src/services/services/sweetCameraEnforcementService.ts"); /* harmony import */ var _services_services_sweetTaffyNicknamesService__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ./services/services/sweetTaffyNicknamesService */ "./src/services/services/sweetTaffyNicknamesService.ts"); /* harmony import */ var _services_services_serverJsVerificationService__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ./services/services/serverJsVerificationService */ "./src/services/services/serverJsVerificationService.ts"); /* harmony import */ var _services_services_sweetTaffyEvalService__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ./services/services/sweetTaffyEvalService */ "./src/services/services/sweetTaffyEvalService.ts"); (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)("update", function () { skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.setINIBool("bAlwaysActive:General", true); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Game.setGameSettingInt("iDeathDropWeaponChance", 0); skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Utility.setINIFloat("fAutoVanityModeDelay:Camera", 3600); }); var main = function () { try { var controller = _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_7__.SpApiInteractor.getControllerInstance(); var listeners = [ new _services_services_blockPapyrusEventsService__WEBPACK_IMPORTED_MODULE_2__.BlockPapyrusEventsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_loadGameService__WEBPACK_IMPORTED_MODULE_4__.LoadGameService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_singlePlayerService__WEBPACK_IMPORTED_MODULE_6__.SinglePlayerService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_enforceLimitationsService__WEBPACK_IMPORTED_MODULE_3__.EnforceLimitationsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sendInputsService__WEBPACK_IMPORTED_MODULE_5__.SendInputsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_skympClient__WEBPACK_IMPORTED_MODULE_1__.SkympClient(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_timeService__WEBPACK_IMPORTED_MODULE_8__.TimeService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_spVersionCheckService__WEBPACK_IMPORTED_MODULE_9__.SpVersionCheckService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_consoleCommandsService__WEBPACK_IMPORTED_MODULE_10__.ConsoleCommandsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_lastInvService__WEBPACK_IMPORTED_MODULE_11__.LastInvService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_activationService__WEBPACK_IMPORTED_MODULE_12__.ActivationService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_craftService__WEBPACK_IMPORTED_MODULE_13__.CraftService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_dropItemService__WEBPACK_IMPORTED_MODULE_14__.DropItemService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_hitService__WEBPACK_IMPORTED_MODULE_15__.HitService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_ragdollService__WEBPACK_IMPORTED_MODULE_16__.RagdollService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_deathService__WEBPACK_IMPORTED_MODULE_17__.DeathService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_containersService__WEBPACK_IMPORTED_MODULE_18__.ContainersService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_networkingService__WEBPACK_IMPORTED_MODULE_19__.NetworkingService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_remoteServer__WEBPACK_IMPORTED_MODULE_20__.RemoteServer(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_spSnippetService__WEBPACK_IMPORTED_MODULE_21__.SpSnippetService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_settingsService__WEBPACK_IMPORTED_MODULE_46__.SettingsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffyDynamicPerksService__WEBPACK_IMPORTED_MODULE_22__.SweetTaffyDynamicPerksService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffyStaticPerksService__WEBPACK_IMPORTED_MODULE_24__.SweetTaffyStaticPerksService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffySweetCantDropService__WEBPACK_IMPORTED_MODULE_23__.SweetTaffySweetCantDropService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffyPlayerCombatService__WEBPACK_IMPORTED_MODULE_28__.SweetTaffyPlayerCombatService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffySkillMenuService__WEBPACK_IMPORTED_MODULE_30__.SweetTaffySkillMenuService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetCameraEnforcementService__WEBPACK_IMPORTED_MODULE_47__.SweetCameraEnforcementService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffyEvalService__WEBPACK_IMPORTED_MODULE_50__.SweetTaffyEvalService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_disableSkillAdvanceService__WEBPACK_IMPORTED_MODULE_25__.DisableSkillAdvanceService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_disableFastTravelService__WEBPACK_IMPORTED_MODULE_26__.DisableFastTravelService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_disableDifficultySelectionService__WEBPACK_IMPORTED_MODULE_27__.DisableDifficultySelectionService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_worldCleanerService__WEBPACK_IMPORTED_MODULE_29__.WorldCleanerService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_loadOrderVerificationService__WEBPACK_IMPORTED_MODULE_31__.LoadOrderVerificationService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_browserService__WEBPACK_IMPORTED_MODULE_32__.BrowserService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_authService__WEBPACK_IMPORTED_MODULE_33__.AuthService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_netInfoService__WEBPACK_IMPORTED_MODULE_34__.NetInfoService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_animDebugService__WEBPACK_IMPORTED_MODULE_35__.AnimDebugService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_timersService__WEBPACK_IMPORTED_MODULE_36__.TimersService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_playerBowShotService__WEBPACK_IMPORTED_MODULE_37__.PlayerBowShotService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_gamemodeEventSourceService__WEBPACK_IMPORTED_MODULE_38__.GamemodeEventSourceService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_gamemodeUpdateService__WEBPACK_IMPORTED_MODULE_39__.GamemodeUpdateService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_frontHotReloadService__WEBPACK_IMPORTED_MODULE_40__.FrontHotReloadService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_blockedAnimationsService__WEBPACK_IMPORTED_MODULE_41__.BlockedAnimationsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _view_worldView__WEBPACK_IMPORTED_MODULE_42__.WorldView(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_keyboardEventsService__WEBPACK_IMPORTED_MODULE_43__.KeyboardEventsService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_magicSyncService__WEBPACK_IMPORTED_MODULE_44__.MagicSyncService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_profilingService__WEBPACK_IMPORTED_MODULE_45__.ProfilingService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_sweetTaffyNicknamesService__WEBPACK_IMPORTED_MODULE_48__.SweetTaffyNicknamesService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller), new _services_services_serverJsVerificationService__WEBPACK_IMPORTED_MODULE_49__.ServerJsVerificationService(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__, controller) ]; _services_spApiInteractor__WEBPACK_IMPORTED_MODULE_7__.SpApiInteractor.setup(listeners); } catch (e) { // TODO: handle setup failure. will output to game console by default throw e; } }; // [18.08.2023] // I saw "attempt to call hooks.add while in hook context" error // I'm not sure if it's a C++ bug in SkyrimPlatform or an artifact of webpack+hotreload // But let's for now ensure that "main" executes inside tick context (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.once)("tick", main); /******/ })() ; //# sourceMappingURL=data:application/json;charset=utf-8;base64,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c0M7QUFDdEM7QUFDQTtBQUNBLHFDQUFxQyw4Q0FBTztBQUM1QyxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLDhDQUFPO0FBQ2pELHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsOENBQU87QUFDakQsc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyw4Q0FBTztBQUNqRCxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLDhDQUFPO0FBQ2pELHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsOENBQU87QUFDakQsc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyw4Q0FBTztBQUNqRCxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLDhDQUFPO0FBQ2pELHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsOENBQU87QUFDakQsc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyw4Q0FBTztBQUNqRCxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLDhDQUFPO0FBQ2pELHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsOENBQU87QUFDakQsc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyw4Q0FBTztBQUNqRCxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLDhDQUFPO0FBQ2pELHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsOENBQU87QUFDakQsc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyw4Q0FBTztBQUNqRCxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLDhDQUFPO0FBQ2pELHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsOENBQU87QUFDakQsc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyw4Q0FBTztBQUNqRCxzQ0FBc0M7QUFDdEM7QUFD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QUU7QUFDaEMsZ0JBQWdCLDBGQUFvQixDQUFDLDJDQUFFO0FBQ3ZDLGdCQUFnQixzR0FBMEIsQ0FBQywyQ0FBRTtBQUM3QyxnQkFBZ0IsNEZBQXFCLENBQUMsMkNBQUU7QUFDeEMsZ0JBQWdCLDRGQUFxQixDQUFDLDJDQUFFO0FBQ3hDLGdCQUFnQixrR0FBd0IsQ0FBQywyQ0FBRTtBQUMzQyxnQkFBZ0IsdURBQVMsQ0FBQywyQ0FBRTtBQUM1QixnQkFBZ0IsNEZBQXFCLENBQUMsMkNBQUU7QUFDeEMsZ0JBQWdCLGtGQUFnQixDQUFDLDJDQUFFO0FBQ25DLGdCQUFnQixrRkFBZ0IsQ0FBQywyQ0FBRTtBQUNuQyxnQkFBZ0Isc0dBQTBCLENBQUMsMkNBQUU7QUFDN0MsZ0JBQWdCLHdHQUEyQixDQUFDLDJDQUFFO0FBQzlDO0FBQ0EsUUFBUSxzRUFBZTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFJIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL25vZGVfbW9kdWxlcy9ldmVudGVtaXR0ZXIzL2luZGV4LmpzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvZXh0ZW5zaW9ucy9mb3JtVHlwZUV4LnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvZXh0ZW5zaW9ucy9vYmplY3RSZWZlcmVuY2VFeC50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL2ZlYXR1cmVzL2F1dGhNb2RlbC50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL2xpYi9lcnJvcnMudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9saWIvZnVuY3Rpb25JbmZvLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvbGliL2lkTWFuYWdlci50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL2xpYi9uYW1lb2YudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9sb2dnaW5nLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvbWVzc2FnZXMudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9ldmVudHMvZXZlbnRzLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvYWN0aXZhdGlvblNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9hbmltRGVidWdTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvYXV0aFNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9ibG9ja1BhcHlydXNFdmVudHNTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvYmxvY2tlZEFuaW1hdGlvbnNTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvYnJvd3NlclNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9jbGllbnRMaXN0ZW5lci50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2NvbnNvbGVDb21tYW5kc1NlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9jb250YWluZXJzU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2NyYWZ0U2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2RlYXRoU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2Rpc2FibGVEaWZmaWN1bHR5U2VsZWN0aW9uU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2Rpc2FibGVGYXN0VHJhdmVsU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2Rpc2FibGVTa2lsbEFkdmFuY2VTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvZHJvcEl0ZW1TZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvZW5mb3JjZUxpbWl0YXRpb25zU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2Zyb250SG90UmVsb2FkU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2dhbWVtb2RlRXZlbnRTb3VyY2VTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvZ2FtZW1vZGVVcGRhdGVTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvaGl0U2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2tleWJvYXJkRXZlbnRzU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL2xhc3RJbnZTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvbG9hZEdhbWVTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvbG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL21hZ2ljU3luY1NlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9uZXRJbmZvU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL25ldHdvcmtpbmdTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvcGxheWVyQm93U2hvdFNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9wcm9maWxpbmdTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvcmFnZG9sbFNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9yZW1vdGVTZXJ2ZXIudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9zZW5kSW5wdXRzU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3NlcnZlckpzVmVyaWZpY2F0aW9uU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3NldHRpbmdzU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3NpbmdsZVBsYXllclNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9za3ltcENsaWVudC50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3NwU25pcHBldFNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9zcFZlcnNpb25DaGVja1NlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9zd2VldENhbWVyYUVuZm9yY2VtZW50U2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3N3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvc3dlZXRUYWZmeUV2YWxTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvc3dlZXRUYWZmeU5pY2tuYW1lc1NlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlcy9zd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3N3ZWV0VGFmZnlTa2lsbE1lbnVTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvc3dlZXRUYWZmeVN0YXRpY1BlcmtzU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3N3ZWV0VGFmZnlTd2VldENhbnREcm9wU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3RpbWVTZXJ2aWNlLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc2VydmljZXMvc2VydmljZXMvdGltZXJzU2VydmljZS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3NlcnZpY2VzL3NlcnZpY2VzL3dvcmxkQ2xlYW5lclNlcnZpY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zZXJ2aWNlcy9zcEFwaUludGVyYWN0b3IudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zeW5jL2FjdG9ydmFsdWVzLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc3luYy9hbmltYXRpb24udHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zeW5jL2FwcGVhcmFuY2UudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy9zeW5jL2VxdWlwbWVudC50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3N5bmMvaW52ZW50b3J5LnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc3luYy9tb3ZlbWVudEFwcGx5LnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvc3luYy9tb3ZlbWVudEdldC50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3N5bmMvc3BlbGwudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy92ZXJzaW9uLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvdmlldy9mb3JtVmlldy50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3ZpZXcvZm9ybVZpZXdBcnJheS50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3ZpZXcvaG9zdEF0dGVtcHRzLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvdmlldy9tb2RlbEFwcGx5VXRpbHMudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy92aWV3L3BsYXllckNoYXJhY3RlckRhdGFIb2xkZXIudHMiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC8uL3NyYy92aWV3L3NwYXduUHJvY2Vzcy50cyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vc3JjL3ZpZXcvd29ybGRWaWV3LnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvdmlldy93b3JsZFZpZXdNaXNjLnRzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvZXh0ZXJuYWwgbm9kZS1jb21tb25qcyBcImNyeXB0b1wiIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvZXh0ZXJuYWwgbm9kZS1jb21tb25qcyBcImZzXCIiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC9leHRlcm5hbCBub2RlLWNvbW1vbmpzIFwiaW5zcGVjdG9yXCIiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC9leHRlcm5hbCBub2RlLWNvbW1vbmpzIFwibm9kZTpjcnlwdG9cIiIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50L2V4dGVybmFsIHZhciBbXCJza3lyaW1QbGF0Zm9ybVwiXSIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50Ly4vbm9kZV9tb2R1bGVzL2V2ZW50ZW1pdHRlcjMvaW5kZXgubWpzIiwid2VicGFjazovL3NreW1wNS1jbGllbnQvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC93ZWJwYWNrL3J1bnRpbWUvY29tcGF0IGdldCBkZWZhdWx0IGV4cG9ydCIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50L3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly9za3ltcDUtY2xpZW50L3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vc2t5bXA1LWNsaWVudC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3NreW1wNS1jbGllbnQvLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGFzID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eVxuICAsIHByZWZpeCA9ICd+JztcblxuLyoqXG4gKiBDb25zdHJ1Y3RvciB0byBjcmVhdGUgYSBzdG9yYWdlIGZvciBvdXIgYEVFYCBvYmplY3RzLlxuICogQW4gYEV2ZW50c2AgaW5zdGFuY2UgaXMgYSBwbGFpbiBvYmplY3Qgd2hvc2UgcHJvcGVydGllcyBhcmUgZXZlbnQgbmFtZXMuXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBFdmVudHMoKSB7fVxuXG4vL1xuLy8gV2UgdHJ5IHRvIG5vdCBpbmhlcml0IGZyb20gYE9iamVjdC5wcm90b3R5cGVgLiBJbiBzb21lIGVuZ2luZXMgY3JlYXRpbmcgYW5cbi8vIGluc3RhbmNlIGluIHRoaXMgd2F5IGlzIGZhc3RlciB0aGFuIGNhbGxpbmcgYE9iamVjdC5jcmVhdGUobnVsbClgIGRpcmVjdGx5LlxuLy8gSWYgYE9iamVjdC5jcmVhdGUobnVsbClgIGlzIG5vdCBzdXBwb3J0ZWQgd2UgcHJlZml4IHRoZSBldmVudCBuYW1lcyB3aXRoIGFcbi8vIGNoYXJhY3RlciB0byBtYWtlIHN1cmUgdGhhdCB0aGUgYnVpbHQtaW4gb2JqZWN0IHByb3BlcnRpZXMgYXJlIG5vdFxuLy8gb3ZlcnJpZGRlbiBvciB1c2VkIGFzIGFuIGF0dGFjayB2ZWN0b3IuXG4vL1xuaWYgKE9iamVjdC5jcmVhdGUpIHtcbiAgRXZlbnRzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbiAgLy9cbiAgLy8gVGhpcyBoYWNrIGlzIG5lZWRlZCBiZWNhdXNlIHRoZSBgX19wcm90b19fYCBwcm9wZXJ0eSBpcyBzdGlsbCBpbmhlcml0ZWQgaW5cbiAgLy8gc29tZSBvbGQgYnJvd3NlcnMgbGlrZSBBbmRyb2lkIDQsIGlQaG9uZSA1LjEsIE9wZXJhIDExIGFuZCBTYWZhcmkgNS5cbiAgLy9cbiAgaWYgKCFuZXcgRXZlbnRzKCkuX19wcm90b19fKSBwcmVmaXggPSBmYWxzZTtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRhdGlvbiBvZiBhIHNpbmdsZSBldmVudCBsaXN0ZW5lci5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgbGlzdGVuZXIgZnVuY3Rpb24uXG4gKiBAcGFyYW0geyp9IGNvbnRleHQgVGhlIGNvbnRleHQgdG8gaW52b2tlIHRoZSBsaXN0ZW5lciB3aXRoLlxuICogQHBhcmFtIHtCb29sZWFufSBbb25jZT1mYWxzZV0gU3BlY2lmeSBpZiB0aGUgbGlzdGVuZXIgaXMgYSBvbmUtdGltZSBsaXN0ZW5lci5cbiAqIEBjb25zdHJ1Y3RvclxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gRUUoZm4sIGNvbnRleHQsIG9uY2UpIHtcbiAgdGhpcy5mbiA9IGZuO1xuICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICB0aGlzLm9uY2UgPSBvbmNlIHx8IGZhbHNlO1xufVxuXG4vKipcbiAqIEFkZCBhIGxpc3RlbmVyIGZvciBhIGdpdmVuIGV2ZW50LlxuICpcbiAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBlbWl0dGVyIFJlZmVyZW5jZSB0byB0aGUgYEV2ZW50RW1pdHRlcmAgaW5zdGFuY2UuXG4gKiBAcGFyYW0geyhTdHJpbmd8U3ltYm9sKX0gZXZlbnQgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgbGlzdGVuZXIgZnVuY3Rpb24uXG4gKiBAcGFyYW0geyp9IGNvbnRleHQgVGhlIGNvbnRleHQgdG8gaW52b2tlIHRoZSBsaXN0ZW5lciB3aXRoLlxuICogQHBhcmFtIHtCb29sZWFufSBvbmNlIFNwZWNpZnkgaWYgdGhlIGxpc3RlbmVyIGlzIGEgb25lLXRpbWUgbGlzdGVuZXIuXG4gKiBAcmV0dXJucyB7RXZlbnRFbWl0dGVyfVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gYWRkTGlzdGVuZXIoZW1pdHRlciwgZXZlbnQsIGZuLCBjb250ZXh0LCBvbmNlKSB7XG4gIGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gIH1cblxuICB2YXIgbGlzdGVuZXIgPSBuZXcgRUUoZm4sIGNvbnRleHQgfHwgZW1pdHRlciwgb25jZSlcbiAgICAsIGV2dCA9IHByZWZpeCA/IHByZWZpeCArIGV2ZW50IDogZXZlbnQ7XG5cbiAgaWYgKCFlbWl0dGVyLl9ldmVudHNbZXZ0XSkgZW1pdHRlci5fZXZlbnRzW2V2dF0gPSBsaXN0ZW5lciwgZW1pdHRlci5fZXZlbnRzQ291bnQrKztcbiAgZWxzZSBpZiAoIWVtaXR0ZXIuX2V2ZW50c1tldnRdLmZuKSBlbWl0dGVyLl9ldmVudHNbZXZ0XS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZSBlbWl0dGVyLl9ldmVudHNbZXZ0XSA9IFtlbWl0dGVyLl9ldmVudHNbZXZ0XSwgbGlzdGVuZXJdO1xuXG4gIHJldHVybiBlbWl0dGVyO1xufVxuXG4vKipcbiAqIENsZWFyIGV2ZW50IGJ5IG5hbWUuXG4gKlxuICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IGVtaXR0ZXIgUmVmZXJlbmNlIHRvIHRoZSBgRXZlbnRFbWl0dGVyYCBpbnN0YW5jZS5cbiAqIEBwYXJhbSB7KFN0cmluZ3xTeW1ib2wpfSBldnQgVGhlIEV2ZW50IG5hbWUuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBjbGVhckV2ZW50KGVtaXR0ZXIsIGV2dCkge1xuICBpZiAoLS1lbWl0dGVyLl9ldmVudHNDb3VudCA9PT0gMCkgZW1pdHRlci5fZXZlbnRzID0gbmV3IEV2ZW50cygpO1xuICBlbHNlIGRlbGV0ZSBlbWl0dGVyLl9ldmVudHNbZXZ0XTtcbn1cblxuLyoqXG4gKiBNaW5pbWFsIGBFdmVudEVtaXR0ZXJgIGludGVyZmFjZSB0aGF0IGlzIG1vbGRlZCBhZ2FpbnN0IHRoZSBOb2RlLmpzXG4gKiBgRXZlbnRFbWl0dGVyYCBpbnRlcmZhY2UuXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKiBAcHVibGljXG4gKi9cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgdGhpcy5fZXZlbnRzID0gbmV3IEV2ZW50cygpO1xuICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG59XG5cbi8qKlxuICogUmV0dXJuIGFuIGFycmF5IGxpc3RpbmcgdGhlIGV2ZW50cyBmb3Igd2hpY2ggdGhlIGVtaXR0ZXIgaGFzIHJlZ2lzdGVyZWRcbiAqIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJucyB7QXJyYXl9XG4gKiBAcHVibGljXG4gKi9cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZXZlbnROYW1lcyA9IGZ1bmN0aW9uIGV2ZW50TmFtZXMoKSB7XG4gIHZhciBuYW1lcyA9IFtdXG4gICAgLCBldmVudHNcbiAgICAsIG5hbWU7XG5cbiAgaWYgKHRoaXMuX2V2ZW50c0NvdW50ID09PSAwKSByZXR1cm4gbmFtZXM7XG5cbiAgZm9yIChuYW1lIGluIChldmVudHMgPSB0aGlzLl9ldmVudHMpKSB7XG4gICAgaWYgKGhhcy5jYWxsKGV2ZW50cywgbmFtZSkpIG5hbWVzLnB1c2gocHJlZml4ID8gbmFtZS5zbGljZSgxKSA6IG5hbWUpO1xuICB9XG5cbiAgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHtcbiAgICByZXR1cm4gbmFtZXMuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMoZXZlbnRzKSk7XG4gIH1cblxuICByZXR1cm4gbmFtZXM7XG59O1xuXG4vKipcbiAqIFJldHVybiB0aGUgbGlzdGVuZXJzIHJlZ2lzdGVyZWQgZm9yIGEgZ2l2ZW4gZXZlbnQuXG4gKlxuICogQHBhcmFtIHsoU3RyaW5nfFN5bWJvbCl9IGV2ZW50IFRoZSBldmVudCBuYW1lLlxuICogQHJldHVybnMge0FycmF5fSBUaGUgcmVnaXN0ZXJlZCBsaXN0ZW5lcnMuXG4gKiBAcHVibGljXG4gKi9cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24gbGlzdGVuZXJzKGV2ZW50KSB7XG4gIHZhciBldnQgPSBwcmVmaXggPyBwcmVmaXggKyBldmVudCA6IGV2ZW50XG4gICAgLCBoYW5kbGVycyA9IHRoaXMuX2V2ZW50c1tldnRdO1xuXG4gIGlmICghaGFuZGxlcnMpIHJldHVybiBbXTtcbiAgaWYgKGhhbmRsZXJzLmZuKSByZXR1cm4gW2hhbmRsZXJzLmZuXTtcblxuICBmb3IgKHZhciBpID0gMCwgbCA9IGhhbmRsZXJzLmxlbmd0aCwgZWUgPSBuZXcgQXJyYXkobCk7IGkgPCBsOyBpKyspIHtcbiAgICBlZVtpXSA9IGhhbmRsZXJzW2ldLmZuO1xuICB9XG5cbiAgcmV0dXJuIGVlO1xufTtcblxuLyoqXG4gKiBSZXR1cm4gdGhlIG51bWJlciBvZiBsaXN0ZW5lcnMgbGlzdGVuaW5nIHRvIGEgZ2l2ZW4gZXZlbnQuXG4gKlxuICogQHBhcmFtIHsoU3RyaW5nfFN5bWJvbCl9IGV2ZW50IFRoZSBldmVudCBuYW1lLlxuICogQHJldHVybnMge051bWJlcn0gVGhlIG51bWJlciBvZiBsaXN0ZW5lcnMuXG4gKiBAcHVibGljXG4gKi9cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uIGxpc3RlbmVyQ291bnQoZXZlbnQpIHtcbiAgdmFyIGV2dCA9IHByZWZpeCA/IHByZWZpeCArIGV2ZW50IDogZXZlbnRcbiAgICAsIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1tldnRdO1xuXG4gIGlmICghbGlzdGVuZXJzKSByZXR1cm4gMDtcbiAgaWYgKGxpc3RlbmVycy5mbikgcmV0dXJuIDE7XG4gIHJldHVybiBsaXN0ZW5lcnMubGVuZ3RoO1xufTtcblxuLyoqXG4gKiBDYWxscyBlYWNoIG9mIHRoZSBsaXN0ZW5lcnMgcmVnaXN0ZXJlZCBmb3IgYSBnaXZlbiBldmVudC5cbiAqXG4gKiBAcGFyYW0geyhTdHJpbmd8U3ltYm9sKX0gZXZlbnQgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gYHRydWVgIGlmIHRoZSBldmVudCBoYWQgbGlzdGVuZXJzLCBlbHNlIGBmYWxzZWAuXG4gKiBAcHVibGljXG4gKi9cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZlbnQsIGExLCBhMiwgYTMsIGE0LCBhNSkge1xuICB2YXIgZXZ0ID0gcHJlZml4ID8gcHJlZml4ICsgZXZlbnQgOiBldmVudDtcblxuICBpZiAoIXRoaXMuX2V2ZW50c1tldnRdKSByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1tldnRdXG4gICAgLCBsZW4gPSBhcmd1bWVudHMubGVuZ3RoXG4gICAgLCBhcmdzXG4gICAgLCBpO1xuXG4gIGlmIChsaXN0ZW5lcnMuZm4pIHtcbiAgICBpZiAobGlzdGVuZXJzLm9uY2UpIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVycy5mbiwgdW5kZWZpbmVkLCB0cnVlKTtcblxuICAgIHN3aXRjaCAobGVuKSB7XG4gICAgICBjYXNlIDE6IHJldHVybiBsaXN0ZW5lcnMuZm4uY2FsbChsaXN0ZW5lcnMuY29udGV4dCksIHRydWU7XG4gICAgICBjYXNlIDI6IHJldHVybiBsaXN0ZW5lcnMuZm4uY2FsbChsaXN0ZW5lcnMuY29udGV4dCwgYTEpLCB0cnVlO1xuICAgICAgY2FzZSAzOiByZXR1cm4gbGlzdGVuZXJzLmZuLmNhbGwobGlzdGVuZXJzLmNvbnRleHQsIGExLCBhMiksIHRydWU7XG4gICAgICBjYXNlIDQ6IHJldHVybiBsaXN0ZW5lcnMuZm4uY2FsbChsaXN0ZW5lcnMuY29udGV4dCwgYTEsIGEyLCBhMyksIHRydWU7XG4gICAgICBjYXNlIDU6IHJldHVybiBsaXN0ZW5lcnMuZm4uY2FsbChsaXN0ZW5lcnMuY29udGV4dCwgYTEsIGEyLCBhMywgYTQpLCB0cnVlO1xuICAgICAgY2FzZSA2OiByZXR1cm4gbGlzdGVuZXJzLmZuLmNhbGwobGlzdGVuZXJzLmNvbnRleHQsIGExLCBhMiwgYTMsIGE0LCBhNSksIHRydWU7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMSwgYXJncyA9IG5ldyBBcnJheShsZW4gLTEpOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgIH1cblxuICAgIGxpc3RlbmVycy5mbi5hcHBseShsaXN0ZW5lcnMuY29udGV4dCwgYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGxlbmd0aCA9IGxpc3RlbmVycy5sZW5ndGhcbiAgICAgICwgajtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGxpc3RlbmVyc1tpXS5vbmNlKSB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcnNbaV0uZm4sIHVuZGVmaW5lZCwgdHJ1ZSk7XG5cbiAgICAgIHN3aXRjaCAobGVuKSB7XG4gICAgICAgIGNhc2UgMTogbGlzdGVuZXJzW2ldLmZuLmNhbGwobGlzdGVuZXJzW2ldLmNvbnRleHQpOyBicmVhaztcbiAgICAgICAgY2FzZSAyOiBsaXN0ZW5lcnNbaV0uZm4uY2FsbChsaXN0ZW5lcnNbaV0uY29udGV4dCwgYTEpOyBicmVhaztcbiAgICAgICAgY2FzZSAzOiBsaXN0ZW5lcnNbaV0uZm4uY2FsbChsaXN0ZW5lcnNbaV0uY29udGV4dCwgYTEsIGEyKTsgYnJlYWs7XG4gICAgICAgIGNhc2UgNDogbGlzdGVuZXJzW2ldLmZuLmNhbGwobGlzdGVuZXJzW2ldLmNvbnRleHQsIGExLCBhMiwgYTMpOyBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBpZiAoIWFyZ3MpIGZvciAoaiA9IDEsIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0xKTsgaiA8IGxlbjsgaisrKSB7XG4gICAgICAgICAgICBhcmdzW2ogLSAxXSA9IGFyZ3VtZW50c1tqXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsaXN0ZW5lcnNbaV0uZm4uYXBwbHkobGlzdGVuZXJzW2ldLmNvbnRleHQsIGFyZ3MpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuLyoqXG4gKiBBZGQgYSBsaXN0ZW5lciBmb3IgYSBnaXZlbiBldmVudC5cbiAqXG4gKiBAcGFyYW0geyhTdHJpbmd8U3ltYm9sKX0gZXZlbnQgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgbGlzdGVuZXIgZnVuY3Rpb24uXG4gKiBAcGFyYW0geyp9IFtjb250ZXh0PXRoaXNdIFRoZSBjb250ZXh0IHRvIGludm9rZSB0aGUgbGlzdGVuZXIgd2l0aC5cbiAqIEByZXR1cm5zIHtFdmVudEVtaXR0ZXJ9IGB0aGlzYC5cbiAqIEBwdWJsaWNcbiAqL1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIG9uKGV2ZW50LCBmbiwgY29udGV4dCkge1xuICByZXR1cm4gYWRkTGlzdGVuZXIodGhpcywgZXZlbnQsIGZuLCBjb250ZXh0LCBmYWxzZSk7XG59O1xuXG4vKipcbiAqIEFkZCBhIG9uZS10aW1lIGxpc3RlbmVyIGZvciBhIGdpdmVuIGV2ZW50LlxuICpcbiAqIEBwYXJhbSB7KFN0cmluZ3xTeW1ib2wpfSBldmVudCBUaGUgZXZlbnQgbmFtZS5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBsaXN0ZW5lciBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7Kn0gW2NvbnRleHQ9dGhpc10gVGhlIGNvbnRleHQgdG8gaW52b2tlIHRoZSBsaXN0ZW5lciB3aXRoLlxuICogQHJldHVybnMge0V2ZW50RW1pdHRlcn0gYHRoaXNgLlxuICogQHB1YmxpY1xuICovXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKGV2ZW50LCBmbiwgY29udGV4dCkge1xuICByZXR1cm4gYWRkTGlzdGVuZXIodGhpcywgZXZlbnQsIGZuLCBjb250ZXh0LCB0cnVlKTtcbn07XG5cbi8qKlxuICogUmVtb3ZlIHRoZSBsaXN0ZW5lcnMgb2YgYSBnaXZlbiBldmVudC5cbiAqXG4gKiBAcGFyYW0geyhTdHJpbmd8U3ltYm9sKX0gZXZlbnQgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBPbmx5IHJlbW92ZSB0aGUgbGlzdGVuZXJzIHRoYXQgbWF0Y2ggdGhpcyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7Kn0gY29udGV4dCBPbmx5IHJlbW92ZSB0aGUgbGlzdGVuZXJzIHRoYXQgaGF2ZSB0aGlzIGNvbnRleHQuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9uY2UgT25seSByZW1vdmUgb25lLXRpbWUgbGlzdGVuZXJzLlxuICogQHJldHVybnMge0V2ZW50RW1pdHRlcn0gYHRoaXNgLlxuICogQHB1YmxpY1xuICovXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnQsIGZuLCBjb250ZXh0LCBvbmNlKSB7XG4gIHZhciBldnQgPSBwcmVmaXggPyBwcmVmaXggKyBldmVudCA6IGV2ZW50O1xuXG4gIGlmICghdGhpcy5fZXZlbnRzW2V2dF0pIHJldHVybiB0aGlzO1xuICBpZiAoIWZuKSB7XG4gICAgY2xlYXJFdmVudCh0aGlzLCBldnQpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1tldnRdO1xuXG4gIGlmIChsaXN0ZW5lcnMuZm4pIHtcbiAgICBpZiAoXG4gICAgICBsaXN0ZW5lcnMuZm4gPT09IGZuICYmXG4gICAgICAoIW9uY2UgfHwgbGlzdGVuZXJzLm9uY2UpICYmXG4gICAgICAoIWNvbnRleHQgfHwgbGlzdGVuZXJzLmNvbnRleHQgPT09IGNvbnRleHQpXG4gICAgKSB7XG4gICAgICBjbGVhckV2ZW50KHRoaXMsIGV2dCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGZvciAodmFyIGkgPSAwLCBldmVudHMgPSBbXSwgbGVuZ3RoID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGxpc3RlbmVyc1tpXS5mbiAhPT0gZm4gfHxcbiAgICAgICAgKG9uY2UgJiYgIWxpc3RlbmVyc1tpXS5vbmNlKSB8fFxuICAgICAgICAoY29udGV4dCAmJiBsaXN0ZW5lcnNbaV0uY29udGV4dCAhPT0gY29udGV4dClcbiAgICAgICkge1xuICAgICAgICBldmVudHMucHVzaChsaXN0ZW5lcnNbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vXG4gICAgLy8gUmVzZXQgdGhlIGFycmF5LCBvciByZW1vdmUgaXQgY29tcGxldGVseSBpZiB3ZSBoYXZlIG5vIG1vcmUgbGlzdGVuZXJzLlxuICAgIC8vXG4gICAgaWYgKGV2ZW50cy5sZW5ndGgpIHRoaXMuX2V2ZW50c1tldnRdID0gZXZlbnRzLmxlbmd0aCA9PT0gMSA/IGV2ZW50c1swXSA6IGV2ZW50cztcbiAgICBlbHNlIGNsZWFyRXZlbnQodGhpcywgZXZ0KTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBSZW1vdmUgYWxsIGxpc3RlbmVycywgb3IgdGhvc2Ugb2YgdGhlIHNwZWNpZmllZCBldmVudC5cbiAqXG4gKiBAcGFyYW0geyhTdHJpbmd8U3ltYm9sKX0gW2V2ZW50XSBUaGUgZXZlbnQgbmFtZS5cbiAqIEByZXR1cm5zIHtFdmVudEVtaXR0ZXJ9IGB0aGlzYC5cbiAqIEBwdWJsaWNcbiAqL1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnQpIHtcbiAgdmFyIGV2dDtcblxuICBpZiAoZXZlbnQpIHtcbiAgICBldnQgPSBwcmVmaXggPyBwcmVmaXggKyBldmVudCA6IGV2ZW50O1xuICAgIGlmICh0aGlzLl9ldmVudHNbZXZ0XSkgY2xlYXJFdmVudCh0aGlzLCBldnQpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuX2V2ZW50cyA9IG5ldyBFdmVudHMoKTtcbiAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vXG4vLyBBbGlhcyBtZXRob2RzIG5hbWVzIGJlY2F1c2UgcGVvcGxlIHJvbGwgbGlrZSB0aGF0LlxuLy9cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub2ZmID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lcjtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uO1xuXG4vL1xuLy8gRXhwb3NlIHRoZSBwcmVmaXguXG4vL1xuRXZlbnRFbWl0dGVyLnByZWZpeGVkID0gcHJlZml4O1xuXG4vL1xuLy8gQWxsb3cgYEV2ZW50RW1pdHRlcmAgdG8gYmUgaW1wb3J0ZWQgYXMgbW9kdWxlIG5hbWVzcGFjZS5cbi8vXG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG4vL1xuLy8gRXhwb3NlIHRoZSBtb2R1bGUuXG4vL1xuaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgbW9kdWxlKSB7XG4gIG1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xufVxuIiwidmFyIEZvcm1UeXBlRXggPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRm9ybVR5cGVFeCgpIHtcbiAgICB9XG4gICAgRm9ybVR5cGVFeC5pc0l0ZW0gPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICByZXR1cm4gdHlwZSA9PT0gNDIgLyogRm9ybVR5cGUuQW1tbyAqLyB8fFxuICAgICAgICAgICAgdHlwZSA9PT0gMjYgLyogRm9ybVR5cGUuQXJtb3IgKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDI3IC8qIEZvcm1UeXBlLkJvb2sgKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDMwIC8qIEZvcm1UeXBlLkluZ3JlZGllbnQgKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDMxIC8qIEZvcm1UeXBlLkxpZ2h0ICovIHx8XG4gICAgICAgICAgICB0eXBlID09PSA0NiAvKiBGb3JtVHlwZS5Qb3Rpb24gKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDIzIC8qIEZvcm1UeXBlLlNjcm9sbEl0ZW0gKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDUyIC8qIEZvcm1UeXBlLlNvdWxHZW0gKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDQxIC8qIEZvcm1UeXBlLldlYXBvbiAqLyB8fFxuICAgICAgICAgICAgdHlwZSA9PT0gMzIgLyogRm9ybVR5cGUuTWlzYyAqLztcbiAgICB9O1xuICAgIHJldHVybiBGb3JtVHlwZUV4O1xufSgpKTtcbmV4cG9ydCB7IEZvcm1UeXBlRXggfTtcbiIsImltcG9ydCB7IEZsb3JhIH0gZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG5pbXBvcnQgeyBGb3JtVHlwZUV4IH0gZnJvbSBcIi4vZm9ybVR5cGVFeFwiO1xudmFyIE9iamVjdFJlZmVyZW5jZUV4ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE9iamVjdFJlZmVyZW5jZUV4KCkge1xuICAgIH1cbiAgICBPYmplY3RSZWZlcmVuY2VFeC5nZXRXb3JsZE9yQ2VsbCA9IGZ1bmN0aW9uIChzZWxmKSB7XG4gICAgICAgIHZhciB3b3JsZCA9IHNlbGYuZ2V0V29ybGRTcGFjZSgpO1xuICAgICAgICBpZiAod29ybGQpIHtcbiAgICAgICAgICAgIHJldHVybiB3b3JsZC5nZXRGb3JtSUQoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbCA9IHNlbGYuZ2V0UGFyZW50Q2VsbCgpO1xuICAgICAgICBpZiAoY2VsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGNlbGwuZ2V0Rm9ybUlEKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfTtcbiAgICBPYmplY3RSZWZlcmVuY2VFeC5nZXRQb3MgPSBmdW5jdGlvbiAoc2VsZikge1xuICAgICAgICByZXR1cm4gW3NlbGYuZ2V0UG9zaXRpb25YKCksIHNlbGYuZ2V0UG9zaXRpb25ZKCksIHNlbGYuZ2V0UG9zaXRpb25aKCldO1xuICAgIH07XG4gICAgO1xuICAgIE9iamVjdFJlZmVyZW5jZUV4LmdldERpc3RhbmNlID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgdmFyIGRlbHRhWCA9IGFbMF0gLSBiWzBdO1xuICAgICAgICB2YXIgZGVsdGFZID0gYVsxXSAtIGJbMV07XG4gICAgICAgIHZhciBkZWx0YVogPSBhWzJdIC0gYlsyXTtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydChkZWx0YVggKiBkZWx0YVggKyBkZWx0YVkgKiBkZWx0YVkgKyBkZWx0YVogKiBkZWx0YVopO1xuICAgIH07XG4gICAgO1xuICAgIE9iamVjdFJlZmVyZW5jZUV4LmdldERpc3RhbmNlTm9aID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgdmFyIGRlbHRhWCA9IGFbMF0gLSBiWzBdO1xuICAgICAgICB2YXIgZGVsdGFZID0gYVsxXSAtIGJbMV07XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQoZGVsdGFYICogZGVsdGFYICsgZGVsdGFZICogZGVsdGFZKTtcbiAgICB9O1xuICAgIDtcbiAgICBPYmplY3RSZWZlcmVuY2VFeC5kZWFsV2l0aFJlZiA9IGZ1bmN0aW9uIChzZWxmLCBiYXNlKSB7XG4gICAgICAgIHZhciBfYSwgX2I7XG4gICAgICAgIHZhciB0ID0gYmFzZS5nZXRUeXBlKCk7XG4gICAgICAgIHZhciBpc0l0ZW0gPSBGb3JtVHlwZUV4LmlzSXRlbSh0KTtcbiAgICAgICAgLy8gQmxhY2tGYWxsc0JhcnJvdzAyLCBkb29yIGlzbid0IG9wZW5pbmcgdmlhIFNldE9wZW4gc28gd2UncmUgaGFja2luZyBpdC5cbiAgICAgICAgLy8gTm90IGJsb2NraW5nIGFjdGl2YXRpb24gJiBhc2tpbmcgcGFyZW50IHRvIGFjdGl2YXRlIHVudGlsIHdpbGwgYmUgaW4gdGhlIGNvcnJlY3Qgc3RhdGVcbiAgICAgICAgLy8gU2VlIGFsc28gbW9kZWxBcHBseVV0aWxzLnRzXG4gICAgICAgIHZhciBjYXZlR1NlY3JldERvb3IwMSA9IDB4NmY3MDM7XG4gICAgICAgIC8vIFlvdSBjYW4gYWxzbyBibG9jayBmb3IgdCA9PT0gRm9ybVR5cGUuRmxvcmEgfHwgdCA9PT0gRm9ybVR5cGUuVHJlZSwgYnV0IEkgZG9uJ3QgdGhpbmsgaXQncyBuZWNlc3NhcnkuXG4gICAgICAgIGlmICh0ID09PSA0MCAvKiBGb3JtVHlwZS5GdXJuaXR1cmUgKi9cbiAgICAgICAgICAgIHx8IHQgPT09IDI0IC8qIEZvcm1UeXBlLkFjdGl2YXRvciAqL1xuICAgICAgICAgICAgfHwgdCA9PT0gMjggLyogRm9ybVR5cGUuQ29udGFpbmVyICovXG4gICAgICAgICAgICB8fCBpc0l0ZW1cbiAgICAgICAgICAgIHx8IHQgPT09IDQzIC8qIEZvcm1UeXBlLk5QQyAqL1xuICAgICAgICAgICAgfHwgKHQgPT09IDI5IC8qIEZvcm1UeXBlLkRvb3IgKi8gJiYgKChfYSA9IHNlbGYuZ2V0QmFzZU9iamVjdCgpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ2V0Rm9ybUlEKCkpICE9PSBjYXZlR1NlY3JldERvb3IwMSkpIHtcbiAgICAgICAgICAgIHNlbGYuYmxvY2tBY3RpdmF0aW9uKHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5ibG9ja0FjdGl2YXRpb24oZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZWxmLmlzTG9ja2VkKCkpIHtcbiAgICAgICAgICAgIHNlbGYubG9jayhmYWxzZSwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0l0ZW0pIHtcbiAgICAgICAgICAgIHNlbGYuc2V0TW90aW9uVHlwZSg0IC8qIE1vdGlvblR5cGUuS2V5ZnJhbWVkICovLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3NreXJpbS1tdWx0aXBsYXllci9pc3N1ZS10cmFja2VyL2lzc3Vlcy8zNlxuICAgICAgICBpZiAodCA9PT0gMzkgLyogRm9ybVR5cGUuRmxvcmEgKi8gJiYgKChfYiA9IEZsb3JhLmZyb20oYmFzZSkpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5nZXRJbmdyZWRpZW50KCkpKSB7XG4gICAgICAgICAgICBzZWxmLnNldE1vdGlvblR5cGUoNCAvKiBNb3Rpb25UeXBlLktleWZyYW1lZCAqLywgZmFsc2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gT2JqZWN0UmVmZXJlbmNlRXg7XG59KCkpO1xuZXhwb3J0IHsgT2JqZWN0UmVmZXJlbmNlRXggfTtcbiIsIjtcbjtcbjtcbmV4cG9ydCB2YXIgYXV0aEdhbWVEYXRhU3RvcmFnZUtleSA9IFwiYXV0aEdhbWVEYXRhXCI7XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIFJlc3Bhd25OZWVkZWRFcnJvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoUmVzcGF3bk5lZWRlZEVycm9yLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJlc3Bhd25OZWVkZWRFcnJvcihtZXNzYWdlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIG1lc3NhZ2UpIHx8IHRoaXM7XG4gICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihfdGhpcywgUmVzcGF3bk5lZWRlZEVycm9yLnByb3RvdHlwZSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIFJlc3Bhd25OZWVkZWRFcnJvcjtcbn0oRXJyb3IpKTtcbmV4cG9ydCB7IFJlc3Bhd25OZWVkZWRFcnJvciB9O1xudmFyIE5ldmVyRXJyb3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKE5ldmVyRXJyb3IsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gTmV2ZXJFcnJvcihtZXNzYWdlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIFwiTmV2ZXJFcnJvcjogXCIuY29uY2F0KEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpKSkgfHwgdGhpcztcbiAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKF90aGlzLCBOZXZlckVycm9yLnByb3RvdHlwZSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIE5ldmVyRXJyb3I7XG59KEVycm9yKSk7XG5leHBvcnQgeyBOZXZlckVycm9yIH07XG4iLCJ2YXIgRnVuY3Rpb25JbmZvID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZ1bmN0aW9uSW5mbyhmKSB7XG4gICAgICAgIHRoaXMuZiA9IGY7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGdW5jdGlvbkluZm8ucHJvdG90eXBlLCBcInRleHRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIHRoaXMgcGFydCBpcyBkaWZmZXJlbnQgdG8gZnVuY3Rpb25JbmZvLnRzIHVzZWQgaW4gc2t5bXA1LWZ1bmN0aW9ucy1saWJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFRleHRXaXRob3V0RXJyb3JIYW5kbGluZygpO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgRnVuY3Rpb25JbmZvLnByb3RvdHlwZS5nZXRUZXh0ID0gZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgaWYgKCFhcmdzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBcIihmdW5jdGlvbigpe2NvbnN0IHtcIi5jb25jYXQoT2JqZWN0LmtleXMoYXJncykuam9pbignLCcpLCBcIn0gPSBcIikuY29uY2F0KEpTT04uc3RyaW5naWZ5KGFyZ3MpLCBcIjtcIikuY29uY2F0KHRoaXMudGV4dCwgXCJ9KSgpXCIpO1xuICAgIH07XG4gICAgRnVuY3Rpb25JbmZvLnByb3RvdHlwZS5nZXRUZXh0V2l0aG91dEVycm9ySGFuZGxpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmdW5jU3RyaW5nID0gdGhpcy5mLnRvU3RyaW5nKCkuc3Vic3RyaW5nKDAsIHRoaXMuZi50b1N0cmluZygpLmxlbmd0aCAtIDEpO1xuICAgICAgICByZXR1cm4gZnVuY1N0cmluZy5yZXBsYWNlKG5ldyBSZWdFeHAoJ14uKz97JywgJ20nKSwgJycpLnRyaW0oKTtcbiAgICB9O1xuICAgIHJldHVybiBGdW5jdGlvbkluZm87XG59KCkpO1xuZXhwb3J0IHsgRnVuY3Rpb25JbmZvIH07XG4iLCJ2YXIgSWRNYW5hZ2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIElkTWFuYWdlcigpIHtcbiAgICAgICAgdGhpcy5pZEJ5VmFsdWUgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy52YWx1ZUJ5SWQgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5taW5pbXVtVW51c2VkSWQgPSAwO1xuICAgIH1cbiAgICBJZE1hbmFnZXIucHJvdG90eXBlLmFsbG9jYXRlSWRGb3IgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMuaWRCeVZhbHVlLmxlbmd0aCA8PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5pZEJ5VmFsdWUubGVuZ3RoID0gdmFsdWUgKyAxO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaWRCeVZhbHVlW3ZhbHVlXSA9IHRoaXMubWluaW11bVVudXNlZElkO1xuICAgICAgICBpZiAodGhpcy52YWx1ZUJ5SWQubGVuZ3RoIDw9IHRoaXMubWluaW11bVVudXNlZElkKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlQnlJZC5sZW5ndGggPSB0aGlzLm1pbmltdW1VbnVzZWRJZCArIDE7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52YWx1ZUJ5SWRbdGhpcy5taW5pbXVtVW51c2VkSWRdID0gdmFsdWU7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLm1pbmltdW1VbnVzZWRJZDtcbiAgICAgICAgdGhpcy5taW5pbXVtVW51c2VkSWQrKztcbiAgICAgICAgd2hpbGUgKHRoaXMudmFsdWVCeUlkLmxlbmd0aCA+IHRoaXMubWluaW11bVVudXNlZElkICYmXG4gICAgICAgICAgICB0eXBlb2YgdGhpcy52YWx1ZUJ5SWRbdGhpcy5taW5pbXVtVW51c2VkSWRdID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICB0aGlzLm1pbmltdW1VbnVzZWRJZCsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBJZE1hbmFnZXIucHJvdG90eXBlLmZyZWVJZEZvciA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgaWQgPSB0aGlzLmlkQnlWYWx1ZVt2YWx1ZV07XG4gICAgICAgIGlmIChpZCA8IHRoaXMubWluaW11bVVudXNlZElkKSB7XG4gICAgICAgICAgICB0aGlzLm1pbmltdW1VbnVzZWRJZCA9IGlkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaWRCeVZhbHVlW3ZhbHVlXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy52YWx1ZUJ5SWRbaWRdID0gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm47XG4gICAgfTtcbiAgICBJZE1hbmFnZXIucHJvdG90eXBlLmdldElkID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciByID0gdGhpcy5pZEJ5VmFsdWVbdmFsdWVdO1xuICAgICAgICByZXR1cm4gdHlwZW9mIHIgPT09IFwibnVtYmVyXCIgPyByIDogLTE7XG4gICAgfTtcbiAgICBJZE1hbmFnZXIucHJvdG90eXBlLmdldFZhbHVlQnlJZCA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZUJ5SWRbaWRdO1xuICAgIH07XG4gICAgcmV0dXJuIElkTWFuYWdlcjtcbn0oKSk7XG5leHBvcnQgeyBJZE1hbmFnZXIgfTtcbiIsImV4cG9ydCBmdW5jdGlvbiBuYW1lb2Yoa2V5KSB7XG4gICAgcmV0dXJuIGtleTtcbn1cbiIsInZhciBfX3NwcmVhZEFycmF5ID0gKHRoaXMgJiYgdGhpcy5fX3NwcmVhZEFycmF5KSB8fCBmdW5jdGlvbiAodG8sIGZyb20sIHBhY2spIHtcbiAgICBpZiAocGFjayB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSBmb3IgKHZhciBpID0gMCwgbCA9IGZyb20ubGVuZ3RoLCBhcjsgaSA8IGw7IGkrKykge1xuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XG4gICAgICAgICAgICBpZiAoIWFyKSBhciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20sIDAsIGkpO1xuICAgICAgICAgICAgYXJbaV0gPSBmcm9tW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0by5jb25jYXQoYXIgfHwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSkpO1xufTtcbmltcG9ydCB7IHByaW50Q29uc29sZSB9IGZyb20gXCJAc2t5cmltLXBsYXRmb3JtL3NreXJpbS1wbGF0Zm9ybVwiO1xuLy8gVE9ETzogcmVkaXJlY3QgdGhpcyB0byBzcGRsb2dcbmV4cG9ydCBmdW5jdGlvbiBsb2dFcnJvcihzZXJ2aWNlKSB7XG4gICAgdmFyIHJlc3QgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDE7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICByZXN0W19pIC0gMV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICB2YXIgcmVzdFByb2Nlc3NlZCA9IHJlc3QubWFwKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmIChpdGVtIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLnN0YWNrIHx8IGl0ZW0ubWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXRlbTtcbiAgICB9KTtcbiAgICBwcmludENvbnNvbGUuYXBwbHkodm9pZCAwLCBfX3NwcmVhZEFycmF5KFtcIkVycm9yIGluIFwiLmNvbmNhdCh0eXBlb2Ygc2VydmljZSAhPT0gXCJzdHJpbmdcIiA/IHNlcnZpY2UuY29uc3RydWN0b3IubmFtZSA6IHNlcnZpY2UsIFwiOlwiKV0sIHJlc3RQcm9jZXNzZWQsIGZhbHNlKSk7XG59XG4vLyBUT0RPOiByZWRpcmVjdCB0aGlzIHRvIHNwZGxvZ1xuZXhwb3J0IGZ1bmN0aW9uIGxvZ1RyYWNlKHNlcnZpY2UpIHtcbiAgICB2YXIgcmVzdCA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHJlc3RbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIHZhciByZXN0UHJvY2Vzc2VkID0gcmVzdC5tYXAoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgaWYgKGl0ZW0gaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0uc3RhY2sgfHwgaXRlbS5tZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpdGVtO1xuICAgIH0pO1xuICAgIHByaW50Q29uc29sZS5hcHBseSh2b2lkIDAsIF9fc3ByZWFkQXJyYXkoW1wiVHJhY2UgaW4gXCIuY29uY2F0KHR5cGVvZiBzZXJ2aWNlICE9PSBcInN0cmluZ1wiID8gc2VydmljZS5jb25zdHJ1Y3Rvci5uYW1lIDogc2VydmljZSwgXCI6XCIpXSwgcmVzdFByb2Nlc3NlZCwgZmFsc2UpKTtcbn1cbiIsImV4cG9ydCB2YXIgTXNnVHlwZTtcbihmdW5jdGlvbiAoTXNnVHlwZSkge1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIkN1c3RvbVBhY2tldFwiXSA9IDFdID0gXCJDdXN0b21QYWNrZXRcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJVcGRhdGVNb3ZlbWVudFwiXSA9IDJdID0gXCJVcGRhdGVNb3ZlbWVudFwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlVwZGF0ZUFuaW1hdGlvblwiXSA9IDNdID0gXCJVcGRhdGVBbmltYXRpb25cIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJVcGRhdGVBcHBlYXJhbmNlXCJdID0gNF0gPSBcIlVwZGF0ZUFwcGVhcmFuY2VcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJVcGRhdGVFcXVpcG1lbnRcIl0gPSA1XSA9IFwiVXBkYXRlRXF1aXBtZW50XCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiQWN0aXZhdGVcIl0gPSA2XSA9IFwiQWN0aXZhdGVcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJVcGRhdGVQcm9wZXJ0eVwiXSA9IDddID0gXCJVcGRhdGVQcm9wZXJ0eVwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlB1dEl0ZW1cIl0gPSA4XSA9IFwiUHV0SXRlbVwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlRha2VJdGVtXCJdID0gOV0gPSBcIlRha2VJdGVtXCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiRmluaXNoU3BTbmlwcGV0XCJdID0gMTBdID0gXCJGaW5pc2hTcFNuaXBwZXRcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJPbkVxdWlwXCJdID0gMTFdID0gXCJPbkVxdWlwXCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiQ29uc29sZUNvbW1hbmRcIl0gPSAxMl0gPSBcIkNvbnNvbGVDb21tYW5kXCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiQ3JhZnRJdGVtXCJdID0gMTNdID0gXCJDcmFmdEl0ZW1cIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJIb3N0XCJdID0gMTRdID0gXCJIb3N0XCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiQ3VzdG9tRXZlbnRcIl0gPSAxNV0gPSBcIkN1c3RvbUV2ZW50XCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiQ2hhbmdlVmFsdWVzXCJdID0gMTZdID0gXCJDaGFuZ2VWYWx1ZXNcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJPbkhpdFwiXSA9IDE3XSA9IFwiT25IaXRcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJEZWF0aFN0YXRlQ29udGFpbmVyXCJdID0gMThdID0gXCJEZWF0aFN0YXRlQ29udGFpbmVyXCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiRHJvcEl0ZW1cIl0gPSAxOV0gPSBcIkRyb3BJdGVtXCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiVGVsZXBvcnRcIl0gPSAyMF0gPSBcIlRlbGVwb3J0XCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiT3BlbkNvbnRhaW5lclwiXSA9IDIxXSA9IFwiT3BlbkNvbnRhaW5lclwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlBsYXllckJvd1Nob3RcIl0gPSAyMl0gPSBcIlBsYXllckJvd1Nob3RcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJTcGVsbENhc3RcIl0gPSAyM10gPSBcIlNwZWxsQ2FzdFwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlVwZGF0ZUFuaW1WYXJpYWJsZXNcIl0gPSAyNF0gPSBcIlVwZGF0ZUFuaW1WYXJpYWJsZXNcIjtcbiAgICAvLyBleC1zdHJpbmdzXG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiRGVzdHJveUFjdG9yXCJdID0gMjVdID0gXCJEZXN0cm95QWN0b3JcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJIb3N0U3RhcnRcIl0gPSAyNl0gPSBcIkhvc3RTdGFydFwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIkhvc3RTdG9wXCJdID0gMjddID0gXCJIb3N0U3RvcFwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlNldEludmVudG9yeVwiXSA9IDI4XSA9IFwiU2V0SW52ZW50b3J5XCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiU2V0UmFjZU1lbnVPcGVuXCJdID0gMjldID0gXCJTZXRSYWNlTWVudU9wZW5cIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJTcFNuaXBwZXRcIl0gPSAzMF0gPSBcIlNwU25pcHBldFwiO1xuICAgIE1zZ1R5cGVbTXNnVHlwZVtcIlRlbGVwb3J0MlwiXSA9IDMxXSA9IFwiVGVsZXBvcnQyXCI7XG4gICAgTXNnVHlwZVtNc2dUeXBlW1wiVXBkYXRlR2FtZW1vZGVEYXRhXCJdID0gMzJdID0gXCJVcGRhdGVHYW1lbW9kZURhdGFcIjtcbiAgICBNc2dUeXBlW01zZ1R5cGVbXCJDcmVhdGVBY3RvclwiXSA9IDMzXSA9IFwiQ3JlYXRlQWN0b3JcIjtcbn0pKE1zZ1R5cGUgfHwgKE1zZ1R5cGUgPSB7fSkpO1xuIiwiaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSBcImV2ZW50ZW1pdHRlcjNcIjtcbnZhciBFdmVudEVtaXR0ZXJGYWN0b3J5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlckZhY3RvcnkoKSB7XG4gICAgfVxuICAgIEV2ZW50RW1pdHRlckZhY3RvcnkubWFrZUV2ZW50RW1pdHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIChuZXcgRXZlbnRFbWl0dGVyKCkpO1xuICAgIH07XG4gICAgcmV0dXJuIEV2ZW50RW1pdHRlckZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgRXZlbnRFbWl0dGVyRmFjdG9yeSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IE1zZ1R5cGUgfSBmcm9tIFwiLi4vLi4vbWVzc2FnZXNcIjtcbmltcG9ydCB7IGdldEludmVudG9yeSB9IGZyb20gXCIuLi8uLi9zeW5jL2ludmVudG9yeVwiO1xuLy8gVE9ETzogcmVmYWN0b3IgdGhpcyBvdXRcbmltcG9ydCB7IGxvY2FsSWRUb1JlbW90ZUlkIH0gZnJvbSBcIi4uLy4uL3ZpZXcvd29ybGRWaWV3TWlzY1wiO1xuaW1wb3J0IHsgTGFzdEludlNlcnZpY2UgfSBmcm9tIFwiLi9sYXN0SW52U2VydmljZVwiO1xuaW1wb3J0IHsgbG9nRXJyb3IsIGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IEZvcm1UeXBlRXggfSBmcm9tIFwiLi4vLi4vZXh0ZW5zaW9ucy9mb3JtVHlwZUV4XCI7XG52YXIgQWN0aXZhdGlvblNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEFjdGl2YXRpb25TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFjdGl2YXRpb25TZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwiYWN0aXZhdGVcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uQWN0aXZhdGUoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFjdGl2YXRpb25TZXJ2aWNlLnByb3RvdHlwZS5vbkFjdGl2YXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGxhc3RJbnZTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKExhc3RJbnZTZXJ2aWNlKTtcbiAgICAgICAgbGFzdEludlNlcnZpY2UubGFzdEludiA9IGdldEludmVudG9yeSh0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCkpO1xuICAgICAgICB2YXIgY2FzdGVyID0gZS5jYXN0ZXIgPyBlLmNhc3Rlci5nZXRGb3JtSUQoKSA6IDA7XG4gICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldCA/IGUudGFyZ2V0LmdldEZvcm1JRCgpIDogMDtcbiAgICAgICAgaWYgKCF0YXJnZXQgfHwgIWNhc3Rlcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEJsb3F1ZWFyIGVsIFwiYWdhcnJlXCIgZGUgaXRlbXMgc3VlbHRvcyBkZWwgbXVuZG86IHNpIGVsIHRhcmdldCBlc1xuICAgICAgICAvLyB1biBpdGVtIChjbHV0dGVyIGRlIGxhIGNpdWRhZCwgZXRjLiksIG5vIG1hbmRhbW9zIGVsIEFjdGl2YXRlIGFsXG4gICAgICAgIC8vIHNlcnZlciwgYXNpIG51bmNhIHBhc2EgYWwgaW52ZW50YXJpby4gTGEgYWN0aXZhY2lvbiB2YW5pbGxhIHlhXG4gICAgICAgIC8vIGVzdGEgYmxvcXVlYWRhIHBvciBPYmplY3RSZWZlcmVuY2VFeC5kZWFsV2l0aFJlZiwgYXNpIHF1ZSBhcHJldGFyXG4gICAgICAgIC8vIEUgc29icmUgZWwgaXRlbSBubyBoYWNlIG5hZGEuIFB1ZXJ0YXMgLyBjb250ZW5lZG9yZXMgLyBOUENzIG5vIHNlXG4gICAgICAgIC8vIHZlbiBhZmVjdGFkb3Mg4oCUIHNvbG8gbG9zIEZvcm1UeXBlIGRlIGl0ZW0gKEZvcm1UeXBlRXguaXNJdGVtKS5cbiAgICAgICAgdmFyIHRhcmdldEJhc2UgPSBlLnRhcmdldCA/IGUudGFyZ2V0LmdldEJhc2VPYmplY3QoKSA6IG51bGw7XG4gICAgICAgIGlmICh0YXJnZXRCYXNlICYmIEZvcm1UeXBlRXguaXNJdGVtKHRhcmdldEJhc2UuZ2V0VHlwZSgpKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFjdG9ycyBuZXZlciBoYXZlIG5vbi1mZiBpZHMgbG9jYWxseSBpbiBza3ltcFxuICAgICAgICBpZiAoY2FzdGVyICE9PSAweDE0ICYmIGNhc3RlciA8IDB4ZmYwMDAwMDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0YXJnZXQgPSBsb2NhbElkVG9SZW1vdGVJZCh0YXJnZXQpO1xuICAgICAgICBpZiAoIXRhcmdldCkge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgJ2xvY2FsSWRUb1JlbW90ZUlkIHJldHVybmVkIDAgKHRhcmdldCkgaW4gb24oXFwnYWN0aXZhdGVcXCcpJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY2FzdGVyID0gbG9jYWxJZFRvUmVtb3RlSWQoY2FzdGVyKTtcbiAgICAgICAgaWYgKCFjYXN0ZXIpIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsICdsb2NhbElkVG9SZW1vdGVJZCByZXR1cm5lZCAwIChjYXN0ZXIpIGluIG9uKFxcJ2FjdGl2YXRlXFwnKScpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvcGVuU3RhdGUgPSBlLnRhcmdldC5nZXRPcGVuU3RhdGUoKTtcbiAgICAgICAgaWYgKG9wZW5TdGF0ZSA9PT0gMiAvKiBPcGVuU3RhdGUuT3BlbmluZyAqLyB8fCBvcGVuU3RhdGUgPT09IDQgLyogT3BlblN0YXRlLkNsb3NpbmcgKi8pIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiSWdub3JpbmcgYWN0aXZhdGlvbiBvZiBkb29yIGJlY2F1c2UgaXQncyBhbHJlYWR5IG9wZW5pbmcgb3IgY2xvc2luZ1wiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgbWVzc2FnZToge1xuICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuQWN0aXZhdGUsXG4gICAgICAgICAgICAgICAgZGF0YTogeyBjYXN0ZXI6IGNhc3RlciwgdGFyZ2V0OiB0YXJnZXQsIGlzU2Vjb25kQWN0aXZhdGlvbjogZmFsc2UgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlbGlhYmlsaXR5OiBcInJlbGlhYmxlXCJcbiAgICAgICAgfSk7XG4gICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiU2VudCBhY3RpdmF0aW9uIGZvciBjYXN0ZXI9XCIsIGNhc3Rlci50b1N0cmluZygxNiksIFwiYW5kIHRhcmdldD1cIiwgdGFyZ2V0LnRvU3RyaW5nKDE2KSk7XG4gICAgfTtcbiAgICByZXR1cm4gQWN0aXZhdGlvblNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBBY3RpdmF0aW9uU2VydmljZSB9O1xuO1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiA9ICh0aGlzICYmIHRoaXMuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG5pbXBvcnQgeyBsb2dUcmFjZSwgbG9nRXJyb3IgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0IHsgc2V0VGV4dFNpemUgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbnZhciBwbGF5ZXJJZCA9IDB4MTQ7XG52YXIgQW5pbURlYnVnU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQW5pbURlYnVnU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBbmltRGVidWdTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMuc2V0dGluZ3MgPSBfdGhpcy5zcC5zZXR0aW5nc1tcInNreW1wNS1jbGllbnRcIl1bXCJhbmltRGVidWdcIl07XG4gICAgICAgIC8vIGNsZWFyIHByZXZpb3VzIHRleHRzIGluIGNhc2Ugb2YgaG90cmVsb2FkXG4gICAgICAgIGlmIChfdGhpcy5zcC5zdG9yYWdlW0FuaW1RdWV1ZUNvbGxlY3Rpb24uTmFtZV0gJiYgX3RoaXMuc3Auc3RvcmFnZVtBbmltUXVldWVDb2xsZWN0aW9uLk5hbWVdLmNsZWFyU1BUZXh0KSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJEZXN0cm95aW5nIG9sZCBBbmltUXVldWVDb2xsZWN0aW9uXCIpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zcC5zdG9yYWdlW0FuaW1RdWV1ZUNvbGxlY3Rpb24uTmFtZV0uY2xlYXJTUFRleHQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiRmFpbGVkIHRvIGRlc3Ryb3kgb2xkIEFuaW1RdWV1ZUNvbGxlY3Rpb246XCIsIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBzZWxmID0gX3RoaXM7XG4gICAgICAgIF90aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIChjdHgpIHsgfSxcbiAgICAgICAgICAgIGxlYXZlOiBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5vblNlbmRBbmltYXRpb25FdmVudExlYXZlKGN0eCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHBsYXllcklkLCBwbGF5ZXJJZCk7XG4gICAgICAgIGlmICghX3RoaXMuc2V0dGluZ3MgfHwgIV90aGlzLnNldHRpbmdzLmlzQWN0aXZlKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChfYSA9IF90aGlzLnNldHRpbmdzLnRleHRPdXRwdXQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pc0FjdGl2ZSkge1xuICAgICAgICAgICAgX3RoaXMucXVldWUgPSBuZXcgQW5pbVF1ZXVlQ29sbGVjdGlvbihfdGhpcy5zcCwgX3RoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgX3RoaXMuc3Auc3RvcmFnZVtBbmltUXVldWVDb2xsZWN0aW9uLm5hbWVdID0gX3RoaXMucXVldWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBbmltRGVidWdTZXJ2aWNlLnByb3RvdHlwZS5vblNlbmRBbmltYXRpb25FdmVudExlYXZlID0gZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKGN0eC5hbmltRXZlbnROYW1lLCBjdHguYW5pbWF0aW9uU3VjY2VlZGVkID8gYW5pbWF0aW9uU3VjY2VlZGVkVGV4dENvbG9yIDogYW5pbWF0aW9uTm90U3VjY2VlZGVkVGV4dENvbG9yKTtcbiAgICB9O1xuICAgIHJldHVybiBBbmltRGVidWdTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgQW5pbURlYnVnU2VydmljZSB9O1xudmFyIGFuaW1hdGlvblN1Y2NlZWRlZFRleHRDb2xvciA9IFsyNTUsIDI1NSwgMjU1LCAxXTtcbnZhciBhbmltYXRpb25Ob3RTdWNjZWVkZWRUZXh0Q29sb3IgPSBbMjU1LCAwLCAwLCAxXTtcbnZhciBBbmltUXVldWVDb2xsZWN0aW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEFuaW1RdWV1ZUNvbGxlY3Rpb24oc3AsIHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBfYSwgX2IsIF9jLCBfZCwgX2UsIF9mO1xuICAgICAgICB0aGlzLnNwID0gc3A7XG4gICAgICAgIHZhciBhcnJheUxlbmd0aCA9IChfYiA9IChfYSA9IHNldHRpbmdzID09PSBudWxsIHx8IHNldHRpbmdzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzZXR0aW5ncy50ZXh0T3V0cHV0KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuaXRlbUNvdW50KSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiA1O1xuICAgICAgICB2YXIgc3RhcnRQb3MgPSAoX2QgPSAoX2MgPSBzZXR0aW5ncyA9PT0gbnVsbCB8fCBzZXR0aW5ncyA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2V0dGluZ3MudGV4dE91dHB1dCkgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLnN0YXJ0UG9zKSAhPT0gbnVsbCAmJiBfZCAhPT0gdm9pZCAwID8gX2QgOiB7IHg6IDY1MCwgeTogNjAwIH07XG4gICAgICAgIDtcbiAgICAgICAgdmFyIHlQb3NEZWx0YSA9IChfZiA9IChfZSA9IHNldHRpbmdzID09PSBudWxsIHx8IHNldHRpbmdzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzZXR0aW5ncy50ZXh0T3V0cHV0KSA9PT0gbnVsbCB8fCBfZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2UueVBvc0RlbHRhKSAhPT0gbnVsbCAmJiBfZiAhPT0gdm9pZCAwID8gX2YgOiAzMjtcbiAgICAgICAgdmFyIHkgPSBzdGFydFBvcy55O1xuICAgICAgICB0aGlzLmxpc3QgPSBuZXcgQXJyYXkoYXJyYXlMZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpZHggPSAwOyBpZHggPCBhcnJheUxlbmd0aDsgKytpZHgpIHtcbiAgICAgICAgICAgIHRoaXMubGlzdFtpZHhdID0geyBuYW1lOiBcIlwiLCB0ZXh0SWQ6IHNwLmNyZWF0ZVRleHQoc3RhcnRQb3MueCwgeSwgXCJcIiwgYW5pbWF0aW9uU3VjY2VlZGVkVGV4dENvbG9yKSwgY29sb3I6IGFuaW1hdGlvblN1Y2NlZWRlZFRleHRDb2xvciB9O1xuICAgICAgICAgICAgc2V0VGV4dFNpemUodGhpcy5saXN0W2lkeF0udGV4dElkLCAwLjUpO1xuICAgICAgICAgICAgeSArPSB5UG9zRGVsdGE7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQW5pbVF1ZXVlQ29sbGVjdGlvbi5wcm90b3R5cGUuY2xlYXJTUFRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLmxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5saXN0LmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHsgcmV0dXJuIF90aGlzLnNwLmRlc3Ryb3lUZXh0KGl0ZW0udGV4dElkKTsgfSk7XG4gICAgfTtcbiAgICBBbmltUXVldWVDb2xsZWN0aW9uLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24gKGFuaW1OYW1lLCBjb2xvcikge1xuICAgICAgICB2YXIgcHJldkl0ZW0gPSBudWxsO1xuICAgICAgICBmb3IgKHZhciBpZHggPSB0aGlzLmxpc3QubGVuZ3RoIC0gMTsgaWR4ID49IDA7IC0taWR4KSB7XG4gICAgICAgICAgICB2YXIgaXRlbSA9IHRoaXMubGlzdFtpZHhdO1xuICAgICAgICAgICAgcHJldkl0ZW0gPSBfX2Fzc2lnbih7fSwgaXRlbSk7XG4gICAgICAgICAgICBpdGVtLm5hbWUgPSBhbmltTmFtZTtcbiAgICAgICAgICAgIGl0ZW0uY29sb3IgPSBjb2xvcjtcbiAgICAgICAgICAgIHRoaXMuc3Auc2V0VGV4dFN0cmluZyhpdGVtLnRleHRJZCwgaXRlbS5uYW1lKTtcbiAgICAgICAgICAgIHRoaXMuc3Auc2V0VGV4dENvbG9yKGl0ZW0udGV4dElkLCBpdGVtLmNvbG9yKTtcbiAgICAgICAgICAgIGFuaW1OYW1lID0gcHJldkl0ZW0ubmFtZTtcbiAgICAgICAgICAgIGNvbG9yID0gcHJldkl0ZW0uY29sb3I7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFuaW1RdWV1ZUNvbGxlY3Rpb24uTmFtZSA9IFwiQW5pbVF1ZXVlQ29sbGVjdGlvblwiO1xuICAgIHJldHVybiBBbmltUXVldWVDb2xsZWN0aW9uO1xufSgpKTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBhdXRoR2FtZURhdGFTdG9yYWdlS2V5IH0gZnJvbSBcIi4uLy4uL2ZlYXR1cmVzL2F1dGhNb2RlbFwiO1xuaW1wb3J0IHsgRnVuY3Rpb25JbmZvIH0gZnJvbSBcIi4uLy4uL2xpYi9mdW5jdGlvbkluZm9cIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IGJyb3dzZXIgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IFRpbWVyc1NlcnZpY2UgfSBmcm9tIFwiLi90aW1lcnNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBsb2dUcmFjZSwgbG9nRXJyb3IgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgTmV0d29ya2luZ1NlcnZpY2UgfSBmcm9tIFwiLi9uZXR3b3JraW5nU2VydmljZVwiO1xuaW1wb3J0IHsgTXNnVHlwZSB9IGZyb20gXCIuLi8uLi9tZXNzYWdlc1wiO1xuaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSBcIi4vc2V0dGluZ3NTZXJ2aWNlXCI7XG4vLyBDb25zdGFudHMgdXNlZCBvbiBib3RoIGNsaWVudCBhbmQgYnJvd3NlciBzaWRlIChzZWUgYnJvd3NlcnNpZGVXaWRnZXRTZXR0ZXIpXG52YXIgZXZlbnRzID0ge1xuICAgIG9wZW5EaXNjb3JkT2F1dGg6ICdvcGVuRGlzY29yZE9hdXRoJyxcbiAgICBhdXRoQXR0ZW1wdDogJ2F1dGhBdHRlbXB0RXZlbnQnLFxuICAgIG9wZW5HaXRodWI6ICdvcGVuR2l0aHViJyxcbiAgICBvcGVuUGF0cmVvbjogJ29wZW5QYXRyZW9uJyxcbiAgICBjbGVhckF1dGhEYXRhOiAnY2xlYXJBdXRoRGF0YScsXG4gICAgdXBkYXRlUmVxdWlyZWQ6ICd1cGRhdGVSZXF1aXJlZCcsXG4gICAgYmFja1RvTG9naW46ICdiYWNrVG9Mb2dpbicsXG4gICAgam9pbkRpc2NvcmQ6ICdqb2luRGlzY29yZCdcbn07XG4vLyBWYWlhYmxlcyB1c2VkIG9uIGJvdGggY2xpZW50IGFuZCBicm93c2VyIHNpZGUgKHNlZSBicm93c2Vyc2lkZVdpZGdldFNldHRlcilcbnZhciBicm93c2VyU3RhdGUgPSB7XG4gICAgY29tbWVudDogJycsXG4gICAgZmFpbENvdW50OiA5MDAwLFxuICAgIGxvZ2luRmFpbGVkUmVhc29uOiAnJyxcbn07XG52YXIgYXV0aERhdGEgPSBudWxsO1xudmFyIHRyYW5zbGF0aW9ucyA9IHtcbiAgICBcInJ1XCI6IHtcbiAgICAgICAgbG9naW5WaWFEaXNjb3JkOiAn0LLQvtC50LTQuNGC0LUg0YfQtdGA0LXQtyBkaXNjb3JkJyxcbiAgICAgICAgam9pbkRpc2NvcmRTZXJ2ZXI6ICfQstGB0YLRg9C/0LjRgtC1INCyIGRpc2NvcmQg0YHQtdGA0LLQtdGAJyxcbiAgICAgICAgYmFubmVkOiAn0LLRiyDQt9Cw0LHQsNC90LXQvdGLJyxcbiAgICAgICAgd2hhdFdhc1RoYXQ6ICfRh9GC0L4g0Y3RgtC+INCx0YvQu9C+PycsXG4gICAgICAgIG9wZW5pbmdCcm93c2VyOiAn0L7RgtC60YDRi9Cy0LDQtdC8INCx0YDQsNGD0LfQtdGALi4uJyxcbiAgICAgICAgbG9naW5GaXJzdDogJ9GB0L3QsNGH0LDQu9CwINCy0L7QudC00LjRgtC1JyxcbiAgICAgICAgbGlua2VkU3VjY2Vzc2Z1bGx5OiAn0L/RgNC40LLRj9C30LDQvSDRg9GB0L/QtdGI0L3QvicsXG4gICAgICAgIGNvbm5lY3Rpbmc6ICfQv9C+0LTQutC70Y7Rh9C10L3QuNC1JyxcbiAgICAgICAgdGVjaG5pY2FsSXNzdWVzOiAn0YLQtdGF0L3QuNGH0LXRgdC60LjQtSDRiNC+0LrQvtC70LDQtNC60LhcXG7Qv9C+0L/RgNC+0LHRg9C50YLQtSDQtdGJ0LUg0YDQsNC3XFxu0L/QvtC20LDQu9GD0LnRgdGC0LBcXG7QuNC70Lgg0L3QsNC/0LjRiNC40YLQtSDQvdCw0Lwg0LIgZGlzY29yZCcsXG4gICAgICAgIGF1dGhvcml6YXRpb246ICfQkNCy0YLQvtGA0LjQt9Cw0YbQuNGPJyxcbiAgICAgICAgbm90QXV0aG9yaXplZDogJ9C90LUg0LDQstGC0L7RgNC40LfQuNGA0L7QstCw0L0nLFxuICAgICAgICBjaGFuZ2VBY2NvdW50OiAn0YHQvNC10L3QuNGC0Ywg0LDQutC60LDRg9C90YInLFxuICAgICAgICBsb2dpblZpYVNreW1wOiAn0LLQvtC50YLQuCDRh9C10YDQtdC3IHNreW1wJyxcbiAgICAgICAgcGxheTogJ9CY0LPRgNCw0YLRjCcsXG4gICAgICAgIGxvZ2luT3JDaGFuZ2VIaW50OiAn0JLRiyDQvNC+0LbQtdGC0LUg0LLQvtC50YLQuCDQuNC70Lgg0L/QvtC80LXQvdGP0YLRjCDQsNC60LrQsNGD0L3RgicsXG4gICAgICAgIGNvbm5lY3RUb1NlcnZlcjogJ9Cf0L7QtNC60LvRjtGH0LjRgtGM0YHRjyDQuiDQuNCz0YDQvtCy0L7QvNGDINGB0LXRgNCy0LXRgNGDJyxcbiAgICAgICAgdXBkYXRlQ2FwdGlvbjogJ9C90L7QstC40L3QutCwJyxcbiAgICAgICAgdXBkYXRlQXZhaWxhYmxlOiAn0YPRgNCwISDQstGL0YjQu9C+INC+0LHQvdC+0LLQu9C10L3QuNC1JyxcbiAgICAgICAgZG93bmxvYWRBdDogJ9GB0L/QtdGI0LjRgtC1INGB0LrQsNGH0LDRgtGMINC90LAnLFxuICAgICAgICBvcGVuU2t5bXBOZXQ6ICfQvtGC0LrRgNGL0YLRjCBza3ltcC5uZXQnLFxuICAgICAgICB1cGRhdGVEb3dubG9hZEhpbnQ6ICfQn9C10YDQtdC50YLQuCDQvdCwINGB0YLRgNCw0L3QuNGG0YMg0YHQutCw0YfQuNCy0LDQvdC40Y8g0L7QsdC90L7QstC70LXQvdC40Y8nLFxuICAgICAgICBvb3BzOiAn0YPQv9GBJyxcbiAgICAgICAgam9pbjogJ9Cy0YHRgtGD0L/QuNGC0YwnLFxuICAgICAgICBiYWNrOiAn0L3QsNC30LDQtCcsXG4gICAgfSxcbiAgICBcImVuXCI6IHtcbiAgICAgICAgbG9naW5WaWFEaXNjb3JkOiAnbG9nIGluIHZpYSBEaXNjb3JkJyxcbiAgICAgICAgam9pbkRpc2NvcmRTZXJ2ZXI6ICdqb2luIHRoZSBEaXNjb3JkIHNlcnZlcicsXG4gICAgICAgIGJhbm5lZDogJ3lvdSBhcmUgYmFubmVkJyxcbiAgICAgICAgd2hhdFdhc1RoYXQ6ICd3aGF0IHdhcyB0aGF0PycsXG4gICAgICAgIG9wZW5pbmdCcm93c2VyOiAnb3BlbmluZyBicm93c2VyLi4uJyxcbiAgICAgICAgbG9naW5GaXJzdDogJ2xvZyBpbiBmaXJzdCcsXG4gICAgICAgIGxpbmtlZFN1Y2Nlc3NmdWxseTogJ2xpbmtlZCBzdWNjZXNzZnVsbHknLFxuICAgICAgICBjb25uZWN0aW5nOiAnY29ubmVjdGluZycsXG4gICAgICAgIHRlY2huaWNhbElzc3VlczogJ3RlY2huaWNhbCBkaWZmaWN1bHRpZXNcXG5wbGVhc2UgdHJ5IGFnYWluXFxub3IgY29udGFjdCB1cyBvbiBEaXNjb3JkJyxcbiAgICAgICAgYXV0aG9yaXphdGlvbjogJ0F1dGhvcml6YXRpb24nLFxuICAgICAgICBub3RBdXRob3JpemVkOiAnbm90IGF1dGhvcml6ZWQnLFxuICAgICAgICBjaGFuZ2VBY2NvdW50OiAnY2hhbmdlIGFjY291bnQnLFxuICAgICAgICBsb2dpblZpYVNreW1wOiAnbG9nIGluIHZpYSBza3ltcCcsXG4gICAgICAgIHBsYXk6ICdQbGF5JyxcbiAgICAgICAgbG9naW5PckNoYW5nZUhpbnQ6ICdZb3UgY2FuIGxvZyBpbiBvciBjaGFuZ2UgeW91ciBhY2NvdW50JyxcbiAgICAgICAgY29ubmVjdFRvU2VydmVyOiAnQ29ubmVjdCB0byBnYW1lIHNlcnZlcicsXG4gICAgICAgIHVwZGF0ZUNhcHRpb246ICdVcGRhdGUnLFxuICAgICAgICB1cGRhdGVBdmFpbGFibGU6ICdhIG5ldyB1cGRhdGUgaXMgYXZhaWxhYmxlIScsXG4gICAgICAgIGRvd25sb2FkQXQ6ICdkb3dubG9hZCBpdCBhdCcsXG4gICAgICAgIG9wZW5Ta3ltcE5ldDogJ29wZW4gc2t5bXAubmV0JyxcbiAgICAgICAgdXBkYXRlRG93bmxvYWRIaW50OiAnR28gdG8gdGhlIHVwZGF0ZSBkb3dubG9hZCBwYWdlJyxcbiAgICAgICAgb29wczogJ29vcHMnLFxuICAgICAgICBqb2luOiAnam9pbicsXG4gICAgICAgIGJhY2s6ICdiYWNrJyxcbiAgICB9LFxufTtcbnZhciBzdHJpbmdzID0gdHJhbnNsYXRpb25zWydlbiddO1xudHJ5IHtcbiAgICB2YXIgbGFuZyA9IGZzLnJlYWRGaWxlU3luYygnLi9EYXRhL1BsYXRmb3JtL0Rpc3RyaWJ1dGlvbi9sb2NhbGUnLCAndXRmOCcpLnRyaW0oKTtcbiAgICBpZiAobGFuZyBpbiB0cmFuc2xhdGlvbnMpIHtcbiAgICAgICAgc3RyaW5ncyA9IHRyYW5zbGF0aW9uc1tsYW5nXTtcbiAgICAgICAgdmFyIHNyYyA9IFwid2luZG93LnNldExhbmd1YWdlKFwiLmNvbmNhdChsYW5nLCBcIilcIik7XG4gICAgICAgIGJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQoc3JjKTtcbiAgICB9XG59XG5jYXRjaCAoX2EpIHtcbiAgICAvLyBsb2NhbGUgZmlsZSBub3QgZm91bmQgb3IgdW5yZWFkYWJsZSwgZGVmYXVsdCB0byAnZW4nXG59XG52YXIgQXV0aFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEF1dGhTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEF1dGhTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5kZW5pZWRXaWRnZXRTZXR0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgd2lkZ2V0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiZm9ybVwiLFxuICAgICAgICAgICAgICAgIGlkOiAyLFxuICAgICAgICAgICAgICAgIGNhcHRpb246IHN0cmluZ3MudXBkYXRlQ2FwdGlvbixcbiAgICAgICAgICAgICAgICBlbGVtZW50czogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IHN0cmluZ3MudXBkYXRlQXZhaWxhYmxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGFnczogW11cbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBzdHJpbmdzLmRvd25sb2FkQXQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdzOiBbXVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IFwic2t5bXAubmV0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdzOiBbXVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImJ1dHRvblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogc3RyaW5ncy5vcGVuU2t5bXBOZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdzOiBbXCJFTEVNRU5UX1NUWUxFX01BUkdJTl9FWFRFTkRFRFwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuc2t5cmltUGxhdGZvcm0uc2VuZE1lc3NhZ2UoZXZlbnRzLnVwZGF0ZVJlcXVpcmVkKTsgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpbnQ6IHN0cmluZ3MudXBkYXRlRG93bmxvYWRIaW50LFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHdpbmRvdy5za3lyaW1QbGF0Zm9ybS53aWRnZXRzLnNldChbd2lkZ2V0XSk7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgZ2FtZW1vZGUgd2lsbCBub3QgYmUgYWJsZSB0byB1cGRhdGUgd2lkZ2V0cyBhbnltb3JlXG4gICAgICAgICAgICB3aW5kb3cuc2t5cmltUGxhdGZvcm0ud2lkZ2V0cyA9IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmxvZ2luRmFpbGVkV2lkZ2V0U2V0dGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNwbGl0UGFydHMgPSBicm93c2VyU3RhdGUubG9naW5GYWlsZWRSZWFzb24uc3BsaXQoJ1xcbicpO1xuICAgICAgICAgICAgdmFyIHRleHRFbGVtZW50cyA9IHNwbGl0UGFydHMubWFwKGZ1bmN0aW9uIChwYXJ0KSB7IHJldHVybiAoe1xuICAgICAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgICAgIHRleHQ6IHBhcnQsXG4gICAgICAgICAgICAgICAgdGFnczogW10sXG4gICAgICAgICAgICB9KTsgfSk7XG4gICAgICAgICAgICB2YXIgd2lkZ2V0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiZm9ybVwiLFxuICAgICAgICAgICAgICAgIGlkOiAyLFxuICAgICAgICAgICAgICAgIGNhcHRpb246IHN0cmluZ3Mub29wcyxcbiAgICAgICAgICAgICAgICBlbGVtZW50czogbmV3IEFycmF5KClcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0ZXh0RWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkgeyByZXR1cm4gd2lkZ2V0LmVsZW1lbnRzLnB1c2goZWxlbWVudCk7IH0pO1xuICAgICAgICAgICAgaWYgKGJyb3dzZXJTdGF0ZS5sb2dpbkZhaWxlZFJlYXNvbiA9PT0gc3RyaW5ncy5qb2luRGlzY29yZFNlcnZlcikge1xuICAgICAgICAgICAgICAgIHdpZGdldC5lbGVtZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJidXR0b25cIixcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogc3RyaW5ncy5qb2luLFxuICAgICAgICAgICAgICAgICAgICB0YWdzOiBbXCJFTEVNRU5UX1NUWUxFX01BUkdJTl9FWFRFTkRFRFwiXSxcbiAgICAgICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5za3lyaW1QbGF0Zm9ybS5zZW5kTWVzc2FnZShldmVudHMuam9pbkRpc2NvcmQpOyB9LFxuICAgICAgICAgICAgICAgICAgICBoaW50OiBudWxsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aWRnZXQuZWxlbWVudHMucHVzaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJidXR0b25cIixcbiAgICAgICAgICAgICAgICB0ZXh0OiBzdHJpbmdzLmJhY2ssXG4gICAgICAgICAgICAgICAgdGFnczogW1wiRUxFTUVOVF9TVFlMRV9NQVJHSU5fRVhURU5ERURcIl0sXG4gICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5za3lyaW1QbGF0Zm9ybS5zZW5kTWVzc2FnZShldmVudHMuYmFja1RvTG9naW4pOyB9LFxuICAgICAgICAgICAgICAgIGhpbnQ6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB3aW5kb3cuc2t5cmltUGxhdGZvcm0ud2lkZ2V0cy5zZXQoW3dpZGdldF0pO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5icm93c2Vyc2lkZVdpZGdldFNldHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBsb2dpbldpZGdldCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcImZvcm1cIixcbiAgICAgICAgICAgICAgICBpZDogMSxcbiAgICAgICAgICAgICAgICBjYXB0aW9uOiBzdHJpbmdzLmF1dGhvcml6YXRpb24sXG4gICAgICAgICAgICAgICAgZWxlbWVudHM6IFtcbiAgICAgICAgICAgICAgICAgICAgLy8ge1xuICAgICAgICAgICAgICAgICAgICAvLyAgIHR5cGU6IFwiYnV0dG9uXCIsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgdGFnczogW1wiQlVUVE9OX1NUWUxFX0dJVEhVQlwiXSxcbiAgICAgICAgICAgICAgICAgICAgLy8gICBoaW50OiBcImdldCBhIGNvbG9yZWQgbmlja25hbWUgYW5kIG1lbnRpb24gaW4gbmV3c1wiLFxuICAgICAgICAgICAgICAgICAgICAvLyAgIGNsaWNrOiAoKSA9PiB3aW5kb3cuc2t5cmltUGxhdGZvcm0uc2VuZE1lc3NhZ2UoZXZlbnRzLm9wZW5HaXRodWIpLFxuICAgICAgICAgICAgICAgICAgICAvLyB9LFxuICAgICAgICAgICAgICAgICAgICAvLyB7XG4gICAgICAgICAgICAgICAgICAgIC8vICAgdHlwZTogXCJidXR0b25cIixcbiAgICAgICAgICAgICAgICAgICAgLy8gICB0YWdzOiBbXCJCVVRUT05fU1RZTEVfUEFUUkVPTlwiLCBcIkVMRU1FTlRfU0FNRV9MSU5FXCIsIFwiSElOVF9TVFlMRV9SSUdIVFwiXSxcbiAgICAgICAgICAgICAgICAgICAgLy8gICBoaW50OiBcImdldCBhIGNvbG9yZWQgbmlja25hbWUgYW5kIG90aGVyIGJvbnVzZXMgZm9yIHBhdHJvbnNcIixcbiAgICAgICAgICAgICAgICAgICAgLy8gICBjbGljazogKCkgPT4gd2luZG93LnNreXJpbVBsYXRmb3JtLnNlbmRNZXNzYWdlKGV2ZW50cy5vcGVuUGF0cmVvbiksXG4gICAgICAgICAgICAgICAgICAgIC8vIH0sXG4gICAgICAgICAgICAgICAgICAgIC8vIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gICB0eXBlOiBcImljb25cIixcbiAgICAgICAgICAgICAgICAgICAgLy8gICB0ZXh0OiBcInVzZXJuYW1lXCIsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgdGFnczogW1wiSUNPTl9TVFlMRV9TS1lNUFwiXSxcbiAgICAgICAgICAgICAgICAgICAgLy8gfSxcbiAgICAgICAgICAgICAgICAgICAgLy8ge1xuICAgICAgICAgICAgICAgICAgICAvLyAgIHR5cGU6IFwiaWNvblwiLFxuICAgICAgICAgICAgICAgICAgICAvLyAgIHRleHQ6IFwiXCIsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgdGFnczogW1wiSUNPTl9TVFlMRV9ESVNDT1JEXCJdLFxuICAgICAgICAgICAgICAgICAgICAvLyB9LFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IChhdXRoRGF0YSA/IChhdXRoRGF0YS5kaXNjb3JkVXNlcm5hbWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IFwiXCIuY29uY2F0KGF1dGhEYXRhLmRpc2NvcmRVc2VybmFtZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IFwiaWQ6IFwiLmNvbmNhdChhdXRoRGF0YS5tYXN0ZXJBcGlJZCkpIDogc3RyaW5ncy5ub3RBdXRob3JpemVkKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ3M6IFsgLypcIkVMRU1FTlRfU0FNRV9MSU5FXCIsIFwiRUxFTUVOVF9TVFlMRV9NQVJHSU5fRVhURU5ERURcIiovXSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgLy8ge1xuICAgICAgICAgICAgICAgICAgICAvLyAgIHR5cGU6IFwiaWNvblwiLFxuICAgICAgICAgICAgICAgICAgICAvLyAgIHRleHQ6IFwiZGlzY29yZFwiLFxuICAgICAgICAgICAgICAgICAgICAvLyAgIHRhZ3M6IFtcIklDT05fU1RZTEVfRElTQ09SRFwiXSxcbiAgICAgICAgICAgICAgICAgICAgLy8gfSxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJidXR0b25cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGF1dGhEYXRhID8gc3RyaW5ncy5jaGFuZ2VBY2NvdW50IDogc3RyaW5ncy5sb2dpblZpYVNreW1wLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGFnczogWyAvKlwiRUxFTUVOVF9TQU1FX0xJTkVcIiovXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuc2t5cmltUGxhdGZvcm0uc2VuZE1lc3NhZ2UoZXZlbnRzLm9wZW5EaXNjb3JkT2F1dGgpOyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgaGludDogc3RyaW5ncy5sb2dpbk9yQ2hhbmdlSGludCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJidXR0b25cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IHN0cmluZ3MucGxheSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ3M6IFtcIkJVVFRPTl9TVFlMRV9GUkFNRVwiLCBcIkVMRU1FTlRfU1RZTEVfTUFSR0lOX0VYVEVOREVEXCJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5za3lyaW1QbGF0Zm9ybS5zZW5kTWVzc2FnZShldmVudHMuYXV0aEF0dGVtcHQpOyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgaGludDogc3RyaW5ncy5jb25uZWN0VG9TZXJ2ZXIsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogYnJvd3NlclN0YXRlLmNvbW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdzOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgd2luZG93LnNreXJpbVBsYXRmb3JtLndpZGdldHMuc2V0KFtsb2dpbldpZGdldF0pO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5faXNMaXN0ZW5Ccm93c2VyTWVzc2FnZSA9IGZhbHNlO1xuICAgICAgICBfdGhpcy50cmlnZ2VyID0ge1xuICAgICAgICAgICAgYXV0aE5lZWRlZEZpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgIGJyb3dzZXJXaW5kb3dMb2FkZWRGaXJlZDogZmFsc2UsXG4gICAgICAgICAgICBnZXQgY29uZGl0aW9uTWV0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmF1dGhOZWVkZWRGaXJlZCAmJiB0aGlzLmJyb3dzZXJXaW5kb3dMb2FkZWRGaXJlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuZGlzY29yZEF1dGhTdGF0ZSA9IGNyeXB0by5yYW5kb21CeXRlcygzMikudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgICBfdGhpcy5hdXRoRGlhbG9nT3BlbiA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5sb2dnaW5nU3RhcnRNb21lbnQgPSAwO1xuICAgICAgICBfdGhpcy5hdXRoQXR0ZW1wdFByb2dyZXNzSW5kaWNhdG9yID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmF1dGhBdHRlbXB0UHJvZ3Jlc3NJbmRpY2F0b3JDb3VudGVyID0gMDtcbiAgICAgICAgX3RoaXMucGxheWVyRXZlclNhd0FjdHVhbEdhbWVwbGF5ID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmdpdGh1YlVybCA9IFwiaHR0cHM6Ly9naXRodWIuY29tL3NreXJpbS1tdWx0aXBsYXllci9za3ltcFwiO1xuICAgICAgICBfdGhpcy5wYXRyZW9uVXJsID0gXCJodHRwczovL3d3dy5wYXRyZW9uLmNvbS9za3ltcFwiO1xuICAgICAgICBfdGhpcy5wbHVnaW5BdXRoRGF0YU5hbWUgPSBcImF1dGgtZGF0YS1uby1sb2FkXCI7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImF1dGhOZWVkZWRcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uQXV0aE5lZWRlZChlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImJyb3dzZXJXaW5kb3dMb2FkZWRcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uQnJvd3NlcldpbmRvd0xvYWRlZChlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImNyZWF0ZUFjdG9yTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25DcmVhdGVBY3Rvck1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJjb25uZWN0aW9uQWNjZXB0ZWRcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuaGFuZGxlQ29ubmVjdGlvbkFjY2VwdGVkKCk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJjb25uZWN0aW9uRGVuaWVkXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5oYW5kbGVDb25uZWN0aW9uRGVuaWVkKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwiY3VzdG9tUGFja2V0TWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25DdXN0b21QYWNrZXRNZXNzYWdlKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbihcImJyb3dzZXJNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkJyb3dzZXJNZXNzYWdlKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbihcInRpY2tcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25UaWNrKCk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUub25BdXRoTmVlZGVkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJSZWNlaXZlZCBhdXRoTmVlZGVkIGV2ZW50XCIpO1xuICAgICAgICB2YXIgc2V0dGluZ3NHYW1lRGF0YSA9IHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wiZ2FtZURhdGFcIl07XG4gICAgICAgIHZhciBpc09mZmxpbmVNb2RlID0gTnVtYmVyLmlzSW50ZWdlcihzZXR0aW5nc0dhbWVEYXRhID09PSBudWxsIHx8IHNldHRpbmdzR2FtZURhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHNldHRpbmdzR2FtZURhdGEucHJvZmlsZUlkKTtcbiAgICAgICAgaWYgKGlzT2ZmbGluZU1vZGUpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiT2ZmbGluZSBtb2RlIGRldGVjdGVkIGluIHNldHRpbmdzLCBlbWl0dGluZyBhdXRoIGV2ZW50IHdpdGggYXV0aEdhbWVEYXRhLmxvY2FsXCIpO1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImF1dGhBdHRlbXB0XCIsIHsgYXV0aEdhbWVEYXRhOiB7IGxvY2FsOiB7IHByb2ZpbGVJZDogc2V0dGluZ3NHYW1lRGF0YS5wcm9maWxlSWQgfSB9IH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJObyBvZmZsaW5lIG1vZGUgZGV0ZWN0dGVkIGluIHNldHRpbmdzLCByZWd1bGFyIGF1dGggbmVlZGVkXCIpO1xuICAgICAgICAgICAgdGhpcy5zZXRMaXN0ZW5Ccm93c2VyTWVzc2FnZSh0cnVlLCAnYXV0aE5lZWRlZCBldmVudCByZWNlaXZlZCcpO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyLmF1dGhOZWVkZWRGaXJlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGhpcy50cmlnZ2VyLmNvbmRpdGlvbk1ldCkge1xuICAgICAgICAgICAgICAgIHRoaXMub25Ccm93c2VyV2luZG93TG9hZGVkQW5kT25saW5lQXV0aE5lZWRlZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUub25Ccm93c2VyV2luZG93TG9hZGVkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJSZWNlaXZlZCBicm93c2VyV2luZG93TG9hZGVkIGV2ZW50XCIpO1xuICAgICAgICB0aGlzLnRyaWdnZXIuYnJvd3NlcldpbmRvd0xvYWRlZEZpcmVkID0gdHJ1ZTtcbiAgICAgICAgaWYgKHRoaXMudHJpZ2dlci5jb25kaXRpb25NZXQpIHtcbiAgICAgICAgICAgIHRoaXMub25Ccm93c2VyV2luZG93TG9hZGVkQW5kT25saW5lQXV0aE5lZWRlZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUub25DcmVhdGVBY3Rvck1lc3NhZ2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS5tZXNzYWdlLmlzTWUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmF1dGhEaWFsb2dPcGVuKSB7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJSZWNlaXZlZCBjcmVhdGVBY3Rvck1lc3NhZ2UgZm9yIHNlbGYsIHJlc2V0dGluZyB3aWRnZXRzXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5leGVjdXRlSmF2YVNjcmlwdCgnd2luZG93LnNreXJpbVBsYXRmb3JtLndpZGdldHMuc2V0KFtdKTsnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dGhEaWFsb2dPcGVuID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlJlY2VpdmVkIGNyZWF0ZUFjdG9yTWVzc2FnZSBmb3Igc2VsZiwgYnV0IGF1dGggZGlhbG9nIHdhcyBub3Qgb3BlbiBzbyBub3QgcmVzZXR0aW5nIHdpZGdldHNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnaW5nU3RhcnRNb21lbnQgPSAwO1xuICAgICAgICB0aGlzLmF1dGhBdHRlbXB0UHJvZ3Jlc3NJbmRpY2F0b3IgPSBmYWxzZTtcbiAgICB9O1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5vbkN1c3RvbVBhY2tldE1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIHZhciBtc2dDb250ZW50ID0ge307XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBtc2dDb250ZW50ID0gSlNPTi5wYXJzZShtc2cuY29udGVudEpzb25EdW1wKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTeW50YXhFcnJvcikge1xuICAgICAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwib25DdXN0b21QYWNrZXRNZXNzYWdlIGZhaWxlZCB0byBwYXJzZSBKU09OXCIsIGUubWVzc2FnZSwgXCJqc29uOlwiLCBtc2cuY29udGVudEpzb25EdW1wKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAobXNnQ29udGVudFtcImN1c3RvbVBhY2tldFR5cGVcIl0pIHtcbiAgICAgICAgICAgIC8vIGNhc2UgJ2xvZ2luUmVxdWlyZWQnOlxuICAgICAgICAgICAgLy8gICBsb2dUcmFjZSh0aGlzLCAnbG9naW5SZXF1aXJlZCByZWNlaXZlZCcpO1xuICAgICAgICAgICAgLy8gICB0aGlzLmxvZ2luV2l0aFNreW1wSW9DcmVkZW50aWFscygpO1xuICAgICAgICAgICAgLy8gICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2xvZ2luRmFpbGVkTm90TG9nZ2VkVmlhRGlzY29yZCc6XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRoQXR0ZW1wdFByb2dyZXNzSW5kaWNhdG9yID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKE5ldHdvcmtpbmdTZXJ2aWNlKS5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsICdsb2dpbkZhaWxlZE5vdExvZ2dlZFZpYURpc2NvcmQgcmVjZWl2ZWQnKTtcbiAgICAgICAgICAgICAgICBicm93c2VyU3RhdGUubG9naW5GYWlsZWRSZWFzb24gPSBzdHJpbmdzLmxvZ2luVmlhRGlzY29yZDtcbiAgICAgICAgICAgICAgICBicm93c2VyU3RhdGUuY29tbWVudCA9ICcnO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0TGlzdGVuQnJvd3Nlck1lc3NhZ2UodHJ1ZSwgJ2xvZ2luRmFpbGVkTm90TG9nZ2VkVmlhRGlzY29yZCByZWNlaXZlZCcpO1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2luZ1N0YXJ0TW9tZW50ID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQobmV3IEZ1bmN0aW9uSW5mbyh0aGlzLmxvZ2luRmFpbGVkV2lkZ2V0U2V0dGVyKS5nZXRUZXh0KHsgZXZlbnRzOiBldmVudHMsIGJyb3dzZXJTdGF0ZTogYnJvd3NlclN0YXRlLCBhdXRoRGF0YTogYXV0aERhdGEsIHN0cmluZ3M6IHN0cmluZ3MgfSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbG9naW5GYWlsZWROb3RJblRoZURpc2NvcmRTZXJ2ZXInOlxuICAgICAgICAgICAgICAgIHRoaXMuYXV0aEF0dGVtcHRQcm9ncmVzc0luZGljYXRvciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihOZXR3b3JraW5nU2VydmljZSkuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCAnbG9naW5GYWlsZWROb3RJblRoZURpc2NvcmRTZXJ2ZXIgcmVjZWl2ZWQnKTtcbiAgICAgICAgICAgICAgICBicm93c2VyU3RhdGUubG9naW5GYWlsZWRSZWFzb24gPSBzdHJpbmdzLmpvaW5EaXNjb3JkU2VydmVyO1xuICAgICAgICAgICAgICAgIGJyb3dzZXJTdGF0ZS5jb21tZW50ID0gJyc7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRMaXN0ZW5Ccm93c2VyTWVzc2FnZSh0cnVlLCAnbG9naW5GYWlsZWROb3RJblRoZURpc2NvcmRTZXJ2ZXIgcmVjZWl2ZWQnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dpbmdTdGFydE1vbWVudCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5zcC5icm93c2VyLmV4ZWN1dGVKYXZhU2NyaXB0KG5ldyBGdW5jdGlvbkluZm8odGhpcy5sb2dpbkZhaWxlZFdpZGdldFNldHRlcikuZ2V0VGV4dCh7IGV2ZW50czogZXZlbnRzLCBicm93c2VyU3RhdGU6IGJyb3dzZXJTdGF0ZSwgYXV0aERhdGE6IGF1dGhEYXRhLCBzdHJpbmdzOiBzdHJpbmdzIH0pKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2xvZ2luRmFpbGVkQmFubmVkJzpcbiAgICAgICAgICAgICAgICB0aGlzLmF1dGhBdHRlbXB0UHJvZ3Jlc3NJbmRpY2F0b3IgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoTmV0d29ya2luZ1NlcnZpY2UpLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ2xvZ2luRmFpbGVkQmFubmVkIHJlY2VpdmVkJyk7XG4gICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmxvZ2luRmFpbGVkUmVhc29uID0gc3RyaW5ncy5iYW5uZWQ7XG4gICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmNvbW1lbnQgPSAnJztcbiAgICAgICAgICAgICAgICB0aGlzLnNldExpc3RlbkJyb3dzZXJNZXNzYWdlKHRydWUsICdsb2dpbkZhaWxlZEJhbm5lZCByZWNlaXZlZCcpO1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2luZ1N0YXJ0TW9tZW50ID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQobmV3IEZ1bmN0aW9uSW5mbyh0aGlzLmxvZ2luRmFpbGVkV2lkZ2V0U2V0dGVyKS5nZXRUZXh0KHsgZXZlbnRzOiBldmVudHMsIGJyb3dzZXJTdGF0ZTogYnJvd3NlclN0YXRlLCBhdXRoRGF0YTogYXV0aERhdGEsIHN0cmluZ3M6IHN0cmluZ3MgfSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbG9naW5GYWlsZWRJcE1pc21hdGNoJzpcbiAgICAgICAgICAgICAgICB0aGlzLmF1dGhBdHRlbXB0UHJvZ3Jlc3NJbmRpY2F0b3IgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoTmV0d29ya2luZ1NlcnZpY2UpLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ2xvZ2luRmFpbGVkSXBNaXNtYXRjaCByZWNlaXZlZCcpO1xuICAgICAgICAgICAgICAgIGJyb3dzZXJTdGF0ZS5sb2dpbkZhaWxlZFJlYXNvbiA9IHN0cmluZ3Mud2hhdFdhc1RoYXQ7XG4gICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmNvbW1lbnQgPSAnJztcbiAgICAgICAgICAgICAgICB0aGlzLnNldExpc3RlbkJyb3dzZXJNZXNzYWdlKHRydWUsICdsb2dpbkZhaWxlZElwTWlzbWF0Y2ggcmVjZWl2ZWQnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dpbmdTdGFydE1vbWVudCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5zcC5icm93c2VyLmV4ZWN1dGVKYXZhU2NyaXB0KG5ldyBGdW5jdGlvbkluZm8odGhpcy5sb2dpbkZhaWxlZFdpZGdldFNldHRlcikuZ2V0VGV4dCh7IGV2ZW50czogZXZlbnRzLCBicm93c2VyU3RhdGU6IGJyb3dzZXJTdGF0ZSwgYXV0aERhdGE6IGF1dGhEYXRhLCBzdHJpbmdzOiBzdHJpbmdzIH0pKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgQXV0aFNlcnZpY2UucHJvdG90eXBlLm9uQnJvd3NlcldpbmRvd0xvYWRlZEFuZE9ubGluZUF1dGhOZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5pc0xpc3RlbkJyb3dzZXJNZXNzYWdlKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcImlzTGlzdGVuQnJvd3Nlck1lc3NhZ2Ugd2FzIGZhbHNlIGZvciBzb21lIHJlYXNvbiwgYWJvcnRpbmcgYXV0aFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlNob3dpbmcgd2lkZ2V0cyBhbmQgc3RhcnRpbmcgbG9vcFwiKTtcbiAgICAgICAgYXV0aERhdGEgPSB0aGlzLnJlYWRBdXRoRGF0YUZyb21EaXNrKCk7XG4gICAgICAgIHRoaXMucmVmcmVzaFdpZGdldHMoKTtcbiAgICAgICAgdGhpcy5zcC5icm93c2VyLnNldFZpc2libGUodHJ1ZSk7XG4gICAgICAgIHRoaXMuc3AuYnJvd3Nlci5zZXRGb2N1c2VkKHRydWUpO1xuICAgICAgICB2YXIgdGltZXJzU2VydmljZSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihUaW1lcnNTZXJ2aWNlKTtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJDYWxsaW5nIHNldFRpbWVvdXQgZm9yIHRlc3RpbmdcIik7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aW1lcnNTZXJ2aWNlLnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlRlc3QgdGltZW91dCBmaXJlZFwiKTtcbiAgICAgICAgICAgIH0sIDEpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIkZhaWxlZCB0byBjYWxsIHNldFRpbWVvdXRcIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5vbkJyb3dzZXJNZXNzYWdlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzTGlzdGVuQnJvd3Nlck1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwib25Ccm93c2VyTWVzc2FnZTogaXNMaXN0ZW5Ccm93c2VyTWVzc2FnZSB3YXMgZmFsc2UsIGlnbm9yaW5nIG1lc3NhZ2VcIiwgSlNPTi5zdHJpbmdpZnkoZS5hcmd1bWVudHMpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2V0dGluZ3NTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFNldHRpbmdzU2VydmljZSk7XG4gICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwib25Ccm93c2VyTWVzc2FnZTpcIiwgSlNPTi5zdHJpbmdpZnkoZS5hcmd1bWVudHMpKTtcbiAgICAgICAgdmFyIGV2ZW50S2V5ID0gZS5hcmd1bWVudHNbMF07XG4gICAgICAgIHN3aXRjaCAoZXZlbnRLZXkpIHtcbiAgICAgICAgICAgIGNhc2UgZXZlbnRzLm9wZW5EaXNjb3JkT2F1dGg6XG4gICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmNvbW1lbnQgPSBzdHJpbmdzLm9wZW5pbmdCcm93c2VyO1xuICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaFdpZGdldHMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLndpbjMyLmxvYWRVcmwoXCJcIi5jb25jYXQoc2V0dGluZ3NTZXJ2aWNlLmdldE1hc3RlclVybCgpLCBcIi9hcGkvdXNlcnMvbG9naW4tZGlzY29yZD9zdGF0ZT1cIikuY29uY2F0KHRoaXMuZGlzY29yZEF1dGhTdGF0ZSkpO1xuICAgICAgICAgICAgICAgIC8vIExhdW5jaCBjaGVja0xvZ2luU3RhdGUgbG9vcFxuICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tMb2dpblN0YXRlKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGV2ZW50cy5hdXRoQXR0ZW1wdDpcbiAgICAgICAgICAgICAgICBpZiAoYXV0aERhdGEgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmNvbW1lbnQgPSBzdHJpbmdzLmxvZ2luRmlyc3Q7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaFdpZGdldHMoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMud3JpdGVBdXRoRGF0YVRvRGlzayhhdXRoRGF0YSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImF1dGhBdHRlbXB0XCIsIHsgYXV0aEdhbWVEYXRhOiB7IHJlbW90ZTogYXV0aERhdGEgfSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dGhBdHRlbXB0UHJvZ3Jlc3NJbmRpY2F0b3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBldmVudHMuY2xlYXJBdXRoRGF0YTpcbiAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IHNlZW0gdG8gYmUgdXNlZFxuICAgICAgICAgICAgICAgIHRoaXMud3JpdGVBdXRoRGF0YVRvRGlzayhudWxsKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgZXZlbnRzLm9wZW5HaXRodWI6XG4gICAgICAgICAgICAgICAgdGhpcy5zcC53aW4zMi5sb2FkVXJsKHRoaXMuZ2l0aHViVXJsKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgZXZlbnRzLm9wZW5QYXRyZW9uOlxuICAgICAgICAgICAgICAgIHRoaXMuc3Aud2luMzIubG9hZFVybCh0aGlzLnBhdHJlb25VcmwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBldmVudHMudXBkYXRlUmVxdWlyZWQ6XG4gICAgICAgICAgICAgICAgdGhpcy5zcC53aW4zMi5sb2FkVXJsKFwiaHR0cHM6Ly9za3ltcC5uZXQvVXBkSW5zdGFsbFwiKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgZXZlbnRzLmJhY2tUb0xvZ2luOlxuICAgICAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5leGVjdXRlSmF2YVNjcmlwdChuZXcgRnVuY3Rpb25JbmZvKHRoaXMuYnJvd3NlcnNpZGVXaWRnZXRTZXR0ZXIpLmdldFRleHQoeyBldmVudHM6IGV2ZW50cywgYnJvd3NlclN0YXRlOiBicm93c2VyU3RhdGUsIGF1dGhEYXRhOiBhdXRoRGF0YSwgc3RyaW5nczogc3RyaW5ncyB9KSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGV2ZW50cy5qb2luRGlzY29yZDpcbiAgICAgICAgICAgICAgICB0aGlzLnNwLndpbjMyLmxvYWRVcmwoXCJodHRwczovL2Rpc2NvcmQuZ2cvOUtoU1o2empHVFwiKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5jcmVhdGVQbGF5U2Vzc2lvbiA9IGZ1bmN0aW9uICh0b2tlbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNldHRpbmdzU2VydmljZSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihTZXR0aW5nc1NlcnZpY2UpO1xuICAgICAgICB2YXIgY2xpZW50ID0gbmV3IHRoaXMuc3AuSHR0cENsaWVudChzZXR0aW5nc1NlcnZpY2UuZ2V0TWFzdGVyVXJsKCkpO1xuICAgICAgICB2YXIgcm91dGUgPSBcIi9hcGkvdXNlcnMvbWUvcGxheS9cIi5jb25jYXQoc2V0dGluZ3NTZXJ2aWNlLmdldFNlcnZlck1hc3RlcktleSgpKTtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJDcmVhdGluZyBwbGF5IHNlc3Npb24gXCIuY29uY2F0KHJvdXRlKSk7XG4gICAgICAgIGNsaWVudC5wb3N0KHJvdXRlLCB7XG4gICAgICAgICAgICBib2R5OiAne30nLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAnYXV0aG9yaXphdGlvbic6IHRva2VuLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgfSwgZnVuY3Rpb24gKHJlcykge1xuICAgICAgICAgICAgaWYgKHJlcy5zdGF0dXMgIT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJycsICdzdGF0dXMgY29kZSAnICsgcmVzLnN0YXR1cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgSlNPTi5wYXJzZSBmYWlsdXJlP1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKEpTT04ucGFyc2UocmVzLmJvZHkpLnNlc3Npb24sICcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUuY2hlY2tMb2dpblN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuaXNMaXN0ZW5Ccm93c2VyTWVzc2FnZSkge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJjaGVja0xvZ2luU3RhdGU6IGlzTGlzdGVuQnJvd3Nlck1lc3NhZ2Ugd2FzIGZhbHNlLCBhYm9ydGluZyBjaGVja1wiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2V0dGluZ3NTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFNldHRpbmdzU2VydmljZSk7XG4gICAgICAgIHZhciB0aW1lcnNTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFRpbWVyc1NlcnZpY2UpO1xuICAgICAgICAvLyBTb2NpYWwgZW5naW5lZXJpbmcgcHJvdGVjdGlvbiwgZG9uJ3Qgc2hvdyB0aGUgZnVsbCBzdGF0ZVxuICAgICAgICB2YXIgaGFsZkRpc2NvcmRBdXRoU3RhdGUgPSB0aGlzLmRpc2NvcmRBdXRoU3RhdGUuc2xpY2UoMCwgMTYpO1xuICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIkNoZWNraW5nIGxvZ2luIHN0YXRlXCIsIGhhbGZEaXNjb3JkQXV0aFN0YXRlLCAnLi4uJyk7XG4gICAgICAgIG5ldyB0aGlzLnNwLkh0dHBDbGllbnQoc2V0dGluZ3NTZXJ2aWNlLmdldE1hc3RlclVybCgpKVxuICAgICAgICAgICAgLmdldChcIi9hcGkvdXNlcnMvbG9naW4tZGlzY29yZC9zdGF0dXM/c3RhdGU9XCIgKyB0aGlzLmRpc2NvcmRBdXRoU3RhdGUsIHVuZGVmaW5lZCwgXG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLnN0YXR1cykge1xuICAgICAgICAgICAgICAgIGNhc2UgMjAwOlxuICAgICAgICAgICAgICAgICAgICB2YXIgX2EgPSBKU09OLnBhcnNlKHJlc3BvbnNlLmJvZHkpLCB0b2tlbiA9IF9hLnRva2VuLCBtYXN0ZXJBcGlJZF8xID0gX2EubWFzdGVyQXBpSWQsIGRpc2NvcmRVc2VybmFtZV8xID0gX2EuZGlzY29yZFVzZXJuYW1lLCBkaXNjb3JkRGlzY3JpbWluYXRvcl8xID0gX2EuZGlzY29yZERpc2NyaW1pbmF0b3IsIGRpc2NvcmRBdmF0YXJfMSA9IF9hLmRpc2NvcmRBdmF0YXI7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJTdGF0ZS5mYWlsQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jcmVhdGVQbGF5U2Vzc2lvbih0b2tlbiwgZnVuY3Rpb24gKHBsYXlTZXNzaW9uLCBlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmZhaWxDb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmNvbW1lbnQgPSAoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVyc1NlcnZpY2Uuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jaGVja0xvZ2luU3RhdGUoKTsgfSwgTWF0aC5mbG9vcigoMS41ICsgTWF0aC5yYW5kb20oKSAqIDIpICogMTAwMCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnJlZnJlc2hXaWRnZXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXV0aERhdGEgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogcGxheVNlc3Npb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFzdGVyQXBpSWQ6IG1hc3RlckFwaUlkXzEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzY29yZFVzZXJuYW1lOiBkaXNjb3JkVXNlcm5hbWVfMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNjb3JkRGlzY3JpbWluYXRvcjogZGlzY29yZERpc2NyaW1pbmF0b3JfMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNjb3JkQXZhdGFyOiBkaXNjb3JkQXZhdGFyXzEsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmNvbW1lbnQgPSBzdHJpbmdzLmxpbmtlZFN1Y2Nlc3NmdWxseTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnJlZnJlc2hXaWRnZXRzKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQwMTogLy8gVW5hdXRob3JpemVkXG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJTdGF0ZS5mYWlsQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyU3RhdGUuY29tbWVudCA9ICcnOyAvLyhgU3RpbGwgd2FpdGluZy4uLmApO1xuICAgICAgICAgICAgICAgICAgICB0aW1lcnNTZXJ2aWNlLnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY2hlY2tMb2dpblN0YXRlKCk7IH0sIE1hdGguZmxvb3IoKDEuNSArIE1hdGgucmFuZG9tKCkgKiAyKSAqIDEwMDApKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0MDM6IC8vIEZvcmJpZGRlblxuICAgICAgICAgICAgICAgIGNhc2UgNDA0OiAvLyBOb3QgZm91bmRcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclN0YXRlLmZhaWxDb3VudCA9IDkwMDA7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJTdGF0ZS5jb21tZW50ID0gKFwiRmFpbDogXCIuY29uY2F0KHJlc3BvbnNlLmJvZHkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgKyticm93c2VyU3RhdGUuZmFpbENvdW50O1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyU3RhdGUuY29tbWVudCA9IFwiU2VydmVyIHJldHVybmVkIFwiLmNvbmNhdChyZXNwb25zZS5zdGF0dXMudG9TdHJpbmcoKSB8fCBcIj8/P1wiLCBcIiBcXFwiXCIpLmNvbmNhdChyZXNwb25zZS5ib2R5IHx8IHJlc3BvbnNlLmVycm9yLCBcIlxcXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyc1NlcnZpY2Uuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jaGVja0xvZ2luU3RhdGUoKTsgfSwgTWF0aC5mbG9vcigoMS41ICsgTWF0aC5yYW5kb20oKSAqIDIpICogMTAwMCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIDtcbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUucmVmcmVzaFdpZGdldHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AuYnJvd3Nlci5leGVjdXRlSmF2YVNjcmlwdChuZXcgRnVuY3Rpb25JbmZvKHRoaXMuYnJvd3NlcnNpZGVXaWRnZXRTZXR0ZXIpLmdldFRleHQoeyBldmVudHM6IGV2ZW50cywgYnJvd3NlclN0YXRlOiBicm93c2VyU3RhdGUsIGF1dGhEYXRhOiBhdXRoRGF0YSwgc3RyaW5nczogc3RyaW5ncyB9KSk7XG4gICAgICAgIHRoaXMuYXV0aERpYWxvZ09wZW4gPSB0cnVlO1xuICAgIH07XG4gICAgO1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5yZWFkQXV0aERhdGFGcm9tRGlzayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJSZWFkaW5nXCIsIHRoaXMucGx1Z2luQXV0aERhdGFOYW1lLCBcImZyb20gZGlza1wiKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgKFRPRE86IFJlbW92ZSBpbiAyLjEwLjApXG4gICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuc3AuZ2V0UGx1Z2luU291cmNlQ29kZSh0aGlzLnBsdWdpbkF1dGhEYXRhTmFtZSwgXCJQbHVnaW5zTm9Mb2FkXCIpO1xuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJSZWFkIGVtcHR5XCIsIHRoaXMucGx1Z2luQXV0aERhdGFOYW1lLCBcInJldHVybmluZyBudWxsXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGF0YS5zbGljZSgyKSkgfHwgbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJFcnJvciByZWFkaW5nXCIsIHRoaXMucGx1Z2luQXV0aERhdGFOYW1lLCBcImZyb20gZGlzazpcIiwgZSwgXCIsIGZhbGxpbmcgYmFjayB0byBudWxsXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS53cml0ZUF1dGhEYXRhVG9EaXNrID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdmFyIGNvbnRlbnQgPSBcIi8vXCIgKyAoZGF0YSA/IEpTT04uc3RyaW5naWZ5KGRhdGEpIDogXCJudWxsXCIpO1xuICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIldyaXRpbmdcIiwgdGhpcy5wbHVnaW5BdXRoRGF0YU5hbWUsIFwidG8gZGlzazpcIiwgY29udGVudCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnNwLndyaXRlUGx1Z2luKHRoaXMucGx1Z2luQXV0aERhdGFOYW1lLCBjb250ZW50LCBcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgKFRPRE86IFJlbW92ZSBpbiAyLjEwLjApXG4gICAgICAgICAgICBcIlBsdWdpbnNOb0xvYWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiRXJyb3Igd3JpdGluZ1wiLCB0aGlzLnBsdWdpbkF1dGhEYXRhTmFtZSwgXCJ0byBkaXNrOlwiLCBlLCBcIiwgd2lsbCBub3QgcmVtZW1iZXIgdXNlclwiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgO1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5oYW5kbGVDb25uZWN0aW9uRGVuaWVkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hdXRoQXR0ZW1wdFByb2dyZXNzSW5kaWNhdG9yID0gZmFsc2U7XG4gICAgICAgIGlmIChlLmVycm9yLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoXCJpbnZhbGlkIHBhc3N3b3JkXCIpKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIub25jZShcInRpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoTmV0d29ya2luZ1NlcnZpY2UpLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5leGVjdXRlSmF2YVNjcmlwdChuZXcgRnVuY3Rpb25JbmZvKHRoaXMuZGVuaWVkV2lkZ2V0U2V0dGVyKS5nZXRUZXh0KHsgZXZlbnRzOiBldmVudHMsIHN0cmluZ3M6IHN0cmluZ3MgfSkpO1xuICAgICAgICAgICAgdGhpcy5zcC5icm93c2VyLnNldFZpc2libGUodHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuc2V0Rm9jdXNlZCh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zcC5HYW1lLmRpc2FibGVQbGF5ZXJDb250cm9scyh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlLCB0cnVlLCB0cnVlLCB0cnVlLCB0cnVlLCAwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRMaXN0ZW5Ccm93c2VyTWVzc2FnZSh0cnVlLCAnY29ubmVjdGlvbkRlbmllZCBldmVudCByZWNlaXZlZCcpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUuaGFuZGxlQ29ubmVjdGlvbkFjY2VwdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldExpc3RlbkJyb3dzZXJNZXNzYWdlKGZhbHNlLCAnY29ubmVjdGlvbkFjY2VwdGVkIGV2ZW50IHJlY2VpdmVkJyk7XG4gICAgICAgIHRoaXMubG9nZ2luZ1N0YXJ0TW9tZW50ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdmFyIGF1dGhEYXRhID0gdGhpcy5zcC5zdG9yYWdlW2F1dGhHYW1lRGF0YVN0b3JhZ2VLZXldO1xuICAgICAgICBpZiAoYXV0aERhdGEgPT09IG51bGwgfHwgYXV0aERhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGF1dGhEYXRhLmxvY2FsKSB7XG4gICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIkxvZ2dpbmcgaW4gb2ZmbGluZSBtb2RlLCBwcm9maWxlSWQgPVwiLCBhdXRoRGF0YS5sb2NhbC5wcm9maWxlSWQpO1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgICAgdDogTXNnVHlwZS5DdXN0b21QYWNrZXQsXG4gICAgICAgICAgICAgICAgY29udGVudEpzb25EdW1wOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgIGN1c3RvbVBhY2tldFR5cGU6ICdsb2dpbldpdGhTa3ltcElvJyxcbiAgICAgICAgICAgICAgICAgICAgZ2FtZURhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2ZpbGVJZDogYXV0aERhdGEubG9jYWwucHJvZmlsZUlkLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXV0aERhdGEgPT09IG51bGwgfHwgYXV0aERhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGF1dGhEYXRhLnJlbW90ZSkge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ0xvZ2dpbmcgaW4gYXMgYSBtYXN0ZXIgQVBJIHVzZXInKTtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0ge1xuICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuQ3VzdG9tUGFja2V0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnRKc29uRHVtcDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBjdXN0b21QYWNrZXRUeXBlOiAnbG9naW5XaXRoU2t5bXBJbycsXG4gICAgICAgICAgICAgICAgICAgIGdhbWVEYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiBhdXRoRGF0YS5yZW1vdGUuc2Vzc2lvbixcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbG9nRXJyb3IodGhpcywgJ05vdCBmb3VuZCBhdXRoZW50aWNhdGlvbiBtZXRob2QnKTtcbiAgICB9O1xuICAgIDtcbiAgICBBdXRoU2VydmljZS5wcm90b3R5cGUub25UaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBUT0RPOiBTaG91bGQgYmUgbm8gaGFyZGNvZGVkL21hZ2ljLW51bWJlciBsaW1pdFxuICAgICAgICAvLyBUT0RPOiBCdXN5IHdhaXRpbmcgaXMgYmFkLiBTaG91bGQgYmUgcmVwbGFjZWQgd2l0aCBzb21lIGtpbmQgb2YgZXZlbnRcbiAgICAgICAgdmFyIG1heExvZ2dpbmdEZWxheSA9IDE1MDAwO1xuICAgICAgICBpZiAodGhpcy5sb2dnaW5nU3RhcnRNb21lbnQgJiYgRGF0ZS5ub3coKSAtIHRoaXMubG9nZ2luZ1N0YXJ0TW9tZW50ID4gbWF4TG9nZ2luZ0RlbGF5KSB7XG4gICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCAnTWF4IGxvZ2dpbmcgZGVsYXkgcmVhY2hlZCByZWNlaXZlZCcpO1xuICAgICAgICAgICAgaWYgKHRoaXMucGxheWVyRXZlclNhd0FjdHVhbEdhbWVwbGF5KSB7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ1BsYXllciBzYXcgYWN0dWFsIGdhbWVwbGF5LCByZWNvbm5lY3RpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dpbmdTdGFydE1vbWVudCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKE5ldHdvcmtpbmdTZXJ2aWNlKS5yZWNvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBzaG91bGQgd2UgcHJvbXB0IHVzZXIgdG8gcmVsb2dpbj9cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsICdQbGF5ZXIgbmV2ZXIgc2F3IGFjdHVhbCBnYW1lcGxheSwgc2hvd2luZyBsb2dpbiBkaWFsb2cnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dpbmdTdGFydE1vbWVudCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRoQXR0ZW1wdFByb2dyZXNzSW5kaWNhdG9yID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKE5ldHdvcmtpbmdTZXJ2aWNlKS5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIGJyb3dzZXJTdGF0ZS5jb21tZW50ID0gXCJcIjtcbiAgICAgICAgICAgICAgICBicm93c2VyU3RhdGUubG9naW5GYWlsZWRSZWFzb24gPSBzdHJpbmdzLnRlY2huaWNhbElzc3VlcztcbiAgICAgICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQobmV3IEZ1bmN0aW9uSW5mbyh0aGlzLmxvZ2luRmFpbGVkV2lkZ2V0U2V0dGVyKS5nZXRUZXh0KHsgZXZlbnRzOiBldmVudHMsIGJyb3dzZXJTdGF0ZTogYnJvd3NlclN0YXRlLCBhdXRoRGF0YTogYXV0aERhdGEsIHN0cmluZ3M6IHN0cmluZ3MgfSkpO1xuICAgICAgICAgICAgICAgIGF1dGhEYXRhID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLndyaXRlQXV0aERhdGFUb0Rpc2sobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYXV0aEF0dGVtcHRQcm9ncmVzc0luZGljYXRvcikge1xuICAgICAgICAgICAgdGhpcy5hdXRoQXR0ZW1wdFByb2dyZXNzSW5kaWNhdG9yQ291bnRlcisrO1xuICAgICAgICAgICAgaWYgKHRoaXMuYXV0aEF0dGVtcHRQcm9ncmVzc0luZGljYXRvckNvdW50ZXIgPT09IDEwMDAwMDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dGhBdHRlbXB0UHJvZ3Jlc3NJbmRpY2F0b3JDb3VudGVyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzbG93Q291bnRlciA9IE1hdGguZmxvb3IodGhpcy5hdXRoQXR0ZW1wdFByb2dyZXNzSW5kaWNhdG9yQ291bnRlciAvIDE1KTtcbiAgICAgICAgICAgIHZhciBkb3QgPSBzbG93Q291bnRlciAlIDMgPT09IDAgPyAnLicgOiBzbG93Q291bnRlciAlIDMgPT09IDEgPyAnLi4nIDogJy4uLic7XG4gICAgICAgICAgICBicm93c2VyU3RhdGUuY29tbWVudCA9IHN0cmluZ3MuY29ubmVjdGluZyArIGRvdDtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaFdpZGdldHMoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQXV0aFNlcnZpY2UucHJvdG90eXBlLm9uY2VVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucGxheWVyRXZlclNhd0FjdHVhbEdhbWVwbGF5ID0gdHJ1ZTtcbiAgICB9O1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5pc0xpc3RlbkJyb3dzZXJNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNMaXN0ZW5Ccm93c2VyTWVzc2FnZTtcbiAgICB9O1xuICAgIEF1dGhTZXJ2aWNlLnByb3RvdHlwZS5zZXRMaXN0ZW5Ccm93c2VyTWVzc2FnZSA9IGZ1bmN0aW9uICh2YWx1ZSwgcmVhc29uKSB7XG4gICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwic2V0TGlzdGVuQnJvd3Nlck1lc3NhZ2U6XCIsIHZhbHVlLCBcInJlYXNvbjpcIiwgcmVhc29uKTtcbiAgICAgICAgdGhpcy5faXNMaXN0ZW5Ccm93c2VyTWVzc2FnZSA9IHZhbHVlO1xuICAgIH07XG4gICAgcmV0dXJuIEF1dGhTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgQXV0aFNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgQmxvY2tQYXB5cnVzRXZlbnRzU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQmxvY2tQYXB5cnVzRXZlbnRzU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBCbG9ja1BhcHlydXNFdmVudHNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ0aWNrXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uY2VUaWNrKCk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBCbG9ja1BhcHlydXNFdmVudHNTZXJ2aWNlLnByb3RvdHlwZS5vbmNlVGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICB0aGlzLnNwLmJsb2NrUGFweXJ1c0V2ZW50cyh0cnVlKTtcbiAgICB9O1xuICAgIEJsb2NrUGFweXJ1c0V2ZW50c1NlcnZpY2UucHJvdG90eXBlLm9uY2VVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AuVEVTTW9kUGxhdGZvcm0uYmxvY2tQYXB5cnVzRXZlbnRzKHRydWUpO1xuICAgIH07XG4gICAgcmV0dXJuIEJsb2NrUGFweXJ1c0V2ZW50c1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBCbG9ja1BhcHlydXNFdmVudHNTZXJ2aWNlIH07XG47XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgbG9nVHJhY2UgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xudmFyIEJsb2NrZWRBbmltYXRpb25zU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQmxvY2tlZEFuaW1hdGlvbnNTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEJsb2NrZWRBbmltYXRpb25zU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgdmFyIGJsb2NrZWRBbmltcyA9IFtdO1xuICAgICAgICB2YXIgc2VsZiA9IF90aGlzO1xuICAgICAgICBibG9ja2VkQW5pbXMuZm9yRWFjaChmdW5jdGlvbiAoYmxvY2tlZEFuaW0pIHtcbiAgICAgICAgICAgIF90aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgICAgIGVudGVyOiBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHNlbGYsIFwiYmxvY2tpbmcgYW5pbWF0aW9uIGV2ZW50XCIsIGN0eC5hbmltRXZlbnROYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgY3R4LmFuaW1FdmVudE5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbGVhdmU6IGZ1bmN0aW9uICgpIHsgfVxuICAgICAgICAgICAgfSwgMHgxNCwgMHgxNCwgYmxvY2tlZEFuaW0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICByZXR1cm4gQmxvY2tlZEFuaW1hdGlvbnNTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgQmxvY2tlZEFuaW1hdGlvbnNTZXJ2aWNlIH07XG47XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuLy8gVE9ETzogc2VuZCBldmVudCBpbnN0ZWFkIG9mIGRpcmVjdCBkZXBlbmRlbmN5IG9uIEZvcm1WaWV3IGNsYXNzXG5pbXBvcnQgeyBGb3JtVmlldyB9IGZyb20gXCIuLi8uLi92aWV3L2Zvcm1WaWV3XCI7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgdW5mb2N1c0V2ZW50U3RyaW5nID0gXCJ3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoJ3NreW1wNS1jbGllbnQ6YnJvd3NlclVuZm9jdXNlZCcsIHt9KSlcIjtcbnZhciBmb2N1c0V2ZW50U3RyaW5nID0gXCJ3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoJ3NreW1wNS1jbGllbnQ6YnJvd3NlckZvY3VzZWQnLCB7fSkpXCI7XG52YXIgQnJvd3NlclNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEJyb3dzZXJTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEJyb3dzZXJTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5iYWRNZW51c09wZW4gPSBuZXcgU2V0KCk7XG4gICAgICAgIF90aGlzLmJhZE1lbnVzID0gW1xuICAgICAgICAgICAgXCJCYXJ0ZXJNZW51XCIgLyogTWVudS5CYXJ0ZXIgKi8sXG4gICAgICAgICAgICBcIkJvb2sgTWVudVwiIC8qIE1lbnUuQm9vayAqLyxcbiAgICAgICAgICAgIFwiQ29udGFpbmVyTWVudVwiIC8qIE1lbnUuQ29udGFpbmVyICovLFxuICAgICAgICAgICAgXCJDcmFmdGluZyBNZW51XCIgLyogTWVudS5DcmFmdGluZyAqLyxcbiAgICAgICAgICAgIFwiR2lmdE1lbnVcIiAvKiBNZW51LkdpZnQgKi8sXG4gICAgICAgICAgICBcIkludmVudG9yeU1lbnVcIiAvKiBNZW51LkludmVudG9yeSAqLyxcbiAgICAgICAgICAgIFwiSm91cm5hbCBNZW51XCIgLyogTWVudS5Kb3VybmFsICovLFxuICAgICAgICAgICAgXCJMb2NrcGlja2luZyBNZW51XCIgLyogTWVudS5Mb2NrcGlja2luZyAqLyxcbiAgICAgICAgICAgIFwiTG9hZGluZyBNZW51XCIgLyogTWVudS5Mb2FkaW5nICovLFxuICAgICAgICAgICAgXCJNYXBNZW51XCIgLyogTWVudS5NYXAgKi8sXG4gICAgICAgICAgICBcIlJhY2VTZXggTWVudVwiIC8qIE1lbnUuUmFjZVNleCAqLyxcbiAgICAgICAgICAgIFwiU3RhdHNNZW51XCIgLyogTWVudS5TdGF0cyAqLyxcbiAgICAgICAgICAgIFwiVHdlZW5NZW51XCIgLyogTWVudS5Ud2VlbiAqLyxcbiAgICAgICAgICAgIFwiQ29uc29sZVwiIC8qIE1lbnUuQ29uc29sZSAqLyxcbiAgICAgICAgICAgIFwiTWFpbiBNZW51XCIgLyogTWVudS5NYWluICovLFxuICAgICAgICBdO1xuICAgICAgICBfdGhpcy5zcC5icm93c2VyLnNldFZpc2libGUoZmFsc2UpO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJxdWVyeUtleUNvZGVCaW5kaW5nc1wiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25RdWVyeUtleUNvZGVCaW5kaW5ncyhlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vbmNlVXBkYXRlKCk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwiYnJvd3Nlck1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uQnJvd3Nlck1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwibWVudU9wZW5cIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uTWVudU9wZW4oZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwibWVudUNsb3NlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbk1lbnVDbG9zZShlKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgLy8gVE9ETzoga2V5Y29kZXMgc2hvdWxkIGJlIGNvbmZpZ3VyYWJsZVxuICAgIEJyb3dzZXJTZXJ2aWNlLnByb3RvdHlwZS5vblF1ZXJ5S2V5Q29kZUJpbmRpbmdzID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUuaXNEb3duKFs1OSAvKiBEeFNjYW5Db2RlLkYxICovXSkpIHtcbiAgICAgICAgICAgIEZvcm1WaWV3LmlzRGlzcGxheWluZ05pY2tuYW1lcyA9ICFGb3JtVmlldy5pc0Rpc3BsYXlpbmdOaWNrbmFtZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUuaXNEb3duKFs2MCAvKiBEeFNjYW5Db2RlLkYyICovXSkpIHtcbiAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5zZXRWaXNpYmxlKCF0aGlzLnNwLmJyb3dzZXIuaXNWaXNpYmxlKCkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmJhZE1lbnVzT3Blbi5zaXplID09PSAwICYmIGUuaXNEb3duKFs2NCAvKiBEeFNjYW5Db2RlLkY2ICovXSkpIHtcbiAgICAgICAgICAgIHZhciBuZXdTdGF0ZSA9ICF0aGlzLnNwLmJyb3dzZXIuaXNGb2N1c2VkKCk7XG4gICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuc2V0Rm9jdXNlZChuZXdTdGF0ZSk7XG4gICAgICAgICAgICBpZiAobmV3U3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQoZm9jdXNFdmVudFN0cmluZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQodW5mb2N1c0V2ZW50U3RyaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5iYWRNZW51c09wZW4uc2l6ZSA9PT0gMCAmJiBlLmlzRG93bihbMjggLyogRHhTY2FuQ29kZS5FbnRlciAqL10pKSB7XG4gICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuc2V0Rm9jdXNlZCh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5leGVjdXRlSmF2YVNjcmlwdChmb2N1c0V2ZW50U3RyaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZS5pc0Rvd24oWzEgLyogRHhTY2FuQ29kZS5Fc2NhcGUgKi9dKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3AuYnJvd3Nlci5pc0ZvY3VzZWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5zZXRGb2N1c2VkKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQodW5mb2N1c0V2ZW50U3RyaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgQnJvd3NlclNlcnZpY2UucHJvdG90eXBlLm9uY2VVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AuYnJvd3Nlci5zZXRWaXNpYmxlKHRydWUpO1xuICAgIH07XG4gICAgQnJvd3NlclNlcnZpY2UucHJvdG90eXBlLm9uQnJvd3Nlck1lc3NhZ2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgb25Gcm9udExvYWRlZEV2ZW50S2V5ID0gXCJmcm9udC1sb2FkZWRcIjtcbiAgICAgICAgaWYgKGUuYXJndW1lbnRzWzBdID09PSBvbkZyb250TG9hZGVkRXZlbnRLZXkpIHtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJicm93c2VyV2luZG93TG9hZGVkXCIsIHt9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQnJvd3NlclNlcnZpY2UucHJvdG90eXBlLm9uTWVudU9wZW4gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5pc0JhZE1lbnUoZS5uYW1lKSkge1xuICAgICAgICAgICAgdGhpcy5zcC5icm93c2VyLnNldFZpc2libGUoZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5iYWRNZW51c09wZW4uYWRkKGUubmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZS5uYW1lID09PSBcIkhVRCBNZW51XCIgLyogTWVudS5IVUQgKi8pIHtcbiAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5zZXRWaXNpYmxlKHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCcm93c2VyU2VydmljZS5wcm90b3R5cGUub25NZW51Q2xvc2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5iYWRNZW51c09wZW4uZGVsZXRlKGUubmFtZSkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmJhZE1lbnVzT3Blbi5zaXplID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zcC5icm93c2VyLnNldFZpc2libGUodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUubmFtZSA9PT0gXCJIVUQgTWVudVwiIC8qIE1lbnUuSFVEICovKSB7XG4gICAgICAgICAgICB0aGlzLnNwLmJyb3dzZXIuc2V0VmlzaWJsZShmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEJyb3dzZXJTZXJ2aWNlLnByb3RvdHlwZS5pc0JhZE1lbnUgPSBmdW5jdGlvbiAobWVudSkge1xuICAgICAgICByZXR1cm4gdGhpcy5iYWRNZW51cy5pbmNsdWRlcyhtZW51KTtcbiAgICB9O1xuICAgIHJldHVybiBCcm93c2VyU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IEJyb3dzZXJTZXJ2aWNlIH07XG4iLCI7XG52YXIgQ2xpZW50TGlzdGVuZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ2xpZW50TGlzdGVuZXIoKSB7XG4gICAgICAgIC8vIERvbid0IGxldCBUeXBlU2NyaXB0IHRyZWF0IHRoaXMgY2xhc3MgYXMgZW1wdHlcbiAgICAgICAgdGhpcy5fbm9uRW1wdHlDbGFzc01hcmsgPSAnJztcbiAgICB9XG4gICAgcmV0dXJuIENsaWVudExpc3RlbmVyO1xufSgpKTtcbmV4cG9ydCB7IENsaWVudExpc3RlbmVyIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgbG9nRXJyb3IsIGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IE1zZ1R5cGUgfSBmcm9tIFwiLi4vLi4vbWVzc2FnZXNcIjtcbi8vIFRPRE86IHJlZmFjdG9yIHRoaXMgb3V0XG5pbXBvcnQgeyBsb2NhbElkVG9SZW1vdGVJZCB9IGZyb20gXCIuLi8uLi92aWV3L3dvcmxkVmlld01pc2NcIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBDbWRBcmd1bWVudDtcbihmdW5jdGlvbiAoQ21kQXJndW1lbnQpIHtcbiAgICBDbWRBcmd1bWVudFtDbWRBcmd1bWVudFtcIk9iamVjdFJlZmVyZW5jZVwiXSA9IDBdID0gXCJPYmplY3RSZWZlcmVuY2VcIjtcbiAgICBDbWRBcmd1bWVudFtDbWRBcmd1bWVudFtcIkJhc2VGb3JtXCJdID0gMV0gPSBcIkJhc2VGb3JtXCI7XG4gICAgQ21kQXJndW1lbnRbQ21kQXJndW1lbnRbXCJJbnRcIl0gPSAyXSA9IFwiSW50XCI7XG4gICAgQ21kQXJndW1lbnRbQ21kQXJndW1lbnRbXCJTdHJpbmdcIl0gPSAzXSA9IFwiU3RyaW5nXCI7XG59KShDbWRBcmd1bWVudCB8fCAoQ21kQXJndW1lbnQgPSB7fSkpO1xudmFyIENvbnNvbGVDb21tYW5kc1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKENvbnNvbGVDb21tYW5kc1NlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ29uc29sZUNvbW1hbmRzU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMuaW1tdW5lU2NoZW1hID0gW1wibXBcIl07XG4gICAgICAgIF90aGlzLm5vblZhbmlsYUNvbW1hbmRzID0gW1wibXBcIl07XG4gICAgICAgIF90aGlzLnNjaGVtYXMgPSBDb25zb2xlQ29tbWFuZHNTZXJ2aWNlLmNyZWF0ZVNjaGVtYXMoKTtcbiAgICAgICAgX3RoaXMuc2V0dXBNcENvbW1hbmQoKTtcbiAgICAgICAgX3RoaXMuc2V0dXBWYW5pbGFDb21tYW5kcygpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENvbnNvbGVDb21tYW5kc1NlcnZpY2UuY3JlYXRlU2NoZW1hcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNjaGVtYXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHNjaGVtYXMuc2V0KFwiYWRkaXRlbVwiLCBbQ21kQXJndW1lbnQuT2JqZWN0UmVmZXJlbmNlLCBDbWRBcmd1bWVudC5CYXNlRm9ybSwgQ21kQXJndW1lbnQuSW50XSk7XG4gICAgICAgIHNjaGVtYXMuc2V0KFwiZXF1aXBpdGVtXCIsIFtDbWRBcmd1bWVudC5PYmplY3RSZWZlcmVuY2UsIENtZEFyZ3VtZW50LkJhc2VGb3JtXSk7XG4gICAgICAgIHNjaGVtYXMuc2V0KFwicGxhY2VhdG1lXCIsIFtDbWRBcmd1bWVudC5PYmplY3RSZWZlcmVuY2UsIENtZEFyZ3VtZW50LkJhc2VGb3JtXSk7XG4gICAgICAgIHNjaGVtYXMuc2V0KFwiZGlzYWJsZVwiLCBbQ21kQXJndW1lbnQuT2JqZWN0UmVmZXJlbmNlXSk7XG4gICAgICAgIHNjaGVtYXMuc2V0KFwibXBcIiwgW0NtZEFyZ3VtZW50Lk9iamVjdFJlZmVyZW5jZSwgQ21kQXJndW1lbnQuU3RyaW5nXSk7XG4gICAgICAgIHJldHVybiBzY2hlbWFzO1xuICAgIH07XG4gICAgQ29uc29sZUNvbW1hbmRzU2VydmljZS5wcm90b3R5cGUuc2V0dXBNcENvbW1hbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb21tYW5kID0gdGhpcy5zcC5maW5kQ29uc29sZUNvbW1hbmQoXCIgQ29uZmlndXJlVU1cIikgfHwgdGhpcy5zcC5maW5kQ29uc29sZUNvbW1hbmQoXCJ0ZXN0XCIpO1xuICAgICAgICBpZiAoY29tbWFuZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJjb21tYW5kIHdhcyBudWxsIGluIHNldHVwTXBDb21tYW5kXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbW1hbmQuc2hvcnROYW1lID0gXCJtcFwiO1xuICAgICAgICBjb21tYW5kLmV4ZWN1dGUgPSB0aGlzLmdldENvbW1hbmRFeGVjdXRvcihcIm1wXCIpO1xuICAgIH07XG4gICAgQ29uc29sZUNvbW1hbmRzU2VydmljZS5wcm90b3R5cGUuc2V0dXBWYW5pbGFDb21tYW5kcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJTZXR0aW5nIHVwIHZhbmlsYSBjb21tYW5kc1wiKTtcbiAgICAgICAgdGhpcy5zY2hlbWFzLmZvckVhY2goZnVuY3Rpb24gKF8sIGNvbW1hbmROYW1lKSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJTZXR0aW5nIHVwIGNvbW1hbmRcIiwgY29tbWFuZE5hbWUpO1xuICAgICAgICAgICAgdmFyIGNvbW1hbmQgPSBfdGhpcy5zcC5maW5kQ29uc29sZUNvbW1hbmQoY29tbWFuZE5hbWUpO1xuICAgICAgICAgICAgaWYgKGNvbW1hbmQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBsb2dFcnJvcihfdGhpcywgXCJjb21tYW5kXCIsIGNvbW1hbmROYW1lLCBcIndhcyBudWxsIGluIHNldHVwVmFuaWxhQ29tbWFuZHNcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLm5vblZhbmlsYUNvbW1hbmRzLmluY2x1ZGVzKGNvbW1hbmROYW1lKSkge1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcImNvbW1hbmRcIiwgY29tbWFuZE5hbWUsIFwiIGlzIG5vbi12YW5pbGEgY29tbWFuZFwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb21tYW5kLmV4ZWN1dGUgPSBfdGhpcy5nZXRDb21tYW5kRXhlY3V0b3IoY29tbWFuZE5hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJWYW5pbGEgY29tbWFuZHMgc2V0IHVwXCIpO1xuICAgIH07XG4gICAgQ29uc29sZUNvbW1hbmRzU2VydmljZS5wcm90b3R5cGUuZ2V0Q29tbWFuZEV4ZWN1dG9yID0gZnVuY3Rpb24gKGNvbW1hbmROYW1lKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICBhcmdzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgcG9zc2libGUgZXhjZXB0aW9ucyBpbiB0aGlzIGZ1bmN0aW9uXG4gICAgICAgICAgICB2YXIgc2NoZW1hID0gX3RoaXMuc2NoZW1hcy5nZXQoY29tbWFuZE5hbWUpO1xuICAgICAgICAgICAgaWYgKHNjaGVtYSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiU2NoZW1hIG5vdCBmb3VuZCBmb3IgY29tbWFuZFwiLCBjb21tYW5kTmFtZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoICE9PSBzY2hlbWEubGVuZ3RoICYmICFfdGhpcy5pbW11bmVTY2hlbWEuaW5jbHVkZXMoY29tbWFuZE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiTWlzbWF0Y2ggZm91bmQgaW4gdGhlIHNjaGVtYSBvZlwiLCBjb21tYW5kTmFtZSwgXCJjb21tYW5kXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoc2NoZW1hW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ21kQXJndW1lbnQuT2JqZWN0UmVmZXJlbmNlOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnc1tpXSA9IGxvY2FsSWRUb1JlbW90ZUlkKHBhcnNlSW50KFwiXCIuY29uY2F0KGFyZ3NbaV0pKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFyZ3NbaV0gIT09IFwic3RyaW5nXCIgJiYgdHlwZW9mIGFyZ3NbaV0gIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiQmFkIGFyZ3VtZW50IHR5cGUgaW4gY29tbWFuZFwiLCBjb21tYW5kTmFtZSwgXCJhcmd1bWVudCBpbmRleFwiLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgdDogTXNnVHlwZS5Db25zb2xlQ29tbWFuZCxcbiAgICAgICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29tbWFuZE5hbWU6IGNvbW1hbmROYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnczogYXJnc1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIE1lYW50IHRvIGJlIHNob3duIHRvIHVzZXIsIG5vdCBmb3IgbG9nZ2luZ1xuICAgICAgICAgICAgX3RoaXMuc3AucHJpbnRDb25zb2xlKFwic2VudFwiKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBDb25zb2xlQ29tbWFuZHNTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgQ29uc29sZUNvbW1hbmRzU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiA9ICh0aGlzICYmIHRoaXMuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG5pbXBvcnQgeyBwcmludENvbnNvbGUgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IE1zZ1R5cGUgfSBmcm9tIFwiLi4vLi4vbWVzc2FnZXNcIjtcbmltcG9ydCB7IGdldFBjSW52ZW50b3J5IH0gZnJvbSBcIi4vcmVtb3RlU2VydmVyXCI7XG5pbXBvcnQgeyBnZXRJbnZlbnRvcnksIGdldERpZmYsIGhhc0V4dHJhcywgcmVtb3ZlU2ltcGxlSXRlbXNBc01hbnlBc1Bvc3NpYmxlLCBzdW1JbnZlbnRvcmllcyB9IGZyb20gXCIuLi8uLi9zeW5jL2ludmVudG9yeVwiO1xuaW1wb3J0IHsgTGFzdEludlNlcnZpY2UgfSBmcm9tIFwiLi9sYXN0SW52U2VydmljZVwiO1xuaW1wb3J0IHsgU3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlIH0gZnJvbSBcIi4vc3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlXCI7XG5pbXBvcnQgeyBsb2NhbElkVG9SZW1vdGVJZCB9IGZyb20gXCIuLi8uLi92aWV3L3dvcmxkVmlld01pc2NcIjtcbnZhciBDb250YWluZXJzU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQ29udGFpbmVyc1NlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ29udGFpbmVyc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIGNvbnRyb2xsZXIub24oJ2NvbnRhaW5lckNoYW5nZWQnLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25Db250YWluZXJDaGFuZ2VkKGUpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBDb250YWluZXJzU2VydmljZS5wcm90b3R5cGUub25Db250YWluZXJDaGFuZ2VkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHN3ZWV0Q2FudERyb3BTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFN3ZWV0VGFmZnlTd2VldENhbnREcm9wU2VydmljZSk7XG4gICAgICAgIGlmIChlLm9sZENvbnRhaW5lciAmJiBlLm5ld0NvbnRhaW5lcikge1xuICAgICAgICAgICAgaWYgKGUub2xkQ29udGFpbmVyLmdldEZvcm1JRCgpID09PSAweDE0IHx8XG4gICAgICAgICAgICAgICAgZS5uZXdDb250YWluZXIuZ2V0Rm9ybUlEKCkgPT09IDB4MTQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdEludlNlcnZpY2VfMSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihMYXN0SW52U2VydmljZSk7XG4gICAgICAgICAgICAgICAgaWYgKCFsYXN0SW52U2VydmljZV8xLmxhc3RJbnYpIHtcbiAgICAgICAgICAgICAgICAgICAgbGFzdEludlNlcnZpY2VfMS5sYXN0SW52ID0gZ2V0UGNJbnZlbnRvcnkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGxhc3RJbnZTZXJ2aWNlXzEubGFzdEludikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SW52ID0gZ2V0SW52ZW50b3J5KHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEl0IHNlZW1zIHRoYXQgJ2lnbm9yZVdvcm4gPSBmYWxzZScgZml4ZXMgdGhpczpcbiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3NreXJpbS1tdWx0aXBsYXllci9pc3N1ZS10cmFja2VyL2lzc3Vlcy80M1xuICAgICAgICAgICAgICAgICAgICAvLyBGb3Igc29tZSByZWFzb24gZXhjZXNzIGRpZmYgaXMgcHJvZHVjZWQgd2hlbiAnaWdub3JlV29ybiA9IHRydWUnXG4gICAgICAgICAgICAgICAgICAgIC8vIEkgdGhvdWdodCB0aGF0IGl0IHdvdWxkIGJlIHZpY2UgdmVyc2EgYnV0IHRoYXQncyBob3cgaXQgd29ya3NcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlnbm9yZVdvcm4gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpZmYgPSBnZXREaWZmKGxhc3RJbnZTZXJ2aWNlXzEubGFzdEludiwgbmV3SW52LCBpZ25vcmVXb3JuKTtcbiAgICAgICAgICAgICAgICAgICAgcHJpbnRDb25zb2xlKCdkaWZmOicpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpZmYuZW50cmllcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJpbnRDb25zb2xlKFwiW1wiLmNvbmNhdChpLCBcIl0gXCIpLmNvbmNhdChKU09OLnN0cmluZ2lmeShkaWZmLmVudHJpZXNbaV0pKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG1zZ3MgPSBkaWZmLmVudHJpZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiByZXZpZXcgdGhpcyBjb25kaXRpb24sIHNlZW1zIHRvIGJlIGluY29ycmVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5LmNvdW50ID4gMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gc3dlZXRDYW50RHJvcFNlcnZpY2UuY2FuRHJvcE9yUHV0SXRlbShlbnRyeS5iYXNlSWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIGVudHJ5LmNvdW50ICE9PSAwOyB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeUNvcHkgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGVudHJ5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbXNnID0gX19hc3NpZ24oX19hc3NpZ24oe30sIGVudHJ5Q29weSksIHsgdDogZW50cnkuY291bnQgPiAwID8gTXNnVHlwZS5QdXRJdGVtIDogTXNnVHlwZS5UYWtlSXRlbSwgdGFyZ2V0OiBlLm9sZENvbnRhaW5lci5nZXRGb3JtSUQoKSA9PT0gMHgxNFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGxvY2FsSWRUb1JlbW90ZUlkKGUubmV3Q29udGFpbmVyLmdldEZvcm1JRCgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGxvY2FsSWRUb1JlbW90ZUlkKGUub2xkQ29udGFpbmVyLmdldEZvcm1JRCgpKSB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5jb3VudCA9IE1hdGguYWJzKG1zZy5jb3VudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKChfYSA9IF90aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KGVudHJ5LmJhc2VJZCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXROYW1lKCkpID09PSBtc2cubmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBtc2cubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtc2c7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBtc2dzLmZvckVhY2goZnVuY3Rpb24gKG1zZykgeyByZXR1cm4gX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBtc2csXG4gICAgICAgICAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiXG4gICAgICAgICAgICAgICAgICAgIH0pOyB9KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gUHJldmVudCBlbWl0dGluZyAxLDIsMyw0LDUgY2hhbmdlcyB3aGVuIHRha2luZy9wdXR0aW5nIDUgcG90aW9ucyBvbmUgYnkgb25lXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgY29kZSBtYWtlcyBpdCAxLDEsMSwxLDEgYnV0IHdvcmtzIG9ubHkgZm9yIGV4dHJhLWxlc3MgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgLy8gQXQgdGhlIG1vbWVudCBvZiB3cml0aW5nIHRoaXMgSSB0aGluayBpdCdzIG5vdCBuZWVkZWQgZm9yIGl0ZW1zIHdpdGggZXh0cmFzXG4gICAgICAgICAgICAgICAgICAgIGRpZmYuZW50cmllcy5mb3JFYWNoKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbnZTZXJ2aWNlXzEubGFzdEludiAmJiAhaGFzRXh0cmFzKGVudHJ5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwdXQgPSBlbnRyeS5jb3VudCA+IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRha2UgPSBlbnRyeS5jb3VudCA8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW52U2VydmljZV8xLmxhc3RJbnYgPSByZW1vdmVTaW1wbGVJdGVtc0FzTWFueUFzUG9zc2libGUobGFzdEludlNlcnZpY2VfMS5sYXN0SW52LCBlbnRyeS5iYXNlSWQsIGVudHJ5LmNvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodGFrZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWRkID0geyBlbnRyaWVzOiBbZW50cnldIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZC5lbnRyaWVzWzBdLmNvdW50ICo9IC0xO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW52U2VydmljZV8xLmxhc3RJbnYgPSBzdW1JbnZlbnRvcmllcyhsYXN0SW52U2VydmljZV8xLmxhc3RJbnYsIGFkZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBDb250YWluZXJzU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IENvbnRhaW5lcnNTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuLy8gVE9ETzogcmVmYWN0b3IgdGhpcyBvdXRcbmltcG9ydCB7IGxvY2FsSWRUb1JlbW90ZUlkIH0gZnJvbSBcIi4uLy4uL3ZpZXcvd29ybGRWaWV3TWlzY1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0IHsgTXNnVHlwZSB9IGZyb20gXCIuLi8uLi9tZXNzYWdlc1wiO1xuaW1wb3J0IHsgbG9nVHJhY2UsIGxvZ0Vycm9yIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbnZhciBDcmFmdFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKENyYWZ0U2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDcmFmdFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmZ1cm5pdHVyZVN0cmVhayA9IG5ldyBNYXAoKTtcbiAgICAgICAgY29udHJvbGxlci5vbignY29udGFpbmVyQ2hhbmdlZCcsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkNvbnRhaW5lckNoYW5nZWQoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENyYWZ0U2VydmljZS5wcm90b3R5cGUub25Db250YWluZXJDaGFuZ2VkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIG9sZENvbnRhaW5lcklkID0gZS5vbGRDb250YWluZXIgPyBlLm9sZENvbnRhaW5lci5nZXRGb3JtSUQoKSA6IDA7XG4gICAgICAgIHZhciBuZXdDb250YWluZXJJZCA9IGUubmV3Q29udGFpbmVyID8gZS5uZXdDb250YWluZXIuZ2V0Rm9ybUlEKCkgOiAwO1xuICAgICAgICB2YXIgYmFzZU9iaklkID0gZS5iYXNlT2JqID8gZS5iYXNlT2JqLmdldEZvcm1JRCgpIDogMDtcbiAgICAgICAgaWYgKG9sZENvbnRhaW5lcklkICE9PSAweDE0ICYmIG5ld0NvbnRhaW5lcklkICE9PSAweDE0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZ1cm5pdHVyZVJlZiA9IHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKS5nZXRGdXJuaXR1cmVSZWZlcmVuY2UoKTtcbiAgICAgICAgaWYgKCFmdXJuaXR1cmVSZWYpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZnVybml0dXJlSWQgPSBmdXJuaXR1cmVSZWYuZ2V0Rm9ybUlEKCk7XG4gICAgICAgIGlmIChvbGRDb250YWluZXJJZCA9PT0gMHgxNCAmJiBuZXdDb250YWluZXJJZCA9PT0gMCkge1xuICAgICAgICAgICAgdmFyIGNyYWZ0SW5wdXRPYmplY3RzID0gdGhpcy5mdXJuaXR1cmVTdHJlYWsuZ2V0KGZ1cm5pdHVyZUlkKTtcbiAgICAgICAgICAgIGlmICghY3JhZnRJbnB1dE9iamVjdHMpIHtcbiAgICAgICAgICAgICAgICBjcmFmdElucHV0T2JqZWN0cyA9IHsgZW50cmllczogW10gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNyYWZ0SW5wdXRPYmplY3RzLmVudHJpZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgYmFzZUlkOiBiYXNlT2JqSWQsXG4gICAgICAgICAgICAgICAgY291bnQ6IGUubnVtSXRlbXMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuZnVybml0dXJlU3RyZWFrLnNldChmdXJuaXR1cmVJZCwgY3JhZnRJbnB1dE9iamVjdHMpO1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJBZGRpbmcgYmFzZU9iaklkXCIsIGJhc2VPYmpJZC50b1N0cmluZygxNiksIFwibnVtSXRlbXNcIiwgZS5udW1JdGVtcywgXCJ0byBjcmFmdFwiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvbGRDb250YWluZXJJZCA9PT0gMCAmJiBuZXdDb250YWluZXJJZCA9PT0gMHgxNCkge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ0ZpbmlzaGluZyBjcmFmdCcpO1xuICAgICAgICAgICAgdmFyIGNyYWZ0SW5wdXRPYmplY3RzID0gdGhpcy5mdXJuaXR1cmVTdHJlYWsuZ2V0KGZ1cm5pdHVyZUlkKTtcbiAgICAgICAgICAgIGlmIChjcmFmdElucHV0T2JqZWN0cyAmJiBjcmFmdElucHV0T2JqZWN0cy5lbnRyaWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZnVybml0dXJlU3RyZWFrLmRlbGV0ZShmdXJuaXR1cmVJZCk7XG4gICAgICAgICAgICAgICAgdmFyIHdvcmtiZW5jaCA9IGxvY2FsSWRUb1JlbW90ZUlkKGZ1cm5pdHVyZUlkKTtcbiAgICAgICAgICAgICAgICBpZiAoIXdvcmtiZW5jaCkge1xuICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcImxvY2FsSWRUb1JlbW90ZUlkIHJldHVybmVkIDAgZm9yIGZ1cm5pdHVyZUlkXCIsIGZ1cm5pdHVyZUlkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0T2JqZWN0SWQgPSBiYXNlT2JqSWQ7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJTZW5kaW5nIGNyYWZ0IHdvcmtiZW5jaFwiLCB3b3JrYmVuY2gsIFwicmVzdWx0T2JqZWN0SWRcIiwgcmVzdWx0T2JqZWN0SWQsIFwiY3JhZnRJbnB1dE9iamVjdHNcIiwgSlNPTi5zdHJpbmdpZnkoY3JhZnRJbnB1dE9iamVjdHMuZW50cmllcykpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuQ3JhZnRJdGVtLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogeyB3b3JrYmVuY2g6IHdvcmtiZW5jaCwgY3JhZnRJbnB1dE9iamVjdHM6IGNyYWZ0SW5wdXRPYmplY3RzLCByZXN1bHRPYmplY3RJZDogcmVzdWx0T2JqZWN0SWQgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gQ3JhZnRTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgQ3JhZnRTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQWN0b3IgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IFJlc3Bhd25OZWVkZWRFcnJvciB9IGZyb20gXCIuLi8uLi9saWIvZXJyb3JzXCI7XG5pbXBvcnQgeyBBbmltYXRpb25FdmVudE5hbWUgfSBmcm9tIFwiLi4vLi4vc3luYy9hbmltYXRpb25cIjtcbmltcG9ydCB7IFJhZ2RvbGxTZXJ2aWNlIH0gZnJvbSBcIi4vcmFnZG9sbFNlcnZpY2VcIjtcbnZhciBEZWF0aFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERlYXRoU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEZWF0aFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmFwcGx5RGVhdGhTdGF0ZSA9IGZ1bmN0aW9uIChhY3RvciwgaXNEZWFkKSB7XG4gICAgICAgICAgICBpZiAoYWN0b3IuaXNEZWFkKCkgPT09IGlzRGVhZCAmJiBfdGhpcy5pc1BsYXllcihhY3RvcikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzRGVhZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmtpbGxBY3RvcihhY3RvciwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZXN1cnJlY3RBY3RvcihhY3Rvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmtpbGxBY3RvciA9IGZ1bmN0aW9uIChhY3Rvciwga2lsbGVyKSB7XG4gICAgICAgICAgICBpZiAoa2lsbGVyID09PSB2b2lkIDApIHsga2lsbGVyID0gbnVsbDsgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmlzUGxheWVyKGFjdG9yKSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnBsYXllckRlYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIF90aGlzLmJ1c3lGb3JPdGhlclJlYXNvbnNDb3VudGVyKys7XG4gICAgICAgICAgICAgICAgX3RoaXMuc3AuVXRpbGl0eS53YWl0KDcuNSkudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5idXN5Rm9yT3RoZXJSZWFzb25zQ291bnRlci0tOyB9KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5hbGxvd2VkUGxheWVyQW5pbWF0aW9ucyA9IFtdO1xuICAgICAgICAgICAgICAgIGFjdG9yLnNldERvbnRNb3ZlKHRydWUpO1xuICAgICAgICAgICAgICAgIF90aGlzLmtpbGxXaXRoUHVzaChhY3Rvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhY3Rvci5lbmREZWZlcnJlZEtpbGwoKTtcbiAgICAgICAgICAgICAgICBhY3Rvci5raWxsKGtpbGxlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLnJlc3VycmVjdEFjdG9yID0gZnVuY3Rpb24gKGFjdG9yKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNQbGF5ZXIoYWN0b3IpID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMucGxheWVyRGVhZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIF90aGlzLmJ1c3lGb3JPdGhlclJlYXNvbnNDb3VudGVyKys7XG4gICAgICAgICAgICAgICAgX3RoaXMuc3AuVXRpbGl0eS53YWl0KDcuNSkudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5idXN5Rm9yT3RoZXJSZWFzb25zQ291bnRlci0tOyB9KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5hbGxvd2VkUGxheWVyQW5pbWF0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICAgICAgYWN0b3Iuc2V0RG9udE1vdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIF90aGlzLnJlc3N1cmVjdFdpdGhQdXNoS2lsbChhY3Rvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmVzcGF3bk5lZWRlZEVycm9yKFwibmVlZHMgdG8gYmUgcmVzcGF3bmVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5raWxsV2l0aFB1c2ggPSBmdW5jdGlvbiAoYWN0b3IpIHtcbiAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgIChfYSA9IF90aGlzLmFsbG93ZWRQbGF5ZXJBbmltYXRpb25zKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EucHVzaChBbmltYXRpb25FdmVudE5hbWUuUmFnZG9sbCk7XG4gICAgICAgICAgICBhY3Rvci5wdXNoQWN0b3JBd2F5KGFjdG9yLCAwKTtcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMucmVzc3VyZWN0V2l0aFB1c2hLaWxsID0gZnVuY3Rpb24gKGFjdCkge1xuICAgICAgICAgICAgdmFyIGZvcm1JZCA9IGFjdC5nZXRGb3JtSUQoKTtcbiAgICAgICAgICAgIHZhciByYWdkb2xsU2VydmljZSA9IF90aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoUmFnZG9sbFNlcnZpY2UpO1xuICAgICAgICAgICAgcmFnZG9sbFNlcnZpY2Uuc2FmZVJlbW92ZVJhZ2RvbGxGcm9tV29ybGQoYWN0LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjdG9yID0gQWN0b3IuZnJvbShfdGhpcy5zcC5HYW1lLmdldEZvcm1FeChmb3JtSWQpKTtcbiAgICAgICAgICAgICAgICBpZiAoIWFjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogc2hvdWxkIHVzZSBhY3RvciB2YXJpYWJsZSBpbnN0ZWFkIG9mIGdldFBsYXllcj9cbiAgICAgICAgICAgICAgICAvLyBUT0RPOiB1c2UgZGlmZmVyZW50IGlHZXRVcFR5cGUgaWYgcmVzc3VyZWN0aW5nIHVuZGVyIHdhdGVyXG4gICAgICAgICAgICAgICAgX3RoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKS5zZXRBbmltYXRpb25WYXJpYWJsZUludChcImlHZXRVcFR5cGVcIiwgMSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuc3AuRGVidWcuc2VuZEFuaW1hdGlvbkV2ZW50KGFjdG9yLCBBbmltYXRpb25FdmVudE5hbWUuR2V0VXBCZWdpbik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaXNQbGF5ZXIgPSBmdW5jdGlvbiAoYWN0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBhY3Rvci5nZXRGb3JtSUQoKSA9PT0gX3RoaXMucGxheWVyQWN0b3JJZDtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gTnVsbCB0byBhbGxvdyBhbGwgYW5pbWF0aW9ucy4gRW1wdHkgYXJyYXkgdG8gZGlzYWxsb3cgYWxsXG4gICAgICAgIF90aGlzLmFsbG93ZWRQbGF5ZXJBbmltYXRpb25zID0gbnVsbDtcbiAgICAgICAgX3RoaXMucGxheWVyQWN0b3JJZCA9IDB4MTQ7XG4gICAgICAgIF90aGlzLnBsYXllckRlYWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuYnVzeUZvck90aGVyUmVhc29uc0NvdW50ZXIgPSAwO1xuICAgICAgICBjb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgY29udHJvbGxlci5lbWl0dGVyLm9uKFwiYXBwbHlEZWF0aFN0YXRlRXZlbnRcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uQXBwbHlEZWF0aFN0YXRlKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuaG9va0Rpc2FibGVLaWxsTW92ZXMoKTtcbiAgICAgICAgX3RoaXMuaG9va0Rpc2FibGVTdGFnZ2VyKCk7XG4gICAgICAgIF90aGlzLmhvb2tEaXNhYmxlQmxvY2tlZEFuaW1zKCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGVhdGhTZXJ2aWNlLnByb3RvdHlwZS5pc0J1c3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBsYXllckRlYWQgfHwgdGhpcy5idXN5Rm9yT3RoZXJSZWFzb25zQ291bnRlciA+IDA7XG4gICAgfTtcbiAgICBEZWF0aFNlcnZpY2UucHJvdG90eXBlLm9uY2VVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwbGF5ZXIgPSB0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgIHBsYXllciA9PT0gbnVsbCB8fCBwbGF5ZXIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBsYXllci5zdGFydERlZmVycmVkS2lsbCgpO1xuICAgIH07XG4gICAgRGVhdGhTZXJ2aWNlLnByb3RvdHlwZS5vbkFwcGx5RGVhdGhTdGF0ZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHRoaXMuYXBwbHlEZWF0aFN0YXRlKGUuYWN0b3IsIGUuaXNEZWFkKTtcbiAgICB9O1xuICAgIERlYXRoU2VydmljZS5wcm90b3R5cGUuaG9va0Rpc2FibGVLaWxsTW92ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AuaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgICAgICBlbnRlcjogZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICAgICAgICAgIGN0eC5hbmltRXZlbnROYW1lID0gXCJcIjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsZWF2ZTogZnVuY3Rpb24gKCkgeyB9LFxuICAgICAgICB9LCAweGZmMDAwMDAwLCAweGZmZmZmZmZmLCBcIktpbGxNb3ZlKlwiKTtcbiAgICB9O1xuICAgIERlYXRoU2VydmljZS5wcm90b3R5cGUuaG9va0Rpc2FibGVTdGFnZ2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGVhdmU6IGZ1bmN0aW9uICgpIHsgfSxcbiAgICAgICAgfSwgMHhmZjAwMDAwMCwgMHhmZmZmZmZmZiwgXCJzdGFnZ2VyU3RhcnRcIik7XG4gICAgfTtcbiAgICBEZWF0aFNlcnZpY2UucHJvdG90eXBlLmhvb2tEaXNhYmxlQmxvY2tlZEFuaW1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYWxsb3dlZFBsYXllckFuaW1hdGlvbnMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmFsbG93ZWRQbGF5ZXJBbmltYXRpb25zLmluY2x1ZGVzKGN0eC5hbmltRXZlbnROYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlYXZlOiBmdW5jdGlvbiAoKSB7IH0sXG4gICAgICAgIH0sIHRoaXMucGxheWVyQWN0b3JJZCwgdGhpcy5wbGF5ZXJBY3RvcklkKTtcbiAgICB9O1xuICAgIHJldHVybiBEZWF0aFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBEZWF0aFNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgRGlzYWJsZURpZmZpY3VsdHlTZWxlY3Rpb25TZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEaXNhYmxlRGlmZmljdWx0eVNlbGVjdGlvblNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGlzYWJsZURpZmZpY3VsdHlTZWxlY3Rpb25TZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5kaWZmaWN1bHR5ID0gNTtcbiAgICAgICAgX3RoaXMuY291bnRlciA9IDA7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGlzYWJsZURpZmZpY3VsdHlTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5vblVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb3VudGVyKys7XG4gICAgICAgIGlmICh0aGlzLmNvdW50ZXIgPj0gNjApIHtcbiAgICAgICAgICAgIHRoaXMuY291bnRlciA9IDA7XG4gICAgICAgICAgICB0aGlzLnNwLlV0aWxpdHkuc2V0SU5JSW50KFwiaURpZmZpY3VsdHk6R2FtZVBsYXlcIiwgdGhpcy5kaWZmaWN1bHR5KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERpc2FibGVEaWZmaWN1bHR5U2VsZWN0aW9uU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IERpc2FibGVEaWZmaWN1bHR5U2VsZWN0aW9uU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBEaXNhYmxlRmFzdFRyYXZlbFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERpc2FibGVGYXN0VHJhdmVsU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEaXNhYmxlRmFzdFRyYXZlbFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGlzYWJsZUZhc3RUcmF2ZWxTZXJ2aWNlLnByb3RvdHlwZS5vblVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zcC5HYW1lLmVuYWJsZUZhc3RUcmF2ZWwoZmFsc2UpO1xuICAgIH07XG4gICAgcmV0dXJuIERpc2FibGVGYXN0VHJhdmVsU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IERpc2FibGVGYXN0VHJhdmVsU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IGxvZ0Vycm9yIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbnZhciBEaXNhYmxlU2tpbGxBZHZhbmNlU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGlzYWJsZVNraWxsQWR2YW5jZVNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGlzYWJsZVNraWxsQWR2YW5jZVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vbmNlVXBkYXRlKCk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERpc2FibGVTa2lsbEFkdmFuY2VTZXJ2aWNlLnByb3RvdHlwZS5vbmNlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB0dXJuIG9mZiBwbGF5ZXIgbGV2ZWwgZXhwXG4gICAgICAgIHRoaXMuc3AuR2FtZS5zZXRHYW1lU2V0dGluZ0Zsb2F0KFwiZlhQUGVyU2tpbGxSYW5rXCIsIDApO1xuICAgICAgICAvLyB0dXJuIG9mZiBza2lsbCBleHBcbiAgICAgICAgdGhpcy50dXJuT2ZmU2tpbGxMb2NhbEV4cCgxOCAvKiBBY3RvclZhbHVlLkFsdGVyYXRpb24gKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDE5IC8qIEFjdG9yVmFsdWUuQ29uanVyYXRpb24gKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDIwIC8qIEFjdG9yVmFsdWUuRGVzdHJ1Y3Rpb24gKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDIxIC8qIEFjdG9yVmFsdWUuSWxsdXNpb24gKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDIyIC8qIEFjdG9yVmFsdWUuUmVzdG9yYXRpb24gKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDIzIC8qIEFjdG9yVmFsdWUuRW5jaGFudGluZyAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoNiAvKiBBY3RvclZhbHVlLk9uZUhhbmRlZCAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoNyAvKiBBY3RvclZhbHVlLlR3b0hhbmRlZCAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoOCAvKiBBY3RvclZhbHVlLkFyY2hlcnkgKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDkgLyogQWN0b3JWYWx1ZS5CbG9jayAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoMTAgLyogQWN0b3JWYWx1ZS5TbWl0aGluZyAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoMTEgLyogQWN0b3JWYWx1ZS5IZWF2eUFybW9yICovKTtcbiAgICAgICAgdGhpcy50dXJuT2ZmU2tpbGxMb2NhbEV4cCgxMiAvKiBBY3RvclZhbHVlLkxpZ2h0QXJtb3IgKi8pO1xuICAgICAgICB0aGlzLnR1cm5PZmZTa2lsbExvY2FsRXhwKDEzIC8qIEFjdG9yVmFsdWUuUGlja3BvY2tldCAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoMTQgLyogQWN0b3JWYWx1ZS5Mb2NrcGlja2luZyAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoMTUgLyogQWN0b3JWYWx1ZS5TbmVhayAqLyk7XG4gICAgICAgIHRoaXMudHVybk9mZlNraWxsTG9jYWxFeHAoMTYgLyogQWN0b3JWYWx1ZS5BbGNoZW15ICovKTtcbiAgICAgICAgdGhpcy50dXJuT2ZmU2tpbGxMb2NhbEV4cCgxNyAvKiBBY3RvclZhbHVlLlNwZWVjaCAqLyk7XG4gICAgfTtcbiAgICBEaXNhYmxlU2tpbGxBZHZhbmNlU2VydmljZS5wcm90b3R5cGUudHVybk9mZlNraWxsTG9jYWxFeHAgPSBmdW5jdGlvbiAoYXYpIHtcbiAgICAgICAgdmFyIGF2aSA9IHRoaXMuc3AuQWN0b3JWYWx1ZUluZm8uZ2V0QWN0b3JWYWx1ZUluZm9CeUlEKGF2KTtcbiAgICAgICAgaWYgKGF2aSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJOb3QgZm91bmQgQWN0b3JWYWx1ZUluZm8gZm9yIGFjdG9yIHZhbHVlXCIsIGF2KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBhdmkuc2V0U2tpbGxVc2VNdWx0KDApO1xuICAgICAgICBhdmkuc2V0U2tpbGxPZmZzZXRNdWx0KDApO1xuICAgIH07XG4gICAgO1xuICAgIHJldHVybiBEaXNhYmxlU2tpbGxBZHZhbmNlU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IERpc2FibGVTa2lsbEFkdmFuY2VTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0IHsgTXNnVHlwZSB9IGZyb20gXCIuLi8uLi9tZXNzYWdlc1wiO1xuaW1wb3J0IHsgU3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlIH0gZnJvbSBcIi4vc3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlXCI7XG5pbXBvcnQgeyBXb3JsZENsZWFuZXJTZXJ2aWNlIH0gZnJvbSBcIi4vd29ybGRDbGVhbmVyU2VydmljZVwiO1xuaW1wb3J0IHsgbG9nVHJhY2UgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xudmFyIERyb3BJdGVtU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRHJvcEl0ZW1TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERyb3BJdGVtU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgY29udHJvbGxlci5vbignY29udGFpbmVyQ2hhbmdlZCcsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkNvbnRhaW5lckNoYW5nZWQoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERyb3BJdGVtU2VydmljZS5wcm90b3R5cGUub25Db250YWluZXJDaGFuZ2VkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgc3dlZXRDYW50RHJvcFNlcnZpY2UgPSB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoU3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlKTtcbiAgICAgICAgdmFyIHBsID0gdGhpcy5zcC5HYW1lLmdldFBsYXllcigpO1xuICAgICAgICB2YXIgaXNQbGF5ZXIgPSBwbCAmJiBlLm9sZENvbnRhaW5lciAmJiBwbC5nZXRGb3JtSUQoKSA9PT0gZS5vbGRDb250YWluZXIuZ2V0Rm9ybUlEKCk7XG4gICAgICAgIHZhciBub0NvbnRhaW5lciA9IGUubmV3Q29udGFpbmVyID09PSBudWxsIHx8IGUubmV3Q29udGFpbmVyID09PSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciBpc1JlZmVyZW5jZSA9IGUucmVmZXJlbmNlICE9PSBudWxsO1xuICAgICAgICBpZiAoZS5uZXdDb250YWluZXIgJiYgZS5uZXdDb250YWluZXIuZ2V0Rm9ybUlEKCkgPT09IHBsLmdldEZvcm1JRCgpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAoIXRoaXMuc3AuVWkuaXNNZW51T3BlbihcIkludmVudG9yeU1lbnVcIikpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmIChpc1BsYXllciAmJlxuICAgICAgICAgICAgaXNSZWZlcmVuY2UgJiZcbiAgICAgICAgICAgIG5vQ29udGFpbmVyICYmXG4gICAgICAgICAgICBzd2VldENhbnREcm9wU2VydmljZS5jYW5Ecm9wT3JQdXRJdGVtKGUuYmFzZU9iai5nZXRGb3JtSUQoKSkpIHtcbiAgICAgICAgICAgIHZhciByYWRpdXMgPSAyMDAwO1xuICAgICAgICAgICAgdmFyIGJhc2VJZCA9IGUuYmFzZU9iai5nZXRGb3JtSUQoKTtcbiAgICAgICAgICAgIHZhciBwbGF5ZXIgPSB0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgICAgICB2YXIgc2V0ID0gbmV3IFNldCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAyMDA7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciByZWZySWQgPSAoX2EgPSB0aGlzLnNwLkdhbWUuZmluZFJhbmRvbVJlZmVyZW5jZU9mVHlwZSh0aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KGJhc2VJZCksIHBsYXllci5nZXRQb3NpdGlvblgoKSwgcGxheWVyLmdldFBvc2l0aW9uWSgpLCBwbGF5ZXIuZ2V0UG9zaXRpb25aKCksIHJhZGl1cykpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRGb3JtSUQoKTtcbiAgICAgICAgICAgICAgICBpZiAocmVmcklkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldC5hZGQocmVmcklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBudW1Gb3VuZF8xID0gMDtcbiAgICAgICAgICAgIHZhciB3b3JsZENsZWFuZXJTZXJ2aWNlXzEgPSB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoV29ybGRDbGVhbmVyU2VydmljZSk7XG4gICAgICAgICAgICBzZXQuZm9yRWFjaChmdW5jdGlvbiAocmVmcklkKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlZiA9IF90aGlzLnNwLk9iamVjdFJlZmVyZW5jZS5mcm9tKF90aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KHJlZnJJZCkpO1xuICAgICAgICAgICAgICAgIGlmIChyZWYgIT09IG51bGwgJiYgcmVmLmlzRGVsZXRlZCgpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVmcklkXzEgPSByZWYuZ2V0Rm9ybUlEKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3b3JsZENsZWFuZXJTZXJ2aWNlXzEuZ2V0V2NQcm90ZWN0aW9uKHJlZnJJZF8xKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVmLmRlbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgKytudW1Gb3VuZF8xO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiRm91bmQgYW5kIGRlbGV0ZWQgcmVmZXJlbmNlIFwiICsgcmVmcklkXzEudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIkZvdW5kIHJlZmVyZW5jZSBcIiArIHJlZnJJZF8xLnRvU3RyaW5nKDE2KSArIFwiIGJ1dCBpdCdzIHByb3RlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFudW1Gb3VuZF8xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvZ1RyYWNlKHRoaXMsIFwiSWdub3JpbmcgaXRlbSBkcm9wIGFzIGZhbHNlIHBvc2l0aXZlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHQgPSBNc2dUeXBlLkRyb3BJdGVtO1xuICAgICAgICAgICAgdmFyIGNvdW50ID0gZS5udW1JdGVtcztcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZToge1xuICAgICAgICAgICAgICAgICAgICB0OiB0LFxuICAgICAgICAgICAgICAgICAgICBiYXNlSWQ6IGJhc2VJZCxcbiAgICAgICAgICAgICAgICAgICAgY291bnQ6IGNvdW50LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBEcm9wSXRlbVNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBEcm9wSXRlbVNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgRW5mb3JjZUxpbWl0YXRpb25zU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRW5mb3JjZUxpbWl0YXRpb25zU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbmZvcmNlTGltaXRhdGlvbnNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBjb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgY29udHJvbGxlci5lbWl0dGVyLm9uKFwiZ2FtZUxvYWRcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uR2FtZUxvYWQoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEVuZm9yY2VMaW1pdGF0aW9uc1NlcnZpY2UucHJvdG90eXBlLm9uY2VVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AuR2FtZS5zZXRJbkNoYXJnZW4odHJ1ZSwgdHJ1ZSwgZmFsc2UpO1xuICAgIH07XG4gICAgRW5mb3JjZUxpbWl0YXRpb25zU2VydmljZS5wcm90b3R5cGUub25HYW1lTG9hZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB0aGlzLnNwLkdhbWUuc2V0SW5DaGFyZ2VuKHRydWUsIHRydWUsIGZhbHNlKTtcbiAgICB9O1xuICAgIHJldHVybiBFbmZvcmNlTGltaXRhdGlvbnNTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgRW5mb3JjZUxpbWl0YXRpb25zU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IGF1dGhHYW1lRGF0YVN0b3JhZ2VLZXkgfSBmcm9tIFwiLi4vLi4vZmVhdHVyZXMvYXV0aE1vZGVsXCI7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgRnJvbnRIb3RSZWxvYWRTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhGcm9udEhvdFJlbG9hZFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRnJvbnRIb3RSZWxvYWRTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICB2YXIgZW5hYmxlID0gISFfdGhpcy5zcC5zZXR0aW5nc1tcInNreW1wNS1jbGllbnRcIl1bXCJlbmFibGUtZnJvbnQtaG90cmVsb2FkXCJdO1xuICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJlbmFibGUtZnJvbnQtaG90cmVsb2FkIGlzXCIsIGVuYWJsZSk7XG4gICAgICAgIGlmICghZW5hYmxlKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogcmVmYWN0b3Igb3V0IHZlcnkgc2ltaWxhciBjb2RlIGluIHNreW1wQ2xpZW50LnRzXG4gICAgICAgIHZhciBhdXRoR2FtZURhdGEgPSBfdGhpcy5zcC5zdG9yYWdlW2F1dGhHYW1lRGF0YVN0b3JhZ2VLZXldO1xuICAgICAgICB2YXIgc3RvcmFnZUhhc1ZhbGlkQXV0aEdhbWVEYXRhID0gKGF1dGhHYW1lRGF0YSA9PT0gbnVsbCB8fCBhdXRoR2FtZURhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGF1dGhHYW1lRGF0YS5sb2NhbCkgfHwgKGF1dGhHYW1lRGF0YSA9PT0gbnVsbCB8fCBhdXRoR2FtZURhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGF1dGhHYW1lRGF0YS5yZW1vdGUpO1xuICAgICAgICBpZiAoc3RvcmFnZUhhc1ZhbGlkQXV0aEdhbWVEYXRhKSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJSZWNvdmVyZWQgQXV0aEdhbWVEYXRhIGZyb20gc3RvcmFnZSwgc3RhcnRpbmcgRnJvbnRIb3RSZWxvYWRTZXJ2aWNlXCIpO1xuICAgICAgICAgICAgX3RoaXMuY29ubmVjdFRvRnJvbnRIb3RSZWxvYWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlVuYWJsZSB0byByZWNvdmVyIEF1dGhHYW1lRGF0YSBmcm9tIHN0b3JhZ2UsIHdhaXRpbmcgZm9yIGF1dGhcIik7XG4gICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJhdXRoQXR0ZW1wdFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25BdXRoQXR0ZW1wdChlKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBGcm9udEhvdFJlbG9hZFNlcnZpY2UucHJvdG90eXBlLm9uQXV0aEF0dGVtcHQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB0aGlzLmNvbm5lY3RUb0Zyb250SG90UmVsb2FkKCk7XG4gICAgfTtcbiAgICBGcm9udEhvdFJlbG9hZFNlcnZpY2UucHJvdG90eXBlLmNvbm5lY3RUb0Zyb250SG90UmVsb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgdXJsID0gXCJsb2NhbGhvc3Q6MTIzNFwiO1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiTG9hZGluZyB1cmxcIiwgdXJsKTtcbiAgICAgICAgICAgIF90aGlzLnNwLmJyb3dzZXIubG9hZFVybCh1cmwpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBGcm9udEhvdFJlbG9hZFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBGcm9udEhvdFJlbG9hZFNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBsb2NhbElkVG9SZW1vdGVJZCwgcmVtb3RlSWRUb0xvY2FsSWQgfSBmcm9tIFwiLi4vLi4vdmlldy93b3JsZFZpZXdNaXNjXCI7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG5pbXBvcnQgeyBNc2dUeXBlIH0gZnJvbSBcIi4uLy4uL21lc3NhZ2VzXCI7XG4vLyBUaGUgcmVhc29uIHdlIHVzZSBnbG9iYWwgc2t5cmltUGxhdGZvcm0gaXMgdGhhdCB0aGlzLnNwIG1heSBiZSBsaW1pdGVkLCBhbmQgZ2FtZW1vZGUgYXBpIG5lZWRzIHVubGltaXRlZCBhY2Nlc3MgdG8gc2t5cmltUGxhdGZvcm1cbi8vIFNsaWd0aGx5IGRpZmZlcmVudCB0eXBlc1xuaW1wb3J0ICogYXMgc2t5cmltUGxhdGZvcm0gZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG5pbXBvcnQgeyBsb2dFcnJvciwgbG9nVHJhY2UgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgU2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlXCI7XG52YXIgR2FtZW1vZGVFdmVudFNvdXJjZVNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEdhbWVtb2RlRXZlbnRTb3VyY2VTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdhbWVtb2RlRXZlbnRTb3VyY2VTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5zZXR1cEV2ZW50U291cmNlID0gZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbmNlKCd1cGRhdGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY3R4Ll9mbihjdHgpO1xuICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCInZXZlbnRTb3VyY2VzXCIsIGN0eC5fZXZlbnROYW1lLCBcIi0gQWRkZWRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKF90aGlzLCBcIidldmVudFNvdXJjZXNcIiwgY3R4Ll9ldmVudE5hbWUsIFwiLVwiLCBlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoX3RoaXMuc3Auc3RvcmFnZVsnZXZlbnRTb3VyY2VDb250ZXh0cyddKSkge1xuICAgICAgICAgICAgX3RoaXMuc3Auc3RvcmFnZVsnZXZlbnRTb3VyY2VDb250ZXh0cyddID0gX3RoaXMuc3Auc3RvcmFnZVsnZXZlbnRTb3VyY2VDb250ZXh0cyddLmZpbHRlcihmdW5jdGlvbiAoY3R4KSB7IHJldHVybiAhY3R4Ll9leHBpcmVkOyB9KTtcbiAgICAgICAgICAgIF90aGlzLnNwLnN0b3JhZ2VbJ2V2ZW50U291cmNlQ29udGV4dHMnXS5mb3JFYWNoKGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXR1cEV2ZW50U291cmNlKGN0eCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ1cGRhdGVHYW1lbW9kZURhdGFNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblVwZGF0ZUdhbWVtb2RlRGF0YU1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEdhbWVtb2RlRXZlbnRTb3VyY2VTZXJ2aWNlLnByb3RvdHlwZS5vblVwZGF0ZUdhbWVtb2RlRGF0YU1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wiZGlzYWJsZS1nYW1lbW9kZS11cGRhdGVzXCJdKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zcC5zdG9yYWdlWydHYW1lbW9kZUV2ZW50U291cmNlU2VydmljZV9zYXdFdmVudFNvdXJjZXMnXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiR2FtZW1vZGUgdXBkYXRlcyBhcmUgZGlzYWJsZWQgYnkgc2V0dGluZ3NcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJHYW1lbW9kZSB1cGRhdGVzIGFyZSBkaXNhYmxlZCBieSBzZXR0aW5ncyAtIHByb2Nlc3NpbmcgZmlyc3QgdXBkYXRlIG9ubHlcIik7XG4gICAgICAgICAgICB0aGlzLnNwLnN0b3JhZ2VbJ0dhbWVtb2RlRXZlbnRTb3VyY2VTZXJ2aWNlX3Nhd0V2ZW50U291cmNlcyddID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5zcC5zdG9yYWdlWydldmVudFNvdXJjZUNvbnRleHRzJ10pKSB7XG4gICAgICAgICAgICB0aGlzLnNwLnN0b3JhZ2VbJ2V2ZW50U291cmNlQ29udGV4dHMnXSA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlWydldmVudFNvdXJjZUNvbnRleHRzJ10uZm9yRWFjaChmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgY3R4LnNlbmRFdmVudCA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgICAgICAgICBjdHguX2V4cGlyZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50U291cmNlc1JlY29yZCA9IHt9O1xuICAgICAgICBldmVudC5tZXNzYWdlLmV2ZW50U291cmNlcy5mb3JFYWNoKGZ1bmN0aW9uIChwYWlyKSB7IHJldHVybiBldmVudFNvdXJjZXNSZWNvcmRbcGFpci5uYW1lXSA9IHBhaXIuY29udGVudDsgfSk7XG4gICAgICAgIHZhciBldmVudE5hbWVzID0gT2JqZWN0LmtleXMoZXZlbnRTb3VyY2VzUmVjb3JkKTtcbiAgICAgICAgdmFyIGJsb2NrZWRFdmVudFNvdXJjZXMgPSB0aGlzLnNwLnNldHRpbmdzW1wic2t5bXA1LWNsaWVudFwiXVtcImJsb2NrZWRFdmVudFNvdXJjZXNcIl07XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGJsb2NrZWRFdmVudFNvdXJjZXMpKSB7XG4gICAgICAgICAgICBibG9ja2VkRXZlbnRTb3VyY2VzLmZvckVhY2goZnVuY3Rpb24gKGJsb2NrZWRFdmVudFNvdXJjZSkge1xuICAgICAgICAgICAgICAgIGV2ZW50TmFtZXMgPSBldmVudE5hbWVzLmZpbHRlcihmdW5jdGlvbiAoZXZlbnROYW1lKSB7IHJldHVybiBldmVudE5hbWUgIT09IGJsb2NrZWRFdmVudFNvdXJjZTsgfSk7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiJ2V2ZW50U291cmNlc1wiLCBibG9ja2VkRXZlbnRTb3VyY2UsIFwiLSBCbG9ja2VkIGJ5IHRoZSBjbGllbnRcIik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFNlcnZlckpzVmVyaWZpY2F0aW9uU2VydmljZSk7XG4gICAgICAgIGV2ZW50TmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gc2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlLnZlcmlmeVNlcnZlckpzKGV2ZW50U291cmNlc1JlY29yZFtldmVudE5hbWVdKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQuc3JjID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiJ2V2ZW50U291cmNlc1wiLCBldmVudE5hbWUsICdWZXJpZmljYXRpb24gZmFpbGVkOicsIHJlc3VsdC5lcnJvcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZm4gPSBuZXcgRnVuY3Rpb24oJ2N0eCcsIHJlc3VsdC5zcmMpO1xuICAgICAgICAgICAgICAgIHZhciBjdHggPSB7XG4gICAgICAgICAgICAgICAgICAgIHJlZnI6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgX21vZGVsOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIF92aWV3OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIGk6IC0xLFxuICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIChfcHJvcE5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImN0eC5nZXQgY2FuJ3QgYmUgdXNlZCBpbiBldmVudCBzb3VyY2VcIik7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHJlc3Bhd246IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImN0eC5yZXNwYXduIGNhbid0IGJlIHVzZWQgaW4gZXZlbnQgc291cmNlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBzcDogc2t5cmltUGxhdGZvcm0sXG4gICAgICAgICAgICAgICAgICAgIHNlbmRFdmVudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJnc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdDogTXNnVHlwZS5DdXN0b21FdmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzSnNvbkR1bXBzOiBhcmdzLm1hcChmdW5jdGlvbiAoYXJnKSB7IHJldHVybiBKU09OLnN0cmluZ2lmeShhcmcpOyB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudE5hbWU6IGV2ZW50TmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGdldEZvcm1JZEluU2VydmVyRm9ybWF0OiBmdW5jdGlvbiAoY2xpZW50c2lkZUZvcm1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxvY2FsSWRUb1JlbW90ZUlkKGNsaWVudHNpZGVGb3JtSWQpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBnZXRGb3JtSWRJbkNsaWVudEZvcm1hdDogZnVuY3Rpb24gKHNlcnZlcnNpZGVGb3JtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdGVJZFRvTG9jYWxJZChzZXJ2ZXJzaWRlRm9ybUlkKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgX2ZuOiBmbixcbiAgICAgICAgICAgICAgICAgICAgX2V2ZW50TmFtZTogZXZlbnROYW1lLFxuICAgICAgICAgICAgICAgICAgICBzdGF0ZToge30sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zcC5zdG9yYWdlWydldmVudFNvdXJjZUNvbnRleHRzJ10ucHVzaChjdHgpO1xuICAgICAgICAgICAgICAgIF90aGlzLnNldHVwRXZlbnRTb3VyY2UoY3R4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiJ2V2ZW50U291cmNlc1wiLCBldmVudE5hbWUsIFwiLVwiLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gR2FtZW1vZGVFdmVudFNvdXJjZVNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBHYW1lbW9kZUV2ZW50U291cmNlU2VydmljZSB9O1xuO1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IFJlbW90ZVNlcnZlciB9IGZyb20gXCIuL3JlbW90ZVNlcnZlclwiO1xuLy8gVE9ETzogcmVmYWN0b3JcbmltcG9ydCB7IGxvY2FsSWRUb1JlbW90ZUlkLCByZW1vdGVJZFRvTG9jYWxJZCB9IGZyb20gXCIuLi8uLi92aWV3L3dvcmxkVmlld01pc2NcIjtcbi8vIFRoZSByZWFzb24gd2UgdXNlIGdsb2JhbCBza3lyaW1QbGF0Zm9ybSBpcyB0aGF0IHRoaXMuc3AgbWF5IGJlIGxpbWl0ZWQsIGFuZCBnYW1lbW9kZSBhcGkgbmVlZHMgdW5saW1pdGVkIGFjY2VzcyB0byBza3lyaW1QbGF0Zm9ybVxuLy8gU2xpZ3RobHkgZGlmZmVyZW50IHR5cGVzXG5pbXBvcnQgKiBhcyBza3lyaW1QbGF0Zm9ybSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IGxvZ0Vycm9yLCBsb2dUcmFjZSB9IGZyb20gXCIuLi8uLi9sb2dnaW5nXCI7XG5pbXBvcnQgeyBTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2VcIjtcbnZhciBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEdhbWVtb2RlVXBkYXRlU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBHYW1lbW9kZVVwZGF0ZVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInVwZGF0ZUdhbWVtb2RlRGF0YU1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uVXBkYXRlR2FtZW1vZGVEYXRhTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImNyZWF0ZUFjdG9yTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25DcmVhdGVBY3Rvck1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwidGlja1wiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vblRpY2soKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIF90aGlzLnVwZGF0ZU93bmVyQ3R4ID0ge1xuICAgICAgICAgICAgc3A6IHNreXJpbVBsYXRmb3JtLFxuICAgICAgICAgICAgcmVmcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIF9tb2RlbDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZ2V0Rm9ybUlkSW5TZXJ2ZXJGb3JtYXQ6IGZ1bmN0aW9uIChjbGllbnRzaWRlRm9ybUlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvY2FsSWRUb1JlbW90ZUlkKGNsaWVudHNpZGVGb3JtSWQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldEZvcm1JZEluQ2xpZW50Rm9ybWF0OiBmdW5jdGlvbiAoc2VydmVyc2lkZUZvcm1JZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZW1vdGVJZFRvTG9jYWxJZChzZXJ2ZXJzaWRlRm9ybUlkKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIChwcm9wTmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb2RlbFtwcm9wTmFtZV07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3RhdGU6IHt9LFxuICAgICAgICAgICAgX3ZpZXc6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGk6IC0xLFxuICAgICAgICAgICAgcmVzcGF3bjogZnVuY3Rpb24gKCkgeyB0aHJvdyBuZXcgRXJyb3IoXCJjdHgucmVzcGF3biBpcyBub3QgYXZhaWxhYmxlIGZvciB1cGRhdGVPd25lclwiKTsgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy51cGRhdGVOZWlnaGJvckN0eCA9IHtcbiAgICAgICAgICAgIHJlZnI6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHZhbHVlOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBfbW9kZWw6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHNwOiBza3lyaW1QbGF0Zm9ybSxcbiAgICAgICAgICAgIHN0YXRlOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBfdmlldzogdW5kZWZpbmVkLFxuICAgICAgICAgICAgaTogLTEsXG4gICAgICAgICAgICBnZXRGb3JtSWRJblNlcnZlckZvcm1hdDogZnVuY3Rpb24gKGNsaWVudHNpZGVGb3JtSWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxJZFRvUmVtb3RlSWQoY2xpZW50c2lkZUZvcm1JZCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0Rm9ybUlkSW5DbGllbnRGb3JtYXQ6IGZ1bmN0aW9uIChzZXJ2ZXJzaWRlRm9ybUlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbW90ZUlkVG9Mb2NhbElkKHNlcnZlcnNpZGVGb3JtSWQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKHByb3BOYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vZGVsW3Byb3BOYW1lXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXNwYXduOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlldy5kZXN0cm95Rm9ybSh0aGlzLmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy51cGRhdGVOZWlnaGJvckZ1bmN0aW9uc0tleXMgPSBbXTtcbiAgICAgICAgX3RoaXMudXBkYXRlTmVpZ2hib3JGdW5jdGlvbnMgPSB7fTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UucHJvdG90eXBlLnNldEZvcm1WaWV3QXJyYXkgPSBmdW5jdGlvbiAoZm9ybVZpZXdBcnJheSkge1xuICAgICAgICB0aGlzLnVwZGF0ZU5laWdoYm9yQ3R4Ll92aWV3ID0gZm9ybVZpZXdBcnJheTtcbiAgICB9O1xuICAgIEdhbWVtb2RlVXBkYXRlU2VydmljZS5wcm90b3R5cGUuc2V0SSA9IGZ1bmN0aW9uIChpKSB7XG4gICAgICAgIHRoaXMudXBkYXRlTmVpZ2hib3JDdHguaSA9IGk7XG4gICAgfTtcbiAgICBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UucHJvdG90eXBlLnVwZGF0ZU5laWdoYm9yID0gZnVuY3Rpb24gKHJlZnIsIG1vZGVsLCBzdGF0ZSkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy51cGRhdGVOZWlnaGJvckZ1bmN0aW9uc0tleXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gX2FbX2ldO1xuICAgICAgICAgICAgdmFyIHYgPSBtb2RlbFtrZXldO1xuICAgICAgICAgICAgLy8gQWNjb3JkaW5nIHRvIGRvY3M6XG4gICAgICAgICAgICAvLyBJbiBgdXBkYXRlT3duZXJgL2B1cGRhdGVOZWlnaGJvcmAgZXF1YWxzIHRvIGEgdmFsdWUgb2YgYSBjdXJyZW50bHkgcHJvY2Vzc2VkIHByb3BlcnR5LlxuICAgICAgICAgICAgLy8gQ2FuJ3QgYmUgYHVuZGVmaW5lZGAgaGVyZSwgc2luY2UgdXBkYXRlcyBhcmUgbm90IHJlY2VpdmVkIGZvciBgdW5kZWZpbmVkYCBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICAgICAgICAvLyBJbiBvdGhlciBjb250ZXh0cyBpcyBhbHdheXMgYHVuZGVmaW5lZGAuXG4gICAgICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVOZWlnaGJvckN0eC5yZWZyID0gcmVmcjtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU5laWdoYm9yQ3R4LnZhbHVlID0gdjtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU5laWdoYm9yQ3R4Ll9tb2RlbCA9IG1vZGVsO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTmVpZ2hib3JDdHguc3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgICAgICAgICB2YXIgZiA9IHRoaXMudXBkYXRlTmVpZ2hib3JGdW5jdGlvbnNba2V5XTtcbiAgICAgICAgICAgICAgICAvLyBBY3R1YWxseSwgJ2YnIHNob3VsZCBhbHdheXMgYmUgYSB2YWxpZCBmdW5jdGlvbiwgYnV0IHdobyBrbm93c1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmKHRoaXMudXBkYXRlTmVpZ2hib3JDdHgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwidXBkYXRlTmVpZ2hib3JcIiwga2V5LCAnLScsIGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlLnByb3RvdHlwZS5vblVwZGF0ZUdhbWVtb2RlRGF0YU1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wiZGlzYWJsZS1nYW1lbW9kZS11cGRhdGVzXCJdKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zcC5zdG9yYWdlWydHYW1lbW9kZVVwZGF0ZVNlcnZpY2Vfc2F3VXBkYXRlRnVuY3Rpb25zJ10gPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIkdhbWVtb2RlIHVwZGF0ZXMgYXJlIGRpc2FibGVkIGJ5IHNldHRpbmdzXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiR2FtZW1vZGUgdXBkYXRlcyBhcmUgZGlzYWJsZWQgYnkgc2V0dGluZ3MgLSBwcm9jZXNzaW5nIGZpcnN0IHVwZGF0ZSBvbmx5XCIpO1xuICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlWydHYW1lbW9kZVVwZGF0ZVNlcnZpY2Vfc2F3VXBkYXRlRnVuY3Rpb25zJ10gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3Auc3RvcmFnZVsndXBkYXRlTmVpZ2hib3JGdW5jdGlvbnMnXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zcC5zdG9yYWdlWyd1cGRhdGVPd25lckZ1bmN0aW9ucyddID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnVwZGF0ZUdhbWVtb2RlVXBkYXRlRnVuY3Rpb25zKCd1cGRhdGVOZWlnaGJvckZ1bmN0aW9ucycsIGV2ZW50Lm1lc3NhZ2UudXBkYXRlTmVpZ2hib3JGdW5jdGlvbnMpO1xuICAgICAgICB0aGlzLnVwZGF0ZUdhbWVtb2RlVXBkYXRlRnVuY3Rpb25zKCd1cGRhdGVPd25lckZ1bmN0aW9ucycsIGV2ZW50Lm1lc3NhZ2UudXBkYXRlT3duZXJGdW5jdGlvbnMpO1xuICAgIH07XG4gICAgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlLnByb3RvdHlwZS5vbkNyZWF0ZUFjdG9yTWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIWV2ZW50Lm1lc3NhZ2UuaXNNZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIE90aGVyd2lzZSB3b3JsZE1vZGVsLnBsYXllckNoYXJhY3RlckZvcm1JZHggbWF5IGJlIHVuYXNzaWduZWRcbiAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ0aWNrXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciByZW1vdGVTZXJ2ZXIgPSBfdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFJlbW90ZVNlcnZlcik7XG4gICAgICAgICAgICB2YXIgd29ybGRNb2RlbCA9IHJlbW90ZVNlcnZlci5nZXRXb3JsZE1vZGVsKCk7XG4gICAgICAgICAgICB2YXIgbXlGb3JtTW9kZWwgPSB3b3JsZE1vZGVsLmZvcm1zW3dvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeF07XG4gICAgICAgICAgICBpZiAoIW15Rm9ybU1vZGVsKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiVW5hYmxlIHRvIGZpbmQgZm9ybU1vZGVsIHdpdGggaW5kZXhcIiwgd29ybGRNb2RlbC5wbGF5ZXJDaGFyYWN0ZXJGb3JtSWR4KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5zZXRPd25lck1vZGVsKG15Rm9ybU1vZGVsKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UucHJvdG90eXBlLm9uVGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGtleXMgPSB0aGlzLnNwLnN0b3JhZ2VbXCJ1cGRhdGVOZWlnaGJvckZ1bmN0aW9uc19rZXlzXCJdO1xuICAgICAgICBpZiAoa2V5cyAmJiBBcnJheS5pc0FycmF5KGtleXMpKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU5laWdoYm9yRnVuY3Rpb25zS2V5cyA9IGtleXM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU5laWdoYm9yRnVuY3Rpb25zS2V5cyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IFNob3VsZG4ndCB3ZSBjaGVjayBzdG9yYWdlIHZhbHVlIGJlZm9yZSBhc3NpZ25tZW50P1xuICAgICAgICB0aGlzLnVwZGF0ZU5laWdoYm9yRnVuY3Rpb25zID0gdGhpcy5zcC5zdG9yYWdlW1widXBkYXRlTmVpZ2hib3JGdW5jdGlvbnNcIl07XG4gICAgfTtcbiAgICBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UucHJvdG90eXBlLm9uVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGxheWVyUmVmID0gdGhpcy5zcC5PYmplY3RSZWZlcmVuY2UuZnJvbSh0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCkpO1xuICAgICAgICB2YXIga2V5cyA9IHRoaXMuc3Auc3RvcmFnZVtcInVwZGF0ZU93bmVyRnVuY3Rpb25zX2tleXNcIl07XG4gICAgICAgIGlmICgha2V5cyB8fCAhQXJyYXkuaXNBcnJheShrZXlzKSkge1xuICAgICAgICAgICAga2V5cyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmdW5jcyA9IHRoaXMuc3Auc3RvcmFnZVtcInVwZGF0ZU93bmVyRnVuY3Rpb25zXCJdO1xuICAgICAgICBpZiAodGhpcy5zcC5zdG9yYWdlW1wib3duZXJNb2RlbFNldFwiXSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvd25lck1vZGVsID0gdGhpcy5zcC5zdG9yYWdlW1wib3duZXJNb2RlbFwiXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBrZXlzXzEgPSBrZXlzOyBfaSA8IGtleXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IGtleXNfMVtfaV07XG4gICAgICAgICAgICB2YXIgZiA9IGZ1bmNzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgIC8vIEFjdHVhbGx5LCBtdXN0IGFsd2F5cyBiZSBhIHZhbGlkIGZ1bmNpdG9uLCBidXQgd2hvIGtub3dzXG4gICAgICAgICAgICBpZiAoIWYpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXBkYXRlT3duZXJDdHguX21vZGVsID0gb3duZXJNb2RlbDtcbiAgICAgICAgICAgIGlmICghdGhpcy51cGRhdGVPd25lckN0eC5fbW9kZWwpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXBkYXRlT3duZXJDdHgudmFsdWUgPSB0aGlzLnVwZGF0ZU93bmVyQ3R4Ll9tb2RlbFtwcm9wTmFtZV07XG4gICAgICAgICAgICBpZiAodGhpcy51cGRhdGVPd25lckN0eC52YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU93bmVyQ3R4LnJlZnIgPSBwbGF5ZXJSZWY7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU93bmVyQ3R4Ll9tb2RlbCA9IG93bmVyTW9kZWw7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChmKSB7XG4gICAgICAgICAgICAgICAgICAgIGYodGhpcy51cGRhdGVPd25lckN0eCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcInVwZGF0ZU93bmVyXCIsIHByb3BOYW1lLCAnLScsIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UucHJvdG90eXBlLnNldE93bmVyTW9kZWwgPSBmdW5jdGlvbiAob3duZXJNb2RlbCkge1xuICAgICAgICB0aGlzLnNwLnN0b3JhZ2VbXCJvd25lck1vZGVsXCJdID0gb3duZXJNb2RlbDtcbiAgICAgICAgdGhpcy5zcC5zdG9yYWdlW1wib3duZXJNb2RlbFNldFwiXSA9IHRydWU7XG4gICAgfTtcbiAgICA7XG4gICAgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlLnByb3RvdHlwZS51cGRhdGVHYW1lbW9kZVVwZGF0ZUZ1bmN0aW9ucyA9IGZ1bmN0aW9uIChzdG9yYWdlVmFyLCBmdW5jdGlvblNvdXJjZXMpIHtcbiAgICAgICAgdmFyIHNlcnZlckpzVmVyaWZpY2F0aW9uU2VydmljZSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UpO1xuICAgICAgICB2YXIgZnVuY3Rpb25Tb3VyY2VzUmVjb3JkID0ge307XG4gICAgICAgIGZ1bmN0aW9uU291cmNlcy5mb3JFYWNoKGZ1bmN0aW9uIChwYWlyKSB7IHJldHVybiBmdW5jdGlvblNvdXJjZXNSZWNvcmRbcGFpci5uYW1lXSA9IHBhaXIuY29udGVudDsgfSk7XG4gICAgICAgIHRoaXMuc3Auc3RvcmFnZVtzdG9yYWdlVmFyXSA9IGZ1bmN0aW9uU291cmNlc1JlY29yZDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IE9iamVjdC5rZXlzKGZ1bmN0aW9uU291cmNlc1JlY29yZCk7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBfYVtfaV07XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gc2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlLnZlcmlmeVNlcnZlckpzKHRoaXMuc3Auc3RvcmFnZVtzdG9yYWdlVmFyXVtwcm9wTmFtZV0pO1xuICAgICAgICAgICAgaWYgKHJlc3VsdC5zcmMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBzdG9yYWdlVmFyLCBwcm9wTmFtZSwgJ1ZlcmlmaWNhdGlvbiBmYWlsZWQ6JywgcmVzdWx0LmVycm9yKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zcC5zdG9yYWdlW3N0b3JhZ2VWYXJdW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlW3N0b3JhZ2VWYXJdW3Byb3BOYW1lXSA9IG5ldyBGdW5jdGlvbignY3R4JywgcmVzdWx0LnNyYyk7XG4gICAgICAgICAgICAgICAgdmFyIGVtcHR5RnVuY3Rpb24gPSBmdW5jdGlvblNvdXJjZXNSZWNvcmRbcHJvcE5hbWVdID09PSAnJztcbiAgICAgICAgICAgICAgICBpZiAoZW1wdHlGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zcC5zdG9yYWdlW3N0b3JhZ2VWYXJdW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgc3RvcmFnZVZhciwgcHJvcE5hbWUsICdBZGRlZCBlbXB0eScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgc3RvcmFnZVZhciwgcHJvcE5hbWUsICdBZGRlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgc3RvcmFnZVZhciwgcHJvcE5hbWUsIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3Auc3RvcmFnZVtcIlwiLmNvbmNhdChzdG9yYWdlVmFyLCBcIl9rZXlzXCIpXSA9IE9iamVjdC5rZXlzKHRoaXMuc3Auc3RvcmFnZVtzdG9yYWdlVmFyXSk7XG4gICAgfTtcbiAgICByZXR1cm4gR2FtZW1vZGVVcGRhdGVTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlIH07XG47XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuLy8gVE9ETzogcmVmYWN0b3IgdGhpcyBvdXRcbmltcG9ydCB7IGxvY2FsSWRUb1JlbW90ZUlkIH0gZnJvbSBcIi4uLy4uL3ZpZXcvd29ybGRWaWV3TWlzY1wiO1xuaW1wb3J0IHsgc3RvcmFnZSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0IHsgTXNnVHlwZSB9IGZyb20gXCIuLi8uLi9tZXNzYWdlc1wiO1xudmFyIEhpdFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEhpdFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gSGl0U2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMucmVjZW50TWFnaWNIaXRzID0gbmV3IE1hcCgpO1xuICAgICAgICBjb250cm9sbGVyLm9uKCdoaXQnLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25IaXQoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEhpdFNlcnZpY2UucHJvdG90eXBlLm9uSGl0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgLy8gVE9ETzogYWRkIG1vcmUgbG9nZ2luZyBpbiBjYXNlIG9mICdyZXR1cm4nXG4gICAgICAgIC8vIFRPRE86IGFsbG93IG5vbi13ZWFwb24gc291cmNlc1xuICAgICAgICB2YXIgYWdncmVzc29yID0gZS5hZ2dyZXNzb3IuZ2V0Rm9ybUlEKCk7XG4gICAgICAgIGlmIChhZ2dyZXNzb3IgPCAweGZmMDAwMDAwICYmIGFnZ3Jlc3NvciAhPT0gMHgxNClcbiAgICAgICAgICAgIHJldHVybjsgLy8gYWxsIHNreW1wIG5wY3MgYXJlIEZGK1xuICAgICAgICBpZiAoYWdncmVzc29yID49IDB4ZmYwMDAwMDApIHtcbiAgICAgICAgICAgIC8vIFRPRE86IG1ha2UgaG9zdCBzZXJ2aWNlXG4gICAgICAgICAgICB2YXIgaG9zdGVkID0gc3RvcmFnZVsnaG9zdGVkJ107XG4gICAgICAgICAgICB2YXIgYWxyZWFkeUhvc3RlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaG9zdGVkKSkge1xuICAgICAgICAgICAgICAgIHZhciByZW1vdGVJZCA9IGxvY2FsSWRUb1JlbW90ZUlkKGFnZ3Jlc3Nvcik7XG4gICAgICAgICAgICAgICAgaWYgKGhvc3RlZC5pbmNsdWRlcyhyZW1vdGVJZCkgfHwgaG9zdGVkLmluY2x1ZGVzKHJlbW90ZUlkICsgMHgxMDAwMDAwMDApKSB7XG4gICAgICAgICAgICAgICAgICAgIGFscmVhZHlIb3N0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghYWxyZWFkeUhvc3RlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgYmFzZSA9IGUudGFyZ2V0LmdldEJhc2VPYmplY3QoKTtcbiAgICAgICAgdmFyIHR5cGUgPSBiYXNlID09PSBudWxsIHx8IGJhc2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGJhc2UuZ2V0VHlwZSgpO1xuICAgICAgICBpZiAodHlwZSA9PT0gMzQgLyogRm9ybVR5cGUuU3RhdGljICovIHx8IHR5cGUgPT09IDM2IC8qIEZvcm1UeXBlLk1vdmFibGVTdGF0aWMgKi8pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNXZWFwb24gPSB0aGlzLnNwLldlYXBvbi5mcm9tKGUuc291cmNlKTtcbiAgICAgICAgdmFyIGlzU3BlbGwgPSAhaXNXZWFwb24gJiYgdGhpcy5zcC5TcGVsbC5mcm9tKGUuc291cmNlKTtcbiAgICAgICAgdmFyIGlzU2Nyb2xsID0gIWlzV2VhcG9uICYmICFpc1NwZWxsICYmIHRoaXMuc3AuU2Nyb2xsLmZyb20oZS5zb3VyY2UpO1xuICAgICAgICBpZiAoIWlzV2VhcG9uICYmICFpc1NwZWxsICYmICFpc1Njcm9sbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByZXZlbnQgZG91YmxlIGhpdCB0aGF0IGhhcHBlbnMgZm9yIHNvbWUgcmVhc29uIHdpdGggbWFnaWMgcHJvamVjdGlsZXNcbiAgICAgICAgaWYgKGlzU3BlbGwgfHwgaXNTY3JvbGwpIHtcbiAgICAgICAgICAgIHZhciBhZ2dyZXNzb3JJZCA9IGUuYWdncmVzc29yLmdldEZvcm1JRCgpO1xuICAgICAgICAgICAgdmFyIG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgICAgICB2YXIgbGFzdEhpdFRpbWUgPSB0aGlzLnJlY2VudE1hZ2ljSGl0cy5nZXQoYWdncmVzc29ySWQpO1xuICAgICAgICAgICAgaWYgKGxhc3RIaXRUaW1lICYmIG5vdyAtIGxhc3RIaXRUaW1lIDwgMTAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZWNlbnRNYWdpY0hpdHMuc2V0KGFnZ3Jlc3NvcklkLCBub3cpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICBtZXNzYWdlOiB7IHQ6IE1zZ1R5cGUuT25IaXQsIGRhdGE6IHRoaXMuZ2V0SGl0RGF0YShlKSB9LFxuICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEhpdFNlcnZpY2UucHJvdG90eXBlLmdldEhpdERhdGEgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgaGl0RGF0YSA9IHtcbiAgICAgICAgICAgIGFnZ3Jlc3NvcjogbG9jYWxJZFRvUmVtb3RlSWQoZS5hZ2dyZXNzb3IuZ2V0Rm9ybUlEKCkpLFxuICAgICAgICAgICAgaXNCYXNoQXR0YWNrOiBlLmlzQmFzaEF0dGFjayxcbiAgICAgICAgICAgIGlzSGl0QmxvY2tlZDogZS5pc0hpdEJsb2NrZWQsXG4gICAgICAgICAgICBpc1Bvd2VyQXR0YWNrOiBlLmlzUG93ZXJBdHRhY2ssXG4gICAgICAgICAgICBpc1NuZWFrQXR0YWNrOiBlLmlzU25lYWtBdHRhY2ssXG4gICAgICAgICAgICBwcm9qZWN0aWxlOiBlLnByb2plY3RpbGUgPyBlLnByb2plY3RpbGUuZ2V0Rm9ybUlEKCkgOiAwLFxuICAgICAgICAgICAgc291cmNlOiBlLnNvdXJjZSA/IGUuc291cmNlLmdldEZvcm1JRCgpIDogMCxcbiAgICAgICAgICAgIHRhcmdldDogbG9jYWxJZFRvUmVtb3RlSWQoZS50YXJnZXQuZ2V0Rm9ybUlEKCkpXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBoaXREYXRhO1xuICAgIH07XG4gICAgcmV0dXJuIEhpdFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBIaXRTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xudmFyIEtleWJvYXJkRXZlbnRzU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoS2V5Ym9hcmRFdmVudHNTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEtleWJvYXJkRXZlbnRzU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMubGFzdE51bUtleXMgPSAwO1xuICAgICAgICBjb250cm9sbGVyLm9uKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uVXBkYXRlKCk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEtleWJvYXJkRXZlbnRzU2VydmljZS5wcm90b3R5cGUub25VcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBudW1LZXlzID0gdGhpcy5zcC5JbnB1dC5nZXROdW1LZXlzUHJlc3NlZCgpO1xuICAgICAgICBpZiAodGhpcy5sYXN0TnVtS2V5cyAhPT0gbnVtS2V5cykge1xuICAgICAgICAgICAgdGhpcy5sYXN0TnVtS2V5cyA9IG51bUtleXM7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwicXVlcnlLZXlDb2RlQmluZGluZ3NcIiwge1xuICAgICAgICAgICAgICAgIGlzRG93bjogZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJpbmRpbmcuZXZlcnkoZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gX3RoaXMuc3AuSW5wdXQuaXNLZXlQcmVzc2VkKGtleSk7IH0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBLZXlib2FyZEV2ZW50c1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBLZXlib2FyZEV2ZW50c1NlcnZpY2UgfTtcbjtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgTGFzdEludlNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKExhc3RJbnZTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIExhc3RJbnZTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShMYXN0SW52U2VydmljZS5wcm90b3R5cGUsIFwibGFzdEludlwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xhc3RJbnY7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24gKG5ld1ZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXN0SW52ID0gbmV3VmFsdWU7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICByZXR1cm4gTGFzdEludlNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBMYXN0SW52U2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBMb2FkR2FtZVNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKExvYWRHYW1lU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBMb2FkR2FtZVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLl9pc0NhdXNlZEJ5U2t5cmltUGxhdGZvcm0gPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbihcImxvYWRHYW1lXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uTG9hZEdhbWUoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgTG9hZEdhbWVTZXJ2aWNlLnByb3RvdHlwZS5sb2FkR2FtZSA9IGZ1bmN0aW9uIChwb3MsIHJvdCwgd29ybGRPckNlbGwsIGNoYW5nZUZvcm1OcGMsIGxvYWRPcmRlciwgdGltZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5zcC5sb2FkR2FtZShwb3MsIHJvdCwgd29ybGRPckNlbGwsIGNoYW5nZUZvcm1OcGMsIGxvYWRPcmRlciwgdGltZSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIEhvdGZpeCBub24tdmFuaWxsYSBoZWFkcGFydHMgYnVnXG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICB0aGlzLnNwLmxvYWRHYW1lKHBvcywgcm90LCB3b3JsZE9yQ2VsbCwgdW5kZWZpbmVkLCBsb2FkT3JkZXIsIHRpbWUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lzQ2F1c2VkQnlTa3lyaW1QbGF0Zm9ybSA9IHRydWU7XG4gICAgfTtcbiAgICBMb2FkR2FtZVNlcnZpY2UucHJvdG90eXBlLm9uTG9hZEdhbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YXIgZ2FtZUxvYWRFdmVudCA9IHtcbiAgICAgICAgICAgICAgICBpc0NhdXNlZEJ5U2t5cmltUGxhdGZvcm06IHRoaXMuX2lzQ2F1c2VkQnlTa3lyaW1QbGF0Zm9ybVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJnYW1lTG9hZFwiLCBnYW1lTG9hZEV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ0aWNrXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5faXNDYXVzZWRCeVNreXJpbVBsYXRmb3JtID0gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ0aWNrXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLl9pc0NhdXNlZEJ5U2t5cmltUGxhdGZvcm0gPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gTG9hZEdhbWVTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgTG9hZEdhbWVTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgR2FtZSwgVXRpbGl0eSwgcHJpbnRDb25zb2xlLCBjcmVhdGVUZXh0LCBzZXRUZXh0U2l6ZSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgZ2V0U2NyZWVuUmVzb2x1dGlvbiB9IGZyb20gXCIuLi8uLi92aWV3L2Zvcm1WaWV3XCI7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG5pbXBvcnQgeyBsb2dUcmFjZSB9IGZyb20gXCIuLi8uLi9sb2dnaW5nXCI7XG5pbXBvcnQgeyBTZXR0aW5nc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXR0aW5nc1NlcnZpY2VcIjtcbnZhciBTVEFURV9LRVkgPSAnbG9hZE9yZGVyQ2hlY2tTdGF0ZSc7XG47XG52YXIgTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBMb2FkT3JkZXJWZXJpZmljYXRpb25TZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBMb2FkT3JkZXJWZXJpZmljYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5vbmNlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnZlcmlmeUxvYWRPcmRlcigpO1xuICAgIH07XG4gICAgTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZS5wcm90b3R5cGUudmVyaWZ5TG9hZE9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgc2V0dGluZ3NTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFNldHRpbmdzU2VydmljZSk7XG4gICAgICAgIHRoaXMucmVzZXRUZXh0KCk7XG4gICAgICAgIHZhciBjbGllbnRNb2RzID0gdGhpcy5nZXRDbGllbnRNb2RzKCk7XG4gICAgICAgIHRoaXMucHJpbnRNb2RPcmRlcignQ2xpZW50IGxvYWQgb3JkZXI6JywgY2xpZW50TW9kcyk7XG4gICAgICAgIHJldHVybiBzZXR0aW5nc1NlcnZpY2UuZ2V0U2VydmVyTW9kcygpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoc2VydmVyTW9kcykge1xuICAgICAgICAgICAgX3RoaXMucHJpbnRNb2RPcmRlcignU2VydmVyIGxvYWQgb3JkZXI6Jywgc2VydmVyTW9kcyk7XG4gICAgICAgICAgICBpZiAoY2xpZW50TW9kcy5sZW5ndGggPCBzZXJ2ZXJNb2RzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3Npbmcgc29tZSBzZXJ2ZXIgbW9kcy4gU2VydmVyIGhhcyBcIi5jb25jYXQoc2VydmVyTW9kcy5sZW5ndGgsIFwiLCB3ZSBoYXZlIFwiKS5jb25jYXQoY2xpZW50TW9kcy5sZW5ndGgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjbGllbnRNb2RzLmxlbmd0aCA+IHNlcnZlck1vZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlVGV4dCgnTE9BRCBPUkRFUiBXQVJOSU5HOiB5b3UgaGF2ZSBtb3JlIG1vZHMgdGhhbiBzZXJ2ZXIhXFxuKG9yIGNvdWxkIG5vdCByZWNlaXZlIHNlcnZlciBtb2QgbGlzdClcXG5DaGVjayBjb25zb2xlIGZvciBkZXRhaWxzLicsIFsyNTUsIDI1NSwgMCwgMV0sIDUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGZhaWwgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VydmVyTW9kcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIC8vIE5lZWQgY2FzZS1pbnNlbnNpdGl2ZSBjaGVjayBmb3IgMS42K1xuICAgICAgICAgICAgICAgIGlmIChjbGllbnRNb2RzW2ldLmZpbGVuYW1lLnRvTG93ZXJDYXNlKCkgIT09IHNlcnZlck1vZHNbaV0uZmlsZW5hbWUudG9Mb3dlckNhc2UoKSB8fFxuICAgICAgICAgICAgICAgICAgICBjbGllbnRNb2RzW2ldLnNpemUgIT09IHNlcnZlck1vZHNbaV0uc2l6ZSB8fFxuICAgICAgICAgICAgICAgICAgICBjbGllbnRNb2RzW2ldLmNyYzMyICE9PSBzZXJ2ZXJNb2RzW2ldLmNyYzMyKSB7XG4gICAgICAgICAgICAgICAgICAgIGZhaWwucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgcHJpbnRDb25zb2xlKFwiXCIuY29uY2F0KGksIFwiLXRoIG1vZCAobnVtYmVyZWQgZnJvbSAwKSBkb2VzIG5vdCBtYXRjaC5cIikpO1xuICAgICAgICAgICAgICAgICAgICBwcmludENvbnNvbGUoXCJTZXJ2ZXIgaGFzIFwiLmNvbmNhdChKU09OLnN0cmluZ2lmeShzZXJ2ZXJNb2RzW2ldKSkpO1xuICAgICAgICAgICAgICAgICAgICBwcmludENvbnNvbGUoXCJXZSBoYXZlIFwiLmNvbmNhdChKU09OLnN0cmluZ2lmeShjbGllbnRNb2RzW2ldKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmYWlsLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTG9hZCBvcmRlciBjaGVjayBmYWlsZWQhIEluZGljZXM6ICcgKyBKU09OLnN0cmluZ2lmeShmYWlsKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgcHJpbnRDb25zb2xlKGVycik7XG4gICAgICAgICAgICBpZiAoX3RoaXMuc3Auc2V0dGluZ3NbJ3NreW1wNS1jbGllbnQnXVsnaWdub3JlTG9hZE9yZGVyTWlzbWF0Y2gnXSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZVRleHQoJ0xPQUQgT1JERVIgRVJST1IhXFxuSG93ZXZlciwgaWdub3JpbmcgaXQgYmVjYXVzZSBvZiBpZ25vcmVMb2FkT3JkZXJNaXNtYXRjaCBiZWluZyBzZXQuJyArXG4gICAgICAgICAgICAgICAgICAgICdcXG5FeHBlY3QgRVZFUllUSElORyBCUkVBSywgdW5sZXNzIHlvdSBrbm93IHdoYXQgeW91IGFyZSBkb2luZy5cXG5DaGVjayBjb25zb2xlIGZvciBkZXRhaWxzLicgK1xuICAgICAgICAgICAgICAgICAgICAnXFxuVGhpcyBtZXNzYWdlIHdpbGwgZGlzYXBwZWFyIGFmdGVyIDMwIHNlY29uZHMuJywgWzI1NSwgMCwgMCwgMV0sIDMwKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy51cGRhdGVUZXh0KCdMT0FEIE9SREVSIEVSUk9SIVxcbkNoZWNrIGNvbnNvbGUgZm9yIGRldGFpbHMuJywgWzI1NSwgMCwgMCwgMV0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIDtcbiAgICBMb2FkT3JkZXJWZXJpZmljYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnNwLnN0b3JhZ2VbU1RBVEVfS0VZXSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5zcC5zdG9yYWdlW1NUQVRFX0tFWV07XG4gICAgfTtcbiAgICA7XG4gICAgTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZS5wcm90b3R5cGUuc2V0U3RhdGUgPSBmdW5jdGlvbiAocmVwbGFjZW1lbnQpIHtcbiAgICAgICAgdmFyIG9sZFN0YXRlID0gdGhpcy5zcC5zdG9yYWdlW1NUQVRFX0tFWV0gPSB0aGlzLmdldFN0YXRlKCk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBPYmplY3QuZW50cmllcyhyZXBsYWNlbWVudCk7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgX2IgPSBfYVtfaV0sIGsgPSBfYlswXSwgdiA9IF9iWzFdO1xuICAgICAgICAgICAgb2xkU3RhdGVba10gPSB2O1xuICAgICAgICB9XG4gICAgfTtcbiAgICA7XG4gICAgTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZS5wcm90b3R5cGUucmVzZXRUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc3RhdHVzVGV4dElkID0gdGhpcy5nZXRTdGF0ZSgpLnN0YXR1c1RleHRJZDtcbiAgICAgICAgaWYgKHN0YXR1c1RleHRJZCkge1xuICAgICAgICAgICAgdGhpcy5zcC5kZXN0cm95VGV4dChzdGF0dXNUZXh0SWQpO1xuICAgICAgICAgICAgc3RhdHVzVGV4dElkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHN0YXR1c1RleHRJZDogc3RhdHVzVGV4dElkIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICA7XG4gICAgTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZS5wcm90b3R5cGUudXBkYXRlVGV4dCA9IGZ1bmN0aW9uICh0ZXh0LCBjb2xvciwgY2xlYXJEZWxheSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EgPSBnZXRTY3JlZW5SZXNvbHV0aW9uKCksIHdpZHRoID0gX2Eud2lkdGgsIGhlaWdodCA9IF9hLmhlaWdodDtcbiAgICAgICAgdGhpcy5yZXNldFRleHQoKTtcbiAgICAgICAgdmFyIHN0YXR1c1RleHRJZCA9IGNyZWF0ZVRleHQod2lkdGggLyAyLCBoZWlnaHQgLyAyLCB0ZXh0LCBjb2xvcik7XG4gICAgICAgIHNldFRleHRTaXplKHN0YXR1c1RleHRJZCwgMC41KTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHN0YXR1c1RleHRJZDogc3RhdHVzVGV4dElkIH0pO1xuICAgICAgICBpZiAoY2xlYXJEZWxheSkge1xuICAgICAgICAgICAgVXRpbGl0eS53YWl0KGNsZWFyRGVsYXkpLnRoZW4oZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMucmVzZXRUZXh0KCk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBMb2FkT3JkZXJWZXJpZmljYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5lbnVtZXJhdGVDbGllbnRNb2RzID0gZnVuY3Rpb24gKGdldENvdW50LCBnZXRBdCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2V0Q291bnQoKTsgKytpKSB7XG4gICAgICAgICAgICB2YXIgZmlsZW5hbWUgPSBnZXRBdChpKTtcbiAgICAgICAgICAgIHZhciBfYSA9IHRoaXMuZ2V0RmlsZUluZm9TYWZlKGZpbGVuYW1lKSwgY3JjMzIgPSBfYS5jcmMzMiwgc2l6ZSA9IF9hLnNpemU7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh7IGZpbGVuYW1lOiBmaWxlbmFtZSwgY3JjMzI6IGNyYzMyLCBzaXplOiBzaXplIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBMb2FkT3JkZXJWZXJpZmljYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRDbGllbnRNb2RzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbnVtZXJhdGVDbGllbnRNb2RzKEdhbWUuZ2V0TW9kQ291bnQsIEdhbWUuZ2V0TW9kTmFtZSk7XG4gICAgfTtcbiAgICA7XG4gICAgTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZS5wcm90b3R5cGUucHJpbnRNb2RPcmRlciA9IGZ1bmN0aW9uIChoZWFkZXIsIG9yZGVyKSB7XG4gICAgICAgIHByaW50Q29uc29sZShoZWFkZXIpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gT2JqZWN0LmVudHJpZXMob3JkZXIpOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIF9iID0gX2FbX2ldLCBpID0gX2JbMF0sIG1vZCA9IF9iWzFdO1xuICAgICAgICAgICAgcHJpbnRDb25zb2xlKFwiI1wiLmNvbmNhdChpLCBcIiBcIikuY29uY2F0KEpTT04uc3RyaW5naWZ5KG1vZCkpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgO1xuICAgIExvYWRPcmRlclZlcmlmaWNhdGlvblNlcnZpY2UucHJvdG90eXBlLmdldEZpbGVJbmZvU2FmZSA9IGZ1bmN0aW9uIChmaWxlbmFtZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3AuZ2V0RmlsZUluZm8oZmlsZW5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IGUubWVzc2FnZTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gXCJzdHJpbmdcIiAmJiBtZXNzYWdlLmluY2x1ZGVzKCdpcyBub3QgYSB2YWxpZCBhcmd1bWVudCcpKSB7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJGYWlsZWQgdG8gZ2V0IGZpbGUgaW5mbyBmb3JcIiwgZmlsZW5hbWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGNyYzMyOiAwLCBzaXplOiAwIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gTG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IExvYWRPcmRlclZlcmlmaWNhdGlvblNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG4vLyBUT0RPOiByZWZhY3RvciB0aGlzIG91dFxuaW1wb3J0IHsgbG9jYWxJZFRvUmVtb3RlSWQsIHJlbW90ZUlkVG9Mb2NhbElkIH0gZnJvbSBcIi4uLy4uL3ZpZXcvd29ybGRWaWV3TWlzY1wiO1xuLy8gQHRzLWV4cGVjdC1lcnJvciAoVE9ETzogUmVtb3ZlIGluIDIuMTAuMClcbmltcG9ydCB7IEdhbWUsIGdldEFuaW1hdGlvblZhcmlhYmxlc0Zyb21BY3RvciwgU3BlbGxUeXBlIH0gZnJvbSAnc2t5cmltUGxhdGZvcm0nO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tICcuL2NsaWVudExpc3RlbmVyJztcbmltcG9ydCB7IE1zZ1R5cGUgfSBmcm9tIFwiLi4vLi4vbWVzc2FnZXNcIjtcbnZhciBNYWdpY1N5bmNTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhNYWdpY1N5bmNTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIE1hZ2ljU3luY1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLnBsYXllcklkID0gMHgxNDtcbiAgICAgICAgX3RoaXMuc2VuZFVwZGF0ZUFuaW1hdGlvblZhcmlhYmxlc1JhdGVNcyA9IDUwMDtcbiAgICAgICAgX3RoaXMubGFzdFNwZWxsQ2FzdEV2ZW50TXNnID0gbnVsbDtcbiAgICAgICAgX3RoaXMubGFzdFNlbmRVcGRhdGVBbmltYXRpb25WYXJpYWJsZXMgPSAwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uVXBkYXRlKCk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwic3BlbGxDYXN0XCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblNwZWxsQ2FzdChlKTsgfSk7XG4gICAgICAgIHZhciBzZWxmID0gX3RoaXM7XG4gICAgICAgIF90aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIChjdHgpIHsgfSxcbiAgICAgICAgICAgIGxlYXZlOiBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5vblNlbmRBbmltYXRpb25FdmVudExlYXZlKGN0eCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIF90aGlzLnBsYXllcklkLCBfdGhpcy5wbGF5ZXJJZCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgTWFnaWNTeW5jU2VydmljZS5wcm90b3R5cGUub25VcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLmlzQW55TWFnaWNTdHVmZkVxdWlwZWQoKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoRGF0ZS5ub3coKSAtIHRoaXMubGFzdFNlbmRVcGRhdGVBbmltYXRpb25WYXJpYWJsZXMgPD0gdGhpcy5zZW5kVXBkYXRlQW5pbWF0aW9uVmFyaWFibGVzUmF0ZU1zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sYXN0U2VuZFVwZGF0ZUFuaW1hdGlvblZhcmlhYmxlcyA9IERhdGUubm93KCk7XG4gICAgICAgIHRoaXMuY29udHJvbGxlci5vbmNlKCd1cGRhdGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYWMgPSBHYW1lLmdldFBsYXllcigpO1xuICAgICAgICAgICAgaWYgKCFhYykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmltVmFyaWFibGVzID0gX3RoaXMuZ2V0QW5pbWF0aW9uVmFyaWFibGVzRnJvbUFjdG9yQ29udmVydGVkKGFjLmdldEZvcm1JRCgpKTtcbiAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHsgdDogTXNnVHlwZS5VcGRhdGVBbmltVmFyaWFibGVzLCBkYXRhOiBfdGhpcy5nZXRVcGRhdGVBbmltVmFyaWFibGVzRXZlbnREYXRhKGFjLCBhbmltVmFyaWFibGVzKSB9LFxuICAgICAgICAgICAgICAgIHJlbGlhYmlsaXR5OiBcInJlbGlhYmxlXCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIE1hZ2ljU3luY1NlcnZpY2UucHJvdG90eXBlLm9uU3BlbGxDYXN0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBpc0ludGVycnVwdENhc3QgPSBmYWxzZTtcbiAgICAgICAgdmFyIG1zZyA9IHRoaXMuZ2V0U3BlbGxDYXN0RXZlbnREYXRhKGV2ZW50LCBpc0ludGVycnVwdENhc3QpO1xuICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgbWVzc2FnZTogeyB0OiBNc2dUeXBlLlNwZWxsQ2FzdCwgZGF0YTogbXNnIH0sXG4gICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmxhc3RTcGVsbENhc3RFdmVudE1zZyA9IG1zZztcbiAgICB9O1xuICAgIE1hZ2ljU3luY1NlcnZpY2UucHJvdG90eXBlLm9uU2VuZEFuaW1hdGlvbkV2ZW50TGVhdmUgPSBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5sYXN0U3BlbGxDYXN0RXZlbnRNc2cgfHwgIXRoaXMuaXNJbnRlcmFwdFNwZWxsQ2FzdEFuaW0oY3R4LmFuaW1FdmVudE5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMubGFzdFNwZWxsQ2FzdEV2ZW50TXNnIHx8IF90aGlzLmxhc3RTcGVsbENhc3RFdmVudE1zZy5pbnRlcnJ1cHRDYXN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG1zZyA9IF90aGlzLmxhc3RTcGVsbENhc3RFdmVudE1zZztcbiAgICAgICAgICAgIG1zZy5pbnRlcnJ1cHRDYXN0ID0gdHJ1ZTtcbiAgICAgICAgICAgIG1zZy5hY3RvckFuaW1hdGlvblZhcmlhYmxlcyA9IF90aGlzLmdldEFuaW1hdGlvblZhcmlhYmxlc0Zyb21BY3RvckNvbnZlcnRlZChyZW1vdGVJZFRvTG9jYWxJZChfdGhpcy5sYXN0U3BlbGxDYXN0RXZlbnRNc2cuY2FzdGVyKSk7XG4gICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNlbmRNZXNzYWdlXCIsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiB7IHQ6IE1zZ1R5cGUuU3BlbGxDYXN0LCBkYXRhOiBtc2cgfSxcbiAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBNYWdpY1N5bmNTZXJ2aWNlLnByb3RvdHlwZS5nZXRTcGVsbENhc3RFdmVudERhdGEgPSBmdW5jdGlvbiAoZSwgaXNJbnRlcnJ1cHRDYXN0KSB7XG4gICAgICAgIHZhciBzcGVsbENhc3REYXRhID0ge1xuICAgICAgICAgICAgY2FzdGVyOiBsb2NhbElkVG9SZW1vdGVJZChlLmNhc3Rlci5nZXRGb3JtSUQoKSwgdHJ1ZSksXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIChUT0RPOiBSZW1vdmUgaW4gMi4xMC4wKVxuICAgICAgICAgICAgdGFyZ2V0OiBlLnRhcmdldCA/IGxvY2FsSWRUb1JlbW90ZUlkKGUudGFyZ2V0LmdldEZvcm1JRCgpLCB0cnVlKSA6IDAsXG4gICAgICAgICAgICBzcGVsbDogZS5zcGVsbCA/IGUuc3BlbGwuZ2V0Rm9ybUlEKCkgOiAwLFxuICAgICAgICAgICAgaW50ZXJydXB0Q2FzdDogaXNJbnRlcnJ1cHRDYXN0LFxuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciAoVE9ETzogUmVtb3ZlIGluIDIuMTAuMClcbiAgICAgICAgICAgIGlzRHVhbENhc3Rpbmc6IGUuaXNEdWFsQ2FzdGluZyxcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgKFRPRE86IFJlbW92ZSBpbiAyLjEwLjApXG4gICAgICAgICAgICBjYXN0aW5nU291cmNlOiBlLmNhc3RpbmdTb3VyY2UsXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIChUT0RPOiBSZW1vdmUgaW4gMi4xMC4wKVxuICAgICAgICAgICAgYWltQW5nbGU6IGUuYWltQW5nbGUsXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIChUT0RPOiBSZW1vdmUgaW4gMi4xMC4wKVxuICAgICAgICAgICAgYWltSGVhZGluZzogZS5haW1IZWFkaW5nLFxuICAgICAgICAgICAgYWN0b3JBbmltYXRpb25WYXJpYWJsZXM6IHRoaXMuZ2V0QW5pbWF0aW9uVmFyaWFibGVzRnJvbUFjdG9yQ29udmVydGVkKGUuY2FzdGVyLmdldEZvcm1JRCgpKSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHNwZWxsQ2FzdERhdGE7XG4gICAgfTtcbiAgICBNYWdpY1N5bmNTZXJ2aWNlLnByb3RvdHlwZS5nZXRBbmltYXRpb25WYXJpYWJsZXNGcm9tQWN0b3JDb252ZXJ0ZWQgPSBmdW5jdGlvbiAoYWN0b3JJZCkge1xuICAgICAgICB2YXIgYW5pbVZhcnMgPSBnZXRBbmltYXRpb25WYXJpYWJsZXNGcm9tQWN0b3IoYWN0b3JJZCk7XG4gICAgICAgIHZhciBib29sZWFucyA9IGFuaW1WYXJzLmJvb2xlYW5zO1xuICAgICAgICB2YXIgZmxvYXRzID0gYW5pbVZhcnMuZmxvYXRzO1xuICAgICAgICB2YXIgaW50ZWdlcnMgPSBhbmltVmFycy5pbnRlZ2VycztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGJvb2xlYW5zOiBBcnJheS5mcm9tKG5ldyBVaW50OEFycmF5KGJvb2xlYW5zKSksXG4gICAgICAgICAgICBmbG9hdHM6IEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoZmxvYXRzKSksXG4gICAgICAgICAgICBpbnRlZ2VyczogQXJyYXkuZnJvbShuZXcgVWludDhBcnJheShpbnRlZ2VycykpLFxuICAgICAgICB9O1xuICAgIH07XG4gICAgTWFnaWNTeW5jU2VydmljZS5wcm90b3R5cGUuZ2V0VXBkYXRlQW5pbVZhcmlhYmxlc0V2ZW50RGF0YSA9IGZ1bmN0aW9uIChhYywgYW5pbVZhcmlhYmxlcykge1xuICAgICAgICB2YXIgYW5pbVZhcnNEYXRhID0ge1xuICAgICAgICAgICAgYWN0b3JSZW1vdGVJZDogbG9jYWxJZFRvUmVtb3RlSWQoYWMuZ2V0Rm9ybUlEKCksIHRydWUpLFxuICAgICAgICAgICAgYWN0b3JBbmltYXRpb25WYXJpYWJsZXM6IGFuaW1WYXJpYWJsZXMsXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBhbmltVmFyc0RhdGE7XG4gICAgfTtcbiAgICBNYWdpY1N5bmNTZXJ2aWNlLnByb3RvdHlwZS5pc0ludGVyYXB0U3BlbGxDYXN0QW5pbSA9IGZ1bmN0aW9uIChhbmltRXZlbnROYW1lKSB7XG4gICAgICAgIHZhciBldmVudE5hbWUgPSBhbmltRXZlbnROYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHJldHVybiBldmVudE5hbWUgPT09IFwibWxoX2VxdWlwcGVkX2V2ZW50XCIgfHwgZXZlbnROYW1lID09PSBcIm1yaF9lcXVpcHBlZF9ldmVudFwiO1xuICAgIH07XG4gICAgO1xuICAgIE1hZ2ljU3luY1NlcnZpY2UucHJvdG90eXBlLmlzU3BlbGxDYXN0QW5pbSA9IGZ1bmN0aW9uIChhbmltRXZlbnROYW1lKSB7XG4gICAgICAgIHZhciBldmVudE5hbWUgPSBhbmltRXZlbnROYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHZhciBpc1NwZWxsQ2FzdEFuaW1Gb3JMZWZ0SGFuZCA9IGV2ZW50TmFtZSA9PT0gXCJtbGhfc3BlbGxhaW1lZGNvbmNlbnRyYXRpb25zdGFydFwiIHx8IGV2ZW50TmFtZSA9PT0gXCJtbGhfc3BlbGxhaW1lZHN0YXJ0XCIgfHwgZXZlbnROYW1lID09PSBcIm1saF9zcGVsbHJlYWR5X2V2ZW50XCIgfHxcbiAgICAgICAgICAgIGV2ZW50TmFtZSA9PT0gXCJtbGhfc3BlbGxyZWxlYXNlX2V2ZW50XCIgfHwgZXZlbnROYW1lID09PSBcIm1saF9lcXVpcHBlZF9ldmVudFwiO1xuICAgICAgICB2YXIgaXNTcGVsbENhc3RBbmltRm9yUmlnaHRIYW5kID0gZXZlbnROYW1lID09PSBcIm1yaF9zcGVsbGFpbWVkY29uY2VudHJhdGlvbnN0YXJ0XCIgfHwgZXZlbnROYW1lID09PSBcIm1yaF9zcGVsbGFpbWVkc3RhcnRcIiB8fCBldmVudE5hbWUgPT09IFwibXJoX3NwZWxscmVhZHlfZXZlbnRcIiB8fFxuICAgICAgICAgICAgZXZlbnROYW1lID09PSBcIm1yaF9zcGVsbHJlbGVhc2VfZXZlbnRcIiB8fCBldmVudE5hbWUgPT09IFwibXJoX2VxdWlwcGVkX2V2ZW50XCI7XG4gICAgICAgIHJldHVybiBpc1NwZWxsQ2FzdEFuaW1Gb3JMZWZ0SGFuZCB8fCBpc1NwZWxsQ2FzdEFuaW1Gb3JSaWdodEhhbmQ7XG4gICAgfTtcbiAgICA7XG4gICAgTWFnaWNTeW5jU2VydmljZS5wcm90b3R5cGUuaXNBbnlNYWdpY1N0dWZmRXF1aXBlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFjID0gR2FtZS5nZXRQbGF5ZXIoKTtcbiAgICAgICAgaWYgKCFhYykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhYy5nZXRFcXVpcHBlZFNwZWxsKFNwZWxsVHlwZS5MZWZ0KSB8fCBhYy5nZXRFcXVpcHBlZFNwZWxsKFNwZWxsVHlwZS5SaWdodCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhYy5nZXRFcXVpcHBlZFNwZWxsKFNwZWxsVHlwZS5Wb2lzZSkgfHwgYWMuZ2V0RXF1aXBwZWRTcGVsbChTcGVsbFR5cGUuSW5zdGFudCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZWZ0SGFuZEVxdWlwbWVudFR5cGUgPSBhYy5nZXRFcXVpcHBlZEl0ZW1UeXBlKDEgLyogU2xvdFR5cGUuTGVmdCAqLyk7XG4gICAgICAgIHZhciByaWdodEhhbmRFcXVpcG1lbnRUeXBlID0gYWMuZ2V0RXF1aXBwZWRJdGVtVHlwZSgyIC8qIFNsb3RUeXBlLlJpZ2h0ICovKTtcbiAgICAgICAgaWYgKGxlZnRIYW5kRXF1aXBtZW50VHlwZSA9PT0gOSB8fCBsZWZ0SGFuZEVxdWlwbWVudFR5cGUgPT09IDggLyogRXF1aXBwZWRJdGVtVHlwZS5TdGFmZiAqLyB8fFxuICAgICAgICAgICAgcmlnaHRIYW5kRXF1aXBtZW50VHlwZSA9PT0gOSB8fCByaWdodEhhbmRFcXVpcG1lbnRUeXBlID09PSA4IC8qIEVxdWlwcGVkSXRlbVR5cGUuU3RhZmYgKi8pIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIHJldHVybiBNYWdpY1N5bmNTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgTWFnaWNTeW5jU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IHNldFRleHRTaXplIH0gZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG5pbXBvcnQgeyBsb2dUcmFjZSwgbG9nRXJyb3IgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xudmFyIE5ldEluZm9TZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhOZXRJbmZvU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBOZXRJbmZvU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLnJlY2VpdmVkUGFja2V0Q291bnQgPSAwO1xuICAgICAgICBfdGhpcy5zZW50UGFja2V0Q291bnQgPSAwO1xuICAgICAgICBfdGhpcy5sb2NhbExhZ1VuaXRzID0gMDtcbiAgICAgICAgX3RoaXMuZGVsYXlNcyA9IDEwMDA7XG4gICAgICAgIF90aGlzLmxhc3REdCA9IDA7XG4gICAgICAgIF90aGlzLmR0ID0gMDtcbiAgICAgICAgX3RoaXMuZ3JlZW5BUkdCID0gWzAsIDEyOCwgMCwgMV07XG4gICAgICAgIF90aGlzLnJlZEFSR0IgPSBbMjU1LCAwLCAwLCAxXTtcbiAgICAgICAgLy8gY2xlYXIgcHJldmlvdXMgdGV4dHMgaW4gY2FzZSBvZiBob3RyZWxvYWRcbiAgICAgICAgaWYgKF90aGlzLnNwLnN0b3JhZ2VbTmV0SW5mb1RleHRzLk5hbWVdICYmIF90aGlzLnNwLnN0b3JhZ2VbTmV0SW5mb1RleHRzLk5hbWVdLmNsZWFyKSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJEZXN0cm95aW5nIG9sZCBOZXRJbmZvVGV4dHNcIik7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIChfYSA9IF90aGlzLnNwLnN0b3JhZ2VbTmV0SW5mb1RleHRzLk5hbWVdKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY2xlYXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiRmFpbGVkIHRvIGRlc3Ryb3kgb2xkIE5ldEluZm9UZXh0czpcIiwgZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFfdGhpcy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgICAgICB9XG4gICAgICAgIF90aGlzLnRleHRJZHMgPSBuZXcgTmV0SW5mb1RleHRzKF90aGlzLnNwKTtcbiAgICAgICAgX3RoaXMuc3Auc3RvcmFnZVtOZXRJbmZvVGV4dHMuTmFtZV0gPSBfdGhpcy50ZXh0SWRzO1xuICAgICAgICBfdGhpcy5sYXN0RHQgPSBEYXRlLm5vdygpO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJzZW5kTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25TZW5kTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInNlbmRNZXNzYWdlV2l0aFJlZnJJZFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25TZW5kTWVzc2FnZVdpdGhSZWZySWQoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJhbnlNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkFueU1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJuZXdMb2NhbExhZ1ZhbHVlQ2FsY3VsYXRlZFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25OZXdMb2NhbExhZ1ZhbHVlQ2FsY3VsYXRlZChlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLm9uU2VuZE1lc3NhZ2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB0aGlzLmFkZFNlbnRQYWNrZXRDb3VudCgxKTtcbiAgICB9O1xuICAgIE5ldEluZm9TZXJ2aWNlLnByb3RvdHlwZS5vblNlbmRNZXNzYWdlV2l0aFJlZnJJZCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHRoaXMuYWRkU2VudFBhY2tldENvdW50KDEpO1xuICAgIH07XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLm9uQW55TWVzc2FnZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHRoaXMuYWRkUmVjZWl2ZWRQYWNrZXRDb3VudCgxKTtcbiAgICB9O1xuICAgIE5ldEluZm9TZXJ2aWNlLnByb3RvdHlwZS5vbk5ld0xvY2FsTGFnVmFsdWVDYWxjdWxhdGVkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5zZXRMb2NhbExhZ1VuaXRzKGUubGFnVW5pdHNOb1opO1xuICAgIH07XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLm9uVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy50ZXh0SWRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmR0ICs9IERhdGUubm93KCkgLSB0aGlzLmxhc3REdDtcbiAgICAgICAgdGhpcy5sYXN0RHQgPSBEYXRlLm5vdygpO1xuICAgICAgICB2YXIgaXNDb25uZWN0ZWQgPSB0aGlzLnNwLm1wQ2xpZW50UGx1Z2luLmlzQ29ubmVjdGVkKCk7XG4gICAgICAgIHRoaXMuc3Auc2V0VGV4dFN0cmluZyh0aGlzLnRleHRJZHMuY29ubmVjdGlvblN0YXRlVGV4dElkLCBcIlwiLmNvbmNhdChpc0Nvbm5lY3RlZCA/IFwiT05cIiA6IFwiT0ZGXCIpKTtcbiAgICAgICAgdGhpcy5zcC5zZXRUZXh0Q29sb3IodGhpcy50ZXh0SWRzLmNvbm5lY3Rpb25TdGF0ZVRleHRJZCwgaXNDb25uZWN0ZWQgPyB0aGlzLmdyZWVuQVJHQiA6IHRoaXMucmVkQVJHQik7XG4gICAgICAgIC8vIGh0dHBzOi8vd3d3LmNyZWF0aW9ua2l0LmNvbS9pbmRleC5waHA/dGl0bGU9VW5pdFxuICAgICAgICB2YXIgdW5pdHMgPSB0aGlzLmdldExvY2FsTGFnVW5pdHMoKTtcbiAgICAgICAgdmFyIHVuaXRzSW5NZXRlciA9IDcwLjAyMTg4MTgzODE7XG4gICAgICAgIHZhciBtZXRlcnMgPSBNYXRoLnJvdW5kKHVuaXRzIC8gdW5pdHNJbk1ldGVyICogMTApIC8gMTA7XG4gICAgICAgIHRoaXMuc3Auc2V0VGV4dFN0cmluZyh0aGlzLnRleHRJZHMubG9jYWxQb3NpdGlvbkxhZ0Ftb3VudFRleHRJZCwgXCJcIi5jb25jYXQodW5pdHMsIFwiIHVuaXRzICh+XCIpLmNvbmNhdChtZXRlcnMsIFwiIG0pXCIpKTtcbiAgICAgICAgaWYgKHRoaXMuZGVsYXlNcyA+IHRoaXMuZHQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNwLnNldFRleHRTdHJpbmcodGhpcy50ZXh0SWRzLnJlY2VpdmVkUGFja2V0QW1vdW50VGV4dElkLCBcIlwiLmNvbmNhdChNYXRoLnJvdW5kKHRoaXMuZ2V0QW5kQ2xlYXJSZWNlaXZlZFBhY2tldENvdW50KCkpKSk7XG4gICAgICAgIHRoaXMuc3Auc2V0VGV4dFN0cmluZyh0aGlzLnRleHRJZHMuc2VudFBhY2tldEFtb3VudFRleHRJZCwgXCJcIi5jb25jYXQoTWF0aC5yb3VuZCh0aGlzLmdldEFuZENsZWFyU2VudFBhY2tldENvdW50KCkpKSk7XG4gICAgICAgIHRoaXMuZHQgPSAwO1xuICAgIH07XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLmFkZFJlY2VpdmVkUGFja2V0Q291bnQgPSBmdW5jdGlvbiAoY291bnQpIHtcbiAgICAgICAgdGhpcy5yZWNlaXZlZFBhY2tldENvdW50ICs9IGNvdW50O1xuICAgIH07XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLmdldEFuZENsZWFyUmVjZWl2ZWRQYWNrZXRDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5yZWNlaXZlZFBhY2tldENvdW50O1xuICAgICAgICB0aGlzLnJlY2VpdmVkUGFja2V0Q291bnQgPSAwO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBOZXRJbmZvU2VydmljZS5wcm90b3R5cGUuYWRkU2VudFBhY2tldENvdW50ID0gZnVuY3Rpb24gKGNvdW50KSB7XG4gICAgICAgIHRoaXMuc2VudFBhY2tldENvdW50ICs9IGNvdW50O1xuICAgIH07XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLmdldEFuZENsZWFyU2VudFBhY2tldENvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLnNlbnRQYWNrZXRDb3VudDtcbiAgICAgICAgdGhpcy5zZW50UGFja2V0Q291bnQgPSAwO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBOZXRJbmZvU2VydmljZS5wcm90b3R5cGUuc2V0TG9jYWxMYWdVbml0cyA9IGZ1bmN0aW9uIChkaXN0YW5jZSkge1xuICAgICAgICB0aGlzLmxvY2FsTGFnVW5pdHMgPSBkaXN0YW5jZTtcbiAgICB9O1xuICAgIE5ldEluZm9TZXJ2aWNlLnByb3RvdHlwZS5nZXRMb2NhbExhZ1VuaXRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbExhZ1VuaXRzO1xuICAgIH07XG4gICAgTmV0SW5mb1NlcnZpY2UucHJvdG90eXBlLmlzRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5zcC5zZXR0aW5nc1tcInNreW1wNS1jbGllbnRcIl1bXCJzaG93LW5ldC1pbmZvXCJdO1xuICAgIH07XG4gICAgcmV0dXJuIE5ldEluZm9TZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgTmV0SW5mb1NlcnZpY2UgfTtcbnZhciBOZXRJbmZvVGV4dHMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTmV0SW5mb1RleHRzKHNwLCBjb25uZWN0aW9uU3RhdGljVGV4dElkLCBjb25uZWN0aW9uU3RhdGVUZXh0SWQsIHJlY2VpdmVkUGFja2V0U3RhdGljVGV4dElkLCByZWNlaXZlZFBhY2tldEFtb3VudFRleHRJZCwgc2VudFBhY2tldFN0YXRpY1RleHRJZCwgc2VudFBhY2tldEFtb3VudFRleHRJZCwgbG9jYWxQb3NpdGlvbkxhZ1N0YXRpY1RleHRJZCwgbG9jYWxQb3NpdGlvbkxhZ0Ftb3VudFRleHRJZCkge1xuICAgICAgICBpZiAoY29ubmVjdGlvblN0YXRpY1RleHRJZCA9PT0gdm9pZCAwKSB7IGNvbm5lY3Rpb25TdGF0aWNUZXh0SWQgPSBzcC5jcmVhdGVUZXh0KDEwMCwgMzUwLCBcImNvbm5lY3Rpb246XCIsIFsyNTUsIDI1NSwgMjU1LCAxXSk7IH1cbiAgICAgICAgaWYgKGNvbm5lY3Rpb25TdGF0ZVRleHRJZCA9PT0gdm9pZCAwKSB7IGNvbm5lY3Rpb25TdGF0ZVRleHRJZCA9IHNwLmNyZWF0ZVRleHQoMjIwLCAzNTAsIFwiXCIsIFsyNTUsIDI1NSwgMjU1LCAxXSk7IH1cbiAgICAgICAgaWYgKHJlY2VpdmVkUGFja2V0U3RhdGljVGV4dElkID09PSB2b2lkIDApIHsgcmVjZWl2ZWRQYWNrZXRTdGF0aWNUZXh0SWQgPSBzcC5jcmVhdGVUZXh0KDEyMCwgMzkwLCBcImluY29taW5nIChwL3MpOlwiLCBbMjU1LCAyNTUsIDI1NSwgMV0pOyB9XG4gICAgICAgIGlmIChyZWNlaXZlZFBhY2tldEFtb3VudFRleHRJZCA9PT0gdm9pZCAwKSB7IHJlY2VpdmVkUGFja2V0QW1vdW50VGV4dElkID0gc3AuY3JlYXRlVGV4dCgyNTAsIDM5MCwgXCJcIiwgWzI1NSwgMjU1LCAyNTUsIDFdKTsgfVxuICAgICAgICBpZiAoc2VudFBhY2tldFN0YXRpY1RleHRJZCA9PT0gdm9pZCAwKSB7IHNlbnRQYWNrZXRTdGF0aWNUZXh0SWQgPSBzcC5jcmVhdGVUZXh0KDEyMCwgNDMwLCBcIm91dGdvaW5nIChwL3MpOlwiLCBbMjU1LCAyNTUsIDI1NSwgMV0pOyB9XG4gICAgICAgIGlmIChzZW50UGFja2V0QW1vdW50VGV4dElkID09PSB2b2lkIDApIHsgc2VudFBhY2tldEFtb3VudFRleHRJZCA9IHNwLmNyZWF0ZVRleHQoMjUwLCA0MzAsIFwiXCIsIFsyNTUsIDI1NSwgMjU1LCAxXSk7IH1cbiAgICAgICAgaWYgKGxvY2FsUG9zaXRpb25MYWdTdGF0aWNUZXh0SWQgPT09IHZvaWQgMCkgeyBsb2NhbFBvc2l0aW9uTGFnU3RhdGljVGV4dElkID0gc3AuY3JlYXRlVGV4dCg5MCwgNDcwLCBcImxvY2FsIGxhZzpcIiwgWzI1NSwgMjU1LCAyNTUsIDFdKTsgfVxuICAgICAgICBpZiAobG9jYWxQb3NpdGlvbkxhZ0Ftb3VudFRleHRJZCA9PT0gdm9pZCAwKSB7IGxvY2FsUG9zaXRpb25MYWdBbW91bnRUZXh0SWQgPSBzcC5jcmVhdGVUZXh0KDI1MCwgNDcwLCBcIlwiLCBbMjU1LCAyNTUsIDI1NSwgMV0pOyB9XG4gICAgICAgIHRoaXMuc3AgPSBzcDtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdGljVGV4dElkID0gY29ubmVjdGlvblN0YXRpY1RleHRJZDtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdGVUZXh0SWQgPSBjb25uZWN0aW9uU3RhdGVUZXh0SWQ7XG4gICAgICAgIHRoaXMucmVjZWl2ZWRQYWNrZXRTdGF0aWNUZXh0SWQgPSByZWNlaXZlZFBhY2tldFN0YXRpY1RleHRJZDtcbiAgICAgICAgdGhpcy5yZWNlaXZlZFBhY2tldEFtb3VudFRleHRJZCA9IHJlY2VpdmVkUGFja2V0QW1vdW50VGV4dElkO1xuICAgICAgICB0aGlzLnNlbnRQYWNrZXRTdGF0aWNUZXh0SWQgPSBzZW50UGFja2V0U3RhdGljVGV4dElkO1xuICAgICAgICB0aGlzLnNlbnRQYWNrZXRBbW91bnRUZXh0SWQgPSBzZW50UGFja2V0QW1vdW50VGV4dElkO1xuICAgICAgICB0aGlzLmxvY2FsUG9zaXRpb25MYWdTdGF0aWNUZXh0SWQgPSBsb2NhbFBvc2l0aW9uTGFnU3RhdGljVGV4dElkO1xuICAgICAgICB0aGlzLmxvY2FsUG9zaXRpb25MYWdBbW91bnRUZXh0SWQgPSBsb2NhbFBvc2l0aW9uTGFnQW1vdW50VGV4dElkO1xuICAgICAgICBzZXRUZXh0U2l6ZSh0aGlzLmNvbm5lY3Rpb25TdGF0aWNUZXh0SWQsIDAuNSk7XG4gICAgICAgIHNldFRleHRTaXplKHRoaXMuY29ubmVjdGlvblN0YXRlVGV4dElkLCAwLjUpO1xuICAgICAgICBzZXRUZXh0U2l6ZSh0aGlzLnJlY2VpdmVkUGFja2V0U3RhdGljVGV4dElkLCAwLjUpO1xuICAgICAgICBzZXRUZXh0U2l6ZSh0aGlzLnJlY2VpdmVkUGFja2V0QW1vdW50VGV4dElkLCAwLjUpO1xuICAgICAgICBzZXRUZXh0U2l6ZSh0aGlzLnNlbnRQYWNrZXRTdGF0aWNUZXh0SWQsIDAuNSk7XG4gICAgICAgIHNldFRleHRTaXplKHRoaXMuc2VudFBhY2tldEFtb3VudFRleHRJZCwgMC41KTtcbiAgICAgICAgc2V0VGV4dFNpemUodGhpcy5sb2NhbFBvc2l0aW9uTGFnU3RhdGljVGV4dElkLCAwLjUpO1xuICAgICAgICBzZXRUZXh0U2l6ZSh0aGlzLmxvY2FsUG9zaXRpb25MYWdBbW91bnRUZXh0SWQsIDAuNSk7XG4gICAgfVxuICAgIE5ldEluZm9UZXh0cy5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AuZGVzdHJveVRleHQodGhpcy5jb25uZWN0aW9uU3RhdGljVGV4dElkKTtcbiAgICAgICAgdGhpcy5zcC5kZXN0cm95VGV4dCh0aGlzLmNvbm5lY3Rpb25TdGF0ZVRleHRJZCk7XG4gICAgICAgIHRoaXMuc3AuZGVzdHJveVRleHQodGhpcy5yZWNlaXZlZFBhY2tldFN0YXRpY1RleHRJZCk7XG4gICAgICAgIHRoaXMuc3AuZGVzdHJveVRleHQodGhpcy5yZWNlaXZlZFBhY2tldEFtb3VudFRleHRJZCk7XG4gICAgICAgIHRoaXMuc3AuZGVzdHJveVRleHQodGhpcy5zZW50UGFja2V0U3RhdGljVGV4dElkKTtcbiAgICAgICAgdGhpcy5zcC5kZXN0cm95VGV4dCh0aGlzLnNlbnRQYWNrZXRBbW91bnRUZXh0SWQpO1xuICAgICAgICB0aGlzLnNwLmRlc3Ryb3lUZXh0KHRoaXMubG9jYWxQb3NpdGlvbkxhZ1N0YXRpY1RleHRJZCk7XG4gICAgICAgIHRoaXMuc3AuZGVzdHJveVRleHQodGhpcy5sb2NhbFBvc2l0aW9uTGFnQW1vdW50VGV4dElkKTtcbiAgICB9O1xuICAgIE5ldEluZm9UZXh0cy5OYW1lID0gXCJuZXRJbmZvVGV4dHNcIjtcbiAgICByZXR1cm4gTmV0SW5mb1RleHRzO1xufSgpKTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBsb2dUcmFjZSwgbG9nRXJyb3IgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgTmV2ZXJFcnJvciB9IGZyb20gXCIuLi8uLi9saWIvZXJyb3JzXCI7XG5pbXBvcnQgeyBNc2dUeXBlIH0gZnJvbSBcIi4uLy4uL21lc3NhZ2VzXCI7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG5pbXBvcnQgeyBSZW1vdGVTZXJ2ZXIgfSBmcm9tIFwiLi9yZW1vdGVTZXJ2ZXJcIjtcbnZhciBOZXR3b3JraW5nU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoTmV0d29ya2luZ1NlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gTmV0d29ya2luZ1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ0aWNrXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uVGljaygpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwic2VuZE1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uU2VuZE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJzZW5kUmF3TWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25TZW5kUmF3TWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInNlbmRNZXNzYWdlV2l0aFJlZnJJZFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25TZW5kTWVzc2FnZVdpdGhSZWZySWQoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE5ldHdvcmtpbmdTZXJ2aWNlLnByb3RvdHlwZS5vblNlbmRNZXNzYWdlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5zcC5tcENsaWVudFBsdWdpbi5zZW5kKEpTT04uc3RyaW5naWZ5KGUubWVzc2FnZSksIHRoaXMuaXNSZWxpYWJsZShlLnJlbGlhYmlsaXR5KSk7XG4gICAgfTtcbiAgICBOZXR3b3JraW5nU2VydmljZS5wcm90b3R5cGUub25TZW5kUmF3TWVzc2FnZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgdGhpcy5zcC5tcENsaWVudFBsdWdpbi5zZW5kUmF3KGUucmF3TWVzc2FnZSwgZS5yYXdNZXNzYWdlLmJ5dGVMZW5ndGgsIHRoaXMuaXNSZWxpYWJsZShlLnJlbGlhYmlsaXR5KSk7XG4gICAgfTtcbiAgICBOZXR3b3JraW5nU2VydmljZS5wcm90b3R5cGUub25TZW5kTWVzc2FnZVdpdGhSZWZySWQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgcmVmcklkID0gZS5tZXNzYWdlLl9yZWZySWQ7XG4gICAgICAgIHZhciByZW1vdGVTZXJ2ZXIgPSB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoUmVtb3RlU2VydmVyKTtcbiAgICAgICAgdmFyIGlkeEluTW9kZWwgPSByZWZySWRcbiAgICAgICAgICAgID8gcmVtb3RlU2VydmVyLmdldFdvcmxkTW9kZWwoKS5mb3Jtcy5maW5kSW5kZXgoZnVuY3Rpb24gKGYpIHsgcmV0dXJuIGYgJiYgZi5yZWZySWQgPT09IHJlZnJJZDsgfSlcbiAgICAgICAgICAgIDogcmVtb3RlU2VydmVyLmdldFdvcmxkTW9kZWwoKS5wbGF5ZXJDaGFyYWN0ZXJGb3JtSWR4O1xuICAgICAgICAvLyBmaXhlcyBcImNhbid0IGdldCBwcm9wZXJ0eSBpZHggb2YgbnVsbCBvciB1bmRlZmluZWRcIlxuICAgICAgICBpZiAoIXJlbW90ZVNlcnZlci5nZXRXb3JsZE1vZGVsKCkuZm9ybXNbaWR4SW5Nb2RlbF0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIGUubWVzc2FnZS5pZHggPSByZW1vdGVTZXJ2ZXIuZ2V0V29ybGRNb2RlbCgpLmZvcm1zW2lkeEluTW9kZWxdLmlkeDtcbiAgICAgICAgZGVsZXRlIGUubWVzc2FnZS5fcmVmcklkO1xuICAgICAgICB0aGlzLnNwLm1wQ2xpZW50UGx1Z2luLnNlbmQoSlNPTi5zdHJpbmdpZnkoZS5tZXNzYWdlKSwgdGhpcy5pc1JlbGlhYmxlKGUucmVsaWFiaWxpdHkpKTtcbiAgICB9O1xuICAgIE5ldHdvcmtpbmdTZXJ2aWNlLnByb3RvdHlwZS5jb25uZWN0ID0gZnVuY3Rpb24gKGhvc3ROYW1lLCBwb3J0KSB7XG4gICAgICAgIHRoaXMuc2VydmVyQWRkcmVzcyA9IHsgaG9zdE5hbWU6IGhvc3ROYW1lLCBwb3J0OiBwb3J0IH07XG4gICAgICAgIHRoaXMuY3JlYXRlQ2xpZW50U2FmZSgpO1xuICAgIH07XG4gICAgTmV0d29ya2luZ1NlcnZpY2UucHJvdG90eXBlLnJlY29ubmVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jcmVhdGVDbGllbnRTYWZlKCk7XG4gICAgfTtcbiAgICBOZXR3b3JraW5nU2VydmljZS5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3AubXBDbGllbnRQbHVnaW4uZGVzdHJveUNsaWVudCgpO1xuICAgIH07XG4gICAgTmV0d29ya2luZ1NlcnZpY2UucHJvdG90eXBlLmlzQ29ubmVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcC5tcENsaWVudFBsdWdpbi5pc0Nvbm5lY3RlZCgpO1xuICAgIH07XG4gICAgTmV0d29ya2luZ1NlcnZpY2UucHJvdG90eXBlLm9uVGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5zcC5tcENsaWVudFBsdWdpbi50aWNrKGZ1bmN0aW9uIChwYWNrZXRUeXBlLCByYXdDb250ZW50LCBlcnJvcikge1xuICAgICAgICAgICAgc3dpdGNoIChwYWNrZXRUeXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcImNvbm5lY3Rpb25BY2NlcHRlZFwiOlxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImNvbm5lY3Rpb25BY2NlcHRlZFwiLCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJjb25uZWN0aW9uRGVuaWVkXCI6XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiY29ubmVjdGlvbkRlbmllZFwiLCB7IGVycm9yOiBlcnJvciB9KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVjb25uZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJjb25uZWN0aW9uRmFpbGVkXCI6XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiY29ubmVjdGlvbkZhaWxlZFwiLCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnJlY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiZGlzY29ubmVjdFwiOlxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImNvbm5lY3Rpb25EaXNjb25uZWN0XCIsIHt9KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVjb25uZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJtZXNzYWdlXCI6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGluIHRoZW9yeSBjYW4gYmUgZW1wdHkganNvbkNvbnRlbnQgYW5kIG5vbi1lbXB0eSBlcnJvclxuICAgICAgICAgICAgICAgICAgICB2YXIgbXNnQW55ID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmF3Q29udGVudCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXNnQW55ID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcihfdGhpcywgXCJudWxsIHJhd0NvbnRlbnRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoKG5ldyBVaW50OEFycmF5KHJhd0NvbnRlbnQpWzBdKSA9PT0gMHg3Yikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzdW1lIGpzb25cbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZ0FueSA9IEpTT04ucGFyc2UoX3RoaXMuc3AuZGVjb2RlVXRmOChyYXdDb250ZW50KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3N1bWUgcmF3XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IHJhd0NvbnRlbnQ6IHJhd0NvbnRlbnQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImFueVJhd01lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5PcGVuQ29udGFpbmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJvcGVuQ29udGFpbmVyTWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImFueU1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1zZ0FueS50ID09PSBNc2dUeXBlLlVwZGF0ZU1vdmVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJ1cGRhdGVNb3ZlbWVudE1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5VcGRhdGVBbmltYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInVwZGF0ZUFuaW1hdGlvbk1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5VcGRhdGVFcXVpcG1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInVwZGF0ZUVxdWlwbWVudE1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5DaGFuZ2VWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImNoYW5nZVZhbHVlc01lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5TcGVsbENhc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNwZWxsQ2FzdE1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5VcGRhdGVBbmltVmFyaWFibGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJ1cGRhdGVBbmltVmFyaWFibGVzTWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImFueU1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1zZ0FueS50ID09PSBNc2dUeXBlLlVwZGF0ZUFwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInVwZGF0ZUFwcGVhcmFuY2VNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnQW55LnQgPT09IE1zZ1R5cGUuVGVsZXBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInRlbGVwb3J0TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImFueU1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1zZ0FueS50ID09PSBNc2dUeXBlLlVwZGF0ZVByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJ1cGRhdGVQcm9wZXJ0eU1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5EZWF0aFN0YXRlQ29udGFpbmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJkZWF0aFN0YXRlQ29udGFpbmVyTWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImFueU1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1zZ0FueS50ID09PSBNc2dUeXBlLkNyZWF0ZUFjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJjcmVhdGVBY3Rvck1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5DdXN0b21QYWNrZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImN1c3RvbVBhY2tldE1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5EZXN0cm95QWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImRlc3Ryb3lBY3Rvck1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5Ib3N0U3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHsgbWVzc2FnZTogbXNnQW55IH07XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcImhvc3RTdGFydE1lc3NhZ2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhbnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChtc2dBbnkudCA9PT0gTXNnVHlwZS5Ib3N0U3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50ID0geyBtZXNzYWdlOiBtc2dBbnkgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiaG9zdFN0b3BNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnQW55LnQgPT09IE1zZ1R5cGUuU2V0SW52ZW50b3J5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZXRJbnZlbnRvcnlNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnQW55LnQgPT09IE1zZ1R5cGUuU2V0UmFjZU1lbnVPcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZXRSYWNlTWVudU9wZW5NZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnQW55LnQgPT09IE1zZ1R5cGUuU3BTbmlwcGV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzcFNuaXBwZXRNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnQW55LnQgPT09IE1zZ1R5cGUuVXBkYXRlR2FtZW1vZGVEYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJ1cGRhdGVHYW1lbW9kZURhdGFNZXNzYWdlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnQW55LnQgPT09IE1zZ1R5cGUuVGVsZXBvcnQyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnQgPSB7IG1lc3NhZ2U6IG1zZ0FueSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJ0ZWxlcG9ydE1lc3NhZ2UyXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYW55TWVzc2FnZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aHJvdyBuZXcgTmV2ZXJFcnJvcihtc2dBbnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5oYW5kbGVkIE1zZ1R5cGUgXCIgKyBtc2dBbnkudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgTmV0d29ya2luZ1NlcnZpY2UucHJvdG90eXBlLmNyZWF0ZUNsaWVudFNhZmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuc2VydmVyQWRkcmVzcywgaG9zdE5hbWUgPSBfYS5ob3N0TmFtZSwgcG9ydCA9IF9hLnBvcnQ7XG4gICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiY3JlYXRlQ2xpZW50U2FmZSBcIiArIGhvc3ROYW1lICsgXCI6XCIgKyBwb3J0KTtcbiAgICAgICAgaWYgKHRoaXMuc2VydmVyQWRkcmVzcy5ob3N0TmFtZSAhPT0gXCJcIiAmJiB0aGlzLnNlcnZlckFkZHJlc3MucG9ydCAhPT0gMCkge1xuICAgICAgICAgICAgdGhpcy5zcC5tcENsaWVudFBsdWdpbi5jcmVhdGVDbGllbnQoaG9zdE5hbWUsIHBvcnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJjcmVhdGVDbGllbnRTYWZlIGZhaWxlZFwiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5ldHdvcmtpbmdTZXJ2aWNlLnByb3RvdHlwZSwgXCJzZXJ2ZXJBZGRyZXNzXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcmVzID0gdGhpcy5zcC5zdG9yYWdlW1wic2VydmVyQWRkcmVzc1wiXTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHJlcztcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlc3VsdC5ob3N0TmFtZSA9PT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgcmVzdWx0LnBvcnQgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyBob3N0TmFtZTogXCJcIiwgcG9ydDogMCB9O1xuICAgICAgICB9LFxuICAgICAgICBzZXQ6IGZ1bmN0aW9uIChuZXdWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlW1wic2VydmVyQWRkcmVzc1wiXSA9IG5ld1ZhbHVlO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgTmV0d29ya2luZ1NlcnZpY2UucHJvdG90eXBlLmlzUmVsaWFibGUgPSBmdW5jdGlvbiAocmVsaWFiaWxpdHkpIHtcbiAgICAgICAgc3dpdGNoIChyZWxpYWJpbGl0eSkge1xuICAgICAgICAgICAgY2FzZSBcInJlbGlhYmxlXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBjYXNlIFwidW5yZWxpYWJsZVwiOlxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5ldmVyRXJyb3IocmVsaWFiaWxpdHkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gTmV0d29ya2luZ1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBOZXR3b3JraW5nU2VydmljZSB9O1xuO1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IEFtbW8sIEdhbWUgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IE1zZ1R5cGUgfSBmcm9tIFwiLi4vLi4vbWVzc2FnZXNcIjtcbmltcG9ydCB7IGdldEVxdWlwbWVudCB9IGZyb20gXCIuLi8uLi9zeW5jL2VxdWlwbWVudFwiO1xuaW1wb3J0IHsgbG9nRXJyb3IsIGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbnZhciBQbGF5ZXJCb3dTaG90U2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoUGxheWVyQm93U2hvdFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUGxheWVyQm93U2hvdFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzXzEgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpc18xLnNwID0gc3A7XG4gICAgICAgIF90aGlzXzEuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzXzEuc2NvcmUgPSAwO1xuICAgICAgICBfdGhpc18xLmludmVudG9yeVVuYmxvY2tNb21lbnQgPSAwO1xuICAgICAgICBfdGhpc18xLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInF1ZXJ5QmxvY2tTZXRJbnZlbnRvcnlFdmVudFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXNfMS5vblF1ZXJ5QmxvY2tTZXRJbnZlbnRvcnlFdmVudChlKTsgfSk7XG4gICAgICAgIF90aGlzXzEuY29udHJvbGxlci5vbihcInBsYXllckJvd1Nob3RcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzXzEub25QbGF5ZXJCb3dTaG90KGUpOyB9KTtcbiAgICAgICAgdmFyIF90aGlzID0gX3RoaXNfMTtcbiAgICAgICAgdmFyIGV2ZW50UGF0dGVybnMgPSBbXCJhdHRhY2tSZWxlYXNlXCIsIFwiY3Jvc3Nib3dBdHRhY2tTdGFydFwiXTtcbiAgICAgICAgZXZlbnRQYXR0ZXJucy5mb3JFYWNoKGZ1bmN0aW9uIChldmVudFBhdHRlcm4pIHtcbiAgICAgICAgICAgIF90aGlzXzEuc3AuaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxlYXZlOiBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY3R4LmFuaW1hdGlvblN1Y2NlZWRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdHguYW5pbUV2ZW50TmFtZSA9PT0gXCJjcm9zc2Jvd0F0dGFja1N0YXJ0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNjb3JlID0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChjdHguYW5pbUV2ZW50TmFtZSA9PT0gXCJhdHRhY2tSZWxlYXNlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5zY29yZSA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7IF90aGlzLm9uUGxheWVyQ3Jvc3Nib3dTaG90KCk7IH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNjb3JlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNjb3JlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIDB4MTQsIDB4MTQsIGV2ZW50UGF0dGVybik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gX3RoaXNfMTtcbiAgICB9XG4gICAgUGxheWVyQm93U2hvdFNlcnZpY2UucHJvdG90eXBlLm9uUXVlcnlCbG9ja1NldEludmVudG9yeUV2ZW50ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKERhdGUubm93KCkgPCB0aGlzLmludmVudG9yeVVuYmxvY2tNb21lbnQpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiQmxvY2tlZCBpbnZlbnRvcnkgb3BlcmF0aW9uXCIpO1xuICAgICAgICAgICAgZS5ibG9jaygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJOb3QgYmxvY2tlZCBpbnZlbnRvcnkgb3BlcmF0aW9uXCIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQbGF5ZXJCb3dTaG90U2VydmljZS5wcm90b3R5cGUub25QbGF5ZXJCb3dTaG90ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNlbmRNZXNzYWdlXCIsIHtcbiAgICAgICAgICAgIG1lc3NhZ2U6IHtcbiAgICAgICAgICAgICAgICB0OiBNc2dUeXBlLlBsYXllckJvd1Nob3QsXG4gICAgICAgICAgICAgICAgd2VhcG9uSWQ6IGUud2VhcG9uLmdldEZvcm1JRCgpLFxuICAgICAgICAgICAgICAgIGFtbW9JZDogZS5hbW1vLmdldEZvcm1JRCgpLFxuICAgICAgICAgICAgICAgIHBvd2VyOiBlLnBvd2VyLFxuICAgICAgICAgICAgICAgIGlzU3VuR2F6aW5nOiBlLmlzU3VuR2F6aW5nIHx8IGZhbHNlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwidW5yZWxpYWJsZVwiXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUGxheWVyQm93U2hvdFNlcnZpY2UucHJvdG90eXBlLm9uUGxheWVyQ3Jvc3Nib3dTaG90ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYWN0b3IgPSB0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgIGlmIChhY3RvciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjcm9zc2JvdyA9IGFjdG9yLmdldEVxdWlwcGVkV2VhcG9uKGZhbHNlKTtcbiAgICAgICAgaWYgKGNyb3NzYm93ID09PSBudWxsKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIkNvdWxkbid0IGdldCBlcXVpcHBlZCB3ZWFwb25cIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHdlYXBvblR5cGUgPSBjcm9zc2Jvdy5nZXRXZWFwb25UeXBlKCk7XG4gICAgICAgIGlmICh3ZWFwb25UeXBlICE9PSA5IC8qIFdlYXBvblR5cGUuQ3Jvc3Nib3cgKi8pIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiRXhwZWN0ZWQgd2VhcG9uIHRvIGJlIGNyb3NzYm93LCBidXQgZ290IFdlYXBvblR5cGVcIiwgd2VhcG9uVHlwZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVxdWlwcGVkQW1tb0VudHJpZXMgPSBnZXRFcXVpcG1lbnQoYWN0b3IsIDApLmludi5lbnRyaWVzLmZpbHRlcihmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIGVudHJ5Lndvcm4gJiYgQW1tby5mcm9tKEdhbWUuZ2V0Rm9ybUV4KGVudHJ5LmJhc2VJZCkpOyB9KTtcbiAgICAgICAgaWYgKGVxdWlwcGVkQW1tb0VudHJpZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIkFtbW8gbm90IGZvdW5kXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlcXVpcHBlZEFtbW9FbnRyaWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIHZhciBlcXVpcHBlZEFtbW9JZHMgPSBlcXVpcHBlZEFtbW9FbnRyaWVzLm1hcChmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIGVudHJ5LmJhc2VJZDsgfSk7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIkZvdW5kIG1vcmUgdGhhbiAxIGFtbW9zOlwiLCBlcXVpcHBlZEFtbW9JZHMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICBtZXNzYWdlOiB7XG4gICAgICAgICAgICAgICAgdDogTXNnVHlwZS5QbGF5ZXJCb3dTaG90LFxuICAgICAgICAgICAgICAgIHdlYXBvbklkOiBjcm9zc2Jvdy5nZXRGb3JtSUQoKSxcbiAgICAgICAgICAgICAgICBhbW1vSWQ6IGVxdWlwcGVkQW1tb0VudHJpZXNbMF0uYmFzZUlkLFxuICAgICAgICAgICAgICAgIGlzU3VuR2F6aW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBwb3dlcjogMS4wXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwidW5yZWxpYWJsZVwiXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBGaXhlcyByYWNlIGNvbmRpdGlvbiB3aGVuIHRoZSBzZXJ2ZXIgcmVtb3ZlcyBhbiBpdGVtIGZhc3RlciB0aGFuIGxvY2FsIGNyb3NzYm93IGRvZXMgdGhhdDogLTEgdG90YWxcbiAgICAgICAgLy8gVGhlbiBjcm9zc2JvdyByZW1vdmVzIG9uZSBtb3JlIGl0ZW06IC0yIHRvdGFsXG4gICAgICAgIC8vIFRoZSBpdGVtIGlzIGJlaW5nIGFkZGVkIGJhY2s6IC0xIHRvdGFsICh3aGljaCBpcyBjb3JyZWN0IGJ1dCBsb29rcyB1Z2x5IGluIHByb2Nlc3MpXG4gICAgICAgIHRoaXMuaW52ZW50b3J5VW5ibG9ja01vbWVudCA9IERhdGUubm93KCkgKyA1ICogMTAwMDtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJTZW50IGNyb3NzYm93IHNob3RcIik7XG4gICAgfTtcbiAgICByZXR1cm4gUGxheWVyQm93U2hvdFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBQbGF5ZXJCb3dTaG90U2VydmljZSB9O1xuO1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICdpbnNwZWN0b3InO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcImZzXCI7XG52YXIgUHJvZmlsaW5nU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoUHJvZmlsaW5nU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBQcm9maWxpbmdTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICB2YXIgc2V0dGluZ3MgPSBzcC5zZXR0aW5nc1tcInNreW1wNS1jbGllbnRcIl07XG4gICAgICAgIGlmICghc2V0dGluZ3NbXCJlbmFibGVQcm9maWxpbmdcIl0pIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlByb2ZpbGluZ1NlcnZpY2U6IGRpc2FibGVkXCIpO1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcm9maWxpbmdEdXJhdGlvbk1zID0gX3RoaXMuZ2V0SW50ZWdlcihzZXR0aW5nc1tcInByb2ZpbGluZ0R1cmF0aW9uTXNcIl0pIHx8IDEwMDAwO1xuICAgICAgICB2YXIgc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKCk7XG4gICAgICAgIHNlc3Npb24uY29ubmVjdCgpO1xuICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJQcm9maWxpbmdTZXJ2aWNlOiBzdGFydFwiKTtcbiAgICAgICAgX3RoaXMuc3RhcnRQcm9maWxpbmcoc2Vzc2lvbiwgcHJvZmlsaW5nRHVyYXRpb25Ncyk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUHJvZmlsaW5nU2VydmljZS5wcm90b3R5cGUuc3RhcnRQcm9maWxpbmcgPSBmdW5jdGlvbiAoc2Vzc2lvbiwgcHJvZmlsaW5nRHVyYXRpb25Ncykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcHJvZmlsZSwgZmlsZU5hbWVTdWZmaXg7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6IHJldHVybiBbNCAvKnlpZWxkKi8sIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLnBvc3QoJ1Byb2ZpbGVyLmVuYWJsZScsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0IC8qeWllbGQqLywgbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLnBvc3QoJ1Byb2ZpbGVyLnN0YXJ0JywgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCAvKnlpZWxkKi8sIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgcHJvZmlsaW5nRHVyYXRpb25Ncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlByb2ZpbGluZ1NlcnZpY2U6IHN0b3BcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucG9zdCgnUHJvZmlsZXIuc3RvcCcsIGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShyZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2ZpbGUgPSAoX2Euc2VudCgpKS5wcm9maWxlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZU5hbWVTdWZmaXggPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKCkucmVwbGFjZShcIi4wXCIsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhcIi4vcHJvZmlsZVwiLmNvbmNhdChmaWxlTmFtZVN1ZmZpeCwgXCIuY3B1cHJvZmlsZVwiKSwgSlNPTi5zdHJpbmdpZnkocHJvZmlsZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi9dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFByb2ZpbGluZ1NlcnZpY2UucHJvdG90eXBlLmdldEludGVnZXIgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgcmV0dXJuIFByb2ZpbGluZ1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBQcm9maWxpbmdTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xudmFyIFJhZ2RvbGxTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhSYWdkb2xsU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSYWdkb2xsU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgLy8gVE9ETzogdGhpbmsgYWJvdXQgdHJhY2tpbmcgcmFnZG9sbCBzdGF0ZSBvZiBwbGF5ZXJcbiAgICAgICAgX3RoaXMuc2FmZVJlbW92ZVJhZ2RvbGxGcm9tV29ybGQgPSBmdW5jdGlvbiAoYWN0b3IsIGFmdGVyUmVtb3ZlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIF90aGlzLnNldExvY2FsRGFtYWdlTXVsdCgwKTtcbiAgICAgICAgICAgIGFjdG9yLmZvcmNlUmVtb3ZlUmFnZG9sbEZyb21Xb3JsZCgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldExvY2FsRGFtYWdlTXVsdChfdGhpcy5kZWZhdWx0TG9jYWxEYW1hZ2VNdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgYWZ0ZXJSZW1vdmVDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmRlZmF1bHRMb2NhbERhbWFnZU11bHQgPSAxO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSYWdkb2xsU2VydmljZS5wcm90b3R5cGUub25jZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRMb2NhbERhbWFnZU11bHQodGhpcy5kZWZhdWx0TG9jYWxEYW1hZ2VNdWx0KTtcbiAgICB9O1xuICAgIFJhZ2RvbGxTZXJ2aWNlLnByb3RvdHlwZS5zZXRMb2NhbERhbWFnZU11bHQgPSBmdW5jdGlvbiAoZGFtYWdlTXVsdCkge1xuICAgICAgICB0aGlzLnNwLkdhbWUuc2V0R2FtZVNldHRpbmdGbG9hdChcImZEaWZmTXVsdEhQVG9QQ0VcIiwgZGFtYWdlTXVsdCk7XG4gICAgICAgIHRoaXMuc3AuR2FtZS5zZXRHYW1lU2V0dGluZ0Zsb2F0KFwiZkRpZmZNdWx0SFBUb1BDSFwiLCBkYW1hZ2VNdWx0KTtcbiAgICAgICAgdGhpcy5zcC5HYW1lLnNldEdhbWVTZXR0aW5nRmxvYXQoXCJmRGlmZk11bHRIUFRvUENMXCIsIGRhbWFnZU11bHQpO1xuICAgICAgICB0aGlzLnNwLkdhbWUuc2V0R2FtZVNldHRpbmdGbG9hdChcImZEaWZmTXVsdEhQVG9QQ05cIiwgZGFtYWdlTXVsdCk7XG4gICAgICAgIHRoaXMuc3AuR2FtZS5zZXRHYW1lU2V0dGluZ0Zsb2F0KFwiZkRpZmZNdWx0SFBUb1BDVkVcIiwgZGFtYWdlTXVsdCk7XG4gICAgICAgIHRoaXMuc3AuR2FtZS5zZXRHYW1lU2V0dGluZ0Zsb2F0KFwiZkRpZmZNdWx0SFBUb1BDVkhcIiwgZGFtYWdlTXVsdCk7XG4gICAgfTtcbiAgICByZXR1cm4gUmFnZG9sbFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBSYWdkb2xsU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbi8vIEB0cy1leHBlY3QtZXJyb3IgKFRPRE86IFJlbW92ZSBpbiAyLjEwLjApXG5pbXBvcnQgeyBBY3RvciwgaW50ZXJydXB0Q2FzdCwgY2FzdFNwZWxsSW1tZWRpYXRlLCBhcHBseUFuaW1hdGlvblZhcmlhYmxlc1RvQWN0b3IgfSBmcm9tICdza3lyaW1QbGF0Zm9ybSc7XG5pbXBvcnQgeyBBcm1vciwgQ2VsbCwgR2FtZSwgT2JqZWN0UmVmZXJlbmNlLCBURVNNb2RQbGF0Zm9ybSwgVWksIFV0aWxpdHksIFdvcmxkU3BhY2UsIG9uLCAvLyBUT0RPOiB1c2UgdGhpcy5jb250cm9sbGVyLm9uIGluc3RlYWRcbm9uY2UsIC8vIFRPRE86IHVzZSB0aGlzLmNvbnRyb2xsZXIub25jZSBpbnN0ZWFkXG5zdG9yYWdlLCAvLyBUT0RPOiB1c2UgdGhpcy5zcC5zdG9yYWdlIGluc3RlYWRcbiB9IGZyb20gJ3NreXJpbVBsYXRmb3JtJztcbmltcG9ydCAqIGFzIG1lc3NhZ2VzIGZyb20gJy4uLy4uL21lc3NhZ2VzJztcbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvbiAqL1xuaW1wb3J0IHsgT2JqZWN0UmVmZXJlbmNlRXggfSBmcm9tICcuLi8uLi9leHRlbnNpb25zL29iamVjdFJlZmVyZW5jZUV4JztcbmltcG9ydCB7IElkTWFuYWdlciB9IGZyb20gJy4uLy4uL2xpYi9pZE1hbmFnZXInO1xuaW1wb3J0IHsgbmFtZW9mIH0gZnJvbSAnLi4vLi4vbGliL25hbWVvZic7XG5pbXBvcnQgeyBzZXRBY3RvclZhbHVlUGVyY2VudGFnZSB9IGZyb20gJy4uLy4uL3N5bmMvYWN0b3J2YWx1ZXMnO1xuaW1wb3J0IHsgYXBwbHlBcHBlYXJhbmNlVG9QbGF5ZXIgfSBmcm9tICcuLi8uLi9zeW5jL2FwcGVhcmFuY2UnO1xuaW1wb3J0IHsgYXBwbHlFcXVpcG1lbnQsIGlzQmFkTWVudVNob3duIH0gZnJvbSAnLi4vLi4vc3luYy9lcXVpcG1lbnQnO1xuaW1wb3J0IHsgYXBwbHlJbnZlbnRvcnkgfSBmcm9tICcuLi8uLi9zeW5jL2ludmVudG9yeSc7XG5pbXBvcnQgeyBsZWFyblNwZWxscywgcmVtb3ZlQWxsU3BlbGxzIH0gZnJvbSAnLi4vLi4vc3luYy9zcGVsbCc7XG5pbXBvcnQgeyBNb2RlbEFwcGx5VXRpbHMgfSBmcm9tICcuLi8uLi92aWV3L21vZGVsQXBwbHlVdGlscyc7XG5pbXBvcnQgeyBMb2FkR2FtZVNlcnZpY2UgfSBmcm9tICcuL2xvYWRHYW1lU2VydmljZSc7XG5pbXBvcnQgeyBSYWdkb2xsU2VydmljZSB9IGZyb20gJy4vcmFnZG9sbFNlcnZpY2UnO1xuaW1wb3J0IHsgUmVzcGF3bk5lZWRlZEVycm9yIH0gZnJvbSAnLi4vLi4vbGliL2Vycm9ycyc7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gJy4vY2xpZW50TGlzdGVuZXInO1xuLy8gVE9ETzogcmVmYWN0b3Igd29ybGRWaWV3TWlzYyBpbnRvIHNlcnZpY2VcbmltcG9ydCB7IGdldE9iamVjdFJlZmVyZW5jZSwgZ2V0Vmlld0Zyb21TdG9yYWdlLCByZW1vdGVJZFRvTG9jYWxJZCwgfSBmcm9tICcuLi8uLi92aWV3L3dvcmxkVmlld01pc2MnO1xuaW1wb3J0IHsgVGltZVNlcnZpY2UgfSBmcm9tICcuL3RpbWVTZXJ2aWNlJztcbmltcG9ydCB7IGxvZ1RyYWNlLCBsb2dFcnJvciB9IGZyb20gJy4uLy4uL2xvZ2dpbmcnO1xuaW1wb3J0IHsgTXNnVHlwZSB9IGZyb20gJy4uLy4uL21lc3NhZ2VzJztcbmV4cG9ydCB2YXIgZ2V0UGNJbnZlbnRvcnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHJlcyA9IHN0b3JhZ2VbJ3BjSW52J107XG4gICAgaWYgKHR5cGVvZiByZXMgPT09ICdvYmplY3QnICYmIHJlc1snZW50cmllcyddKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG59O1xudmFyIHNldFBjSW52ZW50b3J5ID0gZnVuY3Rpb24gKGludikge1xuICAgIHN0b3JhZ2VbJ3BjSW52J10gPSBpbnY7XG59O1xudmFyIHBjSW52TGFzdEFwcGx5ID0gMDtcbm9uKCd1cGRhdGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGlzQmFkTWVudVNob3duKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoRGF0ZS5ub3coKSAtIHBjSW52TGFzdEFwcGx5ID4gNTAwMCkge1xuICAgICAgICBwY0ludkxhc3RBcHBseSA9IERhdGUubm93KCk7XG4gICAgICAgIHZhciBwY0ludiA9IGdldFBjSW52ZW50b3J5KCk7XG4gICAgICAgIGlmIChwY0ludikge1xuICAgICAgICAgICAgYXBwbHlJbnZlbnRvcnkoR2FtZS5nZXRQbGF5ZXIoKSwgcGNJbnYsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xudmFyIHVuZXF1aXBJcm9uSGVsbWV0ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBpcm9uSGVsbWVudCA9IEFybW9yLmZyb20oR2FtZS5nZXRGb3JtRXgoMHgwMDAxMmU0ZCkpO1xuICAgIHZhciBwbCA9IEdhbWUuZ2V0UGxheWVyKCk7XG4gICAgaWYgKHBsKSB7XG4gICAgICAgIHBsLnVuZXF1aXBJdGVtKGlyb25IZWxtZW50LCBmYWxzZSwgdHJ1ZSk7XG4gICAgfVxufTtcbnZhciBSZW1vdGVTZXJ2ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFJlbW90ZVNlcnZlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSZW1vdGVTZXJ2ZXIoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLm51bVNldEludmVudG9yeSA9IDA7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImhvc3RTdGFydE1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uSG9zdFN0YXJ0TWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImhvc3RTdG9wTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25Ib3N0U3RvcE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJzZXRJbnZlbnRvcnlNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblNldEludmVudG9yeU1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJvcGVuQ29udGFpbmVyTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25PcGVuQ29udGFpbmVyTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInVwZGF0ZU1vdmVtZW50TWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25VcGRhdGVNb3ZlbWVudE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ1cGRhdGVBbmltYXRpb25NZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblVwZGF0ZUFuaW1hdGlvbk1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ1cGRhdGVFcXVpcG1lbnRNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblVwZGF0ZUVxdWlwbWVudE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJjaGFuZ2VWYWx1ZXNNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkNoYW5nZVZhbHVlc01lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ1cGRhdGVBcHBlYXJhbmNlTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25VcGRhdGVBcHBlYXJhbmNlTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInRlbGVwb3J0TWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25UZWxlcG9ydE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ0ZWxlcG9ydE1lc3NhZ2UyXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblRlbGVwb3J0TWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImNyZWF0ZUFjdG9yTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25DcmVhdGVBY3Rvck1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJkZXN0cm95QWN0b3JNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkRlc3Ryb3lBY3Rvck1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJzZXRSYWNlTWVudU9wZW5NZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblNldFJhY2VNZW51T3Blbk1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ1cGRhdGVQcm9wZXJ0eU1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uVXBkYXRlUHJvcGVydHlNZXNzYWdlKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwiZGVhdGhTdGF0ZUNvbnRhaW5lck1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uRGVhdGhTdGF0ZUNvbnRhaW5lck1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJjb25uZWN0aW9uQWNjZXB0ZWRcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuaGFuZGxlQ29ubmVjdGlvbkFjY2VwdGVkKCk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJzcGVsbENhc3RNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblNwZWxsQ2FzdE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJ1cGRhdGVBbmltVmFyaWFibGVzTWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25VcGRhdGVBbmltVmFyaWFibGVzTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vbkhvc3RTdGFydE1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIHZhciB0YXJnZXQgPSBtc2cudGFyZ2V0O1xuICAgICAgICB2YXIgaG9zdGVkID0gc3RvcmFnZVsnaG9zdGVkJ107XG4gICAgICAgIGlmICh0eXBlb2YgaG9zdGVkICE9PSB0eXBlb2YgW10pIHtcbiAgICAgICAgICAgIC8vIGlmIHlvdSB0cnkgdG8gc3dpdGNoIHRvIFNldCBwbGVhc2UgY2hlY2tvdXQgLmNvbmNhdCB1c2FnZS5cbiAgICAgICAgICAgIC8vIGNvbmNhdCBjb21waWxlcyBidXQgZG9lc24ndCB3b3JrIGFzIGV4cGVjdGVkXG4gICAgICAgICAgICBob3N0ZWQgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIHN0b3JhZ2VbJ2hvc3RlZCddID0gaG9zdGVkO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaG9zdGVkLmluY2x1ZGVzKHRhcmdldCkpIHtcbiAgICAgICAgICAgIGhvc3RlZC5wdXNoKHRhcmdldCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJlbW90ZVNlcnZlci5wcm90b3R5cGUub25Ib3N0U3RvcE1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIHZhciB0YXJnZXQgPSBtc2cudGFyZ2V0O1xuICAgICAgICBsb2dUcmFjZSh0aGlzLCAnaG9zdFN0b3AgJyArIHRhcmdldC50b1N0cmluZygxNikpO1xuICAgICAgICB2YXIgaG9zdGVkID0gc3RvcmFnZVsnaG9zdGVkJ107XG4gICAgICAgIGlmICh0eXBlb2YgaG9zdGVkID09PSB0eXBlb2YgW10pIHtcbiAgICAgICAgICAgIHN0b3JhZ2VbJ2hvc3RlZCddID0gaG9zdGVkLmZpbHRlcihmdW5jdGlvbiAoeCkgeyByZXR1cm4geCAhPT0gdGFyZ2V0OyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vblNldEludmVudG9yeU1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5udW1TZXRJbnZlbnRvcnkrKztcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNldFBjSW52ZW50b3J5KG1zZy5pbnZlbnRvcnkpO1xuICAgICAgICAgICAgdmFyIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KCdxdWVyeUJsb2NrU2V0SW52ZW50b3J5RXZlbnQnLCB7XG4gICAgICAgICAgICAgICAgYmxvY2s6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGJsb2NrZWQgPSB0cnVlOyB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghYmxvY2tlZCkge1xuICAgICAgICAgICAgICAgIHBjSW52TGFzdEFwcGx5ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uT3BlbkNvbnRhaW5lck1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgb25jZSgndXBkYXRlJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX19hd2FpdGVyKF90aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHJlbW90ZUlkLCBsb2NhbElkLCByZWZyLCBiYXNlT2JqZWN0LCBiYXNlVHlwZSwgZnVuY3Rpb25DaGVja2VyLCBmYWN0TmFtZSwgZGVsYXlTZWNvbmRzO1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIFs0IC8qeWllbGQqLywgVXRpbGl0eS53YWl0KDAuMSldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5zZW50KCk7IC8vIEdpdmUgYSBjaGFuY2UgdG8gdXBkYXRlIGludmVudG9yeVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlSWQgPSBldmVudC5tZXNzYWdlLnRhcmdldDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsSWQgPSByZW1vdGVJZFRvTG9jYWxJZChyZW1vdGVJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgobG9jYWxJZCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZnIgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcih0aGlzLCAnb25PcGVuQ29udGFpbmVyTWVzc2FnZSAtIHJlZnIgbm90IGZvdW5kJywgJ3JlbW90ZUlkJywgcmVtb3RlSWQudG9TdHJpbmcoMTYpLCAnbG9jYWxJZCcsIGxvY2FsSWQudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qL107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyLmFjdGl2YXRlKEdhbWUuZ2V0UGxheWVyKCksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmFzZU9iamVjdCA9IHJlZnIuZ2V0QmFzZU9iamVjdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBiYXNlT2JqZWN0ID09PSBudWxsIHx8IGJhc2VPYmplY3QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGJhc2VPYmplY3QuZ2V0VHlwZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb25DaGVja2VyID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhY3ROYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5U2Vjb25kcyA9IC0xLjA7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZVR5cGUgPT09IDI4IC8qIEZvcm1UeXBlLkNvbnRhaW5lciAqLykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uQ2hlY2tlciA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFVpLmlzTWVudU9wZW4oXCJDb250YWluZXJNZW51XCIpOyB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY3ROYW1lID0gXCInQ29udGFpbmVyTWVudSBvcGVuJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5U2Vjb25kcyA9IDAuMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJhc2VUeXBlID09PSA0MCAvKiBGb3JtVHlwZS5GdXJuaXR1cmUgKi8pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbkNoZWNrZXIgPSBmdW5jdGlvbiAoKSB7IHZhciBfYTsgcmV0dXJuICEhKChfYSA9IEdhbWUuZ2V0UGxheWVyKCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRGdXJuaXR1cmVSZWZlcmVuY2UoKSk7IH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjdE5hbWUgPSBcIidnZXRGdXJuaXR1cmVSZWZlcmVuY2Ugbm90IG51bGwnXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXlTZWNvbmRzID0gMS4wO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZ1bmN0aW9uQ2hlY2tlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwib25PcGVuQ29udGFpbmVyTWVzYWdlIC0gbm90IGEgY29udGFpbmVyIG9yIGZ1cm5pdHVyZVwiLCBiYXNlVHlwZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi9dO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW4gU2t5TVAgY29udGFpbmVycyBoYXZlIDItbmQsIGNsb3NpbmcgYWN0aXZhdGlvbiB1bmRlciB0aGUgaG9vZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgZGlmZmVycyBmcm9tIFNreXJpbSdzIGJlaGF2aW9yLCB3aGVyZSBpdCdzIGp1c3Qgb25lIGFjdGl2YXRpb24uXG4gICAgICAgICAgICAgICAgICAgICAgICAoZnVuY3Rpb24gKCkgeyByZXR1cm4gX19hd2FpdGVyKF90aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJvbk9wZW5Db250YWluZXJNZXNhZ2UgLSB3YWl0aW5nIGZvclwiLCBmYWN0TmFtZSwgXCJ0byBiZSB0cnVlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmdW5jdGlvbkNoZWNrZXIoKSkgcmV0dXJuIFszIC8qYnJlYWsqLywgM107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0IC8qeWllbGQqLywgVXRpbGl0eS53YWl0KDAuMSldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzMgLypicmVhayovLCAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIm9uT3BlbkNvbnRhaW5lck1lc2FnZSAtIHdhaXRpbmcgZm9yXCIsIGZhY3ROYW1lLCBcInRvIGJlIGZhbHNlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gNDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWZ1bmN0aW9uQ2hlY2tlcigpKSByZXR1cm4gWzMgLypicmVhayovLCA2XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBVdGlsaXR5LndhaXQoMC4xKV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMyAvKmJyZWFrKi8sIDRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwib25PcGVuQ29udGFpbmVyTWVzYWdlIC0gbWVudSBjbG9zZWRcIiwgZmFjdE5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQ6IG1lc3NhZ2VzLk1zZ1R5cGUuQWN0aXZhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc3RlcjogMHgxNCwgdGFyZ2V0OiBldmVudC5tZXNzYWdlLnRhcmdldCwgaXNTZWNvbmRBY3RpdmF0aW9uOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwib25PcGVuQ29udGFpbmVyTWVzYWdlIC0gd2FpdGluZ1wiLCBkZWxheVNlY29uZHMsIFwic2Vjb25kcyBiZWZvcmUgc2VuZGluZyBBY3RpdmF0ZU1lc3NhZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVXRpbGl0eS53YWl0TWVudU1vZGUoZGVsYXlTZWNvbmRzKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwib25PcGVuQ29udGFpbmVyTWVzYWdlIC0gc2VudCBBY3RpdmF0ZU1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi9dO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTsgfSkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiAvKnJldHVybiovXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7IH0pO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vblRlbGVwb3J0TWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbXNnID0gZXZlbnQubWVzc2FnZTtcbiAgICAgICAgb25jZSgndXBkYXRlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGlkID0gKFwiaWR4XCIgaW4gbXNnICYmIHR5cGVvZiBtc2cuaWR4ID09PSBcIm51bWJlclwiKSA/IF90aGlzLmdldElkTWFuYWdlcigpLmdldElkKG1zZy5pZHgpIDogX3RoaXMuZ2V0TXlBY3RvckluZGV4KCk7XG4gICAgICAgICAgICB2YXIgcmVmciA9IGlkID09PSBfdGhpcy5nZXRNeUFjdG9ySW5kZXgoKSA/IEdhbWUuZ2V0UGxheWVyKCkgOiBnZXRPYmplY3RSZWZlcmVuY2UoaWQpO1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiVGVsZXBvcnRpbmcgaWRcIiwgaWQsIFwicmVmcklkXCIsIHJlZnIgPT09IG51bGwgfHwgcmVmciA9PT0gdm9pZCAwID8gdm9pZCAwIDogcmVmci5nZXRGb3JtSUQoKS50b1N0cmluZygxNiksIFwiLi4uXCIsIG1zZy5wb3MsICdjZWxsL3dvcmxkIGlzJywgbXNnLndvcmxkT3JDZWxsLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICB2YXIgcmFnZG9sbFNlcnZpY2UgPSBfdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKFJhZ2RvbGxTZXJ2aWNlKTtcbiAgICAgICAgICAgIHZhciByZWZySWQgPSByZWZyID09PSBudWxsIHx8IHJlZnIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHJlZnIuZ2V0Rm9ybUlEKCk7XG4gICAgICAgICAgICB2YXIgcmVtb3ZlUmFnZG9sbENhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIFRFU01vZFBsYXRmb3JtLm1vdmVSZWZyVG9Qb3NpdGlvbihPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm1FeChyZWZySWQgfHwgMCkpLCBDZWxsLmZyb20oR2FtZS5nZXRGb3JtRXgobXNnLndvcmxkT3JDZWxsKSksIFdvcmxkU3BhY2UuZnJvbShHYW1lLmdldEZvcm1FeChtc2cud29ybGRPckNlbGwpKSwgbXNnLnBvc1swXSwgbXNnLnBvc1sxXSwgbXNnLnBvc1syXSwgbXNnLnJvdFswXSwgbXNnLnJvdFsxXSwgbXNnLnJvdFsyXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGFjdG9yID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICAgICAgICAgIGlmIChhY3RvciAvKiYmIGFjdG9yLmdldEZvcm1JRCgpID09PSAweDE0Ki8pIHtcbiAgICAgICAgICAgICAgICByYWdkb2xsU2VydmljZS5zYWZlUmVtb3ZlUmFnZG9sbEZyb21Xb3JsZChhY3RvciwgcmVtb3ZlUmFnZG9sbENhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlbW92ZVJhZ2RvbGxDYWxsYmFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFJlbW90ZVNlcnZlci5wcm90b3R5cGUub25DcmVhdGVBY3Rvck1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgbXNnID0gZXZlbnQubWVzc2FnZTtcbiAgICAgICAgaWYgKHRoaXMuc2tpcEZvcm1WaWV3Q3JlYXRpb24obXNnKSkge1xuICAgICAgICAgICAgdmFyIHJlZnJJZF8xID0gbXNnLnJlZnJJZDtcbiAgICAgICAgICAgIHRoaXMub25jZUxvYWQocmVmcklkXzEsIGZ1bmN0aW9uIChyZWZyKSB7XG4gICAgICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgICAgIGlmIChyZWZyKSB7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdFJlZmVyZW5jZUV4LmRlYWxXaXRoUmVmKHJlZnIsIHJlZnIuZ2V0QmFzZU9iamVjdCgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1zZy5wcm9wcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1zZy5wcm9wcy5pbnZlbnRvcnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBNb2RlbEFwcGx5VXRpbHMuYXBwbHlNb2RlbEludmVudG9yeShyZWZyLCBtc2cucHJvcHMuaW52ZW50b3J5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsSXNPcGVuKHJlZnIsICEhbXNnLnByb3BzWydpc09wZW4nXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBNb2RlbEFwcGx5VXRpbHMuYXBwbHlNb2RlbElzSGFydmVzdGVkKHJlZnIsICEhbXNnLnByb3BzWydpc0hhcnZlc3RlZCddKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsTm9kZVNjYWxlKHJlZnIsIG1zZy5wcm9wcy5zZXROb2RlU2NhbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxOb2RlVGV4dHVyZVNldChyZWZyLCBtc2cucHJvcHMuc2V0Tm9kZVRleHR1cmVTZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJc0Rpc2FibGVkKHJlZnIsICEhbXNnLnByb3BzWydkaXNhYmxlZCddKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gYSBzZXBhcmF0ZSBtb2R1bGVcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbmltYXRpb25fMSA9IG1zZy5wcm9wcy5sYXN0QW5pbWF0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhbmltYXRpb25fMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWZyaWRfMSA9IHJlZnIuZ2V0Rm9ybUlEKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF9fYXdhaXRlcihfdGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlfMSwgcmVzMjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9iKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKF9iLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpXzEgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfYi5sYWJlbCA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShpXzEgPCA1KSkgcmV0dXJuIFszIC8qYnJlYWsqLywgNF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlczIgPSAoX2EgPSBPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm1FeChyZWZyaWRfMSkpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EucGxheUFuaW1hdGlvbihhbmltYXRpb25fMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXMyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzMgLypicmVhayovLCA0XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBVdGlsaXR5LndhaXQoMildO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2Iuc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfYi5sYWJlbCA9IDM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpXzErKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFszIC8qYnJlYWsqLywgMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA0OiByZXR1cm4gWzIgLypyZXR1cm4qL107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOyB9KSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3BsYXlOYW1lID0gbXNnLnByb3BzLmRpc3BsYXlOYW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBpbiBzeW5jIHdpdGggc3BTbmlwcGV0U2VydmljZS50c1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkaXNwbGF5TmFtZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXBsYWNlVmFsdWUgPSAoX2EgPSByZWZyLmdldEJhc2VPYmplY3QoKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldE5hbWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwbGFjZVZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheU5hbWUgPSBkaXNwbGF5TmFtZS5yZXBsYWNlKC8lb3JpZ2luYWxfbmFtZSUvZywgcmVwbGFjZVZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKF90aGlzLCBcIkNvdWxkbid0IGdldCBhIHJlcGxhY2VWYWx1ZSBmb3IgU2V0RGlzcGxheU5hbWUsIHJlZnIuZ2V0Rm9ybUlEKCkgd2FzXCIsIHJlZnIuZ2V0Rm9ybUlEKCkudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmci5zZXREaXNwbGF5TmFtZShkaXNwbGF5TmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiY2FsbGluZyBzZXREaXNwbGF5TmFtZVwiLCBkaXNwbGF5TmFtZSwgXCJmb3JcIiwgcmVmci5nZXRGb3JtSUQoKS50b1N0cmluZygxNikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcihfdGhpcywgJ0ZhaWxlZCB0byBhcHBseSBtb2RlbCB0bycsIHJlZnJJZF8xLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJDcmVhdGUgYWN0b3JcIik7XG4gICAgICAgIHZhciBpID0gdGhpcy5nZXRJZE1hbmFnZXIoKS5hbGxvY2F0ZUlkRm9yKG1zZy5pZHgpO1xuICAgICAgICBpZiAodGhpcy53b3JsZE1vZGVsLmZvcm1zLmxlbmd0aCA8PSBpKSB7XG4gICAgICAgICAgICB0aGlzLndvcmxkTW9kZWwuZm9ybXMubGVuZ3RoID0gaSArIDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1vdmVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAvLyBUT0RPOiBiZXR0ZXIgY2hlY2sgaWYgaXQgaXMgYW4gbnBjIChub3QgYW4gb2JqZWN0IHJlZmVyZW5jZSlcbiAgICAgICAgaWYgKG1zZy5yZWZySWQgIT09IHVuZGVmaW5lZCAmJiBtc2cucmVmcklkID49IDB4ZmYwMDAwMDApIHtcbiAgICAgICAgICAgIG1vdmVtZW50ID0ge1xuICAgICAgICAgICAgICAgIHBvczogbXNnLnRyYW5zZm9ybS5wb3MsXG4gICAgICAgICAgICAgICAgcm90OiBtc2cudHJhbnNmb3JtLnJvdCxcbiAgICAgICAgICAgICAgICB3b3JsZE9yQ2VsbDogbXNnLnRyYW5zZm9ybS53b3JsZE9yQ2VsbCxcbiAgICAgICAgICAgICAgICBydW5Nb2RlOiAnU3RhbmRpbmcnLFxuICAgICAgICAgICAgICAgIGRpcmVjdGlvbjogMCxcbiAgICAgICAgICAgICAgICBpc0luSnVtcFN0YXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc1NuZWFraW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc0Jsb2NraW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc1dlYXBEcmF3bjogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNEZWFkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBoZWFsdGhQZXJjZW50YWdlOiAxLjAsXG4gICAgICAgICAgICAgICAgc3BlZWQ6IDAsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBmb3JtID0ge1xuICAgICAgICAgICAgaWR4OiBtc2cuaWR4LFxuICAgICAgICAgICAgbW92ZW1lbnQ6IG1vdmVtZW50LFxuICAgICAgICAgICAgbnVtTW92ZW1lbnRDaGFuZ2VzOiAwLFxuICAgICAgICAgICAgbnVtQXBwZWFyYW5jZUNoYW5nZXM6IDAsXG4gICAgICAgICAgICBiYXNlSWQ6IG1zZy5iYXNlSWQsXG4gICAgICAgICAgICByZWZySWQ6IG1zZy5yZWZySWQsXG4gICAgICAgICAgICBpc015Q2xvbmU6IG1zZy5pc01lLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLndvcmxkTW9kZWwuZm9ybXNbaV0gPSBmb3JtO1xuICAgICAgICBpZiAobXNnLmFwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgIGZvcm0uYXBwZWFyYW5jZSA9IG1zZy5hcHBlYXJhbmNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtc2cuZXF1aXBtZW50KSB7XG4gICAgICAgICAgICBmb3JtLmVxdWlwbWVudCA9IG1zZy5lcXVpcG1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zZy5pc0RlYWQpIHtcbiAgICAgICAgICAgIGZvcm0uaXNEZWFkID0gbXNnLmlzRGVhZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobXNnLmFuaW1hdGlvbikge1xuICAgICAgICAgICAgZm9ybS5hbmltYXRpb24gPSBtc2cuYW5pbWF0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtc2cucHJvcHMpIHtcbiAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIG1zZy5wcm9wcykge1xuICAgICAgICAgICAgICAgIGZvcm1bcHJvcE5hbWVdID0gbXNnLnByb3BzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtc2cuY3VzdG9tUHJvcHNKc29uRHVtcHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgdmFyIHBhcnNlZDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcGFyc2VkID0gSlNPTi5wYXJzZShlbGVtZW50LnByb3BWYWx1ZUpzb25EdW1wKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTeW50YXhFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcihfdGhpcywgXCJjcmVhdGVBY3RvclwiLCAoX2EgPSBtc2cucmVmcklkKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudG9TdHJpbmcoMTYpLCBcImZhaWxlZCB0byBwYXJzZSBjdXN0b20gcHJvcFwiLCBlbGVtZW50LnByb3BOYW1lLCBlbGVtZW50LnByb3BWYWx1ZUpzb25EdW1wLCBlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3JtW2VsZW1lbnQucHJvcE5hbWVdID0gcGFyc2VkO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG1zZy5pc01lKSB7XG4gICAgICAgICAgICB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeCA9IGk7XG4gICAgICAgICAgICB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyUmVmcklkID0gbXNnLnJlZnJJZCB8fCAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IG1vdmUgdG8gYSBzZXBhcmF0ZSBtb2R1bGVcbiAgICAgICAgaWYgKG1zZy5wcm9wcyAmJiAhbXNnLnByb3BzLmlzSG9zdGVkQnlPdGhlcikge1xuICAgICAgICB9XG4gICAgICAgIGlmIChtc2cucHJvcHMgJiYgbXNnLnByb3BzLmlzUmFjZU1lbnVPcGVuICYmIG1zZy5pc01lKSB7XG4gICAgICAgICAgICB0aGlzLm9uU2V0UmFjZU1lbnVPcGVuTWVzc2FnZSh7IG1lc3NhZ2U6IHsgdDogTXNnVHlwZS5TZXRSYWNlTWVudU9wZW4sIG9wZW46IHRydWUgfSB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbnVtU2V0SW52ZW50b3J5ID0gdGhpcy5udW1TZXRJbnZlbnRvcnk7XG4gICAgICAgIHZhciBhcHBseVBjSW52ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKG1zZy5lcXVpcG1lbnQpIHtcbiAgICAgICAgICAgICAgICBhcHBseUVxdWlwbWVudChHYW1lLmdldFBsYXllcigpLCBtc2cuZXF1aXBtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChudW1TZXRJbnZlbnRvcnkgIT09IF90aGlzLm51bVNldEludmVudG9yeSkge1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCAnU2tpcHBpbmcgaW52ZW50b3J5IGFwcGx5IGR1ZSB0byBuZXdlciBzZXRJbnZlbnRvcnkgbWVzc2FnZScpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtc2cucHJvcHMgJiYgbXNnLnByb3BzLmludmVudG9yeSkge1xuICAgICAgICAgICAgICAgIF90aGlzLm9uU2V0SW52ZW50b3J5TWVzc2FnZSh7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuU2V0SW52ZW50b3J5LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW52ZW50b3J5OiBtc2cucHJvcHMuaW52ZW50b3J5XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKG1zZy5pc01lICYmIG1zZy5wcm9wcyAmJiBtc2cucHJvcHMubGVhcm5lZFNwZWxscykge1xuICAgICAgICAgICAgdmFyIGxlYXJuZWRTcGVsbHNfMSA9IG1zZy5wcm9wcy5sZWFybmVkU3BlbGxzO1xuICAgICAgICAgICAgb25jZSgndXBkYXRlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIFV0aWxpdHkud2FpdCgxKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBsYXllciA9IEdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwbGF5ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZUFsbFNwZWxscyhwbGF5ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVhcm5TcGVsbHMocGxheWVyLCBsZWFybmVkU3BlbGxzXzEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwicGxheWVyIGxlYXJuZWRTcGVsbHM6XCIsIEpTT04uc3RyaW5naWZ5KGxlYXJuZWRTcGVsbHNfMSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobXNnLmlzTWUpIHtcbiAgICAgICAgICAgIGlmICgoX2EgPSBtc2cucHJvcHMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pc0RlYWQpIHtcbiAgICAgICAgICAgICAgICBvbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJhcHBseURlYXRoU3RhdGVFdmVudFwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3RvcjogR2FtZS5nZXRQbGF5ZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzRGVhZDogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobXNnLmlzTWUpIHtcbiAgICAgICAgICAgIHZhciBzcGF3blRhc2tfMSA9IHsgcnVubmluZzogZmFsc2UgfTtcbiAgICAgICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyBVc2UgTW92ZVJlZnJUb1Bvc2l0aW9uIHRvIHNwYXduIGlmIHBvc3NpYmxlIChub3QgaW4gbWFpbiBtZW51KVxuICAgICAgICAgICAgICAgIC8vIEluIGNhc2Ugb2YgY29ubmVjdGlvbiBsb3N0IHRoaXMgaXMgZXNzZW50aWFsXG4gICAgICAgICAgICAgICAgaWYgKCFzcGF3blRhc2tfMS5ydW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwYXduVGFza18xLnJ1bm5pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgJ1VzaW5nIG1vdmVSZWZyVG9Qb3NpdGlvbiB0byBzcGF3biBwbGF5ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF9fYXdhaXRlcihfdGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwbCwgcG9zLCBzcXIsIGRpc3RhbmNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0cnVlKSByZXR1cm4gWzMgLypicmVhayovLCAyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsICdTcGF3bmluZy4uLicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVEVTTW9kUGxhdGZvcm0ubW92ZVJlZnJUb1Bvc2l0aW9uKEdhbWUuZ2V0UGxheWVyKCksIENlbGwuZnJvbShHYW1lLmdldEZvcm1FeChtc2cudHJhbnNmb3JtLndvcmxkT3JDZWxsKSksIFdvcmxkU3BhY2UuZnJvbShHYW1lLmdldEZvcm1FeChtc2cudHJhbnNmb3JtLndvcmxkT3JDZWxsKSksIG1zZy50cmFuc2Zvcm0ucG9zWzBdLCBtc2cudHJhbnNmb3JtLnBvc1sxXSwgbXNnLnRyYW5zZm9ybS5wb3NbMl0sIG1zZy50cmFuc2Zvcm0ucm90WzBdLCBtc2cudHJhbnNmb3JtLnJvdFsxXSwgbXNnLnRyYW5zZm9ybS5yb3RbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0IC8qeWllbGQqLywgVXRpbGl0eS53YWl0KDEpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGwgPSBHYW1lLmdldFBsYXllcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFwbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMyAvKmJyZWFrKi8sIDJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsLmdldFBvc2l0aW9uWCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsLmdldFBvc2l0aW9uWSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsLmdldFBvc2l0aW9uWigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNxciA9IGZ1bmN0aW9uICh4KSB7IHJldHVybiB4ICogeDsgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlID0gTWF0aC5zcXJ0KHNxcihwb3NbMF0gLSBtc2cudHJhbnNmb3JtLnBvc1swXSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNxcihwb3NbMV0gLSBtc2cudHJhbnNmb3JtLnBvc1sxXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpc3RhbmNlIDwgMjU2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFszIC8qYnJlYWsqLywgMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzMgLypicmVhayovLCAwXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOiByZXR1cm4gWzIgLypyZXR1cm4qL107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pOyB9KSgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBVbmZvcnR1bmF0ZWxseSBpdCByZXF1aXJlcyB0d28gY2FsbHMgdG8gd29ya1xuICAgICAgICAgICAgICAgICAgICBVdGlsaXR5LndhaXQoMSkudGhlbihhcHBseVBjSW52KTtcbiAgICAgICAgICAgICAgICAgICAgVXRpbGl0eS53YWl0KDEuMykudGhlbihhcHBseVBjSW52KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gTm90ZTogYXBwZWFyYW5jZSBwYXJ0IHdhcyBjb3B5LXBhc3RlZFxuICAgICAgICAgICAgICAgICAgICBpZiAobXNnLmFwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5QXBwZWFyYW5jZVRvUGxheWVyKG1zZy5hcHBlYXJhbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobXNnLnByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBiYXNlQWN0b3JWYWx1ZXNfMSA9IG5ldyBNYXAoW1xuICAgICAgICAgICAgICAgICAgICAgICAgWydoZWFsUmF0ZScsIG1zZy5wcm9wcy5oZWFsUmF0ZV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbJ2hlYWxSYXRlTXVsdCcsIG1zZy5wcm9wcy5oZWFsUmF0ZU11bHRdLFxuICAgICAgICAgICAgICAgICAgICAgICAgWydoZWFsdGgnLCBtc2cucHJvcHMuaGVhbHRoXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnbWFnaWNrYVJhdGUnLCBtc2cucHJvcHMubWFnaWNrYVJhdGVdLFxuICAgICAgICAgICAgICAgICAgICAgICAgWydtYWdpY2thUmF0ZU11bHQnLCBtc2cucHJvcHMubWFnaWNrYVJhdGVNdWx0XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnbWFnaWNrYScsIG1zZy5wcm9wcy5tYWdpY2thXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnc3RhbWluYVJhdGUnLCBtc2cucHJvcHMuc3RhbWluYVJhdGVdLFxuICAgICAgICAgICAgICAgICAgICAgICAgWydzdGFtaW5hUmF0ZU11bHQnLCBtc2cucHJvcHMuc3RhbWluYVJhdGVNdWx0XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnc3RhbWluYScsIG1zZy5wcm9wcy5zdGFtaW5hXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnaGVhbHRoUGVyY2VudGFnZScsIG1zZy5wcm9wcy5oZWFsdGhQZXJjZW50YWdlXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnc3RhbWluYVBlcmNlbnRhZ2UnLCBtc2cucHJvcHMuc3RhbWluYVBlcmNlbnRhZ2VdLFxuICAgICAgICAgICAgICAgICAgICAgICAgWydtYWdpY2thUGVyY2VudGFnZScsIG1zZy5wcm9wcy5tYWdpY2thUGVyY2VudGFnZV0sXG4gICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGxheWVyXzEgPSBHYW1lLmdldFBsYXllcigpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGxheWVyXzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VBY3RvclZhbHVlc18xLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoa2V5LmluY2x1ZGVzKCdQZXJjZW50YWdlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzdWJLZXkgPSBrZXkucmVwbGFjZSgnUGVyY2VudGFnZScsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzdWJWYWx1ZSA9IGJhc2VBY3RvclZhbHVlc18xLmdldChzdWJLZXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzdWJWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRBY3RvclZhbHVlUGVyY2VudGFnZShwbGF5ZXJfMSwgc3ViS2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGF5ZXJfMS5zZXRBY3RvclZhbHVlKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG9uY2UoJ3RpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgb25jZSgndGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzcGF3blRhc2tfMS5ydW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcGF3blRhc2tfMS5ydW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsb2FkT3JkZXIgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGlfMiA9IDA7IGlfMiA8IF90aGlzLnNwLkdhbWUuZ2V0TW9kQ291bnQoKTsgKytpXzIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkT3JkZXIucHVzaChfdGhpcy5zcC5HYW1lLmdldE1vZE5hbWUoaV8yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJsb2FkaW5nIGdhbWUgaW4gd29ybGQvY2VsbFwiLCBtc2cudHJhbnNmb3JtLndvcmxkT3JDZWxsLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbG9hZEdhbWVTZXJ2aWNlID0gX3RoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihMb2FkR2FtZVNlcnZpY2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9hZEdhbWVTZXJ2aWNlLmxvYWRHYW1lKG1zZy50cmFuc2Zvcm0ucG9zLCBtc2cudHJhbnNmb3JtLnJvdCwgbXNnLnRyYW5zZm9ybS53b3JsZE9yQ2VsbCwgbXNnLmFwcGVhcmFuY2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbXNnLmFwcGVhcmFuY2UubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFjZUlkOiBtc2cuYXBwZWFyYW5jZS5yYWNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IEluIHR5cGVzLCBpc0ZlbWFsZSBpcyB1bmRlciBmYWNlLCBidXQgaW4gdGhlIHJlYWxpdHkgU1AgZXhwZWN0cyBpdCBoZXJlLiBGaXggcmVxdWlyZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNGZW1hbGU6IG1zZy5hcHBlYXJhbmNlLmlzRmVtYWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYWlyQ29sb3I6IG1zZy5hcHBlYXJhbmNlLmhhaXJDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvZHlTa2luQ29sb3I6IG1zZy5hcHBlYXJhbmNlLnNraW5Db2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRUZXh0dXJlU2V0SWQ6IG1zZy5hcHBlYXJhbmNlLmhlYWRUZXh0dXJlU2V0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkUGFydElkczogbXNnLmFwcGVhcmFuY2UuaGVhZHBhcnRJZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVzZXRzOiBtc2cuYXBwZWFyYW5jZS5wcmVzZXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkLCBsb2FkT3JkZXIsIHsgbWludXRlczogMCwgc2Vjb25kczogMCwgaG91cnM6IF90aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoVGltZVNlcnZpY2UpLmdldFRpbWUoKS5uZXdHYW1lSG91clZhbHVlIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgb25jZSgndXBkYXRlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UGNJbnYoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBVdGlsaXR5LndhaXQoMC4zKS50aGVuKGFwcGx5UGNJbnYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IGFwcGVhcmFuY2UgcGFydCB3YXMgY29weS1wYXN0ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobXNnLmFwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlBcHBlYXJhbmNlVG9QbGF5ZXIobXNnLmFwcGVhcmFuY2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vbkRlc3Ryb3lBY3Rvck1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgbXNnID0gZXZlbnQubWVzc2FnZTtcbiAgICAgICAgdmFyIGkgPSB0aGlzLmdldElkTWFuYWdlcigpLmdldElkKG1zZy5pZHgpO1xuICAgICAgICB0aGlzLndvcmxkTW9kZWwuZm9ybXNbaV0gPSB1bmRlZmluZWQ7XG4gICAgICAgIChfYSA9IGdldFZpZXdGcm9tU3RvcmFnZSgpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Euc3luY0Zvcm1BcnJheSh0aGlzLndvcmxkTW9kZWwpO1xuICAgICAgICAvLyBTaHJpbmsgdG8gZml0XG4gICAgICAgIHdoaWxlICgxKSB7XG4gICAgICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy53b3JsZE1vZGVsLmZvcm1zLmxlbmd0aDtcbiAgICAgICAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy53b3JsZE1vZGVsLmZvcm1zW2xlbmd0aCAtIDFdKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndvcmxkTW9kZWwuZm9ybXMubGVuZ3RoID0gbGVuZ3RoIC0gMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy53b3JsZE1vZGVsLnBsYXllckNoYXJhY3RlckZvcm1JZHggPT09IGkpIHtcbiAgICAgICAgICAgIHRoaXMud29ybGRNb2RlbC5wbGF5ZXJDaGFyYWN0ZXJGb3JtSWR4ID0gLTE7XG4gICAgICAgICAgICB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyUmVmcklkID0gMDtcbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gYSBzZXBhcmF0ZSBtb2R1bGVcbiAgICAgICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIEdhbWUucXVpdFRvTWFpbk1lbnUoKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5nZXRJZE1hbmFnZXIoKS5mcmVlSWRGb3IobXNnLmlkeCk7XG4gICAgfTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uVXBkYXRlTW92ZW1lbnRNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICB2YXIgaSA9IHRoaXMuZ2V0SWRNYW5hZ2VyKCkuZ2V0SWQobXNnLmlkeCk7XG4gICAgICAgIHZhciBmb3JtID0gdGhpcy53b3JsZE1vZGVsLmZvcm1zW2ldO1xuICAgICAgICBpZiAoZm9ybSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIm9uVXBkYXRlTW92ZW1lbnRNZXNzYWdlIC0gRm9ybSB3aXRoIGlkeFwiLCBtc2cuaWR4LCBcIm5vdCBmb3VuZFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBmb3JtLm1vdmVtZW50ID0gbXNnLmRhdGE7XG4gICAgICAgIGlmICghZm9ybS5udW1Nb3ZlbWVudENoYW5nZXMpIHtcbiAgICAgICAgICAgIGZvcm0ubnVtTW92ZW1lbnRDaGFuZ2VzID0gMDtcbiAgICAgICAgfVxuICAgICAgICBmb3JtLm51bU1vdmVtZW50Q2hhbmdlcysrO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vblVwZGF0ZUFuaW1hdGlvbk1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIHZhciBpID0gdGhpcy5nZXRJZE1hbmFnZXIoKS5nZXRJZChtc2cuaWR4KTtcbiAgICAgICAgdmFyIGZvcm0gPSB0aGlzLndvcmxkTW9kZWwuZm9ybXNbaV07XG4gICAgICAgIGlmIChmb3JtID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwib25VcGRhdGVBbmltYXRpb25NZXNzYWdlIC0gRm9ybSB3aXRoIGlkeFwiLCBtc2cuaWR4LCBcIm5vdCBmb3VuZFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBmb3JtLmFuaW1hdGlvbiA9IG1zZy5kYXRhO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vblVwZGF0ZUFwcGVhcmFuY2VNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICB2YXIgaSA9IHRoaXMuZ2V0SWRNYW5hZ2VyKCkuZ2V0SWQobXNnLmlkeCk7XG4gICAgICAgIHZhciBmb3JtID0gdGhpcy53b3JsZE1vZGVsLmZvcm1zW2ldO1xuICAgICAgICBpZiAoZm9ybSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIm9uVXBkYXRlQXBwZWFyYW5jZU1lc3NhZ2UgLSBGb3JtIHdpdGggaWR4XCIsIG1zZy5pZHgsIFwibm90IGZvdW5kXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvcm0uYXBwZWFyYW5jZSA9IG1zZy5kYXRhIHx8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKCFmb3JtLm51bUFwcGVhcmFuY2VDaGFuZ2VzKSB7XG4gICAgICAgICAgICBmb3JtLm51bUFwcGVhcmFuY2VDaGFuZ2VzID0gMDtcbiAgICAgICAgfVxuICAgICAgICBmb3JtLm51bUFwcGVhcmFuY2VDaGFuZ2VzKys7XG4gICAgICAgIHZhciBuZXdBcHBlYXJhbmNlID0gbXNnLmRhdGE7XG4gICAgICAgIGlmIChpID09PSB0aGlzLmdldE15QWN0b3JJbmRleCgpICYmIG5ld0FwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBhcHBseUFwcGVhcmFuY2VUb1BsYXllcihuZXdBcHBlYXJhbmNlKTtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJBcHBsaWVkIGFwcGVhcmFuY2UgdG8gdGhlIHBsYXllclwiKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uVXBkYXRlRXF1aXBtZW50TWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgbXNnID0gZXZlbnQubWVzc2FnZTtcbiAgICAgICAgdmFyIGkgPSB0aGlzLmdldElkTWFuYWdlcigpLmdldElkKG1zZy5pZHgpO1xuICAgICAgICB2YXIgZm9ybSA9IHRoaXMud29ybGRNb2RlbC5mb3Jtc1tpXTtcbiAgICAgICAgaWYgKGZvcm0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJvblVwZGF0ZUVxdWlwbWVudE1lc3NhZ2UgLSBGb3JtIHdpdGggaWR4XCIsIG1zZy5pZHgsIFwibm90IGZvdW5kXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvcm0uZXF1aXBtZW50ID0gbXNnLmRhdGE7XG4gICAgfTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uVXBkYXRlUHJvcGVydHlNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICB2YXIgbXNnRGF0YSA9IHRoaXMuZXh0cmFjdFVwZGF0ZVByb3BlcnR5TWVzc2FnZURhdGEobXNnKTtcbiAgICAgICAgaWYgKHRoaXMuc2tpcEZvcm1WaWV3Q3JlYXRpb24obXNnKSkge1xuICAgICAgICAgICAgdmFyIHJlZnJJZF8yID0gbXNnLnJlZnJJZDtcbiAgICAgICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVmciA9IE9iamVjdFJlZmVyZW5jZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHJlZnJJZF8yKSk7XG4gICAgICAgICAgICAgICAgaWYgKCFyZWZyKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKF90aGlzLCAnVXBkYXRlUHJvcGVydHk6IHJlZnIgbm90IGZvdW5kJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1zZy5wcm9wTmFtZSA9PT0gJ2ludmVudG9yeScpIHtcbiAgICAgICAgICAgICAgICAgICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJbnZlbnRvcnkocmVmciwgbXNnRGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1zZy5wcm9wTmFtZSA9PT0gJ2lzT3BlbicpIHtcbiAgICAgICAgICAgICAgICAgICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJc09wZW4ocmVmciwgISFtc2dEYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnLnByb3BOYW1lID09PSAnaXNIYXJ2ZXN0ZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsSXNIYXJ2ZXN0ZWQocmVmciwgISFtc2dEYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAobXNnLnByb3BOYW1lID09PSAnZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsSXNEaXNhYmxlZChyZWZyLCAhIW1zZ0RhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdGhpcy5nZXRJZE1hbmFnZXIoKS5nZXRJZChtc2cuaWR4KTtcbiAgICAgICAgdmFyIGZvcm0gPSB0aGlzLndvcmxkTW9kZWwuZm9ybXNbaV07XG4gICAgICAgIGZvcm1bbXNnLnByb3BOYW1lXSA9IG1zZ0RhdGE7XG4gICAgfTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uRGVhdGhTdGF0ZUNvbnRhaW5lck1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiUmVjZWl2ZWQgZGVhdGggc3RhdGU6XCIsIEpTT04uc3RyaW5naWZ5KG1zZy50SXNEZWFkKSk7XG4gICAgICAgIHZhciBpZCA9IHRoaXMuZ2V0SWRNYW5hZ2VyKCkuZ2V0SWQobXNnLnRJc0RlYWQuaWR4KTtcbiAgICAgICAgdmFyIGZvcm0gPSB0aGlzLndvcmxkTW9kZWwuZm9ybXNbaWRdO1xuICAgICAgICBpZiAoZm9ybSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIm9uRGVhdGhTdGF0ZUNvbnRhaW5lck1lc3NhZ2UgLSBGb3JtIHdpdGggaWR4XCIsIG1zZy50SXNEZWFkLmlkeCwgXCJub3QgZm91bmRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zZy50SXNEZWFkLnByb3BOYW1lICE9PSBuYW1lb2YoJ2lzRGVhZCcpKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIm9uRGVhdGhTdGF0ZUNvbnRhaW5lck1lc3NhZ2UgLSBJbnZhbGlkIHByb3BOYW1lXCIsIG1zZy50SXNEZWFkLnByb3BOYW1lKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbXNnRGF0YSA9IHRoaXMuZXh0cmFjdFVwZGF0ZVByb3BlcnR5TWVzc2FnZURhdGEobXNnLnRJc0RlYWQpO1xuICAgICAgICBpZiAodHlwZW9mIG1zZ0RhdGEgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJvbkRlYXRoU3RhdGVDb250YWluZXJNZXNzYWdlIC0gSW52YWxpZCBkYXRhXCIsIG1zZ0RhdGEpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtc2cudENoYW5nZVZhbHVlcykge1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZVZhbHVlc01lc3NhZ2UoeyBtZXNzYWdlOiBtc2cudENoYW5nZVZhbHVlcyB9KTtcbiAgICAgICAgfVxuICAgICAgICBvbmNlKCd1cGRhdGUnLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vblVwZGF0ZVByb3BlcnR5TWVzc2FnZSh7IG1lc3NhZ2U6IG1zZy50SXNEZWFkIH0pOyB9KTtcbiAgICAgICAgaWYgKG1zZy50VGVsZXBvcnQpIHtcbiAgICAgICAgICAgIHRoaXMub25UZWxlcG9ydE1lc3NhZ2UoeyBtZXNzYWdlOiBtc2cudFRlbGVwb3J0IH0pO1xuICAgICAgICB9XG4gICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgIHZhciBhY3RvciA9IGlkID09PSBfdGhpcy5nZXRXb3JsZE1vZGVsKCkucGxheWVyQ2hhcmFjdGVyRm9ybUlkeFxuICAgICAgICAgICAgICAgID8gR2FtZS5nZXRQbGF5ZXIoKVxuICAgICAgICAgICAgICAgIDogQWN0b3IuZnJvbShHYW1lLmdldEZvcm1FeChyZW1vdGVJZFRvTG9jYWxJZCgoX2EgPSBmb3JtLnJlZnJJZCkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogMCkpKTtcbiAgICAgICAgICAgIGlmIChhY3Rvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYXBwbHlEZWF0aFN0YXRlRXZlbnRcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0b3I6IGFjdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNEZWFkOiBtc2dEYXRhXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFJlc3Bhd25OZWVkZWRFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0b3IuZGlzYWJsZU5vV2FpdChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rvci5kZWxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5oYW5kbGVDb25uZWN0aW9uQWNjZXB0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMud29ybGRNb2RlbC5mb3JtcyA9IFtdO1xuICAgICAgICB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeCA9IC0xO1xuICAgICAgICB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyUmVmcklkID0gMDtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJIYW5kbGUgY29ubmVjdGlvbiBhY2NlcHRlZFwiKTtcbiAgICB9O1xuICAgIFJlbW90ZVNlcnZlci5wcm90b3R5cGUub25DaGFuZ2VWYWx1ZXNNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICBvbmNlKCd1cGRhdGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBfdGhpcy5nZXRJZE1hbmFnZXIoKS5nZXRJZChtc2cuaWR4KTtcbiAgICAgICAgICAgIHZhciByZWZyID0gaWQgPT09IF90aGlzLmdldE15QWN0b3JJbmRleCgpID8gR2FtZS5nZXRQbGF5ZXIoKSA6IGdldE9iamVjdFJlZmVyZW5jZShpZCk7XG4gICAgICAgICAgICB2YXIgYWMgPSBBY3Rvci5mcm9tKHJlZnIpO1xuICAgICAgICAgICAgaWYgKCFhYykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBfYSA9IG1zZy5kYXRhLCBoZWFsdGggPSBfYS5oZWFsdGgsIHN0YW1pbmEgPSBfYS5zdGFtaW5hLCBtYWdpY2thID0gX2EubWFnaWNrYTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhbHRoID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgc2V0QWN0b3JWYWx1ZVBlcmNlbnRhZ2UoYWMsICdoZWFsdGgnLCBoZWFsdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzdGFtaW5hID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgc2V0QWN0b3JWYWx1ZVBlcmNlbnRhZ2UoYWMsICdzdGFtaW5hJywgc3RhbWluYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1hZ2lja2EgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICBzZXRBY3RvclZhbHVlUGVyY2VudGFnZShhYywgJ21hZ2lja2EnLCBtYWdpY2thKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uU2V0UmFjZU1lbnVPcGVuTWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgbXNnID0gZXZlbnQubWVzc2FnZTtcbiAgICAgICAgaWYgKG1zZy5vcGVuKSB7XG4gICAgICAgICAgICAvLyB3YWl0IDAuM3MgY2F1c2Ugd2UgY2FuIHNlZSB2aXN1YWwgYnVncyB3aGVuIHRlbGVwb3J0aW5nXG4gICAgICAgICAgICAvLyBhbmQgc2hvd2luZyB0aGlzIG1lbnUgYXQgdGhlIHNhbWUgdGltZSBpbiBvbkNvbm5lY3RcbiAgICAgICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVXRpbGl0eS53YWl0KDAuMykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuZXF1aXBJcm9uSGVsbWV0KCk7XG4gICAgICAgICAgICAgICAgICAgIEdhbWUuc2hvd1JhY2VNZW51KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRPRE86IEltcGxlbWVudCBjbG9zZU1lbnUgaW4gU2t5cmltUGxhdGZvcm1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqIFBhY2tldCBoYW5kbGVycyBlbmQgKiovXG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5nZXRXb3JsZE1vZGVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53b3JsZE1vZGVsO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5nZXRNeUFjdG9ySW5kZXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeDtcbiAgICB9O1xuICAgIFJlbW90ZVNlcnZlci5wcm90b3R5cGUuZ2V0TXlSZW1vdGVSZWZySWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyUmVmcklkO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5nZXRJZE1hbmFnZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlkTWFuYWdlcl87XG4gICAgfTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVtb3RlU2VydmVyLnByb3RvdHlwZSwgXCJ3b3JsZE1vZGVsXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHN0b3JhZ2VbXCJ3b3JsZE1vZGVsXCJdID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBzdG9yYWdlW1wid29ybGRNb2RlbFwiXSA9IHsgZm9ybXM6IFtdLCBwbGF5ZXJDaGFyYWN0ZXJGb3JtSWR4OiAtMSwgcGxheWVyQ2hhcmFjdGVyUmVmcklkOiAwIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3RvcmFnZVtcIndvcmxkTW9kZWxcIl07XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVtb3RlU2VydmVyLnByb3RvdHlwZSwgXCJpZE1hbmFnZXJfXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHN0b3JhZ2VbXCJpZE1hbmFnZXJcIl0gPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIC8vIE5vdGU6IGZ1bGwgSWRNYW5hZ2VyIG9iamVjdCBwcmVzZXJ2ZWQgYWNyb3NzIGhvdC1yZWxvYWRzLCBpbmNsdWRpbmcgbWV0aG9kcy5cbiAgICAgICAgICAgICAgICBzdG9yYWdlW1wiaWRNYW5hZ2VyXCJdID0gbmV3IElkTWFuYWdlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0b3JhZ2VbXCJpZE1hbmFnZXJcIl07XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBSZW1vdGVTZXJ2ZXIucHJvdG90eXBlLm9uY2VMb2FkID0gZnVuY3Rpb24gKHJlZnJJZCwgY2FsbGJhY2ssIG1heEF0dGVtcHRzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChtYXhBdHRlbXB0cyA9PT0gdm9pZCAwKSB7IG1heEF0dGVtcHRzID0gMTIwOyB9XG4gICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciByZWZyID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgocmVmcklkKSk7XG4gICAgICAgICAgICBpZiAocmVmcikge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHJlZnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbWF4QXR0ZW1wdHMtLTtcbiAgICAgICAgICAgICAgICBpZiAobWF4QXR0ZW1wdHMgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uY2VMb2FkKHJlZnJJZCwgY2FsbGJhY2ssIG1heEF0dGVtcHRzKTsgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcihfdGhpcywgJ0ZhaWxlZCB0byBsb2FkIG9iamVjdCByZWZlcmVuY2UgJyArIHJlZnJJZC50b1N0cmluZygxNikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICA7XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5za2lwRm9ybVZpZXdDcmVhdGlvbiA9IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICAgLy8gT3B0aW1pemF0aW9uIGFkZGVkIGluICMxMTg2LCBob3dldmVyIGl0IGRvZXNuJ3Qgd29yayBmb3IgZG9vcnMgZm9yIHNvbWUgcmVhc29uXG4gICAgICAgIHJldHVybiBtc2cucmVmcklkICYmIG1zZy5yZWZySWQgPCAweGZmMDAwMDAwICYmIG1zZy5iYXNlUmVjb3JkVHlwZSAhPT0gJ0RPT1InO1xuICAgIH07XG4gICAgO1xuICAgIFJlbW90ZVNlcnZlci5wcm90b3R5cGUuZXh0cmFjdFVwZGF0ZVByb3BlcnR5TWVzc2FnZURhdGEgPSBmdW5jdGlvbiAodXBkYXRlUHJvcGVydHlNZXNzYWdlKSB7XG4gICAgICAgIHZhciBtc2dEYXRhID0gdXBkYXRlUHJvcGVydHlNZXNzYWdlLmRhdGE7XG4gICAgICAgIGlmICh1cGRhdGVQcm9wZXJ0eU1lc3NhZ2UuZGF0YUR1bXAgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBtc2dEYXRhID0gSlNPTi5wYXJzZSh1cGRhdGVQcm9wZXJ0eU1lc3NhZ2UuZGF0YUR1bXApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN5bnRheEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsICdleHRyYWN0VXBkYXRlUHJvcGVydHlNZXNzYWdlRGF0YSAtIEZhaWxlZCB0byBwYXJzZSBkYXRhRHVtcCcsIHVwZGF0ZVByb3BlcnR5TWVzc2FnZS5kYXRhRHVtcCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtc2dEYXRhO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vblNwZWxsQ2FzdE1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV2ZW50Lm1lc3NhZ2U7XG4gICAgICAgIG9uY2UoJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhYyA9IEFjdG9yLmZyb20oR2FtZS5nZXRGb3JtRXgocmVtb3RlSWRUb0xvY2FsSWQobXNnLmRhdGEuY2FzdGVyKSkpO1xuICAgICAgICAgICAgaWYgKCFhYykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhY3RvckFuaW1hdGlvblZhcmlhYmxlcyA9IHtcbiAgICAgICAgICAgICAgICBib29sZWFuczogbmV3IFVpbnQ4QXJyYXkobXNnLmRhdGEuYWN0b3JBbmltYXRpb25WYXJpYWJsZXMuYm9vbGVhbnMpLFxuICAgICAgICAgICAgICAgIGZsb2F0czogbmV3IFVpbnQ4QXJyYXkobXNnLmRhdGEuYWN0b3JBbmltYXRpb25WYXJpYWJsZXMuZmxvYXRzKSxcbiAgICAgICAgICAgICAgICBpbnRlZ2VyczogbmV3IFVpbnQ4QXJyYXkobXNnLmRhdGEuYWN0b3JBbmltYXRpb25WYXJpYWJsZXMuaW50ZWdlcnMpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKG1zZy5kYXRhLmludGVycnVwdENhc3QpIHtcbiAgICAgICAgICAgICAgICBpbnRlcnJ1cHRDYXN0KGFjLmdldEZvcm1JRCgpLCBtc2cuZGF0YS5jYXN0aW5nU291cmNlLCBhY3RvckFuaW1hdGlvblZhcmlhYmxlcyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHNwZWxsID0gYWMuZ2V0RXF1aXBwZWRTcGVsbChtc2cuZGF0YS5jYXN0aW5nU291cmNlKTtcbiAgICAgICAgICAgIGlmIChzcGVsbCkge1xuICAgICAgICAgICAgICAgIGNhc3RTcGVsbEltbWVkaWF0ZShhYy5nZXRGb3JtSUQoKSwgbXNnLmRhdGEuY2FzdGluZ1NvdXJjZSwgc3BlbGwuZ2V0Rm9ybUlEKCksIHJlbW90ZUlkVG9Mb2NhbElkKG1zZy5kYXRhLnRhcmdldCksIG1zZy5kYXRhLmFpbUFuZ2xlLCBtc2cuZGF0YS5haW1IZWFkaW5nLCBhY3RvckFuaW1hdGlvblZhcmlhYmxlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUmVtb3RlU2VydmVyLnByb3RvdHlwZS5vblVwZGF0ZUFuaW1WYXJpYWJsZXNNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICBvbmNlKCd1cGRhdGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYWMgPSBBY3Rvci5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHJlbW90ZUlkVG9Mb2NhbElkKG1zZy5kYXRhLmFjdG9yUmVtb3RlSWQpKSk7XG4gICAgICAgICAgICBpZiAoIWFjKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGFjdG9yQW5pbWF0aW9uVmFyaWFibGVzID0ge1xuICAgICAgICAgICAgICAgIGJvb2xlYW5zOiBuZXcgVWludDhBcnJheShtc2cuZGF0YS5hY3RvckFuaW1hdGlvblZhcmlhYmxlcy5ib29sZWFucyksXG4gICAgICAgICAgICAgICAgZmxvYXRzOiBuZXcgVWludDhBcnJheShtc2cuZGF0YS5hY3RvckFuaW1hdGlvblZhcmlhYmxlcy5mbG9hdHMpLFxuICAgICAgICAgICAgICAgIGludGVnZXJzOiBuZXcgVWludDhBcnJheShtc2cuZGF0YS5hY3RvckFuaW1hdGlvblZhcmlhYmxlcy5pbnRlZ2VycylcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgaXNBcHBseWVkID0gYXBwbHlBbmltYXRpb25WYXJpYWJsZXNUb0FjdG9yKGFjLmdldEZvcm1JRCgpLCBhY3RvckFuaW1hdGlvblZhcmlhYmxlcyk7XG4gICAgICAgICAgICBpZiAoIWlzQXBwbHllZCkge1xuICAgICAgICAgICAgICAgIGxvZ0Vycm9yKF90aGlzLCAnRmFpbGVkIGFwcGx5IEFuaW1hdGlvblZhcmlhYmxlcyB0byBhY3RvciB3aXRoIGlkOiAnICsgYWMuZ2V0Rm9ybUlEKCkudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gUmVtb3RlU2VydmVyO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgUmVtb3RlU2VydmVyIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0IHsgU2luZ2xlUGxheWVyU2VydmljZSB9IGZyb20gXCIuL3NpbmdsZVBsYXllclNlcnZpY2VcIjtcbmltcG9ydCB7IE1zZ1R5cGUgfSBmcm9tIFwiLi4vLi4vbWVzc2FnZXNcIjtcbmltcG9ydCB7IGdldE1vdmVtZW50IH0gZnJvbSBcIi4uLy4uL3N5bmMvbW92ZW1lbnRHZXRcIjtcbi8vIFRPRE86IHJlZmFjdG9yIHRoaXMgb3V0XG5pbXBvcnQgKiBhcyB3b3JsZFZpZXdNaXNjIGZyb20gXCIuLi8uLi92aWV3L3dvcmxkVmlld01pc2NcIjtcbmltcG9ydCB7IEFuaW1hdGlvblNvdXJjZSB9IGZyb20gXCIuLi8uLi9zeW5jL2FuaW1hdGlvblwiO1xuaW1wb3J0IHsgZ2V0QXBwZWFyYW5jZSB9IGZyb20gXCIuLi8uLi9zeW5jL2FwcGVhcmFuY2VcIjtcbmltcG9ydCB7IGdldEFjdG9yVmFsdWVzIH0gZnJvbSBcIi4uLy4uL3N5bmMvYWN0b3J2YWx1ZXNcIjtcbmltcG9ydCB7IGdldEVxdWlwbWVudCB9IGZyb20gXCIuLi8uLi9zeW5jL2VxdWlwbWVudFwiO1xuaW1wb3J0IHsgbmV4dEhvc3RBdHRlbXB0IH0gZnJvbSBcIi4uLy4uL3ZpZXcvaG9zdEF0dGVtcHRzXCI7XG5pbXBvcnQgeyBSZW1vdGVTZXJ2ZXIgfSBmcm9tIFwiLi9yZW1vdGVTZXJ2ZXJcIjtcbmltcG9ydCB7IERlYXRoU2VydmljZSB9IGZyb20gXCIuL2RlYXRoU2VydmljZVwiO1xuaW1wb3J0IHsgbG9nVHJhY2UgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xudmFyIHBsYXllckZvcm1JZCA9IDB4MTQ7XG4vLyBUT0RPOiBzcGxpdCB0aGlzIHNlcnZpY2UgaW50byBFcXVpcG1lbnRTZXJ2aWNlLCBNb3ZlbWVudFNlcnZpY2UsIEFuaW1hdGlvblNlcnZpY2UsIEFjdG9yVmFsdWVTZXJ2aWNlLCBIb3N0QXR0ZW1wdHNTZXJ2aWNlXG52YXIgU2VuZElucHV0c1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNlbmRJbnB1dHNTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNlbmRJbnB1dHNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5sYXN0U2VuZE1vdmVtZW50TW9tZW50ID0gbmV3IE1hcCgpO1xuICAgICAgICBfdGhpcy5wbGF5ZXJBbmltU291cmNlID0gbmV3IE1hcCgpOyAvLyBUT0RPOiBtYWtlIHNlcnZpY2VcbiAgICAgICAgX3RoaXMubGFzdEFuaW1hdGlvblNlbnQgPSBuZXcgTWFwKCk7XG4gICAgICAgIF90aGlzLmFjdG9yVmFsdWVzTmVlZFVwZGF0ZSA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc1JhY2VTZXhNZW51U2hvd24gPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuZXF1aXBtZW50Q2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5udW1FcXVpcG1lbnRDaGFuZ2VzID0gMDtcbiAgICAgICAgX3RoaXMucHJldlZhbHVlcyA9IHsgaGVhbHRoOiAwLCBzdGFtaW5hOiAwLCBtYWdpY2thOiAwIH07XG4gICAgICAgIF90aGlzLnByZXZBY3RvclZhbHVlc1VwZGF0ZVRpbWUgPSAwO1xuICAgICAgICBfdGhpcy5wcmV2Q2FzdGluZ0RldGVjdGVkVGltZSA9IDA7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJlcXVpcFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25FcXVpcChlKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1bmVxdWlwXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblVuZXF1aXAoZSk7IH0pO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uKFwibG9hZEdhbWVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25Mb2FkR2FtZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTZW5kSW5wdXRzU2VydmljZS5wcm90b3R5cGUub25VcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zaW5nbGVQbGF5ZXJTZXJ2aWNlLmlzU2luZ2xlUGxheWVyKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRJbnB1dHMoKTtcbiAgICAgICAgICAgIHZhciBwbGF5ZXIgPSB0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgICAgICB2YXIgaXNQbGF5ZXJDYXN0aW5nID0gcGxheWVyLmdldEFuaW1hdGlvblZhcmlhYmxlQm9vbChcIklzQ2FzdGluZ1JpZ2h0XCIpXG4gICAgICAgICAgICAgICAgfHwgcGxheWVyLmdldEFuaW1hdGlvblZhcmlhYmxlQm9vbChcIklzQ2FzdGluZ0xlZnRcIilcbiAgICAgICAgICAgICAgICB8fCBwbGF5ZXIuZ2V0QW5pbWF0aW9uVmFyaWFibGVCb29sKFwiSXNDYXN0aW5nRHVhbFwiKTtcbiAgICAgICAgICAgIGlmIChpc1BsYXllckNhc3RpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZDYXN0aW5nRGV0ZWN0ZWRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgU2VuZElucHV0c1NlcnZpY2UucHJvdG90eXBlLm9uRXF1aXAgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5hY3RvciB8fCAhZXZlbnQuYmFzZU9iaikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudC5hY3Rvci5nZXRGb3JtSUQoKSAhPT0gcGxheWVyRm9ybUlkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR5cGUgPSBldmVudC5iYXNlT2JqLmdldFR5cGUoKTtcbiAgICAgICAgaWYgKHR5cGUgIT09IDI3IC8qIEZvcm1UeXBlLkJvb2sgKi8gJiYgdHlwZSAhPT0gNDYgLyogRm9ybVR5cGUuUG90aW9uICovICYmIHR5cGUgIT09IDMwIC8qIEZvcm1UeXBlLkluZ3JlZGllbnQgKi8pIHtcbiAgICAgICAgICAgIC8vIFRyaWdnZXIgVXBkYXRlRXF1aXBtZW50IG9ubHkgZm9yIGVxdWlwcyB0aGF0IGFyZSBub3Qgc3BlbGwgdG9tZXMsIHBvdGlvbnMsIGluZ3JlZGllbnRzXG4gICAgICAgICAgICB0aGlzLmVxdWlwbWVudENoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNlbmQgT25FcXVpcCBmb3IgYW55IGVxdWlwcyBpbmNsdWRpbmcgc3BlbGwgdG9tZXMsIHBvdGlvbnMsIGluZ3JlZGllbnRzXG4gICAgICAgIC8vIE90aGVyd2lzZSwgdGhlIHNlcnZlciB3b24ndCB0cmlnZ2VyIHNwZWxsIGxlYXJuLCBwb3Rpb24gZHJpbmssIGluZ3JlZGllbnQgZWF0IGFuZCBQYXB5cnVzIHNjcmlwdHNcbiAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNlbmRNZXNzYWdlXCIsIHtcbiAgICAgICAgICAgIG1lc3NhZ2U6IHsgdDogTXNnVHlwZS5PbkVxdWlwLCBiYXNlSWQ6IGV2ZW50LmJhc2VPYmouZ2V0Rm9ybUlEKCkgfSxcbiAgICAgICAgICAgIHJlbGlhYmlsaXR5OiBcInVucmVsaWFibGVcIlxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFNlbmRJbnB1dHNTZXJ2aWNlLnByb3RvdHlwZS5vblVuZXF1aXAgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5hY3RvciB8fCAhZXZlbnQuYmFzZU9iaikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudC5hY3Rvci5nZXRGb3JtSUQoKSA9PT0gcGxheWVyRm9ybUlkKSB7XG4gICAgICAgICAgICB0aGlzLmVxdWlwbWVudENoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTZW5kSW5wdXRzU2VydmljZS5wcm90b3R5cGUub25Mb2FkR2FtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gQ3VycmVudGx5IG9ubHkgYXJtb3IgaXMgZXF1aXBwZWQgYWZ0ZXIgcmVsb2dnaW5nIChzZWUgcmVtb3RlU2VydmVyLnRzKVxuICAgICAgICAvLyBUaGlzIGhhY2sgZm9yY2VzIHNlbmRpbmcgL2VxdWlwbWVudCB3aXRob3V0IHdlYXBvbnMvIGJhY2sgdG8gdGhlIHNlcnZlclxuICAgICAgICB0aGlzLnNwLlV0aWxpdHkud2FpdCgzKS50aGVuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIChfdGhpcy5lcXVpcG1lbnRDaGFuZ2VkID0gdHJ1ZSk7IH0pO1xuICAgIH07XG4gICAgU2VuZElucHV0c1NlcnZpY2UucHJvdG90eXBlLnNlbmRJbnB1dHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBob3N0ZWQgPSB0eXBlb2YgdGhpcy5zcC5zdG9yYWdlWydob3N0ZWQnXSA9PT0gdHlwZW9mIFtdID8gdGhpcy5zcC5zdG9yYWdlWydob3N0ZWQnXSA6IFtdO1xuICAgICAgICB2YXIgdGFyZ2V0cyA9IFt1bmRlZmluZWRdLmNvbmNhdChob3N0ZWQpO1xuICAgICAgICB2YXIgbW9kZWxTb3VyY2UgPSB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoUmVtb3RlU2VydmVyKTtcbiAgICAgICAgdmFyIHdvcmxkID0gbW9kZWxTb3VyY2UuZ2V0V29ybGRNb2RlbCgpO1xuICAgICAgICB0YXJnZXRzLmZvckVhY2goZnVuY3Rpb24gKHRhcmdldCkge1xuICAgICAgICAgICAgdmFyIHRhcmdldEZvcm1Nb2RlbCA9IHRhcmdldCA/IF90aGlzLmdldEZvcm0odGFyZ2V0LCB3b3JsZCkgOiBfdGhpcy5nZXRGb3JtKHVuZGVmaW5lZCwgd29ybGQpO1xuICAgICAgICAgICAgX3RoaXMuc2VuZE1vdmVtZW50KHRhcmdldCwgdGFyZ2V0Rm9ybU1vZGVsKTtcbiAgICAgICAgICAgIF90aGlzLnNlbmRBbmltYXRpb24odGFyZ2V0KTtcbiAgICAgICAgICAgIF90aGlzLnNlbmRBcHBlYXJhbmNlKHRhcmdldCk7XG4gICAgICAgICAgICBfdGhpcy5zZW5kRXF1aXBtZW50KHRhcmdldCk7XG4gICAgICAgICAgICBfdGhpcy5zZW5kQWN0b3JWYWx1ZVBlcmNlbnRhZ2UodGFyZ2V0LCB0YXJnZXRGb3JtTW9kZWwpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zZW5kSG9zdEF0dGVtcHRzKCk7XG4gICAgfTtcbiAgICBTZW5kSW5wdXRzU2VydmljZS5wcm90b3R5cGUuc2VuZE1vdmVtZW50ID0gZnVuY3Rpb24gKF9yZWZySWQsIGZvcm0pIHtcbiAgICAgICAgdmFyIG93bmVyID0gdGhpcy5nZXRJbnB1dE93bmVyKF9yZWZySWQpO1xuICAgICAgICBpZiAoIW93bmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlZnJJZFN0ciA9IFwiXCIuY29uY2F0KF9yZWZySWQpO1xuICAgICAgICB2YXIgc2VuZE1vdmVtZW50UmF0ZU1zID0gMTMwO1xuICAgICAgICB2YXIgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdmFyIGxhc3QgPSB0aGlzLmxhc3RTZW5kTW92ZW1lbnRNb21lbnQuZ2V0KHJlZnJJZFN0cik7XG4gICAgICAgIGlmICghbGFzdCB8fCBub3cgLSBsYXN0ID4gc2VuZE1vdmVtZW50UmF0ZU1zKSB7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgICAgICB0OiBNc2dUeXBlLlVwZGF0ZU1vdmVtZW50LFxuICAgICAgICAgICAgICAgIGRhdGE6IGdldE1vdmVtZW50KG93bmVyLCBmb3JtKSxcbiAgICAgICAgICAgICAgICBfcmVmcklkOiBfcmVmcklkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNlbmRNZXNzYWdlV2l0aFJlZnJJZFwiLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJ1bnJlbGlhYmxlXCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5sYXN0U2VuZE1vdmVtZW50TW9tZW50LnNldChyZWZySWRTdHIsIG5vdyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNlbmRJbnB1dHNTZXJ2aWNlLnByb3RvdHlwZS5zZW5kQWN0b3JWYWx1ZVBlcmNlbnRhZ2UgPSBmdW5jdGlvbiAoX3JlZnJJZCwgZm9ybSkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHZhciBjYW5TZW5kID0gZm9ybSAmJiAoKF9hID0gZm9ybS5pc0RlYWQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGZhbHNlKSA9PT0gZmFsc2U7XG4gICAgICAgIGlmICghY2FuU2VuZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvd25lciA9IHRoaXMuZ2V0SW5wdXRPd25lcihfcmVmcklkKTtcbiAgICAgICAgaWYgKCFvd25lcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhdiA9IGdldEFjdG9yVmFsdWVzKHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKSk7XG4gICAgICAgIHZhciBjdXJyZW50VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIGlmICh0aGlzLmFjdG9yVmFsdWVzTmVlZFVwZGF0ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgIHRoaXMucHJldlZhbHVlcy5oZWFsdGggPT09IGF2LmhlYWx0aCAmJlxuICAgICAgICAgICAgdGhpcy5wcmV2VmFsdWVzLnN0YW1pbmEgPT09IGF2LnN0YW1pbmEgJiZcbiAgICAgICAgICAgIHRoaXMucHJldlZhbHVlcy5tYWdpY2thID09PSBhdi5tYWdpY2thKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGN1cnJlbnRUaW1lIC0gdGhpcy5wcmV2QWN0b3JWYWx1ZXNVcGRhdGVUaW1lIDwgMjAwMCAmJlxuICAgICAgICAgICAgdGhpcy5hY3RvclZhbHVlc05lZWRVcGRhdGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gRGVsYXlpbmcgYWN0b3IgdmFsdWVzIHVwZGF0ZSBkdWUgdG8gY2FzdGluZ1xuICAgICAgICAvLyBUT0RPOiB1c2UgcGFydGlhbCB1cGRhdGVzIGZvciBhY3RvciB2YWx1ZXMgb25jZSBzZXJ2ZXIgZmluYWxseSBzdXBwb3J0cyBpdFxuICAgICAgICAvLyBpLmUuIGtlZXAgc2VuZGluZyBoZWFsdGggYW5kIHN0YW1pbmEgZHVyaW5nIGNhc3RpbmcsIGJ1dCBkZWxheSBtYWdpY2thIHVwZGF0ZVxuICAgICAgICBpZiAoY3VycmVudFRpbWUgLSB0aGlzLnByZXZDYXN0aW5nRGV0ZWN0ZWRUaW1lIDwgNTAwICYmXG4gICAgICAgICAgICBhdi5oZWFsdGggPiAwIC8vIGRvbid0IGRlbGF5IGRlYXRoIGFjdG9yIHZhbHVlIHVwZGF0ZVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGVhdGhTZXJ2aWNlID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKERlYXRoU2VydmljZSk7XG4gICAgICAgIGlmIChkZWF0aFNlcnZpY2UuaXNCdXN5KCkpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiTm90IHNlbmRpbmcgYWN0b3IgdmFsdWVzLCBkZWF0aCBzZXJ2aWNlIGlzIGJ1c3lcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICB0OiBNc2dUeXBlLkNoYW5nZVZhbHVlcyxcbiAgICAgICAgICAgIGRhdGE6IGF2LFxuICAgICAgICAgICAgX3JlZnJJZDogX3JlZnJJZFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VXaXRoUmVmcklkXCIsIHtcbiAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAgICAgICByZWxpYWJpbGl0eTogXCJ1bnJlbGlhYmxlXCJcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWN0b3JWYWx1ZXNOZWVkVXBkYXRlID0gZmFsc2U7XG4gICAgICAgIHRoaXMucHJldlZhbHVlcyA9IGF2O1xuICAgICAgICB0aGlzLnByZXZBY3RvclZhbHVlc1VwZGF0ZVRpbWUgPSBjdXJyZW50VGltZTtcbiAgICB9O1xuICAgIFNlbmRJbnB1dHNTZXJ2aWNlLnByb3RvdHlwZS5zZW5kQW5pbWF0aW9uID0gZnVuY3Rpb24gKF9yZWZySWQpIHtcbiAgICAgICAgdmFyIG93bmVyID0gdGhpcy5nZXRJbnB1dE93bmVyKF9yZWZySWQpO1xuICAgICAgICBpZiAoIW93bmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gRXh0ZXJtbHkgaW1wb3J0YW50IHRoYXQgaXQncyBhIGxvY2FsIGlkIHNpbmNlIEFuaW1hdGlvblNvdXJjZSBkZXBlbmRzIG9uIGl0XG4gICAgICAgIHZhciByZWZySWRTdHIgPSBvd25lci5nZXRGb3JtSUQoKS50b1N0cmluZygxNik7XG4gICAgICAgIHZhciBhbmltU291cmNlID0gdGhpcy5wbGF5ZXJBbmltU291cmNlLmdldChyZWZySWRTdHIpO1xuICAgICAgICBpZiAoIWFuaW1Tb3VyY2UpIHtcbiAgICAgICAgICAgIGFuaW1Tb3VyY2UgPSBuZXcgQW5pbWF0aW9uU291cmNlKG93bmVyKTtcbiAgICAgICAgICAgIHRoaXMucGxheWVyQW5pbVNvdXJjZS5zZXQocmVmcklkU3RyLCBhbmltU291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYW5pbSA9IGFuaW1Tb3VyY2UuZ2V0QW5pbWF0aW9uKCk7XG4gICAgICAgIHZhciBsYXN0QW5pbWF0aW9uU2VudCA9IHRoaXMubGFzdEFuaW1hdGlvblNlbnQuZ2V0KHJlZnJJZFN0cik7XG4gICAgICAgIGlmICghbGFzdEFuaW1hdGlvblNlbnQgfHxcbiAgICAgICAgICAgIGFuaW0ubnVtQ2hhbmdlcyAhPT0gbGFzdEFuaW1hdGlvblNlbnQubnVtQ2hhbmdlcykge1xuICAgICAgICAgICAgLy8gRHJpbmsgcG90aW9uIGFuaW0gZnJvbSB0aGlzIG1vZCBodHRwczovL3d3dy5uZXh1c21vZHMuY29tL3NreXJpbXNwZWNpYWxlZGl0aW9uL21vZHMvOTc2NjBcbiAgICAgICAgICAgIGlmIChhbmltLmFuaW1FdmVudE5hbWUgIT09ICcnICYmICFhbmltLmFuaW1FdmVudE5hbWUuc3RhcnRzV2l0aChcIkRyaW5rUG90aW9uX1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdEFuaW1hdGlvblNlbnQuc2V0KHJlZnJJZFN0ciwgYW5pbSk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVBY3RvclZhbHVlc0FmdGVyQW5pbWF0aW9uKGFuaW0uYW5pbUV2ZW50TmFtZSk7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuVXBkYXRlQW5pbWF0aW9uLFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiBhbmltLFxuICAgICAgICAgICAgICAgICAgICBfcmVmcklkOiBfcmVmcklkXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VXaXRoUmVmcklkXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwidW5yZWxpYWJsZVwiXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNlbmRJbnB1dHNTZXJ2aWNlLnByb3RvdHlwZS5zZW5kQXBwZWFyYW5jZSA9IGZ1bmN0aW9uIChfcmVmcklkKSB7XG4gICAgICAgIGlmIChfcmVmcklkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNob3duID0gdGhpcy5zcC5VaS5pc01lbnVPcGVuKCdSYWNlU2V4IE1lbnUnKTtcbiAgICAgICAgaWYgKHNob3duICE9IHRoaXMuaXNSYWNlU2V4TWVudVNob3duKSB7XG4gICAgICAgICAgICB0aGlzLmlzUmFjZVNleE1lbnVTaG93biA9IHNob3duO1xuICAgICAgICAgICAgaWYgKCFzaG93bikge1xuICAgICAgICAgICAgICAgIHRoaXMuc3AucHJpbnRDb25zb2xlKCdFeGl0ZWQgZnJvbSByYWNlIG1lbnUnKTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwZWFyYW5jZSA9IGdldEFwcGVhcmFuY2UodGhpcy5zcC5HYW1lLmdldFBsYXllcigpKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBsb2cgYXBwZWFyYW5jZSBjb250ZW50cyB0byBkZWJ1ZyBhcHBlYXJhbmNlIGlzc3Vlcz9cbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgdDogTXNnVHlwZS5VcGRhdGVBcHBlYXJhbmNlLFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiBhcHBlYXJhbmNlLFxuICAgICAgICAgICAgICAgICAgICBfcmVmcklkOiBfcmVmcklkXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VXaXRoUmVmcklkXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwicmVsaWFibGVcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBTZW5kSW5wdXRzU2VydmljZS5wcm90b3R5cGUuc2VuZEVxdWlwbWVudCA9IGZ1bmN0aW9uIChfcmVmcklkKSB7XG4gICAgICAgIGlmIChfcmVmcklkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZXF1aXBtZW50Q2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5lcXVpcG1lbnRDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICArK3RoaXMubnVtRXF1aXBtZW50Q2hhbmdlcztcbiAgICAgICAgICAgIHZhciBlcSA9IGdldEVxdWlwbWVudCh0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCksIHRoaXMubnVtRXF1aXBtZW50Q2hhbmdlcyk7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgICAgICB0OiBNc2dUeXBlLlVwZGF0ZUVxdWlwbWVudCxcbiAgICAgICAgICAgICAgICBkYXRhOiBlcSxcbiAgICAgICAgICAgICAgICBfcmVmcklkOiBfcmVmcklkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNlbmRNZXNzYWdlV2l0aFJlZnJJZFwiLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2VuZElucHV0c1NlcnZpY2UucHJvdG90eXBlLnNlbmRIb3N0QXR0ZW1wdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZW1vdGVJZCA9IG5leHRIb3N0QXR0ZW1wdCgpO1xuICAgICAgICBpZiAoIXJlbW90ZUlkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIuZW1pdChcInNlbmRNZXNzYWdlXCIsIHtcbiAgICAgICAgICAgIG1lc3NhZ2U6IHtcbiAgICAgICAgICAgICAgICB0OiBNc2dUeXBlLkhvc3QsXG4gICAgICAgICAgICAgICAgcmVtb3RlSWQ6IHJlbW90ZUlkXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVsaWFiaWxpdHk6IFwidW5yZWxpYWJsZVwiXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU2VuZElucHV0c1NlcnZpY2UucHJvdG90eXBlLmdldElucHV0T3duZXIgPSBmdW5jdGlvbiAoX3JlZnJJZCkge1xuICAgICAgICByZXR1cm4gX3JlZnJJZFxuICAgICAgICAgICAgPyB0aGlzLnNwLkFjdG9yLmZyb20odGhpcy5zcC5HYW1lLmdldEZvcm1FeCh3b3JsZFZpZXdNaXNjLnJlbW90ZUlkVG9Mb2NhbElkKF9yZWZySWQpKSlcbiAgICAgICAgICAgIDogdGhpcy5zcC5HYW1lLmdldFBsYXllcigpO1xuICAgIH07XG4gICAgU2VuZElucHV0c1NlcnZpY2UucHJvdG90eXBlLmdldEZvcm0gPSBmdW5jdGlvbiAocmVmcklkLCB3b3JsZCkge1xuICAgICAgICB2YXIgZm9ybSA9IHJlZnJJZFxuICAgICAgICAgICAgPyB3b3JsZCA9PT0gbnVsbCB8fCB3b3JsZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogd29ybGQuZm9ybXMuZmluZChmdW5jdGlvbiAoZikgeyByZXR1cm4gKGYgPT09IG51bGwgfHwgZiA9PT0gdm9pZCAwID8gdm9pZCAwIDogZi5yZWZySWQpID09PSByZWZySWQ7IH0pXG4gICAgICAgICAgICA6IHdvcmxkLmZvcm1zW3dvcmxkLnBsYXllckNoYXJhY3RlckZvcm1JZHhdO1xuICAgICAgICByZXR1cm4gZm9ybTtcbiAgICB9O1xuICAgIFNlbmRJbnB1dHNTZXJ2aWNlLnByb3RvdHlwZS51cGRhdGVBY3RvclZhbHVlc0FmdGVyQW5pbWF0aW9uID0gZnVuY3Rpb24gKGFuaW1OYW1lKSB7XG4gICAgICAgIGlmIChhbmltTmFtZSA9PT0gJ0p1bXBMYW5kJyB8fFxuICAgICAgICAgICAgYW5pbU5hbWUgPT09ICdKdW1wTGFuZERpcmVjdGlvbmFsJyB8fFxuICAgICAgICAgICAgYW5pbU5hbWUgPT09ICdEZWF0aEFuaW0nKSB7XG4gICAgICAgICAgICB0aGlzLmFjdG9yVmFsdWVzTmVlZFVwZGF0ZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTZW5kSW5wdXRzU2VydmljZS5wcm90b3R5cGUsIFwic2luZ2xlUGxheWVyU2VydmljZVwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihTaW5nbGVQbGF5ZXJTZXJ2aWNlKTtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIHJldHVybiBTZW5kSW5wdXRzU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFNlbmRJbnB1dHNTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgdmVyaWZ5IH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tICcuL2NsaWVudExpc3RlbmVyJztcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gJy4vc2V0dGluZ3NTZXJ2aWNlJztcbmltcG9ydCB7IGxvZ1RyYWNlIH0gZnJvbSAnLi4vLi4vbG9nZ2luZyc7XG52YXIgU2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFNlcnZlckpzVmVyaWZpY2F0aW9uU2VydmljZS5wcm90b3R5cGUudmVyaWZ5U2VydmVySnMgPSBmdW5jdGlvbiAoc3JjLCBjdXN0b21QcmVmaXgpIHtcbiAgICAgICAgaWYgKCFzcmMpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsICdFbXB0eSBzZXJ2ZXIgSlMsIHNraXBwaW5nIHZlcmlmaWNhdGlvbicpO1xuICAgICAgICAgICAgcmV0dXJuIHsgc3JjOiBzcmMsIGVycm9yOiBudWxsIH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNldHRpbmdzU2VydmljZSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihTZXR0aW5nc1NlcnZpY2UpO1xuICAgICAgICB2YXIgZ2V0VGFyZ2V0UGVlclJlc3VsdCA9IHNldHRpbmdzU2VydmljZS5nZXRUYXJnZXRQZWVyKCk7XG4gICAgICAgIGlmICghZ2V0VGFyZ2V0UGVlclJlc3VsdC50YXJnZXRQZWVyQ2FjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzcmM6IG51bGwsIGVycm9yOiAndGFyZ2V0IHBlZXIgbm90IHJlYWR5JyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBwdWJsaWNLZXlzID0gZ2V0VGFyZ2V0UGVlclJlc3VsdC50YXJnZXRQZWVyQ2FjaGVkLnB1YmxpY0tleXM7XG4gICAgICAgIGlmICghcHVibGljS2V5cykge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ05vIHB1YmxpYyBrZXlzIGNvbmZpZ3VyZWQsIHNraXBwaW5nIHNlcnZlciBKUyB2ZXJpZmljYXRpb24nKTtcbiAgICAgICAgICAgIHJldHVybiB7IHNyYzogc3JjLCBlcnJvcjogbnVsbCB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBsYXN0TGluZVN0YXJ0ID0gc3JjLmxhc3RJbmRleE9mKCdcXG4nKSArIDE7XG4gICAgICAgIHZhciBzaWdQcmVmaXggPSBjdXN0b21QcmVmaXggfHwgJy8vIHNreW1wOnNpZzp5Oic7XG4gICAgICAgIGlmIChsYXN0TGluZVN0YXJ0ID09PSAwIHx8ICFzcmMuc3Vic3RyaW5nKGxhc3RMaW5lU3RhcnQpLnN0YXJ0c1dpdGgoc2lnUHJlZml4KSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3JjOiBudWxsLCBlcnJvcjogJ25vIHNpZ25hdHVyZSBmb3VuZCcgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgX2EgPSBzcmMuc3Vic3RyaW5nKGxhc3RMaW5lU3RhcnQgKyBzaWdQcmVmaXgubGVuZ3RoKS5zcGxpdCgnOicpLCBrZXlJZCA9IF9hWzBdLCBzaWcgPSBfYVsxXTtcbiAgICAgICAgaWYgKCF0aGlzLmlzQWxwaGFOdW1lcmljKGtleUlkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3JjOiBudWxsLCBlcnJvcjogJ21hbGZvcm1lZCBrZXkgaWQnIH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGtleSA9IHB1YmxpY0tleXNba2V5SWRdO1xuICAgICAgICBpZiAoIWtleSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3JjOiBudWxsLCBlcnJvcjogJ3Vua25vd24ga2V5ICcgKyBrZXlJZCB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciB0b1ZlcmlmeSA9IHRoaXMudG9BcnJheUJ1ZmZlclZpZXcoc3JjLnN1YnN0cmluZygwLCBsYXN0TGluZVN0YXJ0IC0gMSksICd1dGY4Jyk7XG4gICAgICAgIGlmICghdmVyaWZ5KG51bGwsIHRvVmVyaWZ5LCBrZXksIHRoaXMudG9BcnJheUJ1ZmZlclZpZXcoc2lnLCAnYmFzZTY0JykpKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzcmM6IG51bGwsIGVycm9yOiAnYmFkIHNpZ25hdHVyZScgfTtcbiAgICAgICAgfVxuICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlNlcnZlciBKUyB2ZXJpZmllZCB3aXRoIGtleSBcIi5jb25jYXQoa2V5SWQpKTtcbiAgICAgICAgcmV0dXJuIHsgc3JjOiBzcmMsIGVycm9yOiBudWxsIH07XG4gICAgfTtcbiAgICBTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UucHJvdG90eXBlLmlzQWxwaGFOdW1lcmljID0gZnVuY3Rpb24gKHN0cikge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdmFyIGNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgICAgICAgIGlmICghKCg5NyA8PSBjb2RlICYmIGNvZGUgPD0gMTIyKSB8fFxuICAgICAgICAgICAgICAgICg2NSA8PSBjb2RlICYmIGNvZGUgPD0gOTApIHx8XG4gICAgICAgICAgICAgICAgKDQ4IDw9IGNvZGUgJiYgY29kZSA8PSA1NykpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgU2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlLnByb3RvdHlwZS50b0FycmF5QnVmZmVyVmlldyA9IGZ1bmN0aW9uIChzdHIsIGVuYykge1xuICAgICAgICB2YXIgYnVmID0gQnVmZmVyLmZyb20oc3RyLCBlbmMpO1xuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYnVmLmJ1ZmZlciwgYnVmLmJ5dGVPZmZzZXQsIGJ1Zi5ieXRlTGVuZ3RoKTtcbiAgICB9O1xuICAgIHJldHVybiBTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19hc3NpZ24gPSAodGhpcyAmJiB0aGlzLl9fYXNzaWduKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgSHR0cENsaWVudCwgcHJpbnRDb25zb2xlLCBVdGlsaXR5IH0gZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG5pbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gXCIuL2F1dGhTZXJ2aWNlXCI7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG5pbXBvcnQgeyBUaW1lcnNTZXJ2aWNlIH0gZnJvbSBcIi4vdGltZXJzU2VydmljZVwiO1xuaW1wb3J0IHsgbG9nVHJhY2UgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xudmFyIFNldHRpbmdzU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU2V0dGluZ3NTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNldHRpbmdzU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMudGFyZ2V0UGVlckNhY2hlID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTZXR0aW5nc1NlcnZpY2UucHJvdG90eXBlLmdldFNlcnZlck1hc3RlcktleSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1hc3RlcktleSA9IHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wic2VydmVyLW1hc3Rlci1rZXlcIl07XG4gICAgICAgIGlmICghbWFzdGVyS2V5KSB7XG4gICAgICAgICAgICBtYXN0ZXJLZXkgPSB0aGlzLnNwLnNldHRpbmdzW1wic2t5bXA1LWNsaWVudFwiXVtcIm1hc3Rlci1rZXlcIl07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFtYXN0ZXJLZXkpIHtcbiAgICAgICAgICAgIG1hc3RlcktleSA9IHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wic2VydmVyLWlwXCJdICsgXCI6XCIgKyB0aGlzLnNwLnNldHRpbmdzW1wic2t5bXA1LWNsaWVudFwiXVtcInNlcnZlci1wb3J0XCJdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXN0ZXJLZXk7XG4gICAgfTtcbiAgICBTZXR0aW5nc1NlcnZpY2UucHJvdG90eXBlLmdldE1hc3RlclVybCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplVXJsKHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wibWFzdGVyXCJdIHx8IFwiaHR0cHM6Ly9nYXRld2F5LnNreW1wLm5ldFwiKTtcbiAgICB9O1xuICAgIFNldHRpbmdzU2VydmljZS5wcm90b3R5cGUubWFrZU1hc3RlckFwaUNsaWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1hc3RlckFwaUJhc2VVcmwgPSB0aGlzLmdldE1hc3RlclVybCgpO1xuICAgICAgICByZXR1cm4gbmV3IEh0dHBDbGllbnQobWFzdGVyQXBpQmFzZVVybCk7XG4gICAgfTtcbiAgICBTZXR0aW5nc1NlcnZpY2UucHJvdG90eXBlLmdldFRhcmdldFBlZXIgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMudGFyZ2V0UGVlckNhY2hlKSB7XG4gICAgICAgICAgICBjYWxsYmFjayA9PT0gbnVsbCB8fCBjYWxsYmFjayA9PT0gdm9pZCAwID8gdm9pZCAwIDogY2FsbGJhY2sodGhpcy50YXJnZXRQZWVyQ2FjaGUpO1xuICAgICAgICAgICAgcmV0dXJuIHsgdGFyZ2V0UGVlckNhY2hlZDogdGhpcy50YXJnZXRQZWVyQ2FjaGUgfTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldFRhcmdldFBlZXJJbXBsKGZ1bmN0aW9uICh0YXJnZXRQZWVyKSB7XG4gICAgICAgICAgICBfdGhpcy50YXJnZXRQZWVyQ2FjaGUgPSB0YXJnZXRQZWVyO1xuICAgICAgICAgICAgY2FsbGJhY2sgPT09IG51bGwgfHwgY2FsbGJhY2sgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGNhbGxiYWNrKHRhcmdldFBlZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgdGFyZ2V0UGVlckNhY2hlZDogbnVsbCB9O1xuICAgIH07XG4gICAgLy8gaGF2ZSB0byB1c2UgY2FsbGJhY2tzIGhlcmU6IHByb21pc2VzIGRvbid0IHdvcmsgaW4gdGhlIG1haW4gbWVudVxuICAgIFNldHRpbmdzU2VydmljZS5wcm90b3R5cGUuZ2V0VGFyZ2V0UGVlckltcGwgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG1hc3RlckFwaUNsaWVudCA9IHRoaXMubWFrZU1hc3RlckFwaUNsaWVudCgpO1xuICAgICAgICB2YXIgbWFzdGVyS2V5ID0gdGhpcy5nZXRTZXJ2ZXJNYXN0ZXJLZXkoKTtcbiAgICAgICAgdmFyIHNlcnZlckluZm9SZXF1ZXN0VGltZW91dE1zID0gNTAwMDtcbiAgICAgICAgdmFyIGRlZmF1bHRQZWVyID0ge1xuICAgICAgICAgICAgaG9zdDogdGhpcy5zcC5zZXR0aW5nc1snc2t5bXA1LWNsaWVudCddWydzZXJ2ZXItaXAnXSxcbiAgICAgICAgICAgIHBvcnQ6IHRoaXMuc3Auc2V0dGluZ3NbJ3NreW1wNS1jbGllbnQnXVsnc2VydmVyLXBvcnQnXSxcbiAgICAgICAgICAgIHB1YmxpY0tleXM6IHRoaXMuc3Auc2V0dGluZ3NbJ3NreW1wNS1jbGllbnQnXVsnc2VydmVyLXB1YmxpYy1rZXlzJ10sXG4gICAgICAgIH07XG4gICAgICAgIHZhciByZXNvbHZlZCA9IGZhbHNlO1xuICAgICAgICB2YXIgc3RhdGVzID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgX2E7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLnNwLnNldHRpbmdzWydza3ltcDUtY2xpZW50J11bJ3NlcnZlci1pbmZvLWlnbm9yZSddKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgJ1NraXBwaW5nIHNlcnZlcmluZm8gcmVxdWVzdCBkdWUgdG8gc2VydmVyLWluZm8taWdub3JlIGluIGNvbmZpZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVzLnJlc29sdmUoZGVmYXVsdFBlZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoVGltZXJzU2VydmljZSkuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBzdGF0ZXMucmVqZWN0KG5ldyBFcnJvcignZ2V0VGFyZ2V0UGVlcjogc2VydmVyaW5mbyByZXF1ZXN0IHRpbWVkIG91dCcpKTsgfSwgc2VydmVySW5mb1JlcXVlc3RUaW1lb3V0TXMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaGVhZGVycyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2Vzc2lvbiA9IChfYSA9IF90aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoQXV0aFNlcnZpY2UpLnJlYWRBdXRoRGF0YUZyb21EaXNrKCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zZXNzaW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyc1snWC1TZXNzaW9uJ10gPSBzZXNzaW9uO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG1hc3RlckFwaUNsaWVudC5nZXQoXCIvYXBpL3NlcnZlcnMvXCIuY29uY2F0KG1hc3RlcktleSwgXCIvc2VydmVyaW5mb1wiKSwgeyBoZWFkZXJzOiBoZWFkZXJzIH0sIHN0YXRlcy5oYW5kbGVSZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlcy5yZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGhhbmRsZVJlc3BvbnNlOiBmdW5jdGlvbiAocmVzKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlcy5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic3RhdHVzIFwiLmNvbmNhdChyZXMuc3RhdHVzKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc3RhdGVzLnJlc29sdmUoSlNPTi5wYXJzZShyZXMuYm9keSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZXMucmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXNvbHZlOiBmdW5jdGlvbiAodGFyZ2V0UGVlcikge1xuICAgICAgICAgICAgICAgIGlmIChyZXNvbHZlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJSZXNvbHZlZCB0YXJnZXQgcGVlclwiLCB0YXJnZXRQZWVyKTtcbiAgICAgICAgICAgICAgICB2YXIgZW5yaWNoZWRUYXJnZXRQZWVyID0gX19hc3NpZ24oe30sIHRhcmdldFBlZXIpO1xuICAgICAgICAgICAgICAgIGVucmljaGVkVGFyZ2V0UGVlci5wdWJsaWNLZXlzID0gX19hc3NpZ24oX19hc3NpZ24oe30sIGRlZmF1bHRQZWVyLnB1YmxpY0tleXMpLCB0YXJnZXRQZWVyLnB1YmxpY0tleXMpO1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIkVucmljaGVkIHRhcmdldCBwZWVyXCIsIGVucmljaGVkVGFyZ2V0UGVlcik7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZW5yaWNoZWRUYXJnZXRQZWVyKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZWplY3Q6IGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzb2x2ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNvbHZlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiU2VydmVyIGluZm8gcmVxdWVzdCBmYWlsZWQsIGZhbGxpbmcgYmFjayB0b1wiLCBkZWZhdWx0UGVlciwgXCI7IGVycm9yOlwiLCBlcnIpO1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGRlZmF1bHRQZWVyKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHN0YXRlcy5zdGFydCgpO1xuICAgIH07XG4gICAgU2V0dGluZ3NTZXJ2aWNlLnByb3RvdHlwZS5nZXRTZXJ2ZXJNb2RzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbWFzdGVyQXBpQ2xpZW50LCBtYXN0ZXJLZXksIGF0dGVtcHQsIHJlcywgbWFuaWZlc3QsIGVfMTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc3RlckFwaUNsaWVudCA9IHRoaXMubWFrZU1hc3RlckFwaUNsaWVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFzdGVyS2V5ID0gdGhpcy5nZXRTZXJ2ZXJNYXN0ZXJLZXkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByaW50Q29uc29sZShtYXN0ZXJLZXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXR0ZW1wdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKGF0dGVtcHQgPCA1KSkgcmV0dXJuIFszIC8qYnJlYWsqLywgN107XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDI7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnRyeXMucHVzaChbMiwgNCwgLCA2XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmludENvbnNvbGUoXCJUcnlpbmcgdG8gZ2V0IHNlcnZlciBtb2RzLCBhdHRlbXB0IFwiLmNvbmNhdChhdHRlbXB0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBtYXN0ZXJBcGlDbGllbnQuZ2V0KFwiL2FwaS9zZXJ2ZXJzL1wiLmNvbmNhdChtYXN0ZXJLZXksIFwiL21hbmlmZXN0Lmpzb25cIikpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcy5zdGF0dXMgIT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic3RhdHVzIGNvZGUgXCIuY29uY2F0KHJlcy5zdGF0dXMsIFwiLCBlcnJvciBcIikuY29uY2F0KHJlcy5lcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWFuaWZlc3QgPSBKU09OLnBhcnNlKHJlcy5ib2R5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYW5pZmVzdC52ZXJzaW9uTWFqb3IgIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludENvbnNvbGUoXCJzZXJ2ZXIgbWFuaWZlc3QgdmVyc2lvbiBpcyBcIi5jb25jYXQobWFuaWZlc3QudmVyc2lvbk1ham9yLCBcIiwgd2UgZXhwZWN0IDFcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiAvKnJldHVybiovLCBbXV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgbWFuaWZlc3QubW9kc107XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVfMSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByaW50Q29uc29sZShcIlJlcXVlc3QvcGFyc2UgZXJyb3I6IFwiLmNvbmNhdChlXzEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCAvKnlpZWxkKi8sIFV0aWxpdHkud2FpdCgwLjEgKyBNYXRoLnJhbmRvbSgpKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMyAvKmJyZWFrKi8sIDZdO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICArK2F0dGVtcHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzMgLypicmVhayovLCAxXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA3OiByZXR1cm4gWzIgLypyZXR1cm4qLywgW11dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIDtcbiAgICBTZXR0aW5nc1NlcnZpY2UucHJvdG90eXBlLm5vcm1hbGl6ZVVybCA9IGZ1bmN0aW9uICh1cmwpIHtcbiAgICAgICAgaWYgKHVybC5lbmRzV2l0aCgnLycpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsLnNsaWNlKDAsIHVybC5sZW5ndGggLSAxKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXJsO1xuICAgIH07XG4gICAgO1xuICAgIHJldHVybiBTZXR0aW5nc1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTZXR0aW5nc1NlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG5pbXBvcnQgeyBOZXR3b3JraW5nU2VydmljZSB9IGZyb20gXCIuL25ldHdvcmtpbmdTZXJ2aWNlXCI7XG52YXIgU2luZ2xlUGxheWVyU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU2luZ2xlUGxheWVyU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTaW5nbGVQbGF5ZXJTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5faXNTaW5nbGVQbGF5ZXIgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwiZ2FtZUxvYWRcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uR2FtZUxvYWQoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTaW5nbGVQbGF5ZXJTZXJ2aWNlLnByb3RvdHlwZSwgXCJpc1NpbmdsZVBsYXllclwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzU2luZ2xlUGxheWVyO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgU2luZ2xlUGxheWVyU2VydmljZS5wcm90b3R5cGUub25HYW1lTG9hZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmlzQ2F1c2VkQnlTa3lyaW1QbGF0Zm9ybSAmJiAhdGhpcy5faXNTaW5nbGVQbGF5ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuc3AuRGVidWcubWVzc2FnZUJveCgnU2F2ZSBoYXMgYmVlbiBsb2FkZWQgaW4gbXVsdGlwbGF5ZXIsIHN3aXRjaGluZyB0byB0aGUgc2luZ2xlLXBsYXllciBtb2RlJyk7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoTmV0d29ya2luZ1NlcnZpY2UpLmNsb3NlKCk7XG4gICAgICAgICAgICB0aGlzLl9pc1NpbmdsZVBsYXllciA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnNwLkdhbWUuc2V0SW5DaGFyZ2VuKGZhbHNlLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gU2luZ2xlUGxheWVyU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFNpbmdsZVBsYXllclNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBwcmludENvbnNvbGUsIHNldHRpbmdzLCBzdG9yYWdlLCB9IGZyb20gJ3NreXJpbVBsYXRmb3JtJztcbmltcG9ydCAqIGFzIG5ldHdvcmtpbmcgZnJvbSAnLi9uZXR3b3JraW5nU2VydmljZSc7XG5pbXBvcnQgeyBzZXR1cEhvb2tzIH0gZnJvbSAnLi4vLi4vc3luYy9hbmltYXRpb24nO1xuaW1wb3J0IHsgYXV0aEdhbWVEYXRhU3RvcmFnZUtleSB9IGZyb20gJy4uLy4uL2ZlYXR1cmVzL2F1dGhNb2RlbCc7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gJy4vY2xpZW50TGlzdGVuZXInO1xuaW1wb3J0IHsgbG9nVHJhY2UgfSBmcm9tICcuLi8uLi9sb2dnaW5nJztcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gJy4vc2V0dGluZ3NTZXJ2aWNlJztcbnByaW50Q29uc29sZSgnSGVsbG8gTXVsdGlwbGF5ZXIhJyk7XG5wcmludENvbnNvbGUoJ3NldHRpbmdzOicsIHNldHRpbmdzWydza3ltcDUtY2xpZW50J10pO1xudmFyIFNreW1wQ2xpZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTa3ltcENsaWVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTa3ltcENsaWVudChzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwiY29ubmVjdGlvbkZhaWxlZFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25Db25uZWN0aW9uRmFpbGVkKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwiY29ubmVjdGlvbkRlbmllZFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25Db25uZWN0aW9uRGVuaWVkKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLm9uKFwiY3JlYXRlQWN0b3JNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkFjdG9yQ3JlYXRlTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIC8vIFRPRE86IHJlZmFjdG9yIG91dCB2ZXJ5IHNpbWlsYXIgY29kZSBpbiBmcm9udEhvdFJlbG9hZFNlcnZpY2UudHNcbiAgICAgICAgdmFyIGF1dGhHYW1lRGF0YSA9IHN0b3JhZ2VbYXV0aEdhbWVEYXRhU3RvcmFnZUtleV07XG4gICAgICAgIHZhciBzdG9yYWdlSGFzVmFsaWRBdXRoR2FtZURhdGEgPSAoYXV0aEdhbWVEYXRhID09PSBudWxsIHx8IGF1dGhHYW1lRGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogYXV0aEdhbWVEYXRhLmxvY2FsKSB8fCAoYXV0aEdhbWVEYXRhID09PSBudWxsIHx8IGF1dGhHYW1lRGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogYXV0aEdhbWVEYXRhLnJlbW90ZSk7XG4gICAgICAgIGlmIChzdG9yYWdlSGFzVmFsaWRBdXRoR2FtZURhdGEpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlJlY292ZXJlZCBBdXRoR2FtZURhdGEgZnJvbSBzdG9yYWdlLCBzdGFydGluZyBjbGllbnRcIik7XG4gICAgICAgICAgICBfdGhpcy5zdGFydENsaWVudCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiVW5hYmxlIHRvIHJlY292ZXIgQXV0aEdhbWVEYXRhIGZyb20gc3RvcmFnZSwgcmVxdWVzdGluZyBhdXRoXCIpO1xuICAgICAgICAgICAgLy8gTmV4dCB0aWNrIGJlY2F1c2Ugd2UncmUgaW4gY29uc3RydWN0b3Igb2YgdGhlIHNlcnZpY2UsIEF1dGhTZXJ2aWNlIG1heSBub3QgYmUgbGlzdGVuaW5nIGV2ZW50cyB5ZXRcbiAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIub25jZShcInRpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwiYXV0aE5lZWRlZFwiLCB7fSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImF1dGhBdHRlbXB0XCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkF1dGhBdHRlbXB0KGUpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFNreW1wQ2xpZW50LnByb3RvdHlwZS5vbkF1dGhBdHRlbXB0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJDYXVnaHQgYXV0aCBldmVudFwiKTtcbiAgICAgICAgc3RvcmFnZVthdXRoR2FtZURhdGFTdG9yYWdlS2V5XSA9IGUuYXV0aEdhbWVEYXRhO1xuICAgICAgICB0aGlzLnN0YXJ0Q2xpZW50KCk7XG4gICAgICAgIC8vIFRPRE86IHJlbW92ZSB0aGlzIHdoZW4geW91IHdpbGwgYmUgYWJsZSB0byBzZWUgZXJyb3JzIHdpdGhvdXQgY29uc29sZVxuICAgICAgICAvLyB0aGlzLnNwLmJyb3dzZXIuc2V0Rm9jdXNlZChmYWxzZSk7XG4gICAgfTtcbiAgICBTa3ltcENsaWVudC5wcm90b3R5cGUub25BY3RvckNyZWF0ZU1lc3NhZ2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS5tZXNzYWdlLmlzTWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3AuYnJvd3Nlci5zZXRGb2N1c2VkKGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2t5bXBDbGllbnQucHJvdG90eXBlLm9uQ29ubmVjdGlvbkZhaWxlZCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiQ29ubmVjdGlvbiBmYWlsZWRcIik7XG4gICAgfTtcbiAgICBTa3ltcENsaWVudC5wcm90b3R5cGUub25Db25uZWN0aW9uRGVuaWVkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJDb25uZWN0aW9uIGRlbmllZDogXCIgKyBlLmVycm9yKTtcbiAgICB9O1xuICAgIFNreW1wQ2xpZW50LnByb3RvdHlwZS5zdGFydENsaWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gb25jZShcInRpY2tcIiwgLi4uKSBpcyBuZWVkZWQgdG8gZW5zdXJlIG5ldHdvcmtpbmcgc2VydmljZSBpbml0aWFsaXplZFxuICAgICAgICB0aGlzLmNvbnRyb2xsZXIub25jZShcInRpY2tcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZXN0YWJsaXNoQ29ubmVjdGlvbkNvbmRpdGlvbmFsKCk7IH0pO1xuICAgICAgICB0aGlzLmN0b3IoKTtcbiAgICB9O1xuICAgIFNreW1wQ2xpZW50LnByb3RvdHlwZS5jdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBUT0RPOiByZWZhY3RvciBpbnRvIHNlcnZpY2VcbiAgICAgICAgc2V0dXBIb29rcygpO1xuICAgICAgICB0aGlzLnNwLnByaW50Q29uc29sZSgnU2t5bXBDbGllbnQgY3RvcicpO1xuICAgIH07XG4gICAgU2t5bXBDbGllbnQucHJvdG90eXBlLmVzdGFibGlzaENvbm5lY3Rpb25Db25kaXRpb25hbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGlzQ29ubmVjdGVkID0gdGhpcy5jb250cm9sbGVyLmxvb2t1cExpc3RlbmVyKG5ldHdvcmtpbmcuTmV0d29ya2luZ1NlcnZpY2UpLmlzQ29ubmVjdGVkKCk7XG4gICAgICAgIGlmIChpc0Nvbm5lY3RlZCkge1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ1JlY29ubmVjdCBpcyBub3QgcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoU2V0dGluZ3NTZXJ2aWNlKS5nZXRUYXJnZXRQZWVyKGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIGhvc3QgPSBfYS5ob3N0LCBwb3J0ID0gX2EucG9ydDtcbiAgICAgICAgICAgIHN0b3JhZ2UudGFyZ2V0SXAgPSBob3N0O1xuICAgICAgICAgICAgc3RvcmFnZS50YXJnZXRQb3J0ID0gcG9ydDtcbiAgICAgICAgICAgIHByaW50Q29uc29sZShcIkNvbm5lY3RpbmcgdG8gXCIuY29uY2F0KGhvc3QsIFwiOlwiKS5jb25jYXQocG9ydCkpO1xuICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihuZXR3b3JraW5nLk5ldHdvcmtpbmdTZXJ2aWNlKS5jb25uZWN0KGhvc3QsIHBvcnQpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBTa3ltcENsaWVudDtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFNreW1wQ2xpZW50IH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgTXNnVHlwZSB9IGZyb20gXCIuLi8uLi9tZXNzYWdlc1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuLy8gVE9ETzogcmVmYWN0b3Igd29ybGRWaWV3TWlzYyBpbnRvIHNlcnZpY2VcbmltcG9ydCB7IHJlbW90ZUlkVG9Mb2NhbElkIH0gZnJvbSAnLi4vLi4vdmlldy93b3JsZFZpZXdNaXNjJztcbmltcG9ydCB7IGxvZ0Vycm9yLCBsb2dUcmFjZSB9IGZyb20gXCIuLi8uLi9sb2dnaW5nXCI7XG5pbXBvcnQgeyBXb3JsZFZpZXcgfSBmcm9tIFwiLi4vLi4vdmlldy93b3JsZFZpZXdcIjtcbnZhciBTcFNuaXBwZXRTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTcFNuaXBwZXRTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNwU25pcHBldFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcInNwU25pcHBldE1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uU3BTbmlwcGV0TWVzc2FnZShlKTsgfSk7XG4gICAgICAgIF90aGlzLnNwQW55ID0gc3A7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU3BTbmlwcGV0U2VydmljZS5wcm90b3R5cGUub25TcFNuaXBwZXRNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICB0aGlzLmNvbnRyb2xsZXIub25jZSgndXBkYXRlJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX19hd2FpdGVyKF90aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bihtc2cpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlzTm9SZXN1bHRTbmlwcGV0ID0gbXNnLnNuaXBwZXRJZHggPT09IDB4ZmZmZmZmZmY7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc05vUmVzdWx0U25pcHBldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzICE9PSBudWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAmJiB0eXBlb2YgcmVzICE9PSBcIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAmJiB0eXBlb2YgcmVzICE9PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAmJiB0eXBlb2YgcmVzICE9PSBcImJvb2xlYW5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nRXJyb3IoX3RoaXMsIFwiVW5zdXBwb3J0ZWQgU3BTbmlwcGV0IHJlc3VsdCB0eXBlICdcIi5jb25jYXQodHlwZW9mIHJlcywgXCInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZSA9IHJlcyA9PT0gbnVsbCA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuRmluaXNoU3BTbmlwcGV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgc25pcHBldElkeDogbXNnLnNuaXBwZXRJZHhcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdDogTXNnVHlwZS5GaW5pc2hTcFNuaXBwZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuVmFsdWU6IHJlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbmlwcGV0SWR4OiBtc2cuc25pcHBldElkeCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5lbWl0KFwic2VuZE1lc3NhZ2VcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbGlhYmlsaXR5OiBcInJlbGlhYmxlXCJcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKF90aGlzLCAnU3BTbmlwcGV0ICcgKyBtc2cuY2xhc3MgKyAnICcgKyBtc2cuZnVuY3Rpb24gKyAnIGZhaWxlZCAnICsgZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi9dO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pOyB9KTtcbiAgICB9O1xuICAgIFNwU25pcHBldFNlcnZpY2UucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uIChzbmlwcGV0KSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGZ1bmN0aW9uTG93ZXJDYXNlLCBjbGFzc0xvd2VyQ2FzZSwgbmV3TmFtZSwgc2VsZklkLCBzZWxmLCByZXBsYWNlVmFsdWUsIHdvcmxkVmlld18xLCBmb3JtLCBzaWduLCBjb3VudCwgc291bmRJZCwgc291bmQsIG5hbWUsIG5hbWU7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYikge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uTG93ZXJDYXNlID0gc25pcHBldC5mdW5jdGlvbi50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGNsYXNzTG93ZXJDYXNlID0gc25pcHBldC5jbGFzcy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIC8vIGtlZXAgaW4gc3luYyB3aXRoIHJlbW90ZVNlcnZlci50c1xuICAgICAgICAgICAgICAgIGlmIChjbGFzc0xvd2VyQ2FzZSA9PT0gXCJvYmplY3RyZWZlcmVuY2VcIikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnVuY3Rpb25Mb3dlckNhc2UgPT09IFwic2V0ZGlzcGxheW5hbWVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3TmFtZSA9IHNuaXBwZXQuYXJndW1lbnRzWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdOYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZklkID0gcmVtb3RlSWRUb0xvY2FsSWQoc25pcHBldC5zZWxmSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzLnNwLk9iamVjdFJlZmVyZW5jZS5mcm9tKHRoaXMuc3AuR2FtZS5nZXRGb3JtRXgoc2VsZklkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZVZhbHVlID0gKF9hID0gc2VsZiA9PT0gbnVsbCB8fCBzZWxmID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzZWxmLmdldEJhc2VPYmplY3QoKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldE5hbWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwbGFjZVZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3TmFtZSA9IG5ld05hbWUucmVwbGFjZSgvJW9yaWdpbmFsX25hbWUlL2csIHJlcGxhY2VWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNuaXBwZXQuYXJndW1lbnRzWzBdID0gbmV3TmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiQ291bGRuJ3QgZ2V0IGEgcmVwbGFjZVZhbHVlIGZvciBTZXREaXNwbGF5TmFtZSwgc25pcHBldC5zZWxmSWQgd2FzXCIsIHNuaXBwZXQuc2VsZklkLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJFbmNvdW50ZXJlZCBTZXREaXNwbGF5TmFtZSB3aXRoIG5vbi1zdHJpbmcgYXJndW1lbnRcIiwgbmV3TmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzTG93ZXJDYXNlID09PSBcImdhbWVcIikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnVuY3Rpb25Mb3dlckNhc2UgPT09IFwic2hvd3JhY2VtZW51XCIgfHwgZnVuY3Rpb25Mb3dlckNhc2UgPT09IFwic2hvd2xpbWl0ZWRyYWNlbWVudVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcInNob3dyYWNlbWVudSBjYWxsZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JsZFZpZXdfMSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihXb3JsZFZpZXcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRWaWV3XzEuc2V0Rm9ybVZpZXdVcGRhdGVBbGxvd2VkKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiV2FpdGluZyAxLjBzIGJlZm9yZSBjYWxsaW5nIHNob3dyYWNlbWVudVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3AuVXRpbGl0eS53YWl0KDEuMCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucnVuU3RhdGljKHNuaXBwZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkVmlld18xLndhaXRHYW1lVGltZUFuZEFsbG93Rm9ybVZpZXdVcGRhdGUoMS4wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi9dO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjbGFzc0xvd2VyQ2FzZSA9PT0gXCJza3ltcGhhY2tzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZ1bmN0aW9uTG93ZXJDYXNlID09PSBcImFkZGl0ZW1cIiB8fCBmdW5jdGlvbkxvd2VyQ2FzZSA9PT0gXCJyZW1vdmVpdGVtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm0gPSB0aGlzLnNwLkZvcm0uZnJvbSh0aGlzLmRlc2VyaWFsaXplQXJnKHNuaXBwZXQuYXJndW1lbnRzWzBdKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9ybSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiVW5hYmxlIHRvIGZpbmQgZm9ybSB3aXRoIGlkIFwiICsgc25pcHBldC5hcmd1bWVudHNbMF0uZm9ybUlkLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi9dO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2lnbiA9IHNuaXBwZXQuZnVuY3Rpb24gPT09IFwiQWRkSXRlbVwiID8gXCIrXCIgOiBcIi1cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ID0gc25pcHBldC5hcmd1bWVudHNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VuZElkID0gMHgzMzRhYjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb3JtLmdldEZvcm1JRCgpICE9PSAweGYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VuZElkID0gMHgxNDExNTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNvdW5kID0gdGhpcy5zcC5Tb3VuZC5mcm9tKHRoaXMuc3AuR2FtZS5nZXRGb3JtRXgoc291bmRJZCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNvdW5kICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9IGZvcm0uZ2V0TmFtZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYW1lLnRyaW0oKSA9PT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlNvdW5kIHdpbGwgbm90IGJlIHBsYXllZCBiZWNhdXNlIGl0ZW0gaGFzIG5vIG5hbWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VuZC5wbGF5KHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJVbmFibGUgdG8gZmluZCBzb3VuZCB3aXRoIGlkIFwiICsgc291bmRJZC50b1N0cmluZygxNikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50IDw9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIlBvc2l0aXZlIGNvdW50IGV4cGVjdGVkLCBnb3QgXCIgKyBjb3VudC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBmb3JtLmdldE5hbWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmFtZS50cmltKCkgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJOb3RpZmljYXRpb24gd2lsbCBub3QgYmUgc2hvd24gYmVjYXVzZSBpdGVtIGhhcyBubyBuYW1lXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zcC5EZWJ1Zy5ub3RpZmljYXRpb24oc2lnbiArIFwiIFwiICsgbmFtZSArIFwiIChcIiArIGNvdW50ICsgXCIpXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBzaWduICsgXCIgXCIgKyBuYW1lICsgXCIgKFwiICsgY291bnQgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBTa3ltcEhhY2sgLSBcIiArIHNuaXBwZXQuZnVuY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qL107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbMiAvKnJldHVybiovLCBzbmlwcGV0LnNlbGZJZCA/IHRoaXMucnVuTWV0aG9kKHNuaXBwZXQpIDogdGhpcy5ydW5TdGF0aWMoc25pcHBldCldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgO1xuICAgIFNwU25pcHBldFNlcnZpY2UucHJvdG90eXBlLmRlc2VyaWFsaXplQXJnID0gZnVuY3Rpb24gKGFyZykge1xuICAgICAgICBpZiAodHlwZW9mIGFyZyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgdmFyIGZvcm1JZCA9IHJlbW90ZUlkVG9Mb2NhbElkKGFyZy5mb3JtSWQpO1xuICAgICAgICAgICAgdmFyIGZvcm0gPSB0aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KGZvcm1JZCk7XG4gICAgICAgICAgICB2YXIgY2wgPSB0aGlzLnNwQW55W2FyZy50eXBlXTtcbiAgICAgICAgICAgIGlmICghY2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2hpbmdLZXkgPSBPYmplY3Qua2V5cyh0aGlzLnNwQW55KS5maW5kKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtleS50b0xvd2VyQ2FzZSgpID09PSBhcmcudHlwZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChtYXRjaGluZ0tleSkge1xuICAgICAgICAgICAgICAgICAgICBjbCA9IHRoaXMuc3BBbnlbbWF0Y2hpbmdLZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY2wpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkZXNlcmlhbGl6ZUFyZyAtIENsYXNzIFwiLmNvbmNhdChhcmcudHlwZSwgXCIgbm90IGZvdW5kXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBnYW1lT2JqZWN0ID0gY2wuZnJvbShmb3JtKTtcbiAgICAgICAgICAgIHJldHVybiBnYW1lT2JqZWN0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcmc7XG4gICAgfTtcbiAgICA7XG4gICAgU3BTbmlwcGV0U2VydmljZS5wcm90b3R5cGUucnVuTWV0aG9kID0gZnVuY3Rpb24gKHNuaXBwZXQpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGZJZCwgc2VsZiwgY2wsIG1hdGNoaW5nS2V5LCBzZWxmQ2FzdGVkLCBmO1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGZJZCA9IHJlbW90ZUlkVG9Mb2NhbElkKHNuaXBwZXQuc2VsZklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KHNlbGZJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIGZpbmQgZm9ybSB3aXRoIGlkIFwiLmNvbmNhdChzZWxmSWQudG9TdHJpbmcoMTYpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbCA9IHRoaXMuc3BBbnlbc25pcHBldC5jbGFzc107XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdLZXkgPSBPYmplY3Qua2V5cyh0aGlzLnNwQW55KS5maW5kKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtleS50b0xvd2VyQ2FzZSgpID09PSBzbmlwcGV0LmNsYXNzLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoaW5nS2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsID0gdGhpcy5zcEFueVttYXRjaGluZ0tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInJ1bk1ldGhvZCAtIENsYXNzIFwiLmNvbmNhdChzbmlwcGV0LmNsYXNzLCBcIiBub3QgZm91bmQsIGZvdW5kXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGZDYXN0ZWQgPSBjbC5mcm9tKHNlbGYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmQ2FzdGVkKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZvcm0gXCIuY29uY2F0KHNlbGZJZC50b1N0cmluZygxNiksIFwiIGlzIG5vdCBpbnN0YW5jZSBvZiBcIikuY29uY2F0KHNuaXBwZXQuY2xhc3MsIFwiLCBmb3JtIHR5cGUgaXMgXCIpLmNvbmNhdChzZWxmLmdldFR5cGUoKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZiA9IHNlbGZDYXN0ZWRbc25pcHBldC5mdW5jdGlvbl07XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBmLmFwcGx5KHNlbGZDYXN0ZWQsIHNuaXBwZXQuYXJndW1lbnRzLm1hcChmdW5jdGlvbiAoYXJnKSB7IHJldHVybiBfdGhpcy5kZXNlcmlhbGl6ZUFyZyhhcmcpOyB9KSldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6IHJldHVybiBbMiAvKnJldHVybiovLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIDtcbiAgICBTcFNuaXBwZXRTZXJ2aWNlLnByb3RvdHlwZS5ydW5TdGF0aWMgPSBmdW5jdGlvbiAoc25pcHBldCkge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcGFweXJ1c0NsYXNzO1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcHlydXNDbGFzcyA9IHRoaXMuc3BBbnlbc25pcHBldC5jbGFzc107XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBwYXB5cnVzQ2xhc3Nbc25pcHBldC5mdW5jdGlvbl0uYXBwbHkocGFweXJ1c0NsYXNzLCBzbmlwcGV0LmFyZ3VtZW50cy5tYXAoZnVuY3Rpb24gKGFyZykgeyByZXR1cm4gX3RoaXMuZGVzZXJpYWxpemVBcmcoYXJnKTsgfSkpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOiByZXR1cm4gWzIgLypyZXR1cm4qLywgX2Euc2VudCgpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICA7XG4gICAgcmV0dXJuIFNwU25pcHBldFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTcFNuaXBwZXRTZXJ2aWNlIH07XG47XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgcmVxdWlyZWRWZXJzaW9uIH0gZnJvbSBcIi4uLy4uL3ZlcnNpb25cIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBTcFZlcnNpb25DaGVja1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNwVmVyc2lvbkNoZWNrU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTcFZlcnNpb25DaGVja1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIGNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vbmNlVXBkYXRlKCk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFNwVmVyc2lvbkNoZWNrU2VydmljZS5wcm90b3R5cGUub25jZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlYWxWZXJzaW9uID0gdGhpcy5zcC5nZXRQbGF0Zm9ybVZlcnNpb24oKTtcbiAgICAgICAgaWYgKCFyZXF1aXJlZFZlcnNpb24uaW5jbHVkZXMocmVhbFZlcnNpb24pKSB7XG4gICAgICAgICAgICB0aGlzLnNwLkRlYnVnLm1lc3NhZ2VCb3goXCJZb3UgbmVlZCB0byBoYXZlIG9uIG9mIHRob3NlIFNreXJpbVBsYXRmb3JtIHZlcnNpb25zIFwiLmNvbmNhdChKU09OLnN0cmluZ2lmeShyZXF1aXJlZFZlcnNpb24pLCBcIiB0byBqb2luIHRoaXMgc2VydmVyLiBZb3VyIGN1cnJlbnQgdmVyc2lvbiBpcyBcIikuY29uY2F0KHJlYWxWZXJzaW9uKSk7XG4gICAgICAgICAgICB0aGlzLnNwLlV0aWxpdHkud2FpdE1lbnVNb2RlKDAuNSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbigndXBkYXRlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLnNwLlVpLmlzTWVudU9wZW4oJ01lc3NhZ2VCb3hNZW51JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNwLkdhbWUucXVpdFRvTWFpbk1lbnUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBTcFZlcnNpb25DaGVja1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTcFZlcnNpb25DaGVja1NlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBNc2dUeXBlIH0gZnJvbSBcIi4uLy4uL21lc3NhZ2VzXCI7XG5pbXBvcnQgeyBsb2dUcmFjZSwgbG9nRXJyb3IgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcImZzXCI7XG52YXIgcGxheWVySWQgPSAweDE0O1xudmFyIHRyYW5zbGF0aW9ucyA9IHtcbiAgICBcInJ1XCI6IHtcbiAgICAgICAgcHJlc3NTcGFjZTogJ9Cf0YDQvtCx0LXQuywg0YfRgtC+0LHRiyDQstGL0LnRgtC4INC40Lcg0LDQvdC40LzQsNGG0LjQuCdcbiAgICB9LFxuICAgIFwiZW5cIjoge1xuICAgICAgICBwcmVzc1NwYWNlOiAnU3BhY2UgdG8gZXhpdCBhbmltYXRpb24nXG4gICAgfSxcbn07XG52YXIgc3RyaW5ncyA9IHRyYW5zbGF0aW9uc1snZW4nXTtcbnRyeSB7XG4gICAgdmFyIGxhbmcgPSBmcy5yZWFkRmlsZVN5bmMoJy4vRGF0YS9QbGF0Zm9ybS9EaXN0cmlidXRpb24vbG9jYWxlJywgJ3V0ZjgnKS50cmltKCk7XG4gICAgaWYgKGxhbmcgaW4gdHJhbnNsYXRpb25zKSB7XG4gICAgICAgIHN0cmluZ3MgPSB0cmFuc2xhdGlvbnNbbGFuZ107XG4gICAgfVxufVxuY2F0Y2ggKF9hKSB7XG4gICAgLy8gbG9jYWxlIGZpbGUgbm90IGZvdW5kIG9yIHVucmVhZGFibGUsIGRlZmF1bHQgdG8gJ2VuJ1xufVxuLy8gZXggQW5pbURlYnVnU2VydmljZSBwYXJ0XG52YXIgU3dlZXRDYW1lcmFFbmZvcmNlbWVudFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5jdXJyZW50QW5pbSA9IG51bGw7XG4gICAgICAgIF90aGlzLnN0b3BBbmltSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5leGl0QW5pbU5hbWUgPSBudWxsO1xuICAgICAgICBfdGhpcy5pbnRlcnJ1cHRBbmltTmFtZSA9IG51bGw7XG4gICAgICAgIF90aGlzLnRyeUludm9rZUFuaW1Db3VudCA9IDA7XG4gICAgICAgIF90aGlzLmxhc3ROb3RpZmljYXRpb25Nb21lbnQgPSAwO1xuICAgICAgICBfdGhpcy50cnlJbnZva2VBbmltQ291bnRNYXggPSAxMDAwMDAwMDAwO1xuICAgICAgICBfdGhpcy5leGl0QW5pbUV2ZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICBfdGhpcy5vcHRpb25zQ2FjaGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIF90aGlzLm9wdGlvbkNiID0gdW5kZWZpbmVkO1xuICAgICAgICBfdGhpcy51c2VQbGF5ZXJDb250cm9sc0RlbGF5TXMgPSB0cnVlO1xuICAgICAgICB2YXIgaGFzU3dlZXRQaWUgPSBfdGhpcy5oYXNTd2VldFBpZSgpO1xuICAgICAgICBpZiAoIWhhc1N3ZWV0UGllKSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJTd2VldFRhZmZ5IGZlYXR1cmVzIGRpc2FibGVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiU3dlZXRUYWZmeSBmZWF0dXJlcyBlbmFibGVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIF90aGlzLnNldHRpbmdzID0gX3RoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wiYW5pbURlYnVnXCJdO1xuICAgICAgICBpZiAoaGFzU3dlZXRQaWUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmXzEgPSBfdGhpcztcbiAgICAgICAgICAgIF90aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgICAgIGVudGVyOiBmdW5jdGlvbiAoY3R4KSB7IH0sXG4gICAgICAgICAgICAgICAgbGVhdmU6IGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZl8xLm9uU2VuZEFuaW1hdGlvbkV2ZW50TGVhdmUoY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZl8xLm9uU2VuZEV4aXRBbmltYXRpb25FdmVudExlYXZlKGN0eCk7IC8vIFRyYWNraW5nIHRoZSBzdWNjZXNzZnVsIGxhdW5jaCBvZiB0aGUgZXhpdCBhbmltYXRpb25cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSwgcGxheWVySWQsIHBsYXllcklkKTtcbiAgICAgICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJidXR0b25FdmVudFwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25CdXR0b25FdmVudChlKTsgfSk7XG4gICAgICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJjdXN0b21QYWNrZXRNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkN1c3RvbVBhY2tldE1lc3NhZ2UyKGUpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlLnByb3RvdHlwZS5vbkN1c3RvbVBhY2tldE1lc3NhZ2UyID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNvbnRlbnQgPSB7fTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBKU09OLnBhcnNlKGUubWVzc2FnZS5jb250ZW50SnNvbkR1bXApO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBTeW50YXhFcnJvcikge1xuICAgICAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiRmFpbGVkIHRvIHBhcnNlIGN1c3RvbSBwYWNrZXQgY29udGVudEpzb25EdW1wOlwiLCBlLm1lc3NhZ2UuY29udGVudEpzb25EdW1wLCBcIkVycm9yOlwiLCBlcnIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29udGVudFtcImN1c3RvbVBhY2tldFR5cGVcIl0gIT09IFwiaW52b2tlQW5pbVwiKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJSZWNlaXZlZCBjdXN0b20gcGFja2V0IHdpdGggY3VzdG9tUGFja2V0VHlwZSBpbnZva2VBbmltXCIpO1xuICAgICAgICB2YXIgbmFtZSA9IGNvbnRlbnRbXCJhbmltRXZlbnROYW1lXCJdO1xuICAgICAgICB2YXIgcmVxdWVzdElkID0gY29udGVudFtcInJlcXVlc3RJZFwiXTtcbiAgICAgICAgdmFyIHdlYXBvbkRyYXduQWxsb3dlZCA9IGNvbnRlbnRbXCJ3ZWFwb25EcmF3bkFsbG93ZWRcIl07XG4gICAgICAgIHZhciBmdXJuaXR1cmVBbGxvd2VkID0gY29udGVudFtcImZ1cm5pdHVyZUFsbG93ZWRcIl07XG4gICAgICAgIHZhciBleGl0QW5pbU5hbWUgPSBjb250ZW50W1wiZXhpdEFuaW1OYW1lXCJdO1xuICAgICAgICB2YXIgaW50ZXJydXB0QW5pbU5hbWUgPSBjb250ZW50W1wiaW50ZXJydXB0QW5pbU5hbWVcIl07XG4gICAgICAgIHZhciB0aW1lTXMgPSBjb250ZW50W1widGltZU1zXCJdO1xuICAgICAgICB2YXIgaXNQbGF5RXhpdEFuaW1BZnRlcndhcmRzRW5hYmxlZCA9IGNvbnRlbnRbXCJpc1BsYXlFeGl0QW5pbUFmdGVyd2FyZHNFbmFibGVkXCJdO1xuICAgICAgICB2YXIgcGFyZW50QW5pbUV2ZW50TmFtZSA9IGNvbnRlbnRbXCJwYXJlbnRBbmltRXZlbnROYW1lXCJdO1xuICAgICAgICB2YXIgZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zID0gY29udGVudFtcImVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNc1wiXTtcbiAgICAgICAgdmFyIHByZWZlckludGVycnVwdEFuaW1Bc0V4aXRBbmltVGltZU1zID0gY29udGVudFtcInByZWZlckludGVycnVwdEFuaW1Bc0V4aXRBbmltVGltZU1zXCJdO1xuICAgICAgICB2YXIgcHJldmVudE1hbnVhbEludGVycnVwdCA9IGNvbnRlbnRbXCJwcmV2ZW50TWFudWFsSW50ZXJydXB0XCJdO1xuICAgICAgICBpZiAodHlwZW9mIG5hbWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiRXhwZWN0ZWQgYW5pbUV2ZW50TmFtZSB0byBiZSBzdHJpbmdcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiByZXF1ZXN0SWQgIT09IFwic3RyaW5nXCIgJiYgdHlwZW9mIHJlcXVlc3RJZCAhPT0gXCJudW1iZXJcIiAmJiB0eXBlb2YgcmVxdWVzdElkICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIkV4cGVjdGVkIHJlcXVlc3RJZCB0byBiZSBzdHJpbmcgb3IgbnVtYmVyIG9yIHVuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJUcnlpbmcgdG8gaW52b2tlIGFuaW1cIiwgbmFtZSwgXCJ3aXRoIHdlYXBvbkRyYXduQWxsb3dlZD1cIiwgd2VhcG9uRHJhd25BbGxvd2VkLCBcIiwgZnVybml0dXJlQWxsb3dlZD1cIiwgZnVybml0dXJlQWxsb3dlZCwgXCIsIGV4aXRBbmltTmFtZT1cIiwgZXhpdEFuaW1OYW1lLCBcIiwgaW50ZXJydXB0QW5pbU5hbWU9XCIsIGludGVycnVwdEFuaW1OYW1lLCBcIiwgdGltZU1zPVwiLCB0aW1lTXMsIFwiLCBpc1BsYXlFeGl0QW5pbUFmdGVyd2FyZHNFbmFibGVkPVwiLCBpc1BsYXlFeGl0QW5pbUFmdGVyd2FyZHNFbmFibGVkLCBcIiwgcGFyZW50QW5pbUV2ZW50TmFtZT1cIiwgcGFyZW50QW5pbUV2ZW50TmFtZSwgXCIsIGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNcz1cIiwgZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zLCBcIiwgcHJlZmVySW50ZXJydXB0QW5pbUFzRXhpdEFuaW1UaW1lTXM9XCIsIHByZWZlckludGVycnVwdEFuaW1Bc0V4aXRBbmltVGltZU1zLCBcIiwgcHJldmVudE1hbnVhbEludGVycnVwdD1cIiwgcHJldmVudE1hbnVhbEludGVycnVwdCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gX3RoaXMudHJ5SW52b2tlQW5pbShuYW1lLCB7IHdlYXBvbkRyYXduQWxsb3dlZDogd2VhcG9uRHJhd25BbGxvd2VkLCBmdXJuaXR1cmVBbGxvd2VkOiBmdXJuaXR1cmVBbGxvd2VkLCBleGl0QW5pbU5hbWU6IGV4aXRBbmltTmFtZSwgaW50ZXJydXB0QW5pbU5hbWU6IGludGVycnVwdEFuaW1OYW1lLCB0aW1lTXM6IHRpbWVNcywgaXNQbGF5RXhpdEFuaW1BZnRlcndhcmRzRW5hYmxlZDogaXNQbGF5RXhpdEFuaW1BZnRlcndhcmRzRW5hYmxlZCwgcGFyZW50QW5pbUV2ZW50TmFtZTogcGFyZW50QW5pbUV2ZW50TmFtZSwgZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zOiBlbmFibGVQbGF5ZXJDb250cm9sc0RlbGF5TXMsIHByZWZlckludGVycnVwdEFuaW1Bc0V4aXRBbmltVGltZU1zOiBwcmVmZXJJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbVRpbWVNcywgcHJldmVudE1hbnVhbEludGVycnVwdDogcHJldmVudE1hbnVhbEludGVycnVwdCB9KTtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0ge1xuICAgICAgICAgICAgICAgIHQ6IE1zZ1R5cGUuQ3VzdG9tUGFja2V0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnRKc29uRHVtcDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBjdXN0b21QYWNrZXRUeXBlOiBcImludm9rZUFuaW1SZXN1bHRcIixcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0OiByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZDogcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5lbWl0dGVyLmVtaXQoXCJzZW5kTWVzc2FnZVwiLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICByZWxpYWJpbGl0eTogXCJyZWxpYWJsZVwiLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU3dlZXRDYW1lcmFFbmZvcmNlbWVudFNlcnZpY2UucHJvdG90eXBlLm9uU2VuZEFuaW1hdGlvbkV2ZW50TGVhdmUgPSBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBhbmltTG93ZXJDYXNlID0gY3R4LmFuaW1FdmVudE5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKGFuaW1Mb3dlckNhc2Uuc3RhcnRzV2l0aChcImlkbGVcIikgJiYgIWFuaW1Mb3dlckNhc2Uuc3RhcnRzV2l0aChcImlkbGVmb3JjZWRlZmF1bHRzdGF0ZVwiKSkge1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIG9ubHkgZm9yIHBsYXllci5wbGF5aWRsZVxuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuc3AuVWkuaXNNZW51T3BlbihcIkNvbnNvbGVcIiAvKiBNZW51LkNvbnNvbGUgKi8pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKChfYSA9IF90aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRGdXJuaXR1cmVSZWZlcmVuY2UoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIkZvcmNpbmcgdGhpcmQgcGVyc29uIGFuZCBkaXNhYmxpbmcgcGxheWVyIGNvbnRyb2xzXCIpO1xuICAgICAgICAgICAgICAgIF90aGlzLnNwLkdhbWUuZm9yY2VUaGlyZFBlcnNvbigpO1xuICAgICAgICAgICAgICAgIF90aGlzLnNwLkdhbWUuZGlzYWJsZVBsYXllckNvbnRyb2xzKHRydWUsIGZhbHNlLCB0cnVlLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIDApO1xuICAgICAgICAgICAgICAgIF90aGlzLmN1cnJlbnRBbmltID0geyBuYW1lOiBjdHguYW5pbUV2ZW50TmFtZSwgb3B0aW9uczogbnVsbCwgcHJlZmVySW50ZXJydXB0QW5pbVN0YXRlOiBudWxsIH07XG4gICAgICAgICAgICAgICAgX3RoaXMuc3RhcnRBbnRpRXhwbG9pdFBvbGxpbmcoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTd2VldENhbWVyYUVuZm9yY2VtZW50U2VydmljZS5wcm90b3R5cGUuZXhpdEFuaW0gPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICAvLyBUT0RPKDEpOiBTZWUgYW5vdGhlciBUT0RPKDEpIGluIHRoaXMgZmlsZVxuICAgICAgICBpZiAob3B0aW9ucy5wbGF5RXhpdEFuaW0pIHtcbiAgICAgICAgICAgIHZhciB1c2VJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMudXNlSW50ZXJydXB0QW5pbUFzRXhpdEFuaW0pIHtcbiAgICAgICAgICAgICAgICB1c2VJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbSA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy51c2VQbGF5ZXJDb250cm9sc0RlbGF5TXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlVzaW5nIGludGVycnVwdCBhbmltIGFzIGV4aXQgYW5pbTogXCIuY29uY2F0KHRoaXMuaW50ZXJydXB0QW5pbU5hbWUsIFwiLiBSZWFzb246IHVzZUludGVycnVwdEFuaW1Bc0V4aXRBbmltIGlzIHRydWVcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKChfYiA9IChfYSA9IHRoaXMuY3VycmVudEFuaW0pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5wcmVmZXJJbnRlcnJ1cHRBbmltU3RhdGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5wcmVmZXIpIHtcbiAgICAgICAgICAgICAgICB1c2VJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbSA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy51c2VQbGF5ZXJDb250cm9sc0RlbGF5TXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlVzaW5nIGludGVycnVwdCBhbmltIGFzIGV4aXQgYW5pbTogXCIuY29uY2F0KHRoaXMuaW50ZXJydXB0QW5pbU5hbWUsIFwiLiBSZWFzb246IHByZWZlckludGVycnVwdEFuaW1TdGF0ZS5wcmVmZXIgaXMgdHJ1ZVwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYW5pbUV2ZW50VG9TZW5kID0gdXNlSW50ZXJydXB0QW5pbUFzRXhpdEFuaW0gPyAodGhpcy5pbnRlcnJ1cHRBbmltTmFtZSB8fCBcIklkbGVTdG9wXCIpIDogKHRoaXMuZXhpdEFuaW1OYW1lIHx8IFwiSWRsZUZvcmNlRGVmYXVsdFN0YXRlXCIpO1xuICAgICAgICAgICAgdGhpcy5zcC5EZWJ1Zy5zZW5kQW5pbWF0aW9uRXZlbnQodGhpcy5zcC5HYW1lLmdldFBsYXllcigpLCBhbmltRXZlbnRUb1NlbmQpO1xuICAgICAgICAgICAgdGhpcy5leGl0QW5pbUV2ZW50ID0gYW5pbUV2ZW50VG9TZW5kO1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zQ2FjaGUgPSBvcHRpb25zO1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgXCJTZW50IGFuaW1hdGlvbiBldmVudDpcIiwgYW5pbUV2ZW50VG9TZW5kKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEFuaW0gPSBudWxsO1xuICAgICAgICAgICAgdmFyIGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlTZWNvbmRzID0gKHR5cGVvZiBvcHRpb25zLmVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNcyA9PT0gXCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICYmIG9wdGlvbnMuZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zID4gMFxuICAgICAgICAgICAgICAgICYmIE51bWJlci5pc0Zpbml0ZShvcHRpb25zLmVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNcylcbiAgICAgICAgICAgICAgICAmJiB0aGlzLnVzZVBsYXllckNvbnRyb2xzRGVsYXlNcylcbiAgICAgICAgICAgICAgICA/IG9wdGlvbnMuZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zIC8gMTAwMFxuICAgICAgICAgICAgICAgIDogMC41O1xuICAgICAgICAgICAgdmFyIHN0b3BBbmltRGVsYXlTZWNvbmRzID0gZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheVNlY29uZHMgKyAwLjU7XG4gICAgICAgICAgICB0aGlzLnN0b3BBbmltSW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnNwLlV0aWxpdHkud2FpdChlbmFibGVQbGF5ZXJDb250cm9sc0RlbGF5U2Vjb25kcykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc3AuR2FtZS5lbmFibGVQbGF5ZXJDb250cm9scyh0cnVlLCBmYWxzZSwgdHJ1ZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCAwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zcC5VdGlsaXR5LndhaXQoc3RvcEFuaW1EZWxheVNlY29uZHMpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnN0b3BBbmltSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5vcHRpb25DYikge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcHRpb25DYigpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcHRpb25DYiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU3dlZXRDYW1lcmFFbmZvcmNlbWVudFNlcnZpY2UucHJvdG90eXBlLm9uU2VuZEV4aXRBbmltYXRpb25FdmVudExlYXZlID0gZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoY3R4LmFuaW1hdGlvblN1Y2NlZWRlZCAmJiB0aGlzLmV4aXRBbmltRXZlbnQgJiYgdGhpcy5vcHRpb25zQ2FjaGUgJiYgY3R4LmFuaW1FdmVudE5hbWUgPT09IHRoaXMuZXhpdEFuaW1FdmVudCkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50QW5pbSA9IG51bGw7XG4gICAgICAgICAgICB2YXIgZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheVNlY29uZHMgPSAodHlwZW9mIHRoaXMub3B0aW9uc0NhY2hlLmVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNcyA9PT0gXCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICYmIHRoaXMub3B0aW9uc0NhY2hlLmVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNcyA+IDBcbiAgICAgICAgICAgICAgICAmJiBOdW1iZXIuaXNGaW5pdGUodGhpcy5vcHRpb25zQ2FjaGUuZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zKVxuICAgICAgICAgICAgICAgICYmIHRoaXMudXNlUGxheWVyQ29udHJvbHNEZWxheU1zKVxuICAgICAgICAgICAgICAgID8gdGhpcy5vcHRpb25zQ2FjaGUuZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zIC8gMTAwMFxuICAgICAgICAgICAgICAgIDogMC41O1xuICAgICAgICAgICAgdmFyIHN0b3BBbmltRGVsYXlTZWNvbmRzID0gZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheVNlY29uZHMgKyAwLjU7XG4gICAgICAgICAgICB0aGlzLnN0b3BBbmltSW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnNDYWNoZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuZXhpdEFuaW1FdmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMudXNlUGxheWVyQ29udHJvbHNEZWxheU1zID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3AuVXRpbGl0eS53YWl0KGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlTZWNvbmRzKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zcC5HYW1lLmVuYWJsZVBsYXllckNvbnRyb2xzKHRydWUsIGZhbHNlLCB0cnVlLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIDApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNwLlV0aWxpdHkud2FpdChzdG9wQW5pbURlbGF5U2Vjb25kcykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc3RvcEFuaW1JblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLm9wdGlvbkNiKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wdGlvbkNiKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wdGlvbkNiID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zQ2FjaGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmV4aXRBbmltRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25DYikge1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9uQ2IgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlLnByb3RvdHlwZS5zdGFydEFudGlFeHBsb2l0UG9sbGluZyA9IGZ1bmN0aW9uIChtb2RlKSB7XG4gICAgICAgIC8vIEZpeGVzIGh0dHBzOi8vZ2l0aHViLmNvbS9za3lyaW0tbXVsdGlwbGF5ZXIvc2t5bXA1LWdhbWVtb2RlL2lzc3Vlcy8yNDBcbiAgICAgICAgLy8gUC5TLiBUaGVyZSBpcyBhIHZlcnkgc2ltaWxhciBjb2RlIGluIHNreW1wNS1nYW1lbW9kZVxuICAgICAgICAvLyBTZWUgZGlzYWJsZUNoZWF0cy50cywgc2t5bXA1LWdhbWVtb2RlIGZvciBjb21tZW50c1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAobW9kZSA9PT0gdm9pZCAwKSB7IG1vZGUgPSBcImRlYXRoXCI7IH1cbiAgICAgICAgdmFyIF9jYWxsTmF0aXZlID0gdGhpcy5zcC5jYWxsTmF0aXZlO1xuICAgICAgICB2YXIgY2FtZXJhU3RhdGUgPSAtMTtcbiAgICAgICAgdmFyIG5lZWRzRXhpdGluZ0FuaW0gPSBmYWxzZTtcbiAgICAgICAgdmFyIGYgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgaWYgKGkgPj0gMTAgKiA2MCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbWVyYVN0YXRlID0gX2NhbGxOYXRpdmUoXCJHYW1lXCIsIFwiZ2V0Q2FtZXJhU3RhdGVcIiwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIG5lZWRzRXhpdGluZ0FuaW0gPSBfdGhpcy5uZWVkc0V4aXRpbmdBbmltO1xuICAgICAgICAgICAgaWYgKCFuZWVkc0V4aXRpbmdBbmltKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGYoSW5maW5pdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhbWVyYVN0YXRlID09PSAwKSB7IC8vIDEtc3QgcGVyc29uXG4gICAgICAgICAgICAgICAgX2NhbGxOYXRpdmUoXCJHYW1lXCIsIFwiZm9yY2VUaGlyZFBlcnNvblwiLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIF90aGlzLmV4aXRBbmltKHsgcGxheUV4aXRBbmltOiB0cnVlLCBlbmFibGVQbGF5ZXJDb250cm9sc0RlbGF5TXM6IHVuZGVmaW5lZCB9KTtcbiAgICAgICAgICAgICAgICBpZiAobW9kZSA9PT0gXCJkZWF0aFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIChfYSA9IF90aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5kYW1hZ2VBY3RvclZhbHVlKFwiSGVhbHRoXCIsIDEwMDAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGYoSW5maW5pdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIGYoaSArIDEpOyB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgZigwKTtcbiAgICB9O1xuICAgIFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlLnByb3RvdHlwZS5vbkJ1dHRvbkV2ZW50ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2Y7XG4gICAgICAgIC8vIFRPRE86IGRlLWhhcmRjb2RlIGNvbnRyb2xzXG4gICAgICAgIGlmIChlLmlzUHJlc3NlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlLmNvZGUgPT09IDU3IC8qIER4U2NhbkNvZGUuU3BhY2ViYXIgKi9cbiAgICAgICAgICAgIHx8IGUuY29kZSA9PT0gMTcgLyogRHhTY2FuQ29kZS5XICovXG4gICAgICAgICAgICB8fCBlLmNvZGUgPT09IDMwIC8qIER4U2NhbkNvZGUuQSAqL1xuICAgICAgICAgICAgfHwgZS5jb2RlID09PSAzMSAvKiBEeFNjYW5Db2RlLlMgKi9cbiAgICAgICAgICAgIHx8IGUuY29kZSA9PT0gMzIgLyogRHhTY2FuQ29kZS5EICovKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5uZWVkc0V4aXRpbmdBbmltKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2tpbmcgd2hldGhlciBtYW51YWwgaW50ZXJydXB0aW9uIGlzIHByb2hpYml0ZWRcbiAgICAgICAgICAgICAgICBpZiAoKF9iID0gKF9hID0gdGhpcy5jdXJyZW50QW5pbSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLm9wdGlvbnMpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5wcmV2ZW50TWFudWFsSW50ZXJydXB0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKChfYyA9IHRoaXMuY3VycmVudEFuaW0pID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhpdEFuaW0oeyBwbGF5RXhpdEFuaW06IHRydWUsIGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNczogdGhpcy5jdXJyZW50QW5pbS5vcHRpb25zLmVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNcyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhpdEFuaW0oeyBwbGF5RXhpdEFuaW06IHRydWUsIGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNczogdW5kZWZpbmVkIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm5lZWRzRXhpdGluZ0FuaW0pIHtcbiAgICAgICAgICAgICAgICBpZiAoKF9lID0gKF9kID0gdGhpcy5jdXJyZW50QW5pbSkgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLm9wdGlvbnMpID09PSBudWxsIHx8IF9lID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZS5wcmV2ZW50TWFudWFsSW50ZXJydXB0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGludGVydmFsTXMgPSAoX2YgPSB0aGlzLnNldHRpbmdzKSA9PT0gbnVsbCB8fCBfZiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2YuZXhpdEFuaW1Ob3RpZmljYXRpb25JbnRlcnZhbE1zO1xuICAgICAgICAgICAgICAgIGlmICghaW50ZXJ2YWxNcyB8fCAoRGF0ZS5ub3coKSAtIHRoaXMubGFzdE5vdGlmaWNhdGlvbk1vbWVudCkgPj0gaW50ZXJ2YWxNcykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxhc3ROb3RpZmljYXRpb25Nb21lbnQgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNwLkRlYnVnLm5vdGlmaWNhdGlvbihzdHJpbmdzLnByZXNzU3BhY2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWUuaXNVcCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5zZXR0aW5ncyB8fCAhdGhpcy5zZXR0aW5ncy5hbmltS2V5cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhbmltRXZlbnQgPSB0aGlzLnNldHRpbmdzLmFuaW1LZXlzW2UuY29kZV07XG4gICAgICAgIGlmICghYW5pbUV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbG9nVHJhY2UodGhpcywgXCJTdGFydGluZyBhbmltcyBmcm9tIGtleWJvYXJkIGlzIGRpc2FibGVkIGluIHRoaXMgdmVyc2lvblwiKTtcbiAgICAgICAgLy8gdGhpcy50cnlJbnZva2VBbmltKGFuaW1FdmVudCwge1xuICAgICAgICAvLyAgICAgd2VhcG9uRHJhd25BbGxvd2VkOiBmYWxzZSxcbiAgICAgICAgLy8gICAgIGZ1cm5pdHVyZUFsbG93ZWQ6IGZhbHNlLFxuICAgICAgICAvLyAgICAgZXhpdEFuaW1OYW1lOiBudWxsLFxuICAgICAgICAvLyAgICAgaW50ZXJydXB0QW5pbU5hbWU6IG51bGwsXG4gICAgICAgIC8vICAgICB0aW1lTXM6IDAsXG4gICAgICAgIC8vICAgICBpc1BsYXlFeGl0QW5pbUFmdGVyd2FyZHNFbmFibGVkOiB0cnVlLFxuICAgICAgICAvLyAgICAgcGFyZW50QW5pbUV2ZW50TmFtZTogbnVsbCxcbiAgICAgICAgLy8gICAgIGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNczogbnVsbCxcbiAgICAgICAgLy8gICAgIHByZWZlckludGVycnVwdEFuaW1Bc0V4aXRBbmltVGltZU1zOiBudWxsLFxuICAgICAgICAvLyB9KTtcbiAgICB9O1xuICAgIFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlLnByb3RvdHlwZS50cnlJbnZva2VBbmltID0gZnVuY3Rpb24gKGFuaW1FdmVudCwgb3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnRyeUludm9rZUFuaW1Db3VudCsrO1xuICAgICAgICBpZiAodGhpcy50cnlJbnZva2VBbmltQ291bnQgPj0gdGhpcy50cnlJbnZva2VBbmltQ291bnRNYXgpIHtcbiAgICAgICAgICAgIHRoaXMudHJ5SW52b2tlQW5pbUNvdW50ID0gMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY3VycmVudEludm9rZUFuaW1Db3VudCA9IHRoaXMudHJ5SW52b2tlQW5pbUNvdW50O1xuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuZXhpdEFuaW1OYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICB0aGlzLmV4aXRBbmltTmFtZSA9IG9wdGlvbnMuZXhpdEFuaW1OYW1lO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5leGl0QW5pbU5hbWUgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wcmV2ZW50TWFudWFsSW50ZXJydXB0ICE9PSBcImJvb2xlYW5cIikge1xuICAgICAgICAgICAgb3B0aW9ucy5wcmV2ZW50TWFudWFsSW50ZXJydXB0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmludGVycnVwdEFuaW1OYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICB0aGlzLmludGVycnVwdEFuaW1OYW1lID0gb3B0aW9ucy5pbnRlcnJ1cHRBbmltTmFtZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaW50ZXJydXB0QW5pbU5hbWUgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy50aW1lTXMgPT09IFwibnVtYmVyXCIgJiYgb3B0aW9ucy50aW1lTXMgPiAwICYmIE51bWJlci5pc0Zpbml0ZShvcHRpb25zLnRpbWVNcykpIHtcbiAgICAgICAgICAgIHZhciB0aW1lU2Vjb25kcyA9IG9wdGlvbnMudGltZU1zIC8gMTAwMDtcbiAgICAgICAgICAgIC8vIFVzaW5nIFV0aWxpdHkud2FpdCBtYWtlcyBzZW5zZSBiZWNhdXNlIGl0IHdhaXRzIGdhbWUgdGltZSwgbm90IHNpbXBseSByZWFsIHRpbWUuXG4gICAgICAgICAgICB0aGlzLnNwLlV0aWxpdHkud2FpdCh0aW1lU2Vjb25kcykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLnRyeUludm9rZUFuaW1Db3VudCAhPT0gY3VycmVudEludm9rZUFuaW1Db3VudCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghX3RoaXMubmVlZHNFeGl0aW5nQW5pbSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBpc1BsYXlFeGl0QW5pbUFmdGVyd2FyZHNFbmFibGVkID0gdHlwZW9mIG9wdGlvbnMuaXNQbGF5RXhpdEFuaW1BZnRlcndhcmRzRW5hYmxlZCA9PT0gXCJib29sZWFuXCIgPyBvcHRpb25zLmlzUGxheUV4aXRBbmltQWZ0ZXJ3YXJkc0VuYWJsZWQgOiB0cnVlO1xuICAgICAgICAgICAgICAgIF90aGlzLmV4aXRBbmltKHsgcGxheUV4aXRBbmltOiBpc1BsYXlFeGl0QW5pbUFmdGVyd2FyZHNFbmFibGVkLCBlbmFibGVQbGF5ZXJDb250cm9sc0RlbGF5TXM6IG9wdGlvbnMuZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBsYXllciA9IHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKTtcbiAgICAgICAgaWYgKCFwbGF5ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCByZWFzb246IFwicGxheWVyX25vdF9mb3VuZFwiIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBsYXllci5pc1dlYXBvbkRyYXduKCkgJiYgIW9wdGlvbnMud2VhcG9uRHJhd25BbGxvd2VkKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiBmYWxzZSwgcmVhc29uOiBcIndlYXBvbl9kcmF3blwiIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBsYXllci5nZXRBbmltYXRpb25WYXJpYWJsZUJvb2woXCJiSW5KdW1wU3RhdGVcIikpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCByZWFzb246IFwianVtcF9zdGF0ZVwiIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3AuVWkuaXNNZW51T3BlbihcIkZhdm9yaXRlc01lbnVcIiAvKiBNZW51LkZhdm9yaXRlcyAqLykpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCByZWFzb246IFwiZmF2b3JpdGVzX21lbnVfb3BlblwiIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3AuVWkuaXNNZW51T3BlbihcIkNvbnNvbGVcIiAvKiBNZW51LkNvbnNvbGUgKi8pKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiBmYWxzZSwgcmVhc29uOiBcImNvbnNvbGVfbWVudV9vcGVuXCIgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zdG9wQW5pbUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCByZWFzb246IFwiYnVzeV9zdG9wcGluZ19hbmltXCIgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGxheWVyLmdldEZ1cm5pdHVyZVJlZmVyZW5jZSgpICYmICFvcHRpb25zLmZ1cm5pdHVyZUFsbG93ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCByZWFzb246IFwicGxheWVyX2luX2Z1cm5pdHVyZVwiIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBsYXllci5pc1NuZWFraW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCByZWFzb246IFwicGxheWVyX3NuZWFraW5nXCIgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGxheWVyLmlzU3dpbW1pbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIHJlYXNvbjogXCJwbGF5ZXJfc3dpbW1pbmdcIiB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChhbmltRXZlbnQudG9Mb3dlckNhc2UoKSA9PT0gXCJpZGxlZm9yY2VkZWZhdWx0c3RhdGVcIikge1xuICAgICAgICAgICAgaWYgKHRoaXMubmVlZHNFeGl0aW5nQW5pbSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXhpdEFuaW0oeyBwbGF5RXhpdEFuaW06IHRydWUsIGVuYWJsZVBsYXllckNvbnRyb2xzRGVsYXlNczogdW5kZWZpbmVkIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGRvSW52b2tlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNwLkdhbWUuZm9yY2VUaGlyZFBlcnNvbigpO1xuICAgICAgICAgICAgICAgIF90aGlzLnNwLkdhbWUuZGlzYWJsZVBsYXllckNvbnRyb2xzKHRydWUsIGZhbHNlLCB0cnVlLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIDApO1xuICAgICAgICAgICAgICAgIF90aGlzLnNwLkRlYnVnLnNlbmRBbmltYXRpb25FdmVudChfdGhpcy5zcC5HYW1lLmdldFBsYXllcigpLCBhbmltRXZlbnQpO1xuICAgICAgICAgICAgICAgIHZhciBwcmVmZXJJbnRlcnJ1cHRBbmltU3RhdGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wcmVmZXJJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbVRpbWVNcyA9PT0gXCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICAmJiBvcHRpb25zLnByZWZlckludGVycnVwdEFuaW1Bc0V4aXRBbmltVGltZU1zID4gMFxuICAgICAgICAgICAgICAgICAgICAmJiBOdW1iZXIuaXNGaW5pdGUob3B0aW9ucy5wcmVmZXJJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbVRpbWVNcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRlXzEgPSB7IHByZWZlcjogdHJ1ZSB9O1xuICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJQcmVmZXIgaW50ZXJydXB0IGFuaW0gYXMgZXhpdCBhbmltIGZvciBcIi5jb25jYXQob3B0aW9ucy5wcmVmZXJJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbVRpbWVNcywgXCIgbXNcIikpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zcC5VdGlsaXR5LndhaXQob3B0aW9ucy5wcmVmZXJJbnRlcnJ1cHRBbmltQXNFeGl0QW5pbVRpbWVNcyAvIDEwMDApLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVfMS5wcmVmZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlByZWZlciBpbnRlcnJ1cHQgYW5pbSBhcyBleGl0IGFuaW0gc3RhdGUgY2hhbmdlZCB0byBmYWxzZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHByZWZlckludGVycnVwdEFuaW1TdGF0ZSA9IHN0YXRlXzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmN1cnJlbnRBbmltID0geyBuYW1lOiBhbmltRXZlbnQsIG9wdGlvbnM6IG9wdGlvbnMsIHByZWZlckludGVycnVwdEFuaW1TdGF0ZTogcHJlZmVySW50ZXJydXB0QW5pbVN0YXRlIH07XG4gICAgICAgICAgICAgICAgX3RoaXMuc3RhcnRBbnRpRXhwbG9pdFBvbGxpbmcoXCJub19kZWF0aFwiKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMucGFyZW50QW5pbUV2ZW50TmFtZSA9PT0gXCJzdHJpbmdcIiAmJiB0aGlzLmN1cnJlbnRBbmltTmFtZSA9PT0gb3B0aW9ucy5wYXJlbnRBbmltRXZlbnROYW1lKSB7XG4gICAgICAgICAgICAgICAgZG9JbnZva2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucy5wYXJlbnRBbmltRXZlbnROYW1lKSAmJiBvcHRpb25zLnBhcmVudEFuaW1FdmVudE5hbWUuaW5jbHVkZXModGhpcy5jdXJyZW50QW5pbU5hbWUpKSB7XG4gICAgICAgICAgICAgICAgZG9JbnZva2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMubmVlZHNFeGl0aW5nQW5pbSkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE8gKDEpOiBjb25zaWRlciBub3QgdXNpbmcgZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zIGhlcmUsIGJlY2F1c2UgdXNlSW50ZXJydXB0QW5pbUFzRXhpdEFuaW0gZG9lc24ndCBuZWVkIGl0XG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb25DYiA9IGRvSW52b2tlO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhpdEFuaW0oeyBwbGF5RXhpdEFuaW06IHRydWUsIHVzZUludGVycnVwdEFuaW1Bc0V4aXRBbmltOiB0cnVlLCBlbmFibGVQbGF5ZXJDb250cm9sc0RlbGF5TXM6IG9wdGlvbnMuZW5hYmxlUGxheWVyQ29udHJvbHNEZWxheU1zIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZG9JbnZva2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiU2VudCBhbmltYXRpb24gZXZlbnQ6IFwiLmNvbmNhdChhbmltRXZlbnQpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlIH07XG4gICAgfTtcbiAgICBTd2VldENhbWVyYUVuZm9yY2VtZW50U2VydmljZS5wcm90b3R5cGUuaGFzU3dlZXRQaWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtb2RDb3VudCA9IHRoaXMuc3AuR2FtZS5nZXRNb2RDb3VudCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vZENvdW50OyArK2kpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNwLkdhbWUuZ2V0TW9kTmFtZShpKS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdzd2VldHBpZScpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlLnByb3RvdHlwZSwgXCJuZWVkc0V4aXRpbmdBbmltXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50QW5pbU5hbWUgIT09IG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3dlZXRDYW1lcmFFbmZvcmNlbWVudFNlcnZpY2UucHJvdG90eXBlLCBcImN1cnJlbnRBbmltTmFtZVwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudEFuaW0gPyB0aGlzLmN1cnJlbnRBbmltLm5hbWUgOiBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIFN3ZWV0Q2FtZXJhRW5mb3JjZW1lbnRTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgU3dlZXRDYW1lcmFFbmZvcmNlbWVudFNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG5pbXBvcnQgeyBsb2dUcmFjZSB9IGZyb20gXCIuLi8uLi9sb2dnaW5nXCI7XG52YXIgU3dlZXRUYWZmeUR5bmFtaWNQZXJrc1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFN3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5yZXF1ZXN0QWRkUGVya3NUb0FjdG9ycyA9IGZ1bmN0aW9uIChhY3RvcklkcywgcGVya0lkcykge1xuICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYWN0b3JzID0gYWN0b3JJZHMubWFwKGZ1bmN0aW9uIChhY3RvcklkKSB7IHJldHVybiBfdGhpcy5zcC5BY3Rvci5mcm9tKF90aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KGFjdG9ySWQpKTsgfSkuZmlsdGVyKGZ1bmN0aW9uIChhY3RvcikgeyByZXR1cm4gYWN0b3IgIT09IG51bGw7IH0pO1xuICAgICAgICAgICAgICAgIHZhciBwZXJrcyA9IHBlcmtJZHMubWFwKGZ1bmN0aW9uIChwZXJrSWQpIHsgcmV0dXJuIF90aGlzLnNwLlBlcmsuZnJvbShfdGhpcy5zcC5HYW1lLmdldEZvcm1FeChwZXJrSWQpKTsgfSkuZmlsdGVyKGZ1bmN0aW9uIChwZXJrKSB7IHJldHVybiBwZXJrICE9PSBudWxsOyB9KTtcbiAgICAgICAgICAgICAgICBhY3RvcnMuZm9yRWFjaChmdW5jdGlvbiAoYWN0b3IpIHsgcmV0dXJuIHBlcmtzLmZvckVhY2goZnVuY3Rpb24gKHBlcmspIHsgcmV0dXJuIGFjdG9yID09PSBudWxsIHx8IGFjdG9yID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhY3Rvci5hZGRQZXJrKHBlcmspOyB9KTsgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKCFfdGhpcy5oYXNTd2VldFBpZSgpKSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJTd2VldFRhZmZ5IGZlYXR1cmVzIGRpc2FibGVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiU3dlZXRUYWZmeSBmZWF0dXJlcyBlbmFibGVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRyb2xsZXIub24oJ2NvbnRhaW5lckNoYW5nZWQnLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25Db250YWluZXJDaGFuZ2VkKGUpOyB9KTtcbiAgICAgICAgY29udHJvbGxlci5lbWl0dGVyLm9uKFwic2V0SW52ZW50b3J5TWVzc2FnZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25TZXRJbnZlbnRvcnlNZXNzYWdlKGUpOyB9KTtcbiAgICAgICAgY29udHJvbGxlci5lbWl0dGVyLm9uKFwiY3JlYXRlQWN0b3JNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkNyZWF0ZUFjdG9yTWVzc2FnZShlKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU3dlZXRUYWZmeUR5bmFtaWNQZXJrc1NlcnZpY2UucHJvdG90eXBlLm9uQ29udGFpbmVyQ2hhbmdlZCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICghdGhpcy5oYXNTd2VldFBpZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUub2xkQ29udGFpbmVyICYmIGUubmV3Q29udGFpbmVyKSB7XG4gICAgICAgICAgICBpZiAoZS5uZXdDb250YWluZXIuZ2V0Rm9ybUlEKCkgPT09IDB4MTQgJiYgZS5udW1JdGVtcyA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVBsYXllckludmVudG9yeUNoYW5nZWQoe1xuICAgICAgICAgICAgICAgICAgICBiYXNlSWQ6IGUuYmFzZU9iai5nZXRGb3JtSUQoKSxcbiAgICAgICAgICAgICAgICAgICAgY291bnQ6IGUubnVtSXRlbXMsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlLnByb3RvdHlwZS5vblNldEludmVudG9yeU1lc3NhZ2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuaGFzU3dlZXRQaWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlbnRyaWVzID0gZS5tZXNzYWdlLmludmVudG9yeS5lbnRyaWVzO1xuICAgICAgICBpZiAoZW50cmllcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiUmVjZWl2ZWQgU2V0SW52ZW50b3J5TWVzc2FnZSB3aXRoIGVtcHR5IGludmVudG9yeVwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBlbnRyaWVzLmZvckVhY2goZnVuY3Rpb24gKGVudHJ5KSB7IHJldHVybiBfdGhpcy5oYW5kbGVQbGF5ZXJJbnZlbnRvcnlDaGFuZ2VkKGVudHJ5KTsgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU3dlZXRUYWZmeUR5bmFtaWNQZXJrc1NlcnZpY2UucHJvdG90eXBlLm9uQ3JlYXRlQWN0b3JNZXNzYWdlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgaWYgKCF0aGlzLmhhc1N3ZWV0UGllKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWUubWVzc2FnZS5pc01lKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVudHJpZXMgPSAoX2IgPSAoX2EgPSBlLm1lc3NhZ2UucHJvcHMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pbnZlbnRvcnkpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5lbnRyaWVzO1xuICAgICAgICBpZiAoZW50cmllcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBsb2dUcmFjZSh0aGlzLCBcIlJlY2VpdmVkIENyZWF0ZUFjdG9yTWVzc2FnZSB3aXRob3V0IGludmVudG9yeVwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cmllcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiUmVjZWl2ZWQgQ3JlYXRlQWN0b3JNZXNzYWdlIHdpdGggZW1wdHkgaW52ZW50b3J5XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGVudHJpZXMuZm9yRWFjaChmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIF90aGlzLmhhbmRsZVBsYXllckludmVudG9yeUNoYW5nZWQoZW50cnkpOyB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBTd2VldFRhZmZ5RHluYW1pY1BlcmtzU2VydmljZS5wcm90b3R5cGUuaGFuZGxlUGxheWVySW52ZW50b3J5Q2hhbmdlZCA9IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICBpZiAoIXRoaXMuaGFzU3dlZXRQaWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpdGVtID0gdGhpcy5zcC5HYW1lLmdldEZvcm1FeChlbnRyeS5iYXNlSWQpO1xuICAgICAgICBpZiAoIWl0ZW0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cnkuY291bnQgPD0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwZXJrSWRzID0gdGhpcy5nZXRQZXJrSWRzQnlLZXl3b3JkKGl0ZW0pO1xuICAgICAgICBpZiAocGVya0lkcykge1xuICAgICAgICAgICAgdmFyIHBsYXllcklkID0gMHgxNDtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdEFkZFBlcmtzVG9BY3RvcnMoW3BsYXllcklkXSwgcGVya0lkcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlLnByb3RvdHlwZS5nZXRQZXJrSWRzQnlLZXl3b3JkID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLmdldEtleXdvcmRQZXJrTWFwKCkuZm9yRWFjaChmdW5jdGlvbiAodiwgaykge1xuICAgICAgICAgICAgdmFyIGtleVdvcmQgPSBfdGhpcy5zcC5LZXl3b3JkLmdldEtleXdvcmQoayk7XG4gICAgICAgICAgICBpZiAoaXRlbS5oYXNLZXl3b3JkKGtleVdvcmQpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2godik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0Lmxlbmd0aCA+IDAgPyByZXN1bHQgOiBudWxsO1xuICAgIH07XG4gICAgLy8gVE9ETzogbW92ZSB0aGlzIHRvIGNvbmZpZ1xuICAgIFN3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlLnByb3RvdHlwZS5nZXRLZXl3b3JkUGVya01hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNYXAoW1xuICAgICAgICAgICAgLy8g0KHRgtGA0LXQu9C10YZcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya0JvdzFcIiwgMHgxMDM2RjBdLFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrQm93MlwiLCAweDU4RjYxXSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya0JvdzNcIiwgMHgxMDVGMTldLFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrQm93NFwiLCAweDU4RjYzXSxcbiAgICAgICAgICAgIC8vINCj0LHQuNC50YbQsFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrU25lYWsxXCIsIDB4NTgyMTBdLFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrU25lYWsyXCIsIDB4MTA1RjIzXSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya1NuZWFrM1wiLCAweDU4MjA4XSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya1NuZWFrNFwiLCAweDU4MjExXSxcbiAgICAgICAgICAgIC8vINCf0LXRhdC+0YLQuNC90LXRhlxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrQXJtb3JMaWdodDFcIiwgMHgxMDVGMjJdLFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrQXJtb3JMaWdodDJcIiwgMHg1MUIxQ10sXG4gICAgICAgICAgICAvLyDQl9Cw0YfQsNGA0L7QstCw0YLQtdC70YxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya0VuY2hhbnQyXCIsIDB4MTA4QTQ0XSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya0VuY2hhbnQxXCIsIDB4NThGN0NdLFxuICAgICAgICAgICAgLy8g0JvQsNGC0L3QuNC6XG4gICAgICAgICAgICBbXCJTd2VldFBlcmtBcm1vckhlYXZ5MVwiLCAweEJDRDJCXSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVya0FybW9ySGVhdnkyXCIsIDB4NThGNkRdLFxuICAgICAgICAgICAgLy8g0KnQuNGC0L7QvdC+0YHQtdGGXG4gICAgICAgICAgICBbXCJTd2VldFBlcmtCbG9jazFcIiwgMHg1OEY2N10sXG4gICAgICAgICAgICBbXCJTd2VldFBlcmtCbG9jazJcIiwgMHgxMDYyNTNdLFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrQmxvY2szXCIsIDB4NThGNkFdLFxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrQmxvY2s0XCIsIDB4NThGNjldLFxuICAgICAgICAgICAgLy8g0JzQtdGH0L3QuNC6LCDQutC70LjQvdC+0LosINGA0YPQsdCw0LrQsCwg0LrRgNGD0YjQuNGC0LXQu9GMLCDQvNC+0L3QsNGFLCDQutC+0L/QtdC50YnQuNC6LCDRgdGC0YDQsNC20L3QuNC6ICjQtNCy0YPRgNGD0YfQvdC+0LUg0L7RgNGD0LbQuNC1KVxuICAgICAgICAgICAgW1wiU3dlZXRQZXJrMUhhbmQySGFuZDFcIiwgMHg1OEY2Rl0sXG4gICAgICAgICAgICBbXCJTd2VldFBlcmsySGFuZDJcIiwgMHhDQjQwN10sXG4gICAgICAgICAgICBbXCJTd2VldFBlcmsySGFuZDNcIiwgMHg5NjU5MF0sXG4gICAgICAgICAgICBbXCJTd2VldFBlcmsySGFuZDRcIiwgMHg1MkQ1MV0sXG4gICAgICAgICAgICAvLyDQkNGB0YHQsNGB0LjQvSwg0YDQsNC30LLQtdC00YfQuNC6LCDRiNC/0LjQvtC9LCDQv9GA0LXQtNGI0LXRgdGC0LLQtdC90L3QuNC6LCDRgNGL0YbQsNGA0YwsINGA0LDQt9Cx0L7QudC90LjQuiwg0LHQtdGA0YHQtdGA0LosINCz0YDQvtC80LjQu9CwICjQvtC00L3QvtGA0YPRh9C90L7QtSDQvtGA0YPQttC40LUpXG4gICAgICAgICAgICBbXCJTd2VldFBlcmsxSGFuZDJIYW5kMVwiLCAweDU4RjZGXSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVyazFIYW5kMlwiLCAweENCNDA2XSxcbiAgICAgICAgICAgIFtcIlN3ZWV0UGVyazFIYW5kM1wiLCAweDEwNjI1Nl0sXG4gICAgICAgICAgICBbXCJTd2VldFBlcmsxSGFuZDRcIiwgMHg1MkQ1MF0sXG4gICAgICAgIF0pO1xuICAgIH07XG4gICAgU3dlZXRUYWZmeUR5bmFtaWNQZXJrc1NlcnZpY2UucHJvdG90eXBlLmhhc1N3ZWV0UGllID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbW9kQ291bnQgPSB0aGlzLnNwLkdhbWUuZ2V0TW9kQ291bnQoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb2RDb3VudDsgKytpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zcC5HYW1lLmdldE1vZE5hbWUoaSkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnc3dlZXRwaWUnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIHJldHVybiBTd2VldFRhZmZ5RHluYW1pY1BlcmtzU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFN3ZWV0VGFmZnlEeW5hbWljUGVya3NTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgbG9jYWxJZFRvUmVtb3RlSWQsIHJlbW90ZUlkVG9Mb2NhbElkIH0gZnJvbSBcIi4uLy4uL3ZpZXcvd29ybGRWaWV3TWlzY1wiO1xuaW1wb3J0IHsgbG9nRXJyb3IgfSBmcm9tIFwiLi4vLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuaW1wb3J0IHsgUmVtb3RlU2VydmVyIH0gZnJvbSBcIi4vcmVtb3RlU2VydmVyXCI7XG5pbXBvcnQgeyBTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IHByaW50Q29uc29sZSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0ICogYXMgc3AgZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG52YXIgU3dlZXRUYWZmeUV2YWxTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTd2VldFRhZmZ5RXZhbFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU3dlZXRUYWZmeUV2YWxTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyLmVtaXR0ZXIub24oXCJjdXN0b21QYWNrZXRNZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkN1c3RvbVBhY2tldE1lc3NhZ2UoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFN3ZWV0VGFmZnlFdmFsU2VydmljZS5wcm90b3R5cGUub25DdXN0b21QYWNrZXRNZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBtc2cgPSBldmVudC5tZXNzYWdlO1xuICAgICAgICB2YXIgbXNnQ29udGVudCA9IHt9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbXNnQ29udGVudCA9IEpTT04ucGFyc2UobXNnLmNvbnRlbnRKc29uRHVtcCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3ludGF4RXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIm9uQ3VzdG9tUGFja2V0TWVzc2FnZSBmYWlsZWQgdG8gcGFyc2UgSlNPTlwiLCBlLm1lc3NhZ2UsIFwianNvbjpcIiwgbXNnLmNvbnRlbnRKc29uRHVtcCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKG1zZ0NvbnRlbnRbXCJjdXN0b21QYWNrZXRUeXBlXCJdKSB7XG4gICAgICAgICAgICBjYXNlICdldmFsJzpcbiAgICAgICAgICAgICAgICB2YXIgY29kZSA9IG1zZ0NvbnRlbnRbXCJjb2RlXCJdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29kZSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIm9uQ3VzdG9tUGFja2V0TWVzc2FnZSBleHBlY3RlZCAnY29kZScgdG8gYmUgYSBzdHJpbmdcIiwgXCJjb2RlOlwiLCBjb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc0V2YWwoY29kZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlFdmFsU2VydmljZS5wcm90b3R5cGUucHJvY2Vzc0V2YWwgPSBmdW5jdGlvbiAoY29kZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBDb25zaWRlciByZW1vdmluZyB0cnkgY2F0Y2hcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciBzcmMgPSBjb2RlO1xuICAgICAgICAgICAgdmFyIHNlcnZlckpzVmVyaWZpY2F0aW9uU2VydmljZSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2UpO1xuICAgICAgICAgICAgdmFyIHByZWZpeCA9IFwiLy8gc2t5bXA6c2lnOnk6R01cIjtcbiAgICAgICAgICAgIHZhciByZXN1bHRfMSA9IHNlcnZlckpzVmVyaWZpY2F0aW9uU2VydmljZS52ZXJpZnlTZXJ2ZXJKcyhzcmMsIHByZWZpeCk7XG4gICAgICAgICAgICBpZiAocmVzdWx0XzEuc3JjICYmICFyZXN1bHRfMS5lcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlbW90ZVNlcnZlciA9IF90aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoUmVtb3RlU2VydmVyKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdvcmxkTW9kZWwgPSByZW1vdGVTZXJ2ZXIuZ2V0V29ybGRNb2RlbCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbXlGb3JtTW9kZWwgPSB3b3JsZE1vZGVsLmZvcm1zW3dvcmxkTW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeF07XG4gICAgICAgICAgICAgICAgICAgIHZhciBjdHggPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcDogc3AsXG4gICAgICAgICAgICAgICAgICAgICAgICBfbW9kZWw6IG15Rm9ybU1vZGVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0Rm9ybUlkSW5TZXJ2ZXJGb3JtYXQ6IGxvY2FsSWRUb1JlbW90ZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0Rm9ybUlkSW5DbGllbnRGb3JtYXQ6IHJlbW90ZUlkVG9Mb2NhbElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAocHJvcE5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2E7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChfYSA9IHRoaXMuX21vZGVsKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAobmV3IEZ1bmN0aW9uKCdjdHgnLCByZXN1bHRfMS5zcmMpKShjdHgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHByaW50Q29uc29sZShcIkV2YWwgZXhlY3V0ZWQgc3VjY2Vzc2Z1bGx5XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJwcm9jZXNzRXZhbCBmYWlsZWQgc2VydmVyIEpTIHZlcmlmaWNhdGlvblwiLCBcImVycm9yOlwiLCByZXN1bHRfMS5lcnJvciwgXCJzcmM6XCIsIHNyYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwicHJvY2Vzc0V2YWwgZXJyb3JcIiwgZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBTd2VldFRhZmZ5RXZhbFNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTd2VldFRhZmZ5RXZhbFNlcnZpY2UgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBDbGllbnRMaXN0ZW5lciB9IGZyb20gXCIuL2NsaWVudExpc3RlbmVyXCI7XG52YXIgU3dlZXRUYWZmeU5pY2tuYW1lc1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFN3ZWV0VGFmZnlOaWNrbmFtZXNTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN3ZWV0VGFmZnlOaWNrbmFtZXNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBjb250cm9sbGVyLmVtaXR0ZXIub24oXCJuaWNrbmFtZUNyZWF0ZVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25OaWNrbmFtZUNyZWF0ZShlKTsgfSk7XG4gICAgICAgIGNvbnRyb2xsZXIuZW1pdHRlci5vbihcIm5pY2tuYW1lRGVzdHJveVwiLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25OaWNrbmFtZURlc3Ryb3koZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFN3ZWV0VGFmZnlOaWNrbmFtZXNTZXJ2aWNlLnByb3RvdHlwZS5vbk5pY2tuYW1lQ3JlYXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgc3RvcmFnZU5pY2tuYW1lID0gdHlwZW9mIHRoaXMuc3Auc3RvcmFnZVtcImlkVGV4dE5pY2tuYW1lXCJdID09PSAnb2JqZWN0J1xuICAgICAgICAgICAgPyB0aGlzLnNwLnN0b3JhZ2VbXCJpZFRleHROaWNrbmFtZVwiXVxuICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICBpZiAoc3RvcmFnZU5pY2tuYW1lID09PSBudWxsICYmIGUucmVtb3RlUmVmcklkKSB7XG4gICAgICAgICAgICB0aGlzLnNwLnN0b3JhZ2VbXCJpZFRleHROaWNrbmFtZVwiXSA9IChfYSA9IHt9LCBfYVtlLnJlbW90ZVJlZnJJZF0gPSBlLnRleHRJZCwgX2EpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHN0b3JhZ2VOaWNrbmFtZSAhPT0gbnVsbCAmJiBlLnJlbW90ZVJlZnJJZCkge1xuICAgICAgICAgICAgc3RvcmFnZU5pY2tuYW1lW2UucmVtb3RlUmVmcklkXSA9IGUudGV4dElkO1xuICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlW1wiaWRUZXh0Tmlja25hbWVcIl0gPSBzdG9yYWdlTmlja25hbWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlOaWNrbmFtZXNTZXJ2aWNlLnByb3RvdHlwZS5vbk5pY2tuYW1lRGVzdHJveSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBzdG9yYWdlTmlja25hbWUgPSB0eXBlb2YgdGhpcy5zcC5zdG9yYWdlW1wiaWRUZXh0Tmlja25hbWVcIl0gPT09ICdvYmplY3QnXG4gICAgICAgICAgICA/IHRoaXMuc3Auc3RvcmFnZVtcImlkVGV4dE5pY2tuYW1lXCJdXG4gICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGlmIChzdG9yYWdlTmlja25hbWUgIT09IG51bGwgJiYgZS5yZW1vdGVSZWZySWQpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBzdG9yYWdlTmlja25hbWVbZS5yZW1vdGVSZWZySWRdO1xuICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlW1wiaWRUZXh0Tmlja25hbWVcIl0gPSBzdG9yYWdlTmlja25hbWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBTd2VldFRhZmZ5Tmlja25hbWVzU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFN3ZWV0VGFmZnlOaWNrbmFtZXNTZXJ2aWNlIH07XG47XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgbG9nVHJhY2UsIGxvZ0Vycm9yIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbi8vIFRPRE86IG1vdmUgdG8gc2VydmljZVxudmFyIHBsYXllckxhc3RTdGFtaW5hVmFsdWUgPSAwO1xudmFyIHBsYXllckxhc3RJc1NwcmludGluZ1ZhbHVlID0gZmFsc2U7XG52YXIgYmxvY2tQbGF5ZXJDb250cm9sVGltZVN0YW1wID0gMDtcbnZhciBpc1BsYXllckNvbnRyb2xEaXNhYmxlZCA9IHRydWU7XG52YXIgcGxheWVyQXR0YWNrVGltZW91dCA9IDA7XG52YXIgYWN0aXZlVGltZXJzID0gbmV3IFNldCgpO1xuLy8gVE9ETzogbW92ZSB0byBjb25maWdcbnZhciBzdGFtaW5hQXR0YWNrTWFwID0gbmV3IE1hcChbXG4gICAgW1wiU3RkXCIsIDddLFxuICAgIFtcIlBvd2VyXCIsIDM1XSxcbiAgICBbXCJKdW1wXCIsIDE1XSxcbiAgICBbXCJCb3dcIiwgMjVdLFxuICAgIFtcIkNyb3NzYm93XCIsIDMwXSxcbl0pO1xuLy8gVE9ETzogY29uc2lkZXIgc3BsaXR0aW5nIHRoaXMgc2VydmljZSAoc2VwYXJhdGUgc3RhbWluYSBhbmQgdGltZXIgbWFuYWdlbWVudClcbi8vIFRPRE86IHN1YnNjcmliZSBldmVudHMvaG9va3MgaW4gY29uc3RydWN0b3JcbnZhciBTd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIGlmICghX3RoaXMuaGFzU3dlZXRQaWUoKSkge1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsIFwiU3dlZXRUYWZmeSBmZWF0dXJlcyBkaXNhYmxlZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlN3ZWV0VGFmZnkgZmVhdHVyZXMgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBfdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25jZVVwZGF0ZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZS5wcm90b3R5cGUub25jZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRBdHRhY2tTdGFtaW5hUmVzdHJpY3Rpb24oKTtcbiAgICAgICAgdGhpcy5yZWdpc3RlckhhbmRsZXJzSWZOZWVkZWQoKTtcbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlLnByb3RvdHlwZS5zZXRBdHRhY2tTdGFtaW5hUmVzdHJpY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5oYXNTd2VldFBpZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBwbGF5ZXIgPSBfdGhpcy5zcC5HYW1lLmdldFBsYXllcigpO1xuICAgICAgICAgICAgcGxheWVyTGFzdFN0YW1pbmFWYWx1ZSA9IHBsYXllci5nZXRBY3RvclZhbHVlKFwiU3RhbWluYVwiKTtcbiAgICAgICAgICAgIHBsYXllckxhc3RJc1NwcmludGluZ1ZhbHVlID0gcGxheWVyLmlzU3ByaW50aW5nKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gWydTcHJpbnRTdGFydCddOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHBhdHRlcm4gPSBfYVtfaV07XG4gICAgICAgICAgICB2YXIgc3AgPSB0aGlzLnNwO1xuICAgICAgICAgICAgdGhpcy5zcC5ob29rcy5zZW5kQW5pbWF0aW9uRXZlbnQuYWRkKHtcbiAgICAgICAgICAgICAgICBlbnRlcjogKGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXllckxhc3RTdGFtaW5hVmFsdWUgPCA3LjUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5hbmltRXZlbnROYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIGxlYXZlOiAoZnVuY3Rpb24gKCkgeyB9KSxcbiAgICAgICAgICAgIH0sIDB4MTQsIDB4MTQsIHBhdHRlcm4pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9iID0gMCwgX2MgPSBbJ2Jsb2NrU3RhcnQnXTsgX2IgPCBfYy5sZW5ndGg7IF9iKyspIHtcbiAgICAgICAgICAgIHZhciBwYXR0ZXJuID0gX2NbX2JdO1xuICAgICAgICAgICAgdGhpcy5zcC5ob29rcy5zZW5kQW5pbWF0aW9uRXZlbnQuYWRkKHtcbiAgICAgICAgICAgICAgICBlbnRlcjogKGZ1bmN0aW9uIChjdHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXllckxhc3RJc1NwcmludGluZ1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBsZWF2ZTogKGZ1bmN0aW9uICgpIHsgfSksXG4gICAgICAgICAgICB9LCAweDE0LCAweDE0LCBwYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBfZCA9IDAsIF9lID0gWydhdHRhY2tTdGFydConLCAnQXR0YWNrU3RhcnQqJ107IF9kIDwgX2UubGVuZ3RoOyBfZCsrKSB7XG4gICAgICAgICAgICB2YXIgcGF0dGVybiA9IF9lW19kXTtcbiAgICAgICAgICAgIHRoaXMuc3AuaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgICAgICAgICAgZW50ZXI6IChmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXllckxhc3RTdGFtaW5hVmFsdWUgPCAoKF9hID0gc3RhbWluYUF0dGFja01hcC5nZXQoXCJTdGRcIikpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBsZWF2ZTogKGZ1bmN0aW9uICgpIHsgfSksXG4gICAgICAgICAgICB9LCAweDE0LCAweDE0LCBwYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBfZiA9IDAsIF9nID0gWydhdHRhY2tQb3dlclN0YXJ0KicsICdBdHRhY2tQb3dlclN0YXJ0KiddOyBfZiA8IF9nLmxlbmd0aDsgX2YrKykge1xuICAgICAgICAgICAgdmFyIHBhdHRlcm4gPSBfZ1tfZl07XG4gICAgICAgICAgICB0aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgICAgIGVudGVyOiAoZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgX2E7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwbGF5ZXJMYXN0U3RhbWluYVZhbHVlIDwgKChfYSA9IHN0YW1pbmFBdHRhY2tNYXAuZ2V0KFwiUG93ZXJcIikpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBsZWF2ZTogKGZ1bmN0aW9uICgpIHsgfSksXG4gICAgICAgICAgICB9LCAweDE0LCAweDE0LCBwYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBfaCA9IDAsIF9qID0gWydKdW1wRGlyZWN0aW9uYWxTdGFydConLCAnSnVtcFN0YW5kaW5nU3RhcnQqJ107IF9oIDwgX2oubGVuZ3RoOyBfaCsrKSB7XG4gICAgICAgICAgICB2YXIgcGF0dGVybiA9IF9qW19oXTtcbiAgICAgICAgICAgIHRoaXMuc3AuaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgICAgICAgICAgZW50ZXI6IChmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXllckxhc3RTdGFtaW5hVmFsdWUgPCAoKF9hID0gc3RhbWluYUF0dGFja01hcC5nZXQoXCJKdW1wXCIpKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmFuaW1FdmVudE5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgbGVhdmU6IChmdW5jdGlvbiAoKSB7IH0pLFxuICAgICAgICAgICAgfSwgMHgxNCwgMHgxNCwgcGF0dGVybik7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgX2sgPSAwLCBfbCA9IFsnYm93QXR0YWNrU3RhcnQqJ107IF9rIDwgX2wubGVuZ3RoOyBfaysrKSB7XG4gICAgICAgICAgICB2YXIgcGF0dGVybiA9IF9sW19rXTtcbiAgICAgICAgICAgIHRoaXMuc3AuaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgICAgICAgICAgZW50ZXI6IChmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBsYXllckxhc3RTdGFtaW5hVmFsdWUgPCAoKF9hID0gc3RhbWluYUF0dGFja01hcC5nZXQoXCJCb3dcIikpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBsZWF2ZTogKGZ1bmN0aW9uICgpIHsgfSksXG4gICAgICAgICAgICB9LCAweDE0LCAweDE0LCBwYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBfbSA9IDAsIF9vID0gWydjcm9zc2Jvd0F0dGFja1N0YXJ0KiddOyBfbSA8IF9vLmxlbmd0aDsgX20rKykge1xuICAgICAgICAgICAgdmFyIHBhdHRlcm4gPSBfb1tfbV07XG4gICAgICAgICAgICB0aGlzLnNwLmhvb2tzLnNlbmRBbmltYXRpb25FdmVudC5hZGQoe1xuICAgICAgICAgICAgICAgIGVudGVyOiAoZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgX2E7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwbGF5ZXJMYXN0U3RhbWluYVZhbHVlIDwgKChfYSA9IHN0YW1pbmFBdHRhY2tNYXAuZ2V0KFwiQ3Jvc3Nib3dcIikpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBsZWF2ZTogKGZ1bmN0aW9uICgpIHsgfSksXG4gICAgICAgICAgICB9LCAweDE0LCAweDE0LCBwYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVySGFuZGxlcnNJZk5lZWRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuaGFzU3dlZXRQaWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBbJ2F0dGFja1N0YXJ0KicsICdBdHRhY2tTdGFydConXTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBwYXR0ZXJuID0gX2FbX2ldO1xuICAgICAgICAgICAgdGhpcy5zcC5ob29rcy5zZW5kQW5pbWF0aW9uRXZlbnQuYWRkKHtcbiAgICAgICAgICAgICAgICBlbnRlcjogKGZ1bmN0aW9uICgpIHsgfSksXG4gICAgICAgICAgICAgICAgbGVhdmU6IChmdW5jdGlvbiAoY3R4KSB7IHJldHVybiBzZWxmLmJsb2NrUGxheWVyQXR0YWNrKGN0eC5hbmltRXZlbnROYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ2xlZnRoYW5kJykpOyB9KSxcbiAgICAgICAgICAgIH0sIDB4MTQsIDB4MTQsIHBhdHRlcm4pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9iID0gMCwgX2MgPSBbJ2F0dGFja1Bvd2VyU3RhcnQqJywgJ0F0dGFja1Bvd2VyU3RhcnQqJywgJ0p1bXAqJ107IF9iIDwgX2MubGVuZ3RoOyBfYisrKSB7XG4gICAgICAgICAgICB2YXIgcGF0dGVybiA9IF9jW19iXTtcbiAgICAgICAgICAgIHRoaXMuc3AuaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgICAgICAgICAgZW50ZXI6IChmdW5jdGlvbiAoKSB7IH0pLFxuICAgICAgICAgICAgICAgIGxlYXZlOiAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBwbGF5ZXJBdHRhY2tUaW1lb3V0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlVGltZXJzLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB9LCAweDE0LCAweDE0LCBwYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGlzUGxheWVyQ29udHJvbERpc2FibGVkID09PSB0cnVlICYmIERhdGUubm93KCkgLSBibG9ja1BsYXllckNvbnRyb2xUaW1lU3RhbXAgPj0gcGxheWVyQXR0YWNrVGltZW91dCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCkuc2V0RG9udE1vdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIGlzUGxheWVyQ29udHJvbERpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UucHJvdG90eXBlLmJsb2NrUGxheWVyQXR0YWNrID0gZnVuY3Rpb24gKGlzTGVmdEhhbmQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jb250cm9sbGVyLm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgdmFyIHBsYXllciA9IF90aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgICAgICBpZiAocGxheWVyLmdldEFuaW1hdGlvblZhcmlhYmxlQm9vbChcImJJbkp1bXBTdGF0ZVwiKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBfYiA9IF90aGlzLmdldFRpbWluZ3MoKF9hID0gcGxheWVyLmdldEVxdWlwcGVkV2VhcG9uKGlzTGVmdEhhbmQpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ2V0V2VhcG9uVHlwZSgpKSwgZGVsYXkgPSBfYlswXSwgdGltZW91dCA9IF9iWzFdO1xuICAgICAgICAgICAgdmFyIHJuZCA9IE1hdGgucmFuZG9tKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGFjdGl2ZVRpbWVycy5hZGQocm5kKTtcbiAgICAgICAgICAgIF90aGlzLnNwLlV0aWxpdHkud2FpdChkZWxheSAvIDEwMDApLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICghYWN0aXZlVGltZXJzLmRlbGV0ZShybmQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNQbGF5ZXJDb250cm9sRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBibG9ja1BsYXllckNvbnRyb2xUaW1lU3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zcC5HYW1lLmdldFBsYXllcigpLnNldERvbnRNb3ZlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBwbGF5ZXJBdHRhY2tUaW1lb3V0ID0gdGltZW91dDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlLnByb3RvdHlwZS5nZXRBbmRWYWxpZGF0ZVRpbWluZ3NDb25maWdLZXkgPSBmdW5jdGlvbiAoa2V5LCB3ZWFwb25UaW1pbmdzKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHdlYXBvblRpbWluZ3Nba2V5XTtcbiAgICAgICAgaWYgKHZhbHVlICYmIEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgdmFyIGVsZW1lbnQwID0gdmFsdWVbMF07XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1lbnQwICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJJbnZhbGlkIHRpbWluZ3MgY29uZmlnIGZvciB3ZWFwb24gdHlwZVwiLCBrZXksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gWzAsIDBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGVsZW1lbnQxID0gdmFsdWVbMV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1lbnQxICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJJbnZhbGlkIHRpbWluZ3MgY29uZmlnIGZvciB3ZWFwb24gdHlwZVwiLCBrZXksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gWzAsIDBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFtlbGVtZW50MCwgZWxlbWVudDFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbMCwgMF07XG4gICAgfTtcbiAgICA7XG4gICAgU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UucHJvdG90eXBlLmdldFNldHRpbmdzRnJvbUZpbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZSA9IHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wic3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2VcIl07XG4gICAgICAgIGlmICghc3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UgfHwgdHlwZW9mIHN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBsb2dFcnJvcih0aGlzLCBcIk5vIHN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlIHNldHRpbmdzIGZvdW5kXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHdlYXBvblRpbWluZ3MgPSBzd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZS53ZWFwb25UaW1pbmdzO1xuICAgICAgICBpZiAoIXdlYXBvblRpbWluZ3MgfHwgdHlwZW9mIHdlYXBvblRpbWluZ3MgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHRoaXMsIFwiTm8gd2VhcG9uVGltaW5ncyBzZXR0aW5ncyBmb3VuZFwiKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB3ZWFwb25UaW1pbmdzO1xuICAgIH07XG4gICAgU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UucHJvdG90eXBlLmdldFNldHRpbmdzRGVmYXVsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZpc3Q6IFswLCAzMF0sXG4gICAgICAgICAgICBzd29yZDogWzAsIDMwXSxcbiAgICAgICAgICAgIGRhZ2dlcjogWzAsIDYwXSxcbiAgICAgICAgICAgIHdhckF4ZTogWzAsIDYwXSxcbiAgICAgICAgICAgIG1hY2U6IFswLCA2NV0sXG4gICAgICAgICAgICBncmVhdHN3b3JkOiBbMCwgNjVdLFxuICAgICAgICAgICAgLy8gTm90ZTogYm90aCBvZiBCYXR0bGVheGUgYW5kIFdhcmhhbW1lciB3ZWFwb24gdHlwZXMgY29ycmVzcG9uZCB0byBpZD02LlxuICAgICAgICAgICAgYmF0dGxlYXhlOiBbMCwgNzBdLFxuICAgICAgICAgICAgd2FyaGFtbWVyOiBbMCwgNzBdLFxuICAgICAgICAgICAgYm93OiBbMCwgNzBdLFxuICAgICAgICAgICAgc3RhZmY6IFswLCA3MF0sXG4gICAgICAgICAgICBjcm9zc2JvdzogWzAsIDcwXSxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlLnByb3RvdHlwZS5nZXRUaW1pbmdzRnJvbUNvbmZpZyA9IGZ1bmN0aW9uICh3ZWFwb24pIHtcbiAgICAgICAgaWYgKCF3ZWFwb24pIHtcbiAgICAgICAgICAgIHdlYXBvbiA9IDAgLyogV2VhcG9uVHlwZS5GaXN0ICovO1xuICAgICAgICB9XG4gICAgICAgIC8vIHNreW1wNS1jbGllbnQtc2V0dGluZ3MudHh0IGlzIHBlcmZlY3RseSBlZGl0YWJsZSBieSB1c2Vycywgc28gd2UgZG9uJ3QgdXNlIGl0IGZvciBub3cuXG4gICAgICAgIC8vIEl0J3Mgd2VsbC10ZXN0ZWQgdGhvdWdoLCBzbyB3ZSBjYW4gZW5hYmxlIGl0IG9uY2Ugd2UgaGF2ZSBhIHByb3RlY3Rpb24gbWVjaGFuaXNtLlxuICAgICAgICAvLyBjb25zdCB3ZWFwb25UaW1pbmdzID0gdGhpcy5nZXRTZXR0aW5nc0Zyb21GaWxlKCk7XG4gICAgICAgIHZhciB3ZWFwb25UaW1pbmdzID0gdGhpcy5nZXRTZXR0aW5nc0RlZmF1bHQoKTtcbiAgICAgICAgaWYgKCF3ZWFwb25UaW1pbmdzKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd2VhcG9uVGltaW5nc1Jlc3VsdCA9IHtcbiAgICAgICAgICAgIGZpc3Q6IFswLCAwXSxcbiAgICAgICAgICAgIHN3b3JkOiBbMCwgMF0sXG4gICAgICAgICAgICBkYWdnZXI6IFswLCAwXSxcbiAgICAgICAgICAgIHdhckF4ZTogWzAsIDBdLFxuICAgICAgICAgICAgbWFjZTogWzAsIDBdLFxuICAgICAgICAgICAgZ3JlYXRzd29yZDogWzAsIDBdLFxuICAgICAgICAgICAgYmF0dGxlYXhlOiBbMCwgMF0sXG4gICAgICAgICAgICB3YXJoYW1tZXI6IFswLCAwXSxcbiAgICAgICAgICAgIGJvdzogWzAsIDBdLFxuICAgICAgICAgICAgc3RhZmY6IFswLCAwXSxcbiAgICAgICAgICAgIGNyb3NzYm93OiBbMCwgMF0sXG4gICAgICAgIH07XG4gICAgICAgIHdlYXBvblRpbWluZ3NSZXN1bHQuZmlzdCA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwiZmlzdFwiLCB3ZWFwb25UaW1pbmdzKTtcbiAgICAgICAgd2VhcG9uVGltaW5nc1Jlc3VsdC5zd29yZCA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwic3dvcmRcIiwgd2VhcG9uVGltaW5ncyk7XG4gICAgICAgIHdlYXBvblRpbWluZ3NSZXN1bHQuZGFnZ2VyID0gdGhpcy5nZXRBbmRWYWxpZGF0ZVRpbWluZ3NDb25maWdLZXkoXCJkYWdnZXJcIiwgd2VhcG9uVGltaW5ncyk7XG4gICAgICAgIHdlYXBvblRpbWluZ3NSZXN1bHQud2FyQXhlID0gdGhpcy5nZXRBbmRWYWxpZGF0ZVRpbWluZ3NDb25maWdLZXkoXCJ3YXJBeGVcIiwgd2VhcG9uVGltaW5ncyk7XG4gICAgICAgIHdlYXBvblRpbWluZ3NSZXN1bHQubWFjZSA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwibWFjZVwiLCB3ZWFwb25UaW1pbmdzKTtcbiAgICAgICAgd2VhcG9uVGltaW5nc1Jlc3VsdC5ncmVhdHN3b3JkID0gdGhpcy5nZXRBbmRWYWxpZGF0ZVRpbWluZ3NDb25maWdLZXkoXCJncmVhdHN3b3JkXCIsIHdlYXBvblRpbWluZ3MpO1xuICAgICAgICB3ZWFwb25UaW1pbmdzUmVzdWx0LmJhdHRsZWF4ZSA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwiYmF0dGxlYXhlXCIsIHdlYXBvblRpbWluZ3MpO1xuICAgICAgICB3ZWFwb25UaW1pbmdzUmVzdWx0LndhcmhhbW1lciA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwid2FyaGFtbWVyXCIsIHdlYXBvblRpbWluZ3MpO1xuICAgICAgICB3ZWFwb25UaW1pbmdzUmVzdWx0LmJvdyA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwiYm93XCIsIHdlYXBvblRpbWluZ3MpO1xuICAgICAgICB3ZWFwb25UaW1pbmdzUmVzdWx0LnN0YWZmID0gdGhpcy5nZXRBbmRWYWxpZGF0ZVRpbWluZ3NDb25maWdLZXkoXCJzdGFmZlwiLCB3ZWFwb25UaW1pbmdzKTtcbiAgICAgICAgd2VhcG9uVGltaW5nc1Jlc3VsdC5jcm9zc2JvdyA9IHRoaXMuZ2V0QW5kVmFsaWRhdGVUaW1pbmdzQ29uZmlnS2V5KFwiY3Jvc3Nib3dcIiwgd2VhcG9uVGltaW5ncyk7XG4gICAgICAgIHN3aXRjaCAod2VhcG9uKSB7XG4gICAgICAgICAgICBjYXNlIDAgLyogV2VhcG9uVHlwZS5GaXN0ICovOlxuICAgICAgICAgICAgICAgIHJldHVybiB3ZWFwb25UaW1pbmdzUmVzdWx0LmZpc3Q7XG4gICAgICAgICAgICBjYXNlIDEgLyogV2VhcG9uVHlwZS5Td29yZCAqLzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VhcG9uVGltaW5nc1Jlc3VsdC5zd29yZDtcbiAgICAgICAgICAgIGNhc2UgMiAvKiBXZWFwb25UeXBlLkRhZ2dlciAqLzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VhcG9uVGltaW5nc1Jlc3VsdC5kYWdnZXI7XG4gICAgICAgICAgICBjYXNlIDMgLyogV2VhcG9uVHlwZS5XYXJBeGUgKi86XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdlYXBvblRpbWluZ3NSZXN1bHQud2FyQXhlO1xuICAgICAgICAgICAgY2FzZSA0IC8qIFdlYXBvblR5cGUuTWFjZSAqLzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VhcG9uVGltaW5nc1Jlc3VsdC5tYWNlO1xuICAgICAgICAgICAgY2FzZSA1IC8qIFdlYXBvblR5cGUuR3JlYXRzd29yZCAqLzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VhcG9uVGltaW5nc1Jlc3VsdC5ncmVhdHN3b3JkO1xuICAgICAgICAgICAgY2FzZSA2IC8qIFdlYXBvblR5cGUuQmF0dGxlYXhlICovOlxuICAgICAgICAgICAgICAgIHJldHVybiB3ZWFwb25UaW1pbmdzUmVzdWx0LmJhdHRsZWF4ZTtcbiAgICAgICAgICAgIGNhc2UgNiAvKiBXZWFwb25UeXBlLldhcmhhbW1lciAqLzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VhcG9uVGltaW5nc1Jlc3VsdC53YXJoYW1tZXI7XG4gICAgICAgICAgICBjYXNlIDcgLyogV2VhcG9uVHlwZS5Cb3cgKi86XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdlYXBvblRpbWluZ3NSZXN1bHQuYm93O1xuICAgICAgICAgICAgY2FzZSA4IC8qIFdlYXBvblR5cGUuU3RhZmYgKi86XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdlYXBvblRpbWluZ3NSZXN1bHQuc3RhZmY7XG4gICAgICAgICAgICBjYXNlIDkgLyogV2VhcG9uVHlwZS5Dcm9zc2JvdyAqLzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VhcG9uVGltaW5nc1Jlc3VsdC5jcm9zc2JvdztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJObyB0aW1pbmdzIGZvdW5kIGZvciB3ZWFwb24gdHlwZVwiLCB3ZWFwb24pO1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZS5wcm90b3R5cGUuZ2V0VGltaW5ncyA9IGZ1bmN0aW9uICh3ZWFwb24pIHtcbiAgICAgICAgdmFyIHRpbWluZ3NGcm9tQ29uZmlnID0gdGhpcy5nZXRUaW1pbmdzRnJvbUNvbmZpZyh3ZWFwb24pO1xuICAgICAgICBpZiAoIXdlYXBvbiB8fCAhdGltaW5nc0Zyb21Db25maWcpIHtcbiAgICAgICAgICAgIHdlYXBvbiA9IDAgLyogV2VhcG9uVHlwZS5GaXN0ICovO1xuICAgICAgICAgICAgdGltaW5nc0Zyb21Db25maWcgPSB0aGlzLmdldFRpbWluZ3NGcm9tQ29uZmlnKHdlYXBvbik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aW1pbmdzRnJvbUNvbmZpZykge1xuICAgICAgICAgICAgbG9nRXJyb3IodGhpcywgXCJObyB0aW1pbmdzIGZvdW5kIGZvciB3ZWFwb24gdHlwZVwiLCB3ZWFwb24pO1xuICAgICAgICAgICAgcmV0dXJuIFswLCAwXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGltaW5nc0Zyb21Db25maWc7XG4gICAgfTtcbiAgICA7XG4gICAgU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2UucHJvdG90eXBlLmhhc1N3ZWV0UGllID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbW9kQ291bnQgPSB0aGlzLnNwLkdhbWUuZ2V0TW9kQ291bnQoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb2RDb3VudDsgKytpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zcC5HYW1lLmdldE1vZE5hbWUoaSkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnc3dlZXRwaWUnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIHJldHVybiBTd2VldFRhZmZ5UGxheWVyQ29tYmF0U2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgYnJvd3NlciB9IGZyb20gJ3NreXJpbVBsYXRmb3JtJztcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSAnLi9jbGllbnRMaXN0ZW5lcic7XG5pbXBvcnQgeyBsb2dUcmFjZSB9IGZyb20gJy4uLy4uL2xvZ2dpbmcnO1xuLy8gVE9ETzogbW92ZSB0byBzZXJ2ZXIvZ2FtZW1vZGVcbnZhciBTd2VldFRhZmZ5U2tpbGxNZW51U2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU3dlZXRUYWZmeVNraWxsTWVudVNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU3dlZXRUYWZmeVNraWxsTWVudVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmFsdGFycyA9IFtcbiAgICAgICAgICAgIDB4MDAxMDA3ODAsIDB4MDAwRDk4ODMsIDB4MDAwRDk4N0IsIDB4MDAwRDk4ODEsIDB4MDAwRDk4ODcsIDB4MDAwRkI5OTcsXG4gICAgICAgICAgICAweDAwMEQ5ODg1LCAweDAwMEQ5ODdELCAweDAwMDcxODU0LCAweDA3MTg3NTAwLCAweDAyMDBjODZiLCAweDAwMGQ5ODdmLFxuICAgICAgICAgICAgMHgwNzA1OGQ0ZSwgMHgwNzA1OGQ1MywgMHgwNzBBNjkxMiwgMHgwNzA1OGQ1MSwgMHgwNzA1OGQ1MCwgMHgwNzA1OGQ0ZixcbiAgICAgICAgICAgIDB4MDcwNThkNGQsIDB4MDcwNThkNGMsIDB4MDcwNThkNGIsIDB4MDcwNWUyZmEsIDB4MDcwNThkNGEsIDB4MDcwNThkNDksXG4gICAgICAgICAgICAweDA3MDVlMzY3LCAweDA3MDU4ZDQ4LCAweDA3MDU4ZDU1LCAweDA3MDU4ZDQ2LCAweDA3MDU4ZDQ3LCAweDA3MDVlMmIwLFxuICAgICAgICAgICAgMHgwNzA1OGQ0NVxuICAgICAgICBdO1xuICAgICAgICBpZiAoIV90aGlzLmhhc1N3ZWV0UGllKCkpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlN3ZWV0VGFmZnkgZmVhdHVyZXMgZGlzYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJTd2VldFRhZmZ5IGZlYXR1cmVzIGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbmNlKFwiYWN0aXZhdGVcIiwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uQWN0aXZhdGUoZSk7IH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFN3ZWV0VGFmZnlTa2lsbE1lbnVTZXJ2aWNlLnByb3RvdHlwZS5vbkFjdGl2YXRlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgaWYgKCF0aGlzLmhhc1N3ZWV0UGllKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuYWx0YXJzLmluY2x1ZGVzKCgoX2EgPSBldmVudC50YXJnZXQuZ2V0QmFzZU9iamVjdCgpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ2V0Rm9ybUlEKCkpIHx8IC0xKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGJyb3dzZXIuc2V0Rm9jdXNlZCh0cnVlKTtcbiAgICAgICAgdmFyIHNyYyA9IFwid2luZG93LmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KCdpbml0U2tpbGxNZW51JykpXCI7XG4gICAgICAgIGJyb3dzZXIuZXhlY3V0ZUphdmFTY3JpcHQoc3JjKTtcbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlTa2lsbE1lbnVTZXJ2aWNlLnByb3RvdHlwZS5oYXNTd2VldFBpZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1vZENvdW50ID0gdGhpcy5zcC5HYW1lLmdldE1vZENvdW50KCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW9kQ291bnQ7ICsraSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3AuR2FtZS5nZXRNb2ROYW1lKGkpLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ3N3ZWV0cGllJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICByZXR1cm4gU3dlZXRUYWZmeVNraWxsTWVudVNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTd2VldFRhZmZ5U2tpbGxNZW51U2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBTd2VldFRhZmZ5U3RhdGljUGVya3NTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTd2VldFRhZmZ5U3RhdGljUGVya3NTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN3ZWV0VGFmZnlTdGF0aWNQZXJrc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIC8vIFRPRE86IG1vdmUgdGhpcyB0byBjb25maWdcbiAgICAgICAgX3RoaXMuc3RlYWx0aCA9IFsweEJFMTI2LCAweEMwN0M2LCAweEMwN0M3LCAweEMwN0M4LCAweEMwN0M5XTtcbiAgICAgICAgX3RoaXMubWFnaWMgPSBbMHg1ODIxMywgMHgxMDVGMjQsIDB4NTgyMTRdO1xuICAgICAgICBfdGhpcy53YXJyaW9yID0gWzB4Q0I0MEQsIDB4Q0I0MEYsIDB4Q0I0MTQsIDB4Q0I0MTEsIDB4Q0I0MTIsIDB4Q0I0MTAsIDB4Q0I0MEVdO1xuICAgICAgICBpZiAoIV90aGlzLmhhc1N3ZWV0UGllKCkpIHtcbiAgICAgICAgICAgIGxvZ1RyYWNlKF90aGlzLCBcIlN3ZWV0VGFmZnkgZmVhdHVyZXMgZGlzYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsb2dUcmFjZShfdGhpcywgXCJTd2VldFRhZmZ5IGZlYXR1cmVzIGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbmNlKFwidXBkYXRlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uY2VVcGRhdGUoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU3dlZXRUYWZmeVN0YXRpY1BlcmtzU2VydmljZS5wcm90b3R5cGUub25jZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmhhc1N3ZWV0UGllKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZFN0YXRpY1BlcmtzVG9UaGVQbGF5ZXIoKTtcbiAgICB9O1xuICAgIFN3ZWV0VGFmZnlTdGF0aWNQZXJrc1NlcnZpY2UucHJvdG90eXBlLmFkZFN0YXRpY1BlcmtzVG9UaGVQbGF5ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwbGF5ZXIgPSB0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgIHZhciBhbGxTdGF0aWNQZXJrSWRzID0gdGhpcy5zdGVhbHRoLmNvbmNhdCh0aGlzLm1hZ2ljKS5jb25jYXQodGhpcy53YXJyaW9yKTtcbiAgICAgICAgYWxsU3RhdGljUGVya0lkcy5mb3JFYWNoKGZ1bmN0aW9uIChwZXJrSWQpIHtcbiAgICAgICAgICAgIHBsYXllci5hZGRQZXJrKF90aGlzLnNwLlBlcmsuZnJvbShfdGhpcy5zcC5HYW1lLmdldEZvcm1FeChwZXJrSWQpKSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU3dlZXRUYWZmeVN0YXRpY1BlcmtzU2VydmljZS5wcm90b3R5cGUuaGFzU3dlZXRQaWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtb2RDb3VudCA9IHRoaXMuc3AuR2FtZS5nZXRNb2RDb3VudCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vZENvdW50OyArK2kpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNwLkdhbWUuZ2V0TW9kTmFtZShpKS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdzd2VldHBpZScpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgcmV0dXJuIFN3ZWV0VGFmZnlTdGF0aWNQZXJrc1NlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBTd2VldFRhZmZ5U3RhdGljUGVya3NTZXJ2aWNlIH07XG4iLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tIFwiLi9jbGllbnRMaXN0ZW5lclwiO1xuLy8gVE9ETzogbW92ZSB0byB0aGUgc2VydmVyL2dhbWVtb2RlXG52YXIgU3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTd2VldFRhZmZ5U3dlZXRDYW50RHJvcFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNwID0gc3A7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5jYW50RHJvcEtleXdvcmQgPSBcIlN3ZWV0Q2FudERyb3BcIjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTd2VldFRhZmZ5U3dlZXRDYW50RHJvcFNlcnZpY2UucHJvdG90eXBlLmNhbkRyb3BPclB1dEl0ZW0gPSBmdW5jdGlvbiAoaXRlbUlkKSB7XG4gICAgICAgIHZhciBpdGVtID0gdGhpcy5zcC5HYW1lLmdldEZvcm1FeChpdGVtSWQpO1xuICAgICAgICBpZiAoaXRlbSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGl0ZW0uaGFzS2V5d29yZCh0aGlzLnNwLktleXdvcmQuZ2V0S2V5d29yZCh0aGlzLmNhbnREcm9wS2V5d29yZCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgcmV0dXJuIFN3ZWV0VGFmZnlTd2VldENhbnREcm9wU2VydmljZTtcbn0oQ2xpZW50TGlzdGVuZXIpKTtcbmV4cG9ydCB7IFN3ZWV0VGFmZnlTd2VldENhbnREcm9wU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBUaW1lU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoVGltZVNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVGltZVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLmxhc3RUaW1lVXBkID0gMDtcbiAgICAgICAgY29udHJvbGxlci5vbihcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vblVwZGF0ZSgpOyB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBUaW1lU2VydmljZS5wcm90b3R5cGUuZ2V0VGltZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGhvdXJzT2Zmc2V0U2V0dGluZyA9IHRoaXMuc3Auc2V0dGluZ3NbXCJza3ltcDUtY2xpZW50XCJdW1wiaG91cnNPZmZzZXRcIl07XG4gICAgICAgIHZhciBob3Vyc09mZnNldCA9IHR5cGVvZiBob3Vyc09mZnNldFNldHRpbmcgPT09IFwibnVtYmVyXCIgPyBob3Vyc09mZnNldFNldHRpbmcgOiAwO1xuICAgICAgICB2YXIgaG91cnNPZmZzZXRNcyA9IGhvdXJzT2Zmc2V0ICogNjAgKiA2MCAqIDEwMDA7XG4gICAgICAgIHZhciBkID0gbmV3IERhdGUoRGF0ZS5ub3coKSArIGhvdXJzT2Zmc2V0TXMpO1xuICAgICAgICB2YXIgbmV3R2FtZUhvdXJWYWx1ZSA9IDA7XG4gICAgICAgIG5ld0dhbWVIb3VyVmFsdWUgKz0gZC5nZXRVVENIb3VycygpO1xuICAgICAgICBuZXdHYW1lSG91clZhbHVlICs9IGQuZ2V0VVRDTWludXRlcygpIC8gNjA7XG4gICAgICAgIG5ld0dhbWVIb3VyVmFsdWUgKz0gZC5nZXRVVENTZWNvbmRzKCkgLyA2MCAvIDYwO1xuICAgICAgICBuZXdHYW1lSG91clZhbHVlICs9IGQuZ2V0VVRDTWlsbGlzZWNvbmRzKCkgLyA2MCAvIDYwIC8gMTAwMDtcbiAgICAgICAgcmV0dXJuIHsgbmV3R2FtZUhvdXJWYWx1ZTogbmV3R2FtZUhvdXJWYWx1ZSwgZGF0ZTogZCB9O1xuICAgIH07XG4gICAgVGltZVNlcnZpY2UucHJvdG90eXBlLmV2ZXJ5MnNlY29uZHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBnYW1lSG91cklkID0gMHgzODtcbiAgICAgICAgdmFyIGdhbWVNb250aElkID0gMHgzNjtcbiAgICAgICAgdmFyIGdhbWVEYXlJZCA9IDB4Mzc7XG4gICAgICAgIHZhciBnYW1lWWVhcklkID0gMHgzNTtcbiAgICAgICAgdmFyIHRpbWVTY2FsZUlkID0gMHgzYTtcbiAgICAgICAgdmFyIGdhbWVIb3VyID0gdGhpcy5zcC5HbG9iYWxWYXJpYWJsZS5mcm9tKHRoaXMuc3AuR2FtZS5nZXRGb3JtRXgoZ2FtZUhvdXJJZCkpO1xuICAgICAgICB2YXIgZ2FtZURheSA9IHRoaXMuc3AuR2xvYmFsVmFyaWFibGUuZnJvbSh0aGlzLnNwLkdhbWUuZ2V0Rm9ybUV4KGdhbWVEYXlJZCkpO1xuICAgICAgICB2YXIgZ2FtZU1vbnRoID0gdGhpcy5zcC5HbG9iYWxWYXJpYWJsZS5mcm9tKHRoaXMuc3AuR2FtZS5nZXRGb3JtRXgoZ2FtZU1vbnRoSWQpKTtcbiAgICAgICAgdmFyIGdhbWVZZWFyID0gdGhpcy5zcC5HbG9iYWxWYXJpYWJsZS5mcm9tKHRoaXMuc3AuR2FtZS5nZXRGb3JtRXgoZ2FtZVllYXJJZCkpO1xuICAgICAgICB2YXIgdGltZVNjYWxlID0gdGhpcy5zcC5HbG9iYWxWYXJpYWJsZS5mcm9tKHRoaXMuc3AuR2FtZS5nZXRGb3JtRXgodGltZVNjYWxlSWQpKTtcbiAgICAgICAgaWYgKCFnYW1lSG91ciB8fCAhZ2FtZURheSB8fCAhZ2FtZU1vbnRoIHx8ICFnYW1lWWVhciB8fCAhdGltZVNjYWxlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIF9hID0gdGhpcy5nZXRUaW1lKCksIG5ld0dhbWVIb3VyVmFsdWUgPSBfYS5uZXdHYW1lSG91clZhbHVlLCBkYXRlID0gX2EuZGF0ZTtcbiAgICAgICAgdmFyIGRpZmYgPSBNYXRoLmFicyhnYW1lSG91ci5nZXRWYWx1ZSgpIC0gbmV3R2FtZUhvdXJWYWx1ZSk7XG4gICAgICAgIGlmIChkaWZmID49IDEgLyA2MCkge1xuICAgICAgICAgICAgZ2FtZUhvdXIuc2V0VmFsdWUobmV3R2FtZUhvdXJWYWx1ZSk7XG4gICAgICAgICAgICBnYW1lRGF5LnNldFZhbHVlKGRhdGUuZ2V0VVRDRGF0ZSgpKTtcbiAgICAgICAgICAgIGdhbWVNb250aC5zZXRWYWx1ZShkYXRlLmdldFVUQ01vbnRoKCkpO1xuICAgICAgICAgICAgZ2FtZVllYXIuc2V0VmFsdWUoZGF0ZS5nZXRVVENGdWxsWWVhcigpIC0gMjAyMCArIDE5OSk7XG4gICAgICAgIH1cbiAgICAgICAgdGltZVNjYWxlLnNldFZhbHVlKGdhbWVIb3VyLmdldFZhbHVlKCkgPiBuZXdHYW1lSG91clZhbHVlID8gMC42IDogMS4yKTtcbiAgICB9O1xuICAgIFRpbWVTZXJ2aWNlLnByb3RvdHlwZS5vblVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKERhdGUubm93KCkgLSB0aGlzLmxhc3RUaW1lVXBkIDw9IDIwMDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhc3RUaW1lVXBkID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdGhpcy5ldmVyeTJzZWNvbmRzKCk7XG4gICAgfTtcbiAgICByZXR1cm4gVGltZVNlcnZpY2U7XG59KENsaWVudExpc3RlbmVyKSk7XG5leHBvcnQgeyBUaW1lU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbnZhciBQcm9jZXNzTWV0aG9kVHlwZTtcbihmdW5jdGlvbiAoUHJvY2Vzc01ldGhvZFR5cGUpIHtcbiAgICBQcm9jZXNzTWV0aG9kVHlwZVtcInVwZGF0ZVwiXSA9IFwidXBkYXRlXCI7XG4gICAgUHJvY2Vzc01ldGhvZFR5cGVbXCJ0aWNrXCJdID0gXCJ0aWNrXCI7XG59KShQcm9jZXNzTWV0aG9kVHlwZSB8fCAoUHJvY2Vzc01ldGhvZFR5cGUgPSB7fSkpO1xudmFyIFRpbWVyc1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFRpbWVyc1NlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVGltZXJzU2VydmljZShzcCwgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zcCA9IHNwO1xuICAgICAgICBfdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMudGltZXJzQXJyID0gbmV3IEFycmF5KCk7XG4gICAgICAgIF90aGlzLmludGVydmFsc0FyciA9IG5ldyBBcnJheSgpO1xuICAgICAgICBfdGhpcy5sYXN0Q2FsbFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICBfdGhpcy5wcm9jZXNzTWV0aG9kVHlwZVN0b3JhZ2VLZXkgPSBcInVwZGF0ZVR5cGVTdG9yYWdlS2V5XCI7XG4gICAgICAgIHZhciBzdG9yYWdlUHJvY2Vzc01ldGhvZCA9IHNwLnN0b3JhZ2VbX3RoaXMucHJvY2Vzc01ldGhvZFR5cGVTdG9yYWdlS2V5XTtcbiAgICAgICAgaWYgKHR5cGVvZiBzdG9yYWdlUHJvY2Vzc01ldGhvZCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICBfdGhpcy5zZXRQcm9jZXNzTWV0aG9kKHN0b3JhZ2VQcm9jZXNzTWV0aG9kKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIF90aGlzLnNldFByb2Nlc3NNZXRob2QoUHJvY2Vzc01ldGhvZFR5cGUudGljayk7XG4gICAgICAgIH1cbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbihcIm1lbnVPcGVuXCIsIGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbk1lbnVPcGVuKGUpOyB9KTtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlci5vbihcInByZUxvYWRHYW1lXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uUHJlTG9hZEdhbWUoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVGltZXJzU2VydmljZS5wcm90b3R5cGUuc2V0VGltZW91dCA9IGZ1bmN0aW9uIChoYW5kbGVyLCB0aW1lb3V0KSB7XG4gICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMjsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBhcmdzW19pIC0gMl0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0aW1lciA9IHsgaGFuZGxlcjogaGFuZGxlciwgYXJnczogYXJncywgZGVsYXlNczogdGltZW91dCAhPT0gbnVsbCAmJiB0aW1lb3V0ICE9PSB2b2lkIDAgPyB0aW1lb3V0IDogMCwgcGFzc2VkTXM6IDAgfTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRpbWVyc0Fyci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnRpbWVyc0FycltpXSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXJzQXJyW2ldID0gdGltZXI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGkgKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnRpbWVyc0Fyci5wdXNoKHRpbWVyKTtcbiAgICB9O1xuICAgIFRpbWVyc1NlcnZpY2UucHJvdG90eXBlLmNsZWFyVGltZW91dCA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICBpZiAoaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy50aW1lcnNBcnIgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaWQgPD0gMCB8fCBpZCA+IHRoaXMudGltZXJzQXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudGltZXJzQXJyW2lkIC0gMV0gPSBudWxsO1xuICAgICAgICByZXR1cm47XG4gICAgfTtcbiAgICBUaW1lcnNTZXJ2aWNlLnByb3RvdHlwZS5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uIChoYW5kbGVyLCB0aW1lb3V0KSB7XG4gICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMjsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBhcmdzW19pIC0gMl0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0aW1lciA9IHsgaGFuZGxlcjogaGFuZGxlciwgYXJnczogYXJncywgZGVsYXlNczogdGltZW91dCAhPT0gbnVsbCAmJiB0aW1lb3V0ICE9PSB2b2lkIDAgPyB0aW1lb3V0IDogMCwgcGFzc2VkTXM6IDAgfTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmludGVydmFsc0Fyci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmludGVydmFsc0FycltpXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW50ZXJ2YWxzQXJyW2ldID0gdGltZXI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGkgKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmludGVydmFsc0Fyci5wdXNoKHRpbWVyKTtcbiAgICB9O1xuICAgIFRpbWVyc1NlcnZpY2UucHJvdG90eXBlLmNsZWFySW50ZXJ2YWwgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgaWYgKGlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaW50ZXJ2YWxzQXJyID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlkIDw9IDAgfHwgaWQgPiB0aGlzLmludGVydmFsc0Fyci5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmludGVydmFsc0FycltpZCAtIDFdID0gbnVsbDtcbiAgICAgICAgcmV0dXJuO1xuICAgIH07XG4gICAgVGltZXJzU2VydmljZS5wcm90b3R5cGUuc2V0UHJvY2Vzc01ldGhvZCA9IGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgc3dpdGNoIChtZXRob2QpIHtcbiAgICAgICAgICAgIGNhc2UgUHJvY2Vzc01ldGhvZFR5cGUudGljazpcbiAgICAgICAgICAgICAgICB0aGlzLnNwLnN0b3JhZ2VbdGhpcy5wcm9jZXNzTWV0aG9kVHlwZVN0b3JhZ2VLZXldID0gUHJvY2Vzc01ldGhvZFR5cGUudGljaztcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUV2ZW50SGFuZGxlID0gdGhpcy5jb250cm9sbGVyLm9uKFByb2Nlc3NNZXRob2RUeXBlLnRpY2ssIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnByb2Nlc3NUaW1lcnMoKTsgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY2FzZSBQcm9jZXNzTWV0aG9kVHlwZS51cGRhdGU6XG4gICAgICAgICAgICAgICAgdGhpcy5zcC5zdG9yYWdlW3RoaXMucHJvY2Vzc01ldGhvZFR5cGVTdG9yYWdlS2V5XSA9IFByb2Nlc3NNZXRob2RUeXBlLnVwZGF0ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUV2ZW50SGFuZGxlID0gdGhpcy5jb250cm9sbGVyLm9uKFByb2Nlc3NNZXRob2RUeXBlLnVwZGF0ZSwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMucHJvY2Vzc1RpbWVycygpOyB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zcC5HYW1lLmdldFBsYXllcigpKSB7XG4gICAgICAgICAgICAgICAgLy8gRklYTUUoR00tMTAwOClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2V0UHJvY2Vzc01ldGhvZChQcm9jZXNzTWV0aG9kVHlwZS51cGRhdGUpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChfYSkge1xuICAgICAgICAgICAgdGhpcy5zZXRQcm9jZXNzTWV0aG9kKFByb2Nlc3NNZXRob2RUeXBlLnRpY2spO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUaW1lcnNTZXJ2aWNlLnByb3RvdHlwZS5wcm9jZXNzVGltZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZHQgPSBEYXRlLm5vdygpIC0gdGhpcy5sYXN0Q2FsbFRpbWU7XG4gICAgICAgIHRoaXMubGFzdENhbGxUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgLy8gcHJvY2VzcyB0aW1lcnNcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRpbWVyc0Fyci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdmFyIHRpbWVyID0gdGhpcy50aW1lcnNBcnJbaV07XG4gICAgICAgICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgICAgICAgICB0aW1lci5wYXNzZWRNcyArPSBkdDtcbiAgICAgICAgICAgICAgICBpZiAodGltZXIucGFzc2VkTXMgPj0gdGltZXIuZGVsYXlNcykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRpbWVyc0FycltpXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGltZXIuaGFuZGxlciA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lci5oYW5kbGVyLmNhbGwodGhpcywgdGltZXIuYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmFsKHRpbWVyLmhhbmRsZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaSA9PT0gdGhpcy50aW1lcnNBcnIubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBsYXN0IHVudXNlZCBlbGVtZW50XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lcnNBcnIubGVuZ3RoIC09IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBpbnRlcnZhbHNcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmludGVydmFsc0Fyci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdmFyIGludGVydmFsID0gdGhpcy5pbnRlcnZhbHNBcnJbaV07XG4gICAgICAgICAgICBpZiAoaW50ZXJ2YWwpIHtcbiAgICAgICAgICAgICAgICBpbnRlcnZhbC5wYXNzZWRNcyArPSBkdDtcbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJ2YWwucGFzc2VkTXMgPj0gaW50ZXJ2YWwuZGVsYXlNcykge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbC5wYXNzZWRNcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaW50ZXJ2YWwuaGFuZGxlciA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbC5oYW5kbGVyLmNhbGwodGhpcywgaW50ZXJ2YWwuYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmFsKGludGVydmFsLmhhbmRsZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaSA9PT0gdGhpcy5pbnRlcnZhbHNBcnIubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBsYXN0IHVudXNlZCBlbGVtZW50XG4gICAgICAgICAgICAgICAgdGhpcy5pbnRlcnZhbHNBcnIubGVuZ3RoIC09IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFRpbWVyc1NlcnZpY2UucHJvdG90eXBlLm9uTWVudU9wZW4gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS5uYW1lID09PSBcIk1haW4gTWVudVwiIC8qIE1lbnUuTWFpbiAqLykge1xuICAgICAgICAgICAgaWYgKHRoaXMudXBkYXRlRXZlbnRIYW5kbGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNwLnVuc3Vic2NyaWJlKHRoaXMudXBkYXRlRXZlbnRIYW5kbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRQcm9jZXNzTWV0aG9kKFByb2Nlc3NNZXRob2RUeXBlLnRpY2spO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUaW1lcnNTZXJ2aWNlLnByb3RvdHlwZS5vblByZUxvYWRHYW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy51cGRhdGVFdmVudEhhbmRsZSkge1xuICAgICAgICAgICAgdGhpcy5zcC51bnN1YnNjcmliZSh0aGlzLnVwZGF0ZUV2ZW50SGFuZGxlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFByb2Nlc3NNZXRob2QoUHJvY2Vzc01ldGhvZFR5cGUudXBkYXRlKTtcbiAgICB9O1xuICAgIHJldHVybiBUaW1lcnNTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgVGltZXJzU2VydmljZSB9O1xuIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IENsaWVudExpc3RlbmVyIH0gZnJvbSBcIi4vY2xpZW50TGlzdGVuZXJcIjtcbmltcG9ydCB7IE9iamVjdFJlZmVyZW5jZUV4IH0gZnJvbSBcIi4uLy4uL2V4dGVuc2lvbnMvb2JqZWN0UmVmZXJlbmNlRXhcIjtcbmltcG9ydCB7IHN0b3JhZ2UgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IGxvZ1RyYWNlIH0gZnJvbSBcIi4uLy4uL2xvZ2dpbmdcIjtcbnZhciBXb3JsZENsZWFuZXJTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhXb3JsZENsZWFuZXJTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFdvcmxkQ2xlYW5lclNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIF90aGlzLnByb3RlY3Rpb24gPSBuZXcgTWFwKCk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIF90aGlzLmNvbnRyb2xsZXIuZW1pdHRlci5vbihcImdhbWVMb2FkXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uR2FtZUxvYWQoKTsgfSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgV29ybGRDbGVhbmVyU2VydmljZS5wcm90b3R5cGUubW9kV2NQcm90ZWN0aW9uID0gZnVuY3Rpb24gKGFjdG9ySWQsIG1vZCkge1xuICAgICAgICB2YXIgY3VycmVudFByb3RlY3Rpb24gPSB0aGlzLnByb3RlY3Rpb24uZ2V0KGFjdG9ySWQpO1xuICAgICAgICB0aGlzLnByb3RlY3Rpb24uc2V0KGFjdG9ySWQsIGN1cnJlbnRQcm90ZWN0aW9uID8gY3VycmVudFByb3RlY3Rpb24gKyBtb2QgOiBtb2QpO1xuICAgIH07XG4gICAgV29ybGRDbGVhbmVyU2VydmljZS5wcm90b3R5cGUuZ2V0V2NQcm90ZWN0aW9uID0gZnVuY3Rpb24gKGFjdG9ySWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvdGVjdGlvbi5nZXQoYWN0b3JJZCkgfHwgMDtcbiAgICB9O1xuICAgIFdvcmxkQ2xlYW5lclNlcnZpY2UucHJvdG90eXBlLm9uR2FtZUxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwbGF5ZXIgPSB0aGlzLnNwLkdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgIGlmICghcGxheWVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbml0aWFsUG9zID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0UG9zKHBsYXllcik7XG4gICAgICAgIHRoaXMuaW5pdGlhbENlbGxPcldvcmxkID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0V29ybGRPckNlbGwocGxheWVyKTtcbiAgICB9O1xuICAgIFdvcmxkQ2xlYW5lclNlcnZpY2UucHJvdG90eXBlLm9uVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnByb2Nlc3NPbmVBY3RvcigpO1xuICAgIH07XG4gICAgV29ybGRDbGVhbmVyU2VydmljZS5wcm90b3R5cGUucHJvY2Vzc09uZUFjdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHZhciBwYyA9IHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKTtcbiAgICAgICAgaWYgKHBjID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFjdG9yID0gdGhpcy5zcC5HYW1lLmZpbmRSYW5kb21BY3RvcihwYy5nZXRQb3NpdGlvblgoKSwgcGMuZ2V0UG9zaXRpb25ZKCksIHBjLmdldFBvc2l0aW9uWigpLCA4MTkyKTtcbiAgICAgICAgaWYgKGFjdG9yID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFjdG9ySWQgPSBhY3Rvci5nZXRGb3JtSUQoKTtcbiAgICAgICAgdmFyIGN1cnJlbnRQcm90ZWN0aW9uID0gdGhpcy5wcm90ZWN0aW9uLmdldChhY3RvcklkKSB8fCAwO1xuICAgICAgICBpZiAoY3VycmVudFByb3RlY3Rpb24gPiAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gRWxkZXJ2YWxlOiBhbGxvd2xpc3QgZGUgYWN0b3JlcyBDTElFTlQtTE9DQUwgKGNhYmFsbG9zIHZpYSBwbGFjZUF0TWUgZW4gZWwgZ2FtZW1vZGUpIHF1ZVxuICAgICAgICAvLyBubyBlc3RhbiBlbiBlbCBtb2RlbG8gZGVsIHNlcnZlciB5IHBvciBlc28gbm8gdGllbmVuIHByb3RlY2Npb24gdmlhIEZvcm1WaWV3LiBFbCBnYW1lbW9kZVxuICAgICAgICAvLyBtYXJjYSBzdSBmb3JtSWQgZW4gZWwgbWlzbW8gc3RvcmFnZSBnbG9iYWwgKGN0eC5zcC5zdG9yYWdlWydlbGRIb3JzZVByb3RlY3QnXSkuIFNpbiBlc3RvIGVsXG4gICAgICAgIC8vIFdvcmxkQ2xlYW5lciBsb3MgYm9ycmEgYSBsb3MgcG9jb3MgZnJhbWVzLlxuICAgICAgICB2YXIgZWxkUHJvdGVjdCA9IHN0b3JhZ2VbXCJlbGRIb3JzZVByb3RlY3RcIl07XG4gICAgICAgIGlmIChlbGRQcm90ZWN0ICYmIHR5cGVvZiBlbGRQcm90ZWN0ID09PSBcIm9iamVjdFwiICYmIGVsZFByb3RlY3RbYWN0b3JJZF0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWN0b3JJZCA9PT0gMHgxNCB8fCBhY3Rvci5pc0Rpc2FibGVkKCkgfHwgYWN0b3IuaXNEZWxldGVkKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0FjdG9ySW5EaWFsb2d1ZShhY3RvcikpIHtcbiAgICAgICAgICAgIC8vIERlbGV0aW5nIGFjdG9yIGluIGRpYWxvZ3VlIGNyYXNoZXMgU2t5cmltXG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vc2t5cmltLW11bHRpcGxheWVyL2lzc3VlLXRyYWNrZXIvaXNzdWVzLzEzXG4gICAgICAgICAgICBhY3Rvci5zZXRQb3NpdGlvbigwLCAwLCAwKTtcbiAgICAgICAgICAgIGFjdG9yLmRpc2FibGVOb1dhaXQodHJ1ZSk7IC8vIFNlZW1zIHRvIG5vdCBjcmFzaFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEtlZXAgdmFuaWxhIHByZS1wbGFjZWQgYm9kaWVzLCBidXQgZGVsZXRlIHBsYXllciBib2RpZXNcbiAgICAgICAgaWYgKGFjdG9yLmlzRGVhZCgpICYmIGFjdG9ySWQgPCAweGZmMDAwMDAwKSB7XG4gICAgICAgICAgICBhY3Rvci5ibG9ja0FjdGl2YXRpb24odHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBvcyA9IE9iamVjdFJlZmVyZW5jZUV4LmdldFBvcyhhY3Rvcik7XG4gICAgICAgIHZhciBjZWxsT3JXb3JsZCA9IE9iamVjdFJlZmVyZW5jZUV4LmdldFdvcmxkT3JDZWxsKGFjdG9yKTtcbiAgICAgICAgdmFyIGNoaWNrZW5SYWNlID0gMHhhOTE5ZDtcbiAgICAgICAgLy8gV2UgZGlzY292ZXJlZCBhbm9tYWx5IGNoaWNrZW5zIHRoYXQgZmFpbCB0byBEaXNhYmxlIGlmIHdlIGxvYWQgZ2FtZSBuZWFyIHRvIHRoZW1cbiAgICAgICAgLy8gUmVmczogMTA2QzIyLCAxMDZDMjNcbiAgICAgICAgaWYgKGFjdG9ySWQgPCAweGZmMDAwMDAwICYmICgoX2EgPSBhY3Rvci5nZXRSYWNlKCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRGb3JtSUQoKSkgPT09IGNoaWNrZW5SYWNlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pbml0aWFsUG9zICYmIE9iamVjdFJlZmVyZW5jZUV4LmdldERpc3RhbmNlTm9aKHBvcywgdGhpcy5pbml0aWFsUG9zKSA8IDQwOTYpIHtcbiAgICAgICAgICAgICAgICBpZiAoY2VsbE9yV29ybGQgPT09IHRoaXMuaW5pdGlhbENlbGxPcldvcmxkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQWN0b3JJbkRpYWxvZ3VlKGFjdG9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsIFwiRGVsZXRpbmcgY2hpY2tlbiBhbm9tYWx5XCIsIGFjdG9ySWQudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgICAgICAgICAgICAgYWN0b3Iua2lsbFNpbGVudChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgYWN0b3IuYmxvY2tBY3RpdmF0aW9uKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBhY3Rvci5kaXNhYmxlTm9XYWl0KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgYWN0b3Iuc2V0QWxwaGEoMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFjdG9yLmRpc2FibGUoZmFsc2UpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGFjID0gX3RoaXMuc3AuQWN0b3IuZnJvbShfdGhpcy5zcC5HYW1lLmdldEZvcm1FeChhY3RvcklkKSk7XG4gICAgICAgICAgICBpZiAoIWFjIHx8IF90aGlzLmlzQWN0b3JJbkRpYWxvZ3VlKGFjKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjLmRlbGV0ZSgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFdvcmxkQ2xlYW5lclNlcnZpY2UucHJvdG90eXBlLmlzQWN0b3JJbkRpYWxvZ3VlID0gZnVuY3Rpb24gKGFjKSB7XG4gICAgICAgIHJldHVybiBhYy5pc0luRGlhbG9ndWVXaXRoUGxheWVyKCkgfHwgYWMuZ2V0RGlhbG9ndWVUYXJnZXQoKSAhPT0gbnVsbDtcbiAgICB9O1xuICAgIHJldHVybiBXb3JsZENsZWFuZXJTZXJ2aWNlO1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgV29ybGRDbGVhbmVyU2VydmljZSB9O1xuIiwiaW1wb3J0IHsgRXZlbnRFbWl0dGVyRmFjdG9yeSB9IGZyb20gXCIuL2V2ZW50cy9ldmVudHNcIjtcbmltcG9ydCAqIGFzIHNwIGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xudmFyIFNwQXBpSW50ZXJhY3RvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTcEFwaUludGVyYWN0b3IoKSB7XG4gICAgfVxuICAgIFNwQXBpSW50ZXJhY3Rvci5zZXR1cCA9IGZ1bmN0aW9uIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgbGlzdGVuZXJzLmZvckVhY2goZnVuY3Rpb24gKGxpc3RlbmVyKSB7IHJldHVybiBTcEFwaUludGVyYWN0b3IucmVnaXN0ZXJMaXN0ZW5lckZvckxvb2t1cChsaXN0ZW5lci5jb25zdHJ1Y3RvciwgbGlzdGVuZXIpOyB9KTtcbiAgICB9O1xuICAgIFNwQXBpSW50ZXJhY3Rvci5nZXRDb250cm9sbGVySW5zdGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChTcEFwaUludGVyYWN0b3IuY29udHJvbGxlcikge1xuICAgICAgICAgICAgcmV0dXJuIFNwQXBpSW50ZXJhY3Rvci5jb250cm9sbGVyO1xuICAgICAgICB9XG4gICAgICAgIFNwQXBpSW50ZXJhY3Rvci5jb250cm9sbGVyID0ge1xuICAgICAgICAgICAgLy8gVE9ETzogaGFuZGxlIGVycm9ycyBpbiBldmVudCBoYW5kbGVycy4gd2lsbCBvdXRwdXQgdG8gZ2FtZSBjb25zb2xlIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgIG9uOiBzcC5vbixcbiAgICAgICAgICAgIG9uY2U6IHNwLm9uY2UsXG4gICAgICAgICAgICBlbWl0dGVyOiBFdmVudEVtaXR0ZXJGYWN0b3J5Lm1ha2VFdmVudEVtaXR0ZXIoKSxcbiAgICAgICAgICAgIGxvb2t1cExpc3RlbmVyOiBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBTcEFwaUludGVyYWN0b3IubGlzdGVuZXJzRm9yTG9va3VwQnlOYW1lLmdldChjb25zdHJ1Y3Rvcik7XG4gICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwibGlzdGVuZXIgbm90IGZvdW5kIGZvciBuYW1lICdcIi5jb25jYXQoY29uc3RydWN0b3IubmFtZSwgXCInXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEobGlzdGVuZXIgaW5zdGFuY2VvZiBjb25zdHJ1Y3RvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwibGlzdGVuZXIgY2xhc3MgbWlzbWF0Y2ggZm9yIG5hbWUgJ1wiLmNvbmNhdChjb25zdHJ1Y3Rvci5uYW1lLCBcIidcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbGlzdGVuZXI7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gU3BBcGlJbnRlcmFjdG9yLmNvbnRyb2xsZXI7XG4gICAgfTtcbiAgICBTcEFwaUludGVyYWN0b3IucmVnaXN0ZXJMaXN0ZW5lckZvckxvb2t1cCA9IGZ1bmN0aW9uIChjb25zdHJ1Y3RvciwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKFNwQXBpSW50ZXJhY3Rvci5saXN0ZW5lcnNGb3JMb29rdXBCeU5hbWUuaGFzKGNvbnN0cnVjdG9yKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwibGlzdGVuZXIgcmUtcmVnaXN0cmF0aW9uIGZvciBuYW1lICdcIi5jb25jYXQoY29uc3RydWN0b3IsIFwiJ1wiKSk7XG4gICAgICAgIH1cbiAgICAgICAgU3BBcGlJbnRlcmFjdG9yLmxpc3RlbmVyc0Zvckxvb2t1cEJ5TmFtZS5zZXQoY29uc3RydWN0b3IsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIFNwQXBpSW50ZXJhY3Rvci5saXN0ZW5lcnNGb3JMb29rdXBCeU5hbWUgPSBuZXcgTWFwKCk7XG4gICAgcmV0dXJuIFNwQXBpSW50ZXJhY3Rvcjtcbn0oKSk7XG5leHBvcnQgeyBTcEFwaUludGVyYWN0b3IgfTtcbiIsImV4cG9ydCB2YXIgZ2V0QWN0b3JWYWx1ZXMgPSBmdW5jdGlvbiAoYWMpIHtcbiAgICBpZiAoIWFjKSB7XG4gICAgICAgIHJldHVybiB7IGhlYWx0aDogMCwgc3RhbWluYTogMCwgbWFnaWNrYTogMCB9O1xuICAgIH1cbiAgICB2YXIgaGVhbHRoUGVyY2VudGFnZSA9IChhYy5pc0RlYWQoKSkgPyAwIDogYWMuZ2V0QWN0b3JWYWx1ZVBlcmNlbnRhZ2UoXCJoZWFsdGhcIik7XG4gICAgdmFyIHN0YW1pbmFQZXJjZW50YWdlID0gYWMuZ2V0QWN0b3JWYWx1ZVBlcmNlbnRhZ2UoXCJzdGFtaW5hXCIpO1xuICAgIHZhciBtYWdpY2thUGVyY2VudGFnZSA9IGFjLmdldEFjdG9yVmFsdWVQZXJjZW50YWdlKFwibWFnaWNrYVwiKTtcbiAgICB2YXIgcmVzdWx0QWN0b3JWYWx1ZSA9IHtcbiAgICAgICAgaGVhbHRoOiBoZWFsdGhQZXJjZW50YWdlLFxuICAgICAgICBzdGFtaW5hOiBzdGFtaW5hUGVyY2VudGFnZSxcbiAgICAgICAgbWFnaWNrYTogbWFnaWNrYVBlcmNlbnRhZ2UsXG4gICAgfTtcbiAgICByZXR1cm4gcmVzdWx0QWN0b3JWYWx1ZTtcbn07XG5leHBvcnQgdmFyIGdldE1heGltdW1BY3RvclZhbHVlID0gZnVuY3Rpb24gKGFjLCBhdk5hbWUpIHtcbiAgICB2YXIgY3VycmVudFBlcmNlbnRhZ2UgPSBhYy5nZXRBY3RvclZhbHVlUGVyY2VudGFnZShhdk5hbWUpO1xuICAgIHJldHVybiBjdXJyZW50UGVyY2VudGFnZSA9PT0gMCA/XG4gICAgICAgIGFjLmdldEJhc2VBY3RvclZhbHVlKGF2TmFtZSkgOlxuICAgICAgICBNYXRoLmNlaWwoYWMuZ2V0QWN0b3JWYWx1ZShhdk5hbWUpIC8gY3VycmVudFBlcmNlbnRhZ2UpO1xufTtcbmV4cG9ydCB2YXIgc2V0QWN0b3JWYWx1ZVBlcmNlbnRhZ2UgPSBmdW5jdGlvbiAoYWMsIGF2TmFtZSwgcGVyY2VudGFnZSkge1xuICAgIC8vIEFjdG9yIHZhbHVlIHBlcmNlbnRhZ2UgZm9yIGhlYWx0aCBtYXkgYmUgYmVsb3cgemVybyAoLTEuOCBmb3IgZXhhbXBsZSwgaXQgbWVhbnMgdSBoYXZlIC0xODAlIGhlYWx0aClcbiAgICB2YXIgY3VycmVudFBlcmNlbnRhZ2UgPSBhYy5nZXRBY3RvclZhbHVlUGVyY2VudGFnZShhdk5hbWUpO1xuICAgIGlmIChjdXJyZW50UGVyY2VudGFnZSA9PT0gcGVyY2VudGFnZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBjdXJyZW50TWF4VmFsdWUgPSBnZXRNYXhpbXVtQWN0b3JWYWx1ZShhYywgYXZOYW1lKTtcbiAgICB2YXIgZGVsdGFQZXJjZW50YWdlID0gcGVyY2VudGFnZSAtIGN1cnJlbnRQZXJjZW50YWdlO1xuICAgIGlmIChkZWx0YVBlcmNlbnRhZ2UgPiAwKSB7XG4gICAgICAgIGFjLnJlc3RvcmVBY3RvclZhbHVlKGF2TmFtZSwgZGVsdGFQZXJjZW50YWdlICogY3VycmVudE1heFZhbHVlKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZGVsdGFQZXJjZW50YWdlIDwgMCkge1xuICAgICAgICBhYy5kYW1hZ2VBY3RvclZhbHVlKGF2TmFtZSwgZGVsdGFQZXJjZW50YWdlICogY3VycmVudE1heFZhbHVlKTtcbiAgICB9XG59O1xuIiwiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uICovXG5pbXBvcnQgeyBEZWJ1ZywgaG9va3MsIEFjdG9yLCBwcmludENvbnNvbGUsIFV0aWxpdHksIEdhbWUsIHN0b3JhZ2UsIFxuLy8gQHRzLWV4cGVjdC1lcnJvciAoVE9ETzogUmVtb3ZlIGluIDIuMTAuMClcbnNldENvbGxpc2lvbiB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgYXBwbHlXZWFwRHJhd24gfSBmcm9tIFwiLi9tb3ZlbWVudEFwcGx5XCI7XG5leHBvcnQgdmFyIEFuaW1hdGlvbkV2ZW50TmFtZTtcbihmdW5jdGlvbiAoQW5pbWF0aW9uRXZlbnROYW1lKSB7XG4gICAgQW5pbWF0aW9uRXZlbnROYW1lW1wiUmFnZG9sbFwiXSA9IFwiUmFnZG9sbFwiO1xuICAgIEFuaW1hdGlvbkV2ZW50TmFtZVtcIkdldFVwQmVnaW5cIl0gPSBcIkdldFVwQmVnaW5cIjtcbn0pKEFuaW1hdGlvbkV2ZW50TmFtZSB8fCAoQW5pbWF0aW9uRXZlbnROYW1lID0ge30pKTtcbjtcbnZhciBhbGxvd2VkSWRsZXMgPSBuZXcgQXJyYXkoKTtcbnZhciByZWZzV2l0aERlZmF1bHRBbmltc0Rpc2FibGVkID0gbmV3IFNldCgpO1xudmFyIGFsbG93ZWRBbmltcyA9IG5ldyBTZXQoKTtcbnZhciBhY3RvclNpdEFuaW1zTG93ZXJDYXNlID0gW1xuICAgICdpZGxlc3Rvb2xlbnRlcnBsYXllcicsXG4gICAgJ2lkbGVzdG9vbGVudGVyJyxcbiAgICAnaWRsZXN0b29sZW50ZXJpbnN0YW50JyxcbiAgICAnaWRsZWNoYWlycmlnaHRlbnRlcicsXG4gICAgJ2lkbGVjaGFpcmxlZnRlbnRlcicsXG4gICAgJ2lkbGVjaGFpcmZyb250ZW50ZXInLFxuICAgICdpZGxlY2hhaXJlbnRlcmluc3RhbnQnLFxuICAgICdpZGxlamFybGNoYWlyZW50ZXInLFxuICAgICdpZGxlamFybGNoYWlyZW50ZXJpbnN0YW50JyxcbiAgICAnaWRsZXNub3dlbGZwcmluY2VjaGFpcmRpYWxvZ3VlJyxcbiAgICAnaWRsZXNub3dlbGZwcmluY2VjaGFpcmVudGVyJyxcbiAgICAnaWRsZXNub3dlbGZwcmluY2VjaGFpcmVudGVyaW5zdGFudCcsXG4gICAgJ2lkbGVjaGFpcmNoaWxkZW50ZXJpbnN0YW50JyxcbiAgICAnaWRsZWNoYWlyY2hpbGRmcm9udGVudGVyJyxcbiAgICAnaWRsZWNoYWlyY2hpbGRsZWZ0ZW50ZXInLFxuICAgICdpZGxlY2hhaXJjaGlsZHJpZ2h0ZW50ZXInLFxuXTtcbnZhciBhY3RvckdldFVwQW5pbXNMb3dlckNhc2UgPSBbXG4gICAgJ2lkbGVzdG9vbGJhY2tleGl0JyxcbiAgICAnaWRsZWNoYWlycmlnaHRleGl0JyxcbiAgICAnaWRsZWNoYWlycmlnaHRxdWlja2V4aXQnLFxuICAgICdpZGxlY2hhaXJsZWZ0ZXhpdCcsXG4gICAgJ2lkbGVjaGFpcmxlZnRxdWlja2V4aXQnLFxuICAgICdpZGxlY2hhaXJmcm9udGV4aXQnLFxuICAgICdpZGxlY2hhaXJmcm9udHF1aWNrZXhpdCcsXG4gICAgJ2lkbGVjaGFpcmNoaWxkZnJvbnRleGl0JyxcbiAgICAnaWRsZWNoYWlyY2hpbGRsZWZ0ZXhpdCcsXG4gICAgJ2lkbGVjaGFpcmNoaWxkcmlnaHRleGl0J1xuXTtcbi8vIEl0J3MgY3JpdGljYWwgZm9yIHZhbHVlcyB0byBiZSB0aGUgY29ycmVjdCBjYXNlLCBub3QganVzdCBsb3dlcmNhc2UsIG90aGVyd2lzZSAnYWxsb3dlZElkbGVzJyBjaGVjayB3aWxsIGJyZWFrXG4vLyBXZSBkb24ndCB3YW50IHRvIG1vZGlmeSB0aGUgY2hlY2sgaXRzZWxmLCBiZWNhdXNlIGl0J2xsIGJlIHNsb3dlclxudmFyIGFuaW1PdmVycmlkZXNMb3dlckNhc2UgPSB7XG4gICAgJ2lkbGVjaGFpcmJvb2tfb25lcGFnZSc6ICdJZGxlQ2hhaXJFbnRlckluc3RhbnQnLFxuICAgICdpZGxlY2hhaXJzaG91bGRlcmZsZXgnOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAnaWRsZWNoYWlyd3JpdGUnOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAnaWRsZWNoYWlyYXJtc2Nyb3NzZWR2YXIxJzogJ0lkbGVDaGFpckVudGVySW5zdGFudCcsXG4gICAgJ2NoYWlyZWF0aW5nc3RhcnRfdmFtcGlyZW1lYXQnOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAnY2hhaXJyZWFkaW5nc3RhcnQnOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAnY2hhaXJ2YW1waXJlZWF0aW5nc3RhcnQnOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAnY2hhaXJkcmlua2luZ3N0YXJ0JzogJ0lkbGVDaGFpckVudGVySW5zdGFudCcsXG4gICAgJ2NoYWlyZWF0aW5nc3RhcnQnOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAvLyBUaGUgb25seSB0cmlwbGUgYW5pbWF0aW9uIHdlIGtub3cgZm9yIG5vdy4gT25lIGJhc2UgYW5pbSB0byBzaXQsIHRoZW4gdHdvIHRvIGVhdFxuICAgICdjaGFpcmVhdGluZ3NvdXBzdGFydCc6ICdJZGxlQ2hhaXJFbnRlckluc3RhbnQnLFxuICAgICdpZGxlZWF0c291cCc6ICdJZGxlQ2hhaXJFbnRlckluc3RhbnQnLFxuICAgIC8vIE5vIG5lZWQgdG8gcmUtcGxheSB0aGUgYW5pbWF0aW9uLCB1c2UgaW5zdGFudCB2YXJpYW50IGZvciBzcGF3bmluZyBhY3RvcnNcbiAgICAvLyBUaGlzIGlzIG5vdCBlc3NlbnRpYWwsIGJ1dCBtYWtlcyB0aGUgc3luYyBmZWVsIG1vcmUgc21vb3RoLiBUaGUgbGlzdCBpcyBub3QgY29tcGxldGUuXG4gICAgJ2lkbGVjaGFpcnJpZ2h0ZW50ZXInOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAnaWRsZWNoYWlybGVmdGVudGVyJzogJ0lkbGVDaGFpckVudGVySW5zdGFudCcsXG4gICAgJ2lkbGVjaGFpcmZyb250ZW50ZXInOiAnSWRsZUNoYWlyRW50ZXJJbnN0YW50JyxcbiAgICAvLyBVbnRlc3RlZCB5ZXQgbG9va3MgY29ycmVjdFxuICAgICdpZGxlc25vd2VsZnByaW5jZWZpcmVhbmRmb3JnZXQnOiAnSWRsZVNub3dFbGZQcmluY2VDaGFpckVudGVySW5zdGFudCcsXG4gICAgJ2lkbGV0YWJsZW11Z2VudGVyJzogJ0lkbGVUYWJsZUVudGVySW5zdGFudCcsXG4gICAgJ2lkbGV0YWJsZWRyaW5rZW50ZXInOiAnSWRsZVRhYmxlRW50ZXJJbnN0YW50JyxcbiAgICAnaWRsZXRhYmxlZHJpbmthbmRtdWdlbnRlcic6ICdJZGxlVGFibGVFbnRlckluc3RhbnQnXG59O1xuLy8gdW5jbGFzc2lmaWVkOlxuLy8gSWRsZUNoYWlyRW50ZXJJbnN0YW50XG4vLyBJZGxlQ2hhaXJFbnRlclN0YXJ0XG4vLyBJZGxlQ2hhaXJFbnRlclN0b3Bcbi8vIElkbGVDaGFpckVudGVyVG9TaXRcbi8vIElkbGVDaGFpckV4aXRTdGFydFxuLy8gSWRsZUNoYWlyRXhpdFRvU3RhbmRcbi8vIElkbGVDaGFpclNpdHRpbmdcbi8vIElkbGVMZWZ0Q2hhaXJFbnRlclN0YXJ0XG4vLyBDaGFpcklkbGVcbi8vIElkbGVSaWdodENoYWlyRW50ZXJTdGFydFxuLy8gSWRsZUxlZnRDaGFpckVudGVyU3RhcnRcbnZhciBpc0lkbGUgPSBmdW5jdGlvbiAoYW5pbUV2ZW50TmFtZSkge1xuICAgIHZhciBhbmltRXZlbnROYW1lTG93ZXJDYXNlID0gYW5pbUV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIHJldHVybiAoYW5pbUV2ZW50TmFtZUxvd2VyQ2FzZSA9PT0gXCJtb3Rpb25kcml2ZW5pZGxlXCIgfHxcbiAgICAgICAgKGFuaW1FdmVudE5hbWVMb3dlckNhc2Uuc3RhcnRzV2l0aChcImlkbGVcIikgJiZcbiAgICAgICAgICAgIGFuaW1FdmVudE5hbWVMb3dlckNhc2UgIT09IFwiaWRsZXN0b3BcIiAmJlxuICAgICAgICAgICAgYW5pbUV2ZW50TmFtZUxvd2VyQ2FzZSAhPT0gXCJpZGxlZm9yY2VkZWZhdWx0c3RhdGVcIikpO1xufTtcbmV4cG9ydCB2YXIgYXBwbHlBbmltYXRpb24gPSBmdW5jdGlvbiAocmVmciwgYW5pbSwgc3RhdGUpIHtcbiAgICBpZiAoc3RhdGUubGFzdE51bUNoYW5nZXMgPT09IGFuaW0ubnVtQ2hhbmdlcykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHN0YXRlLmxhc3ROdW1DaGFuZ2VzID0gYW5pbS5udW1DaGFuZ2VzO1xuICAgIGlmIChzdGF0ZS51c2VBbmltT3ZlcnJpZGVzKSB7XG4gICAgICAgIHZhciBhbmltT3ZlcnJpZGUgPSBhbmltT3ZlcnJpZGVzTG93ZXJDYXNlW2FuaW0uYW5pbUV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpXTtcbiAgICAgICAgaWYgKGFuaW1PdmVycmlkZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBhbmltLmFuaW1FdmVudE5hbWUgPSBhbmltT3ZlcnJpZGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIGFuaW1FdmVudE5hbWVMb3dlckNhc2UgPSBhbmltLmFuaW1FdmVudE5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAoaXNJZGxlKGFuaW0uYW5pbUV2ZW50TmFtZSkpIHtcbiAgICAgICAgYWxsb3dlZElkbGVzLnB1c2goW3JlZnIuZ2V0Rm9ybUlEKCksIGFuaW0uYW5pbUV2ZW50TmFtZV0pO1xuICAgIH1cbiAgICB2YXIgYWMgPSBBY3Rvci5mcm9tKHJlZnIpO1xuICAgIGlmIChhbmltLmFuaW1FdmVudE5hbWUgPT09IFwiU2t5bXBGYWtlRXF1aXBcIikge1xuICAgICAgICBpZiAoYWMpIHtcbiAgICAgICAgICAgIGFwcGx5V2VhcERyYXduKGFjLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChhbmltLmFuaW1FdmVudE5hbWUgPT09IFwiU2t5bXBGYWtlVW5lcXVpcFwiKSB7XG4gICAgICAgIGlmIChhYykge1xuICAgICAgICAgICAgYXBwbHlXZWFwRHJhd24oYWMsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChhbmltLmFuaW1FdmVudE5hbWUgPT09IFwiUmFnZG9sbFwiKSB7XG4gICAgICAgIGlmIChhYykge1xuICAgICAgICAgICAgaWYgKHN0b3JhZ2VbXCJhbmltYXRpb25GdW5jMVNldFwiXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICBzdG9yYWdlW1wiYW5pbWF0aW9uRnVuYzFcIl0oYWMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYWMucHVzaEFjdG9yQXdheShhYywgMCk7XG4gICAgICAgICAgICAgICAgYWMuc2V0QWN0b3JWYWx1ZShcIlZhcmlhYmxlMTBcIiwgLTEwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHJlZnNXaXRoRGVmYXVsdEFuaW1zRGlzYWJsZWQuaGFzKHJlZnIuZ2V0Rm9ybUlEKCkpKSB7XG4gICAgICAgIGlmIChhbmltRXZlbnROYW1lTG93ZXJDYXNlLmluY2x1ZGVzKFwiYXR0YWNrXCIpKSB7XG4gICAgICAgICAgICBhbGxvd2VkQW5pbXMuYWRkKHJlZnIuZ2V0Rm9ybUlEKCkgKyBcIjpcIiArIGFuaW0uYW5pbUV2ZW50TmFtZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGVidWcuc2VuZEFuaW1hdGlvbkV2ZW50KHJlZnIsIGFuaW0uYW5pbUV2ZW50TmFtZSk7XG4gICAgaWYgKGFuaW0uYW5pbUV2ZW50TmFtZSA9PT0gXCJHZXRVcEJlZ2luXCIpIHtcbiAgICAgICAgdmFyIHJlZnJJZF8xID0gcmVmci5nZXRGb3JtSUQoKTtcbiAgICAgICAgVXRpbGl0eS53YWl0KDEpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGFjID0gQWN0b3IuZnJvbShHYW1lLmdldEZvcm1FeChyZWZySWRfMSkpO1xuICAgICAgICAgICAgaWYgKGFjKSB7XG4gICAgICAgICAgICAgICAgYWMuc2V0QWN0b3JWYWx1ZShcIlZhcmlhYmxlMTBcIiwgMTAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoYWN0b3JTaXRBbmltc0xvd2VyQ2FzZS5maW5kKGZ1bmN0aW9uICh4KSB7IHJldHVybiB4ID09PSBhbmltRXZlbnROYW1lTG93ZXJDYXNlOyB9KSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHNldENvbGxpc2lvbihyZWZyLmdldEZvcm1JRCgpLCBmYWxzZSk7XG4gICAgfVxuICAgIGlmIChhY3RvckdldFVwQW5pbXNMb3dlckNhc2UuZmluZChmdW5jdGlvbiAoeCkgeyByZXR1cm4geCA9PT0gYW5pbUV2ZW50TmFtZUxvd2VyQ2FzZTsgfSkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRDb2xsaXNpb24ocmVmci5nZXRGb3JtSUQoKSwgdHJ1ZSk7XG4gICAgfVxufTtcbmV4cG9ydCB2YXIgc2V0RGVmYXVsdEFuaW1zRGlzYWJsZWQgPSBmdW5jdGlvbiAocmVmcklkLCBkaXNhYmxlZCkge1xuICAgIGlmIChkaXNhYmxlZCkge1xuICAgICAgICByZWZzV2l0aERlZmF1bHRBbmltc0Rpc2FibGVkLmFkZChyZWZySWQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmVmc1dpdGhEZWZhdWx0QW5pbXNEaXNhYmxlZC5kZWxldGUocmVmcklkKTtcbiAgICB9XG59O1xudmFyIEFuaW1hdGlvblNvdXJjZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBBbmltYXRpb25Tb3VyY2UocmVmcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlZnJJZCA9IDA7XG4gICAgICAgIHRoaXMubnVtQ2hhbmdlcyA9IDA7XG4gICAgICAgIHRoaXMuYW5pbUV2ZW50TmFtZSA9IFwiXCI7XG4gICAgICAgIHRoaXMud2VhcE5vbkRyYXduQmxvY2tlciA9IDA7XG4gICAgICAgIHRoaXMud2VhcERyYXduQmxvY2tlciA9IDA7XG4gICAgICAgIHRoaXMuc25lYWtCbG9ja2VyID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWZySWQgPSByZWZyLmdldEZvcm1JRCgpO1xuICAgICAgICBob29rcy5zZW5kQW5pbWF0aW9uRXZlbnQuYWRkKHtcbiAgICAgICAgICAgIGVudGVyOiBmdW5jdGlvbiAoKSB7IH0sXG4gICAgICAgICAgICBsZWF2ZTogZnVuY3Rpb24gKGN0eCkge1xuICAgICAgICAgICAgICAgIGlmIChjdHguc2VsZklkICE9PSBfdGhpcy5yZWZySWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWN0eC5hbmltYXRpb25TdWNjZWVkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV29ya2Fyb3VuZCwgc2VlIGNhcnJ5QW5pbVN5c3RlbS50cyBpbiBnYW1lbW9kZVxuICAgICAgICAgICAgICAgICAgICAvLyBDYXNlLXNlbnNldGl2ZSBjaGVjayBoZXJlIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN0eC5hbmltRXZlbnROYW1lICE9PSBcIk9mZnNldENhcnJ5QmFza2V0U3RhcnRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLm9uU2VuZEFuaW1hdGlvbkV2ZW50KGN0eC5hbmltRXZlbnROYW1lKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBBbmltYXRpb25Tb3VyY2UucHJvdG90eXBlLmZpbHRlck1vdmVtZW50ID0gZnVuY3Rpb24gKG1vdikge1xuICAgICAgICBpZiAodGhpcy53ZWFwRHJhd25CbG9ja2VyID49IERhdGUubm93KCkpIHtcbiAgICAgICAgICAgIG1vdi5pc1dlYXBEcmF3biA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMud2VhcE5vbkRyYXduQmxvY2tlciA+PSBEYXRlLm5vdygpKSB7XG4gICAgICAgICAgICBtb3YuaXNXZWFwRHJhd24gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zbmVha0Jsb2NrZXIgPT09IG1vdi5pc1NuZWFraW5nKSB7XG4gICAgICAgICAgICB0aGlzLnNuZWFrQmxvY2tlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5zbmVha0Jsb2NrZXIgPT09IHRydWUpIHtcbiAgICAgICAgICAgIG1vdi5pc1NuZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnNuZWFrQmxvY2tlciA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIG1vdi5pc1NuZWFraW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1vdjtcbiAgICB9O1xuICAgIEFuaW1hdGlvblNvdXJjZS5wcm90b3R5cGUuZ2V0QW5pbWF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBudW1DaGFuZ2VzID0gX2EubnVtQ2hhbmdlcywgYW5pbUV2ZW50TmFtZSA9IF9hLmFuaW1FdmVudE5hbWU7XG4gICAgICAgIHJldHVybiB7IG51bUNoYW5nZXM6IG51bUNoYW5nZXMsIGFuaW1FdmVudE5hbWU6IGFuaW1FdmVudE5hbWUgfTtcbiAgICB9O1xuICAgIEFuaW1hdGlvblNvdXJjZS5wcm90b3R5cGUub25TZW5kQW5pbWF0aW9uRXZlbnQgPSBmdW5jdGlvbiAoYW5pbUV2ZW50TmFtZSkge1xuICAgICAgICBpZiAoaWdub3JlZEFuaW1zLmhhcyhhbmltRXZlbnROYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsb3dlciA9IGFuaW1FdmVudE5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgdmFyIGlzVG9yY2hFdmVudCA9IGxvd2VyLmluY2x1ZGVzKFwidG9yY2hcIik7XG4gICAgICAgIGlmIChhbmltRXZlbnROYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoXCJ1bmVxdWlwXCIpICYmICFpc1RvcmNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMud2VhcE5vbkRyYXduQmxvY2tlciA9IERhdGUubm93KCkgKyAzMDA7XG4gICAgICAgICAgICBhbmltRXZlbnROYW1lID0gXCJTa3ltcEZha2VVbmVxdWlwXCI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoYW5pbUV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKFwiZXF1aXBcIikgJiYgIWlzVG9yY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy53ZWFwRHJhd25CbG9ja2VyID0gRGF0ZS5ub3coKSArIDMwMDtcbiAgICAgICAgICAgIGFuaW1FdmVudE5hbWUgPSBcIlNreW1wRmFrZUVxdWlwXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFuaW1FdmVudE5hbWUgPT09IFwiU25lYWtTdGFydFwiKSB7XG4gICAgICAgICAgICB0aGlzLnNuZWFrQmxvY2tlciA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFuaW1FdmVudE5hbWUgPT09IFwiU25lYWtTdG9wXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc25lYWtCbG9ja2VyID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5udW1DaGFuZ2VzKys7XG4gICAgICAgIHRoaXMuYW5pbUV2ZW50TmFtZSA9IGFuaW1FdmVudE5hbWU7XG4gICAgfTtcbiAgICByZXR1cm4gQW5pbWF0aW9uU291cmNlO1xufSgpKTtcbmV4cG9ydCB7IEFuaW1hdGlvblNvdXJjZSB9O1xudmFyIGlnbm9yZWRBbmltcyA9IG5ldyBTZXQoW1xuICAgIFwibW92ZVN0YXJ0XCIsXG4gICAgXCJtb3ZlU3RvcFwiLFxuICAgIFwidHVyblN0b3BcIixcbiAgICBcIkN5Y2xpY0Nyb3NzQmxlbmRcIixcbiAgICBcIkN5Y2xpY0ZyZWV6ZVwiLFxuICAgIFwiVHVybkxlZnRcIixcbiAgICBcIlR1cm5SaWdodFwiLFxuXSk7XG5leHBvcnQgdmFyIHNldHVwSG9va3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgaG9va3Muc2VuZEFuaW1hdGlvbkV2ZW50LmFkZCh7XG4gICAgICAgIGVudGVyOiBmdW5jdGlvbiAoY3R4KSB7XG4gICAgICAgICAgICBpZiAocmVmc1dpdGhEZWZhdWx0QW5pbXNEaXNhYmxlZC5oYXMoY3R4LnNlbGZJZCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoY3R4LmFuaW1FdmVudE5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhcImF0dGFja1wiKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYW5pbUtleSA9IGN0eC5zZWxmSWQgKyBcIjpcIiArIGN0eC5hbmltRXZlbnROYW1lO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWxsb3dlZEFuaW1zLmhhcyhhbmltS2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dlZEFuaW1zLmRlbGV0ZShhbmltS2V5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByaW50Q29uc29sZShcImJsb2NrIGFuaW0gXCIgKyBjdHguYW5pbUV2ZW50TmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGN0eC5hbmltRXZlbnROYW1lID0gXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTaG93UmFjZU1lbnUgZm9yY2VzIHRoaXMgYW5pbVxuICAgICAgICAgICAgaWYgKGN0eC5hbmltRXZlbnROYW1lID09PSBcIk9mZnNldEJvdW5kU3RhbmRpbmdQbGF5ZXJJbnN0YW50XCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKGN0eC5hbmltRXZlbnROYW1lID0gXCJcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEaXNhYmxlIGlkbGUgYW5pbWF0aW9ucyBmb3IgMHhmZiBhY3RvcnNcbiAgICAgICAgICAgIGlmIChjdHguc2VsZklkIDwgMHhmZjAwMDAwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0lkbGUoY3R4LmFuaW1FdmVudE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGkgPSBhbGxvd2VkSWRsZXMuZmluZEluZGV4KGZ1bmN0aW9uIChwYWlyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYWlyWzBdID09PSBjdHguc2VsZklkICYmIHBhaXJbMV0gPT09IGN0eC5hbmltRXZlbnROYW1lO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGkgPT09IC0xID8gKGN0eC5hbmltRXZlbnROYW1lID0gXCJcIikgOiBhbGxvd2VkSWRsZXMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsZWF2ZTogZnVuY3Rpb24gKCkgeyB9LFxuICAgIH0pO1xufTtcbiIsImltcG9ydCB7IEFjdG9yQmFzZSwgR2FtZSwgVEVTTW9kUGxhdGZvcm0sIFJhY2UsIEhlYWRQYXJ0LCBUZXh0dXJlU2V0LCBwcmludENvbnNvbGUsIFZvaWNlVHlwZSwgb25jZSwgVXRpbGl0eSwgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmV4cG9ydCB2YXIgZ2V0QXBwZWFyYW5jZSA9IGZ1bmN0aW9uIChhY3Rvcikge1xuICAgIHZhciBiYXNlID0gQWN0b3JCYXNlLmZyb20oYWN0b3IuZ2V0QmFzZU9iamVjdCgpKTtcbiAgICB2YXIgaGFpckNvbG9yID0gYmFzZS5nZXRIYWlyQ29sb3IoKTtcbiAgICB2YXIgc2tpbkNvbG9yID0gVEVTTW9kUGxhdGZvcm0uZ2V0U2tpbkNvbG9yKGJhc2UpO1xuICAgIHZhciBuZXdBcHBlYXJhbmNlID0ge1xuICAgICAgICBpc0ZlbWFsZTogYmFzZS5nZXRTZXgoKSA9PT0gMSxcbiAgICAgICAgcmFjZUlkOiBiYXNlLmdldFJhY2UoKSA/IGJhc2UuZ2V0UmFjZSgpLmdldEZvcm1JRCgpIDogMCxcbiAgICAgICAgd2VpZ2h0OiBiYXNlLmdldFdlaWdodCgpLFxuICAgICAgICBoYWlyQ29sb3I6IGhhaXJDb2xvciA/IGhhaXJDb2xvci5nZXRDb2xvcigpIDogMCxcbiAgICAgICAgaGVhZHBhcnRJZHM6IFtdLFxuICAgICAgICBoZWFkVGV4dHVyZVNldElkOiBiYXNlLmdldEZhY2VUZXh0dXJlU2V0KClcbiAgICAgICAgICAgID8gYmFzZS5nZXRGYWNlVGV4dHVyZVNldCgpLmdldEZvcm1JRCgpXG4gICAgICAgICAgICA6IDAsXG4gICAgICAgIG9wdGlvbnM6IG5ldyBBcnJheSgxOSksXG4gICAgICAgIHByZXNldHM6IG5ldyBBcnJheSg0KSxcbiAgICAgICAgdGludHM6IFtdLFxuICAgICAgICBza2luQ29sb3I6IHNraW5Db2xvciA/IHNraW5Db2xvci5nZXRDb2xvcigpIDogMCxcbiAgICAgICAgbmFtZTogYWN0b3IuZ2V0QmFzZU9iamVjdCgpLmdldE5hbWUoKSxcbiAgICB9O1xuICAgIHZhciBudW1IZWFkcGFydHMgPSBiYXNlLmdldE51bUhlYWRQYXJ0cygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtSGVhZHBhcnRzOyArK2kpIHtcbiAgICAgICAgdmFyIHBhcnQgPSBiYXNlLmdldE50aEhlYWRQYXJ0KGkpO1xuICAgICAgICBpZiAocGFydCkge1xuICAgICAgICAgICAgbmV3QXBwZWFyYW5jZS5oZWFkcGFydElkcy5wdXNoKHBhcnQuZ2V0Rm9ybUlEKCkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmV3QXBwZWFyYW5jZS5vcHRpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIG5ld0FwcGVhcmFuY2Uub3B0aW9uc1tpXSA9IGJhc2UuZ2V0RmFjZU1vcnBoKGkpO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5ld0FwcGVhcmFuY2UucHJlc2V0cy5sZW5ndGg7ICsraSkge1xuICAgICAgICBuZXdBcHBlYXJhbmNlLnByZXNldHNbaV0gPSBiYXNlLmdldEZhY2VQcmVzZXQoaSk7XG4gICAgfVxuICAgIHZhciBudW1UaW50cyA9IEdhbWUuZ2V0UGxheWVyKCkuZ2V0Rm9ybUlEKCkgPT09IGFjdG9yLmdldEZvcm1JRCgpXG4gICAgICAgID8gR2FtZS5nZXROdW1UaW50TWFza3MoKVxuICAgICAgICA6IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1UaW50czsgKytpKSB7XG4gICAgICAgIHZhciB0aW50ID0ge1xuICAgICAgICAgICAgdGV4dHVyZVBhdGg6IEdhbWUuZ2V0TnRoVGludE1hc2tUZXh0dXJlUGF0aChpKSxcbiAgICAgICAgICAgIHR5cGU6IEdhbWUuZ2V0TnRoVGludE1hc2tUeXBlKGkpLFxuICAgICAgICAgICAgYXJnYjogR2FtZS5nZXROdGhUaW50TWFza0NvbG9yKGkpLFxuICAgICAgICB9O1xuICAgICAgICBuZXdBcHBlYXJhbmNlLnRpbnRzLnB1c2godGludCk7XG4gICAgfVxuICAgIHJldHVybiBuZXdBcHBlYXJhbmNlO1xufTtcbnZhciBpc1Zpc2libGUgPSBmdW5jdGlvbiAoYXJnYikgeyByZXR1cm4gYXJnYiA+IDB4MDBmZmZmZmYgfHwgYXJnYiA8IDA7IH07XG5leHBvcnQgdmFyIGFwcGx5VGludHMgPSBmdW5jdGlvbiAoYWN0b3IsIGFwcGVhcmFuY2UpIHtcbiAgICBpZiAoIWFwcGVhcmFuY2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwibnVsbCBhcHBlYXJhbmNlIGhhcyBiZWVuIHBhc3NlZCB0byBhcHBseVRpbnRzXCIpO1xuICAgIH1cbiAgICB2YXIgdGludHMgPSBhcHBlYXJhbmNlLnRpbnRzLmZpbHRlcihmdW5jdGlvbiAodCkgeyByZXR1cm4gaXNWaXNpYmxlKHQuYXJnYik7IH0pO1xuICAgIHZhciByYWNlV2FyUGFpbnRSZWdleCA9IC8uKkhlYWQuK1dhclBhaW50LiovO1xuICAgIHZhciB1bmlXYXJQYWludFJlZ2V4ID0gLy4qSGVhZFdhclBhaW50LiovO1xuICAgIHZhciByYWNlU3BlY2lmaWNXYXJQYWludCA9IHRpbnRzLmZpbHRlcihmdW5jdGlvbiAodCkgeyByZXR1cm4gaXNWaXNpYmxlKHQuYXJnYikgJiYgdC50ZXh0dXJlUGF0aC5tYXRjaChyYWNlV2FyUGFpbnRSZWdleCk7IH0pLmxlbmd0aDsgLy8gTWFsZUhlYWROb3JkV2FyUGFpbnRcbiAgICB2YXIgdW5pV2FyUGFpbnQgPSB0aW50cy5maWx0ZXIoZnVuY3Rpb24gKHQpIHsgcmV0dXJuIGlzVmlzaWJsZSh0LmFyZ2IpICYmIHQudGV4dHVyZVBhdGgubWF0Y2godW5pV2FyUGFpbnRSZWdleCk7IH0pLmxlbmd0aDsgLy8gTWFsZUhlYWRXYXJQYWludFxuICAgIGlmIChyYWNlU3BlY2lmaWNXYXJQYWludCArIHVuaVdhclBhaW50ID4gMSkge1xuICAgICAgICAvLyBJZiB2aXNpYmxlIHdhciBwYWludHMgb2YgdGhlc2UgdHdvIHR5cGVzIHByZXNlbnQsIHRoZW4gU2t5cmltIGNyYXNoZXNcbiAgICAgICAgcHJpbnRDb25zb2xlKFwiYmFkIHdhcnBhaW50IVwiLCByYWNlU3BlY2lmaWNXYXJQYWludCwgdW5pV2FyUGFpbnQpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIFRFU01vZFBsYXRmb3JtLmNsZWFyVGludE1hc2tzKGFjdG9yKTtcbiAgICB0aW50cy5mb3JFYWNoKGZ1bmN0aW9uICh0aW50KSB7XG4gICAgICAgIFRFU01vZFBsYXRmb3JtLnB1c2hUaW50TWFzayhhY3RvciwgdGludC50eXBlLCB0aW50LmFyZ2IsIHRpbnQudGV4dHVyZVBhdGgpO1xuICAgIH0pO1xuICAgIHZhciBwbGF5ZXJCYXNlSWQgPSBHYW1lLmdldFBsYXllcigpLmdldEJhc2VPYmplY3QoKS5nZXRGb3JtSUQoKTtcbiAgICBpZiAoYWN0b3IpXG4gICAgICAgIFRFU01vZFBsYXRmb3JtLnNldEZvcm1JZFVuc2FmZShhY3Rvci5nZXRCYXNlT2JqZWN0KCksIHBsYXllckJhc2VJZCk7XG59O1xuZXhwb3J0IHZhciBzaWxlbnRWb2ljZVR5cGVJZCA9IDB4MDAwMmY3YzM7XG52YXIgYXBwbHlBcHBlYXJhbmNlQ29tbW9uID0gZnVuY3Rpb24gKGFwcGVhcmFuY2UsIG5wYykge1xuICAgIHZhciByYWNlID0gUmFjZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KGFwcGVhcmFuY2UucmFjZUlkKSk7XG4gICAgdmFyIGhlYWRwYXJ0cyA9IGFwcGVhcmFuY2UuaGVhZHBhcnRJZHNcbiAgICAgICAgLm1hcChmdW5jdGlvbiAoaWQpIHsgcmV0dXJuIEhlYWRQYXJ0LmZyb20oR2FtZS5nZXRGb3JtRXgoaWQpKTsgfSlcbiAgICAgICAgLmZpbHRlcihmdW5jdGlvbiAoaGVhZHBhcnQpIHsgcmV0dXJuICEhaGVhZHBhcnQ7IH0pO1xuICAgIFRFU01vZFBsYXRmb3JtLnNldE5wY1NleChucGMsIGFwcGVhcmFuY2UuaXNGZW1hbGUgPyAxIDogMCk7XG4gICAgaWYgKHJhY2UpIHtcbiAgICAgICAgVEVTTW9kUGxhdGZvcm0uc2V0TnBjUmFjZShucGMsIHJhY2UpO1xuICAgIH1cbiAgICBucGMuc2V0V2VpZ2h0KGFwcGVhcmFuY2Uud2VpZ2h0KTtcbiAgICBURVNNb2RQbGF0Zm9ybS5zZXROcGNTa2luQ29sb3IobnBjLCBhcHBlYXJhbmNlLnNraW5Db2xvcik7XG4gICAgVEVTTW9kUGxhdGZvcm0uc2V0TnBjSGFpckNvbG9yKG5wYywgYXBwZWFyYW5jZS5oYWlyQ29sb3IpO1xuICAgIFRFU01vZFBsYXRmb3JtLnJlc2l6ZUhlYWRwYXJ0c0FycmF5KG5wYywgaGVhZHBhcnRzLmxlbmd0aCk7XG4gICAgaGVhZHBhcnRzLmZvckVhY2goZnVuY3Rpb24gKHYsIGkpIHsgcmV0dXJuIG5wYy5zZXROdGhIZWFkUGFydCh2LCBpKTsgfSk7XG4gICAgbnBjLnNldEZhY2VUZXh0dXJlU2V0KFRleHR1cmVTZXQuZnJvbShHYW1lLmdldEZvcm1FeChhcHBlYXJhbmNlLmhlYWRUZXh0dXJlU2V0SWQpKSk7IC8vIHNldEZhY2VUZXh0dXJlU2V0IHN1cHBvcnRzIG51bGwgYXJndW1lbnRcbiAgICBucGMuc2V0Vm9pY2VUeXBlKFZvaWNlVHlwZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHNpbGVudFZvaWNlVHlwZUlkKSkpO1xuICAgIGFwcGVhcmFuY2Uub3B0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7IHJldHVybiBucGMuc2V0RmFjZU1vcnBoKHYsIGkpOyB9KTtcbiAgICBhcHBlYXJhbmNlLnByZXNldHMuZm9yRWFjaChmdW5jdGlvbiAodiwgaSkgeyByZXR1cm4gbnBjLnNldEZhY2VQcmVzZXQodiwgaSk7IH0pO1xuICAgIGlmIChhcHBlYXJhbmNlLm5hbWUpIHtcbiAgICAgICAgbnBjLnNldE5hbWUoYXBwZWFyYW5jZS5uYW1lKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIGZvciB1bmRlZmluZWQgb3IgZW1wdHkgbmFtZVxuICAgICAgICBucGMuc2V0TmFtZShcIiBcIik7XG4gICAgfVxufTtcbmV4cG9ydCB2YXIgYXBwbHlBcHBlYXJhbmNlID0gZnVuY3Rpb24gKGFwcGVhcmFuY2UpIHtcbiAgICB2YXIgbnBjID0gVEVTTW9kUGxhdGZvcm0uY3JlYXRlTnBjKCk7XG4gICAgaWYgKCFucGMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3JlYXRlTnBjIHJldHVybmVkIG51bGxcIik7XG4gICAgfVxuICAgIGFwcGx5QXBwZWFyYW5jZUNvbW1vbihhcHBlYXJhbmNlLCBucGMpO1xuICAgIHJldHVybiBucGM7XG59O1xuZXhwb3J0IHZhciBhcHBseUFwcGVhcmFuY2VUb1BsYXllciA9IGZ1bmN0aW9uIChhcHBlYXJhbmNlKSB7XG4gICAgYXBwbHlBcHBlYXJhbmNlQ29tbW9uKGFwcGVhcmFuY2UsIEFjdG9yQmFzZS5mcm9tKEdhbWUuZ2V0UGxheWVyKCkuZ2V0QmFzZU9iamVjdCgpKSk7XG4gICAgYXBwbHlUaW50cyhudWxsLCBhcHBlYXJhbmNlKTtcbiAgICBHYW1lLmdldFBsYXllcigpLnF1ZXVlTmlOb2RlVXBkYXRlKCk7XG4gICAgVXRpbGl0eS53YWl0KDAuMDYyNSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIG9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgKF9hID0gR2FtZS5nZXRQbGF5ZXIoKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnN0YXJ0RGVmZXJyZWRLaWxsKCk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcbiIsImltcG9ydCB7IEFjdG9yLCBBbW1vLCBHYW1lLCBTcGVsbCwgVWksIHNldEludmVudG9yeSwgfSBmcm9tICdza3lyaW1QbGF0Zm9ybSc7XG5pbXBvcnQgeyBnZXRJbnZlbnRvcnkgfSBmcm9tICcuL2ludmVudG9yeSc7XG5leHBvcnQgdmFyIGdldEVxdWlwZWRTcGVsbCA9IGZ1bmN0aW9uIChyZWZyLCBzcGVsbFR5cGUpIHtcbiAgICB2YXIgYWN0b3IgPSBBY3Rvci5mcm9tKHJlZnIpO1xuICAgIGlmICghYWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHN3aXRjaCAoc3BlbGxUeXBlKSB7XG4gICAgICAgIGNhc2UgMCAvKiBTcGVsbFR5cGUuTGVmdCAqLzoge1xuICAgICAgICAgICAgdmFyIHNwZWxsID0gYWN0b3IuZ2V0RXF1aXBwZWRTcGVsbCgwIC8qIFNwZWxsVHlwZS5MZWZ0ICovKTtcbiAgICAgICAgICAgIHJldHVybiBzcGVsbCA/IHNwZWxsLmdldEZvcm1JRCgpIDogMDtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDEgLyogU3BlbGxUeXBlLlJpZ2h0ICovOiB7XG4gICAgICAgICAgICB2YXIgc3BlbGwgPSBhY3Rvci5nZXRFcXVpcHBlZFNwZWxsKDEgLyogU3BlbGxUeXBlLlJpZ2h0ICovKTtcbiAgICAgICAgICAgIHJldHVybiBzcGVsbCA/IHNwZWxsLmdldEZvcm1JRCgpIDogMDtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDIgLyogU3BlbGxUeXBlLlZvaWNlICovOiB7XG4gICAgICAgICAgICB2YXIgc3BlbGwgPSBhY3Rvci5nZXRFcXVpcHBlZFNwZWxsKDIgLyogU3BlbGxUeXBlLlZvaWNlICovKTtcbiAgICAgICAgICAgIHJldHVybiBzcGVsbCA/IHNwZWxsLmdldEZvcm1JRCgpIDogMDtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDMgLyogU3BlbGxUeXBlLkluc3RhbnQgKi86IHtcbiAgICAgICAgICAgIHZhciBzcGVsbCA9IGFjdG9yLmdldEVxdWlwcGVkU3BlbGwoMyAvKiBTcGVsbFR5cGUuSW5zdGFudCAqLyk7XG4gICAgICAgICAgICByZXR1cm4gc3BlbGwgPyBzcGVsbC5nZXRGb3JtSUQoKSA6IDA7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICB9XG59O1xudmFyIGZpbHRlcldvcm4gPSBmdW5jdGlvbiAoaW52KSB7XG4gICAgcmV0dXJuIHsgZW50cmllczogaW52LmVudHJpZXMuZmlsdGVyKGZ1bmN0aW9uICh4KSB7IHJldHVybiB4Lndvcm4gfHwgeC53b3JuTGVmdDsgfSkgfTtcbn07XG52YXIgcmVtb3ZlVW5uZWNlc3NhcnlFeHRyYSA9IGZ1bmN0aW9uIChpbnYsIGlnbm9yZUFtbW8pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBlbnRyaWVzOiBpbnYuZW50cmllcy5tYXAoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgIHZhciByID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh4KSk7XG4gICAgICAgICAgICByLmNoYXJnZVBlcmNlbnQgPSByLm1heENoYXJnZTtcbiAgICAgICAgICAgIGlmIChpZ25vcmVBbW1vKSB7XG4gICAgICAgICAgICAgICAgci5jb3VudCA9IEFtbW8uZnJvbShHYW1lLmdldEZvcm1FeCh4LmJhc2VJZCkpID8gci5jb3VudCA6IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByLmNvdW50ID0gQW1tby5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHguYmFzZUlkKSkgPyAxMDAwIDogMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSByLm5hbWU7XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgfSksXG4gICAgfTtcbn07XG5leHBvcnQgdmFyIGdldEVxdWlwbWVudCA9IGZ1bmN0aW9uIChhYywgbnVtQ2hhbmdlcykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGludjogZ2V0SW52ZW50b3J5KGFjKSxcbiAgICAgICAgbGVmdFNwZWxsOiBnZXRFcXVpcGVkU3BlbGwoYWMsIDAgLyogU3BlbGxUeXBlLkxlZnQgKi8pLFxuICAgICAgICByaWdodFNwZWxsOiBnZXRFcXVpcGVkU3BlbGwoYWMsIDEgLyogU3BlbGxUeXBlLlJpZ2h0ICovKSxcbiAgICAgICAgdm9pY2VTcGVsbDogZ2V0RXF1aXBlZFNwZWxsKGFjLCAyIC8qIFNwZWxsVHlwZS5Wb2ljZSAqLyksXG4gICAgICAgIGluc3RhbnRTcGVsbDogZ2V0RXF1aXBlZFNwZWxsKGFjLCAzIC8qIFNwZWxsVHlwZS5JbnN0YW50ICovKSxcbiAgICAgICAgbnVtQ2hhbmdlczogbnVtQ2hhbmdlcyxcbiAgICB9O1xufTtcbmV4cG9ydCB2YXIgc3luY1NwZWxsRXF1aXBtZW50ID0gZnVuY3Rpb24gKGFjLCBzcGVsbEJhc2VJZCwgc3BlbGxUeXBlKSB7XG4gICAgaWYgKHNwZWxsQmFzZUlkICE9PSB1bmRlZmluZWQgJiYgc3BlbGxCYXNlSWQgPiAwKSB7XG4gICAgICAgIGFjLmVxdWlwU3BlbGwoU3BlbGwuZnJvbShHYW1lLmdldEZvcm1FeChzcGVsbEJhc2VJZCkpLCBzcGVsbFR5cGUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGVxdWlwZWRTcGVsbCA9IGFjLmdldEVxdWlwcGVkU3BlbGwoc3BlbGxUeXBlKTtcbiAgICAgICAgaWYgKGVxdWlwZWRTcGVsbCkge1xuICAgICAgICAgICAgYWMudW5lcXVpcFNwZWxsKGVxdWlwZWRTcGVsbCwgc3BlbGxUeXBlKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5leHBvcnQgdmFyIGFwcGx5RXF1aXBtZW50ID0gZnVuY3Rpb24gKGFjLCBlcSkge1xuICAgIGFjLnJlbW92ZUFsbEl0ZW1zKG51bGwsIGZhbHNlLCB0cnVlKTtcbiAgICBhYy51bmVxdWlwQWxsKCk7XG4gICAgYWMucmVtb3ZlQWxsSXRlbXMobnVsbCwgZmFsc2UsIHRydWUpO1xuICAgIHZhciBuZXdJbnZlbnRvcnkgPSByZW1vdmVVbm5lY2Vzc2FyeUV4dHJhKGZpbHRlcldvcm4oZXEuaW52KSwgYWMuZ2V0Rm9ybUlEKCkgPT09IDB4MTQpO1xuICAgIHNldEludmVudG9yeShhYy5nZXRGb3JtSUQoKSwgbmV3SW52ZW50b3J5KTtcbiAgICBzeW5jU3BlbGxFcXVpcG1lbnQoYWMsIGVxLmxlZnRTcGVsbCwgMCAvKiBTcGVsbFR5cGUuTGVmdCAqLyk7XG4gICAgc3luY1NwZWxsRXF1aXBtZW50KGFjLCBlcS5yaWdodFNwZWxsLCAxIC8qIFNwZWxsVHlwZS5SaWdodCAqLyk7XG4gICAgc3luY1NwZWxsRXF1aXBtZW50KGFjLCBlcS52b2ljZVNwZWxsLCAyIC8qIFNwZWxsVHlwZS5Wb2ljZSAqLyk7XG4gICAgc3luY1NwZWxsRXF1aXBtZW50KGFjLCBlcS5pbnN0YW50U3BlbGwsIDMgLyogU3BlbGxUeXBlLkluc3RhbnQgKi8pO1xuICAgIHJldHVybiB0cnVlO1xufTtcbmV4cG9ydCB2YXIgaXNCYWRNZW51U2hvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChVaS5pc01lbnVPcGVuKCdJbnZlbnRvcnlNZW51JykgfHxcbiAgICAgICAgVWkuaXNNZW51T3BlbignRmF2b3JpdGVzTWVudScpIHx8XG4gICAgICAgIFVpLmlzTWVudU9wZW4oJ01hZ2ljTWVudScpIHx8XG4gICAgICAgIFVpLmlzTWVudU9wZW4oJ0NvbnRhaW5lck1lbnUnKSB8fFxuICAgICAgICBVaS5pc01lbnVPcGVuKCdDcmFmdGluZyBNZW51JykgLy8gQWN0dWFsbHkgSSBkb24ndCB0aGluayBpdCBjYXVzZXMgY3Jhc2hlc1xuICAgICk7XG59O1xuIiwiaW1wb3J0IHsgZ2V0RXh0cmFDb250YWluZXJDaGFuZ2VzLCBnZXRDb250YWluZXIsIFRFU01vZFBsYXRmb3JtLCBHYW1lLCBzdG9yYWdlLCBFbmNoYW50bWVudCwgUG90aW9uLCBBY3RvciwgQW1tbywgcHJpbnRDb25zb2xlLCB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuLy8gJ2xveHN3b3JkIChMZWdlbmRhcnkpJyA9PiAnbG94c3dvcmQnXG52YXIgZ2V0UmVhbE5hbWUgPSBmdW5jdGlvbiAocykge1xuICAgIGlmICghcykge1xuICAgICAgICByZXR1cm4gcztcbiAgICB9XG4gICAgdmFyIGFyciA9IHMuc3BsaXQoXCIgXCIpO1xuICAgIGlmIChhcnIubGVuZ3RoICYmIGFyclthcnIubGVuZ3RoIC0gMV0ubWF0Y2goL15cXCguKlxcKSQvKSkge1xuICAgICAgICBhcnIucG9wKCk7XG4gICAgfVxuICAgIHJldHVybiBhcnIuam9pbihcIiBcIik7XG59O1xuLy8gJ2FhYWFhYWFhYWFhYWFhYWEnID0+ICdhYWEuLi4nXG52YXIgY3JvcE5hbWUgPSBmdW5jdGlvbiAocykge1xuICAgIGlmICghcykge1xuICAgICAgICByZXR1cm4gcztcbiAgICB9XG4gICAgdmFyIG1heCA9IDEyODtcbiAgICByZXR1cm4gcy5sZW5ndGggPj0gbWF4XG4gICAgICAgID8gc1xuICAgICAgICAgICAgLnNwbGl0KFwiXCIpXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uICh4LCBpKSB7IHJldHVybiBpIDwgbWF4OyB9KVxuICAgICAgICAgICAgLmpvaW4oXCJcIilcbiAgICAgICAgICAgIC5jb25jYXQoXCIuLi5cIilcbiAgICAgICAgOiBzO1xufTtcbnZhciBjaGVja0lmTmFtZUlzR2VuZXJhdGVkQnlHYW1lID0gZnVuY3Rpb24gKGFTdHIsIGJTdHIsIGZvcm1OYW1lKSB7XG4gICAgaWYgKCFhU3RyLmxlbmd0aCAmJiBiU3RyLnN0YXJ0c1dpdGgoZm9ybU5hbWUpKSB7XG4gICAgICAgIHZhciBiRW5kaW5nID0gYlN0ci5zdWJzdHIoZm9ybU5hbWUubGVuZ3RoKTtcbiAgICAgICAgaWYgKGJFbmRpbmcubWF0Y2goL15cXHNcXCguKlxcKSQvKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcbnZhciBuYW1lc0VxdWFsID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICB2YXIgYVN0ciA9IGEubmFtZSB8fCBcIlwiO1xuICAgIHZhciBiU3RyID0gYi5uYW1lIHx8IFwiXCI7XG4gICAgaWYgKGNyb3BOYW1lKGdldFJlYWxOYW1lKGFTdHIpKSA9PT0gY3JvcE5hbWUoZ2V0UmVhbE5hbWUoYlN0cikpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoYS5iYXNlSWQgPT09IGIuYmFzZUlkKSB7XG4gICAgICAgIHZhciBmb3JtID0gR2FtZS5nZXRGb3JtRXgoYS5iYXNlSWQpO1xuICAgICAgICBpZiAoZm9ybSkge1xuICAgICAgICAgICAgdmFyIGZvcm1OYW1lID0gZm9ybS5nZXROYW1lKCk7XG4gICAgICAgICAgICBpZiAoY2hlY2tJZk5hbWVJc0dlbmVyYXRlZEJ5R2FtZShhU3RyLCBiU3RyLCBmb3JtTmFtZSkgfHxcbiAgICAgICAgICAgICAgICBjaGVja0lmTmFtZUlzR2VuZXJhdGVkQnlHYW1lKGJTdHIsIGFTdHIsIGZvcm1OYW1lKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xudmFyIGV4dHJhc0VxdWFsID0gZnVuY3Rpb24gKGEsIGIsIGlnbm9yZVdvcm4pIHtcbiAgICBpZiAoaWdub3JlV29ybiA9PT0gdm9pZCAwKSB7IGlnbm9yZVdvcm4gPSBmYWxzZTsgfVxuICAgIHJldHVybiAoYS5oZWFsdGggPT09IGIuaGVhbHRoICYmXG4gICAgICAgIGEuZW5jaGFudG1lbnRJZCA9PT0gYi5lbmNoYW50bWVudElkICYmXG4gICAgICAgIGEubWF4Q2hhcmdlID09PSBiLm1heENoYXJnZSAmJlxuICAgICAgICAhIWEucmVtb3ZlRW5jaGFudG1lbnRPblVuZXF1aXAgPT09ICEhYi5yZW1vdmVFbmNoYW50bWVudE9uVW5lcXVpcCAmJlxuICAgICAgICAvL2EuY2hhcmdlUGVyY2VudCA9PT0gYi5jaGFyZ2VQZXJjZW50ICYmXG4gICAgICAgIC8vbmFtZXNFcXVhbChhLCBiKSAmJlxuICAgICAgICBhLnNvdWwgPT09IGIuc291bCAmJlxuICAgICAgICBhLnBvaXNvbklkID09PSBiLnBvaXNvbklkICYmXG4gICAgICAgIGEucG9pc29uQ291bnQgPT09IGIucG9pc29uQ291bnQgJiZcbiAgICAgICAgKCghIWEud29ybiA9PT0gISFiLndvcm4gJiYgISFhLndvcm5MZWZ0ID09PSAhIWIud29ybkxlZnQpIHx8IGlnbm9yZVdvcm4pKTtcbn07XG5leHBvcnQgdmFyIGhhc0V4dHJhcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuICFleHRyYXNFcXVhbChlLCB7IGJhc2VJZDogMCwgY291bnQ6IDAgfSk7XG59O1xudmFyIGV4dHJhY3RFeHRyYURhdGEgPSBmdW5jdGlvbiAocmVmciwgZXh0cmFMaXN0LCBvdXQpIHtcbiAgICAvLyBJIHNlZSB0aGF0IEV4dHJhV29ybiBpcyBub3QgZW1pdHRlZCBmb3IgMHhGRiBhY3RvcnMgd2hlbiBhcnJvd3MgYXJlIGVxdWlwcGVkLiBGaXhpbmdcbiAgICB2YXIgaXRlbSA9IEdhbWUuZ2V0Rm9ybUV4KG91dC5iYXNlSWQpO1xuICAgIGlmIChBbW1vLmZyb20oaXRlbSkpIHtcbiAgICAgICAgdmFyIGFjdG9yID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICAgICAgaWYgKGFjdG9yICYmIGFjdG9yLmlzRXF1aXBwZWQoaXRlbSkpIHtcbiAgICAgICAgICAgIG91dC53b3JuID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAoZXh0cmFMaXN0IHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChleHRyYSkge1xuICAgICAgICBzd2l0Y2ggKGV4dHJhLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgXCJIZWFsdGhcIjpcbiAgICAgICAgICAgICAgICBvdXQuaGVhbHRoID0gTWF0aC5yb3VuZChleHRyYS5oZWFsdGggKiAxMCkgLyAxMDtcbiAgICAgICAgICAgICAgICAvLyBURVNNb2RQbGF0Zm9ybTo6QWRkSXRlbUV4IG1ha2VzIGFsbCBpdGVtcyBhdCBsZWFzdCAxLjAxIGhlYWx0aFxuICAgICAgICAgICAgICAgIGlmIChvdXQuaGVhbHRoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBvdXQuaGVhbHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJDb3VudFwiOlxuICAgICAgICAgICAgICAgIG91dC5jb3VudCA9IGV4dHJhLmNvdW50O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIkVuY2hhbnRtZW50XCI6XG4gICAgICAgICAgICAgICAgb3V0LmVuY2hhbnRtZW50SWQgPSBleHRyYS5lbmNoYW50bWVudElkO1xuICAgICAgICAgICAgICAgIG91dC5tYXhDaGFyZ2UgPSBleHRyYS5tYXhDaGFyZ2U7XG4gICAgICAgICAgICAgICAgb3V0LnJlbW92ZUVuY2hhbnRtZW50T25VbmVxdWlwID0gZXh0cmEucmVtb3ZlT25VbmVxdWlwO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIkNoYXJnZVwiOlxuICAgICAgICAgICAgICAgIG91dC5jaGFyZ2VQZXJjZW50ID0gZXh0cmEuY2hhcmdlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIlBvaXNvblwiOlxuICAgICAgICAgICAgICAgIG91dC5wb2lzb25JZCA9IGV4dHJhLnBvaXNvbklkO1xuICAgICAgICAgICAgICAgIG91dC5wb2lzb25Db3VudCA9IGV4dHJhLmNvdW50O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIlNvdWxcIjpcbiAgICAgICAgICAgICAgICBvdXQuc291bCA9IGV4dHJhLnNvdWw7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiVGV4dERpc3BsYXlEYXRhXCI6XG4gICAgICAgICAgICAgICAgb3V0Lm5hbWUgPSBleHRyYS5uYW1lO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIldvcm5cIjpcbiAgICAgICAgICAgICAgICBvdXQud29ybiA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiV29ybkxlZnRcIjpcbiAgICAgICAgICAgICAgICBvdXQud29ybkxlZnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xudmFyIHNxdWFzaCA9IGZ1bmN0aW9uIChpbnYpIHtcbiAgICB2YXIgcmVzID0gbmV3IEFycmF5KCk7XG4gICAgaW52LmVudHJpZXMuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgc2FtZSA9IHJlcy5maW5kKGZ1bmN0aW9uICh4KSB7IHJldHVybiBlLmJhc2VJZCA9PT0geC5iYXNlSWQgJiYgZXh0cmFzRXF1YWwoeCwgZSk7IH0pO1xuICAgICAgICBpZiAoc2FtZSkge1xuICAgICAgICAgICAgc2FtZS5jb3VudCArPSBlLmNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzLnB1c2goSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShlKSkpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHsgZW50cmllczogcmVzLmZpbHRlcihmdW5jdGlvbiAoeCkgeyByZXR1cm4geC5jb3VudCAhPT0gMDsgfSkgfTtcbn07XG52YXIgZ2V0RXh0cmFDb250YWluZXJDaGFuZ2VzQXNJbnZlbnRvcnkgPSBmdW5jdGlvbiAocmVmcikge1xuICAgIHZhciBleHRyYUNvbnRhaW5lckNoYW5nZXMgPSBnZXRFeHRyYUNvbnRhaW5lckNoYW5nZXMocmVmci5nZXRGb3JtSUQoKSk7XG4gICAgdmFyIGVudHJpZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAoZXh0cmFDb250YWluZXJDaGFuZ2VzIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFuZ2VzRW50cnkpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0ge1xuICAgICAgICAgICAgYmFzZUlkOiBjaGFuZ2VzRW50cnkuYmFzZUlkLFxuICAgICAgICAgICAgY291bnQ6IGNoYW5nZXNFbnRyeS5jb3VudERlbHRhLFxuICAgICAgICB9O1xuICAgICAgICAoY2hhbmdlc0VudHJ5LmV4dGVuZERhdGFMaXN0IHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChleHRyYUxpc3QpIHtcbiAgICAgICAgICAgIHZhciBlID0ge1xuICAgICAgICAgICAgICAgIGJhc2VJZDogZW50cnkuYmFzZUlkLFxuICAgICAgICAgICAgICAgIGNvdW50OiAxLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGV4dHJhY3RFeHRyYURhdGEocmVmciwgZXh0cmFMaXN0LCBlKTtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaChlKTtcbiAgICAgICAgICAgIGVudHJ5LmNvdW50IC09IGUuY291bnQ7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZW50cnkuY291bnQgIT09IDApIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaChlbnRyeSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICB2YXIgcmVzID0geyBlbnRyaWVzOiBlbnRyaWVzIH07XG4gICAgcmVzID0gc3F1YXNoKHJlcyk7XG4gICAgcmV0dXJuIHJlcztcbn07XG52YXIgZ2V0QmFzZUNvbnRhaW5lckFzSW52ZW50b3J5ID0gZnVuY3Rpb24gKHJlZnIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBlbnRyaWVzOiBnZXRDb250YWluZXIocmVmci5nZXRCYXNlT2JqZWN0KCkuZ2V0Rm9ybUlEKCkpLFxuICAgIH07XG59O1xuZXhwb3J0IHZhciBzdW1JbnZlbnRvcmllcyA9IGZ1bmN0aW9uIChsaHMsIHJocykge1xuICAgIHZhciBsZWZ0RW50cmllc1dpdGhFeHRyYXMgPSBsaHMuZW50cmllcy5maWx0ZXIoZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGhhc0V4dHJhcyhlKTsgfSk7XG4gICAgdmFyIHJpZ2h0RW50cmllc1dpdGhFeHRyYXMgPSByaHMuZW50cmllcy5maWx0ZXIoZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGhhc0V4dHJhcyhlKTsgfSk7XG4gICAgdmFyIGxlZnRFbnRyaWVzU2ltcGxlID0gbGhzLmVudHJpZXMuZmlsdGVyKGZ1bmN0aW9uIChlKSB7IHJldHVybiAhaGFzRXh0cmFzKGUpOyB9KTtcbiAgICB2YXIgcmlnaHRFbnRyaWVzU2ltcGxlID0gcmhzLmVudHJpZXMuZmlsdGVyKGZ1bmN0aW9uIChlKSB7IHJldHVybiAhaGFzRXh0cmFzKGUpOyB9KTtcbiAgICBsZWZ0RW50cmllc1NpbXBsZS5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBtYXRjaGluZyA9IHJpZ2h0RW50cmllc1NpbXBsZS5maW5kKGZ1bmN0aW9uICh4KSB7IHJldHVybiB4LmJhc2VJZCA9PT0gZS5iYXNlSWQ7IH0pO1xuICAgICAgICBpZiAobWF0Y2hpbmcpIHtcbiAgICAgICAgICAgIGUuY291bnQgKz0gbWF0Y2hpbmcuY291bnQ7XG4gICAgICAgICAgICBtYXRjaGluZy5jb3VudCA9IDA7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgICBlbnRyaWVzOiBsZWZ0RW50cmllc1dpdGhFeHRyYXNcbiAgICAgICAgICAgIC5jb25jYXQocmlnaHRFbnRyaWVzV2l0aEV4dHJhcylcbiAgICAgICAgICAgIC5jb25jYXQobGVmdEVudHJpZXNTaW1wbGUpXG4gICAgICAgICAgICAuY29uY2F0KHJpZ2h0RW50cmllc1NpbXBsZSlcbiAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUuY291bnQgIT09IDA7IH0pLFxuICAgIH07XG59O1xuZXhwb3J0IHZhciByZW1vdmVTaW1wbGVJdGVtc0FzTWFueUFzUG9zc2libGUgPSBmdW5jdGlvbiAoaW52LCBiYXNlSWQsIGNvdW50KSB7XG4gICAgdmFyIHJlcyA9IHsgZW50cmllczogW10gfTtcbiAgICByZXMuZW50cmllcyA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW52LmVudHJpZXMpKTtcbiAgICB2YXIgZW50cnkgPSByZXMuZW50cmllcy5maW5kKGZ1bmN0aW9uIChlKSB7IHJldHVybiAhaGFzRXh0cmFzKGUpICYmIGUuYmFzZUlkID09PSBiYXNlSWQ7IH0pO1xuICAgIGlmIChlbnRyeSkge1xuICAgICAgICBlbnRyeS5jb3VudCAtPSBjb3VudDtcbiAgICB9XG4gICAgcmVzLmVudHJpZXMgPSByZXMuZW50cmllcy5maWx0ZXIoZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUuY291bnQgPiAwOyB9KTtcbiAgICByZXR1cm4gcmVzO1xufTtcbmV4cG9ydCB2YXIgZ2V0RGlmZiA9IGZ1bmN0aW9uIChsaHMsIHJocywgaWdub3JlV29ybikge1xuICAgIHZhciBsaHNDb3B5ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShsaHMpKTtcbiAgICB2YXIgcmhzQ29weSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkocmhzKSk7XG4gICAgcmhzQ29weS5lbnRyaWVzLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHNhbWVGcm9tTGVmdCA9IGxoc0NvcHkuZW50cmllcy5maW5kKGZ1bmN0aW9uICh4KSB7IHJldHVybiB4LmJhc2VJZCA9PT0gZS5iYXNlSWQgJiYgZXh0cmFzRXF1YWwoeCwgZSwgaWdub3JlV29ybik7IH0pO1xuICAgICAgICBpZiAoc2FtZUZyb21MZWZ0KSB7XG4gICAgICAgICAgICBzYW1lRnJvbUxlZnQuY291bnQgLT0gZS5jb3VudDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxoc0NvcHkuZW50cmllcy5wdXNoKGUpO1xuICAgICAgICAgICAgbGhzQ29weS5lbnRyaWVzW2xoc0NvcHkuZW50cmllcy5sZW5ndGggLSAxXS5jb3VudCAqPSAtMTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7IGVudHJpZXM6IGxoc0NvcHkuZW50cmllcy5maWx0ZXIoZnVuY3Rpb24gKHgpIHsgcmV0dXJuIHguY291bnQgIT09IDA7IH0pIH07XG59O1xuZXhwb3J0IHZhciBnZXRJbnZlbnRvcnkgPSBmdW5jdGlvbiAocmVmcikge1xuICAgIHJldHVybiBzcXVhc2goc3VtSW52ZW50b3JpZXMoZ2V0QmFzZUNvbnRhaW5lckFzSW52ZW50b3J5KHJlZnIpLCBnZXRFeHRyYUNvbnRhaW5lckNoYW5nZXNBc0ludmVudG9yeShyZWZyKSkpO1xufTtcbnZhciBiYXNlc1Jlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmIChzdG9yYWdlW1wiYmFzZXNSZXNldEV4aXN0c1wiXSAhPT0gdHJ1ZSkge1xuICAgICAgICBzdG9yYWdlW1wiYmFzZXNSZXNldEV4aXN0c1wiXSA9IHRydWU7XG4gICAgICAgIHN0b3JhZ2VbXCJiYXNlc1Jlc2V0XCJdID0gbmV3IFNldCgpO1xuICAgIH1cbiAgICByZXR1cm4gc3RvcmFnZVtcImJhc2VzUmVzZXRcIl07XG59O1xudmFyIHJlc2V0QmFzZSA9IGZ1bmN0aW9uIChyZWZyKSB7XG4gICAgdmFyIGJhc2UgPSByZWZyLmdldEJhc2VPYmplY3QoKTtcbiAgICB2YXIgYmFzZUlkID0gYmFzZSA/IGJhc2UuZ2V0Rm9ybUlEKCkgOiAwO1xuICAgIGlmICghYmFzZXNSZXNldCgpLmhhcyhiYXNlSWQpKSB7XG4gICAgICAgIGJhc2VzUmVzZXQoKS5hZGQoYmFzZUlkKTtcbiAgICAgICAgVEVTTW9kUGxhdGZvcm0ucmVzZXRDb250YWluZXIoYmFzZSk7XG4gICAgICAgIHJlZnIucmVtb3ZlQWxsSXRlbXMobnVsbCwgZmFsc2UsIHRydWUpO1xuICAgIH1cbn07XG5leHBvcnQgdmFyIGFwcGx5SW52ZW50b3J5ID0gZnVuY3Rpb24gKHJlZnIsIG5ld0ludmVudG9yeSwgZW5hYmxlQ3Jhc2hQcm90ZWN0aW9uLCBpZ25vcmVXb3JuKSB7XG4gICAgaWYgKGlnbm9yZVdvcm4gPT09IHZvaWQgMCkgeyBpZ25vcmVXb3JuID0gZmFsc2U7IH1cbiAgICByZXNldEJhc2UocmVmcik7XG4gICAgdmFyIGRpZmYgPSBnZXREaWZmKG5ld0ludmVudG9yeSwgZ2V0SW52ZW50b3J5KHJlZnIpLCBpZ25vcmVXb3JuKS5lbnRyaWVzO1xuICAgIHZhciByZXMgPSB0cnVlO1xuICAgIGRpZmYuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gKGEuY291bnQgPCBiLmNvdW50ID8gLTEgOiAxKTsgfSk7XG4gICAgZGlmZi5mb3JFYWNoKGZ1bmN0aW9uIChlLCBpKSB7XG4gICAgICAgIGlmIChpID4gMCAmJiBlbmFibGVDcmFzaFByb3RlY3Rpb24pIHtcbiAgICAgICAgICAgIHJlcyA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhYnNDb3VudCA9IE1hdGguYWJzKGUuY291bnQpO1xuICAgICAgICB2YXIgcXVldWVOaU5vZGVVcGRhdGVOZWVkZWQgPSBmYWxzZTtcbiAgICAgICAgdmFyIHdvcm4gPSAhIWUud29ybjtcbiAgICAgICAgdmFyIHdvcm5MZWZ0ID0gISFlLndvcm5MZWZ0O1xuICAgICAgICB2YXIgb25lU3RlcENvdW50ID0gZS5jb3VudCAvIGFic0NvdW50O1xuICAgICAgICB2YXIgZiA9IEdhbWUuZ2V0Rm9ybUV4KGUuYmFzZUlkKTtcbiAgICAgICAgaWYgKCFmKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJpbnRDb25zb2xlKFwiQmFkIGZvcm0gSUQgXCIuY29uY2F0KGUuYmFzZUlkLnRvU3RyaW5nKDE2KSkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0eXBlID0gZi5nZXRUeXBlKCk7XG4gICAgICAgIC8vIEZvciBtaXNjIGl0ZW1zLCBwb3Rpb25zIGFuZCBpbmdyZWRpZW50cyB3ZSBkb24ndCB3YW50IHRvIHNwbGl0IHRoZW0gaW50byBtdWx0aXBsZSBpdGVtc1xuICAgICAgICAvLyBUaGlzIHdhcyBtYWRlIHRvIGZpeCBhIHBlcmZvcm1hbmNlIGlzc3VlIHdpdGggdXNlcnMgaGF2aW5nIDEwMDAwKyBvZiBtaXNjIGl0ZW1zIChpLmUuIGdvbGQpXG4gICAgICAgIGlmICh0eXBlID09PSAzMiAvKiBGb3JtVHlwZS5NaXNjICovIHx8XG4gICAgICAgICAgICB0eXBlID09PSA0NiAvKiBGb3JtVHlwZS5Qb3Rpb24gKi8gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IDMwIC8qIEZvcm1UeXBlLkluZ3JlZGllbnQgKi8pIHtcbiAgICAgICAgICAgIGFic0NvdW50ID0gMTtcbiAgICAgICAgICAgIG9uZVN0ZXBDb3VudCA9IGUuY291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoYWJzQ291bnQgPiAxMDAwKSB7XG4gICAgICAgICAgICAgICAgYWJzQ291bnQgPSAxO1xuICAgICAgICAgICAgICAgIG9uZVN0ZXBDb3VudCA9IDE7XG4gICAgICAgICAgICAgICAgLy8gQWxzbyBmb3IgYXJyb3dzIHdpdGggc3RyYW5nZSBjb3VudFxuICAgICAgICAgICAgICAgIGlmICh3b3JuICYmIGUuY291bnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGFic0NvdW50ID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZS5jb3VudCA+IDEgJiYgQW1tby5mcm9tKEdhbWUuZ2V0Rm9ybUV4KGUuYmFzZUlkKSkpIHtcbiAgICAgICAgICAgICAgICBhYnNDb3VudCA9IDE7XG4gICAgICAgICAgICAgICAgb25lU3RlcENvdW50ID0gZS5jb3VudDtcbiAgICAgICAgICAgICAgICBpZiAoZS5jb3VudCA+IDYwMDAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoeSB3b3VsZCBhY3RvciBoYXZlIDYwayBhcnJvd3M/XG4gICAgICAgICAgICAgICAgICAgIGUuY291bnQgPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpXzEgPSAwOyBpXzEgPCBhYnNDb3VudDsgKytpXzEpIHtcbiAgICAgICAgICAgIGlmICh3b3JuIHx8IHdvcm5MZWZ0KSB7XG4gICAgICAgICAgICAgICAgVEVTTW9kUGxhdGZvcm0ucHVzaFdvcm5TdGF0ZSghIXdvcm4sICEhd29ybkxlZnQpO1xuICAgICAgICAgICAgICAgIHF1ZXVlTmlOb2RlVXBkYXRlTmVlZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhZGRJdGVtRXhBcmdzID0gdm9pZCAwO1xuICAgICAgICAgICAgYWRkSXRlbUV4QXJncyA9IFtcbiAgICAgICAgICAgICAgICByZWZyLFxuICAgICAgICAgICAgICAgIGYsXG4gICAgICAgICAgICAgICAgb25lU3RlcENvdW50LFxuICAgICAgICAgICAgICAgIGUuaGVhbHRoID8gZS5oZWFsdGggOiAxLFxuICAgICAgICAgICAgICAgIGUuZW5jaGFudG1lbnRJZFxuICAgICAgICAgICAgICAgICAgICA/IEVuY2hhbnRtZW50LmZyb20oR2FtZS5nZXRGb3JtRXgoZS5lbmNoYW50bWVudElkKSlcbiAgICAgICAgICAgICAgICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIGUubWF4Q2hhcmdlID8gZS5tYXhDaGFyZ2UgOiAwLFxuICAgICAgICAgICAgICAgICEhZS5yZW1vdmVFbmNoYW50bWVudE9uVW5lcXVpcCxcbiAgICAgICAgICAgICAgICBlLmNoYXJnZVBlcmNlbnQgPyBlLmNoYXJnZVBlcmNlbnQgOiAwLFxuICAgICAgICAgICAgICAgIGUubmFtZSA/IGNyb3BOYW1lKGUubmFtZSkgOiBmLmdldE5hbWUoKSxcbiAgICAgICAgICAgICAgICBlLnNvdWwgPyBlLnNvdWwgOiAwLFxuICAgICAgICAgICAgICAgIGUucG9pc29uSWQgPyBQb3Rpb24uZnJvbShHYW1lLmdldEZvcm1FeChlLnBvaXNvbklkKSkgOiBudWxsLFxuICAgICAgICAgICAgICAgIGUucG9pc29uQ291bnQgPyBlLnBvaXNvbkNvdW50IDogMFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIC8vIExvZyBkZWJ1ZyByZW1vdmlkbzogZW4gc2VydmVyIGNvbiBtdWNob3MgaXRlbXMgcG9yIHBsYXllciAoc3RhcnRlclxuICAgICAgICAgICAgLy8gaW52ZW50b3J5ICsgZHJvcHMpIGVzdGUgcHJpbnRDb25zb2xlIHNwYW1tZWFiYSBsYSBjb25zb2xhIGRlIFNQXG4gICAgICAgICAgICAvLyB2YXJpYXMgdmVjZXMgcG9yIHNlZ3VuZG8uIFNpIG5lY2VzaXRhcyBkZWJ1ZywgZGVzY29tZW50YSBlc3RvLlxuICAgICAgICAgICAgLy8gY29uc3QgYXJnc1RvUHJpbnQgPSBhZGRJdGVtRXhBcmdzLm1hcCgoYXJnKSA9PiB7XG4gICAgICAgICAgICAvLyAgIGlmIChhcmcgaW5zdGFuY2VvZiBPYmplY3RSZWZlcmVuY2UpIHJldHVybiBgT2JqZWN0UmVmZXJlbmNlKCR7YXJnLmdldEZvcm1JRCgpLnRvU3RyaW5nKDE2KX0pYDtcbiAgICAgICAgICAgIC8vICAgaWYgKGFyZyBpbnN0YW5jZW9mIEZvcm0pIHJldHVybiBgRm9ybSgke2FyZy5nZXRGb3JtSUQoKS50b1N0cmluZygxNil9KWA7XG4gICAgICAgICAgICAvLyAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmcpO1xuICAgICAgICAgICAgLy8gfSk7XG4gICAgICAgICAgICAvLyBwcmludENvbnNvbGUoYFRFU01vZFBsYXRmb3JtLmFkZEl0ZW1FeCgke2FyZ3NUb1ByaW50LmpvaW4oXCIsIFwiKX0pYCk7XG4gICAgICAgICAgICBURVNNb2RQbGF0Zm9ybS5hZGRJdGVtRXguYXBwbHkoVEVTTW9kUGxhdGZvcm0sIGFkZEl0ZW1FeEFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChxdWV1ZU5pTm9kZVVwZGF0ZU5lZWRlZCkge1xuICAgICAgICAgICAgdmFyIGFjID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICAgICAgICAgIGlmIChhYykge1xuICAgICAgICAgICAgICAgIGFjLnF1ZXVlTmlOb2RlVXBkYXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzO1xufTtcbiIsImltcG9ydCB7IE9iamVjdFJlZmVyZW5jZSwgQWN0b3IsIEdhbWUsIFRFU01vZFBsYXRmb3JtLCBEZWJ1Zywgc3RvcmFnZSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgUmVzcGF3bk5lZWRlZEVycm9yIH0gZnJvbSBcIi4uL2xpYi9lcnJvcnNcIjtcbmltcG9ydCB7IE9iamVjdFJlZmVyZW5jZUV4IH0gZnJvbSBcIi4uL2V4dGVuc2lvbnMvb2JqZWN0UmVmZXJlbmNlRXhcIjtcbmltcG9ydCB7IFNwQXBpSW50ZXJhY3RvciB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zcEFwaUludGVyYWN0b3JcIjtcbnZhciBzcXIgPSBmdW5jdGlvbiAoeCkgeyByZXR1cm4geCAqIHg7IH07XG52YXIgcHJveHlNb3VudHMgPSBuZXcgTWFwKCk7IC8vIHJpZGVyUmVtb3RlRm9ybUlkIC0+IHByb3h5IGxvY2FsXG4vLyBtLnZlaGljbGVGb3JtSWQgdmllbmUgZGUgbGEgUkVEIChubyBjb25maWFibGUpLiBTb2xvIHNwYXduZWFtb3MgcHJveGllcyBkZSBiYXNlcyBkZSBDQUJBTExPXG4vLyBjb25vY2lkYXMsIHBhcmEgcXVlIHVuIGNsaWVudGUgbW9kaWZpY2FkbyBubyBmdWVyY2UgYSBsb3Mgb2JzZXJ2YWRvcmVzIGEgaW5zdGFuY2lhci9wcm90ZWdlclxuLy8gZm9ybXMgYXJiaXRyYXJpb3MuIFBST1RPVElQTzogaGFyZGNvZGUgZGUgbGFzIGJhc2VzIGRlbCBjYXTDoWxvZ28gKDY4Y2ZhLzY4ZDA0KTsgZWwgbGlmZWN5Y2xlXG4vLyBmaW5hbCBsYXMgcmVjaWJpcsOhIGRlbCBnYW1lbW9kZSAoY2F0w6Fsb2dvIC9jYWJhbGxvcykgdsOtYSBzdG9yYWdlLlxudmFyIEFMTE9XRURfSE9SU0VfQkFTRVMgPSBuZXcgU2V0KFsweDY4Y2ZhLCAweDY4ZDA0XSk7XG52YXIgc2V0SG9yc2VQcm90ZWN0ID0gZnVuY3Rpb24gKGlkLCBvbikge1xuICAgIC8vIE1pc21hIGFsbG93bGlzdCBxdWUgcmVzcGV0YSBlbCBXb3JsZENsZWFuZXJTZXJ2aWNlIChzaSBubywgYm9ycmEgZWwgcHJveHkgZW4gcG9jb3MgZnJhbWVzKS5cbiAgICB0cnkge1xuICAgICAgICB2YXIgcHIgPSBzdG9yYWdlW1wiZWxkSG9yc2VQcm90ZWN0XCJdO1xuICAgICAgICBpZiAoIXByIHx8IHR5cGVvZiBwciAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgIHByID0ge307XG4gICAgICAgIGlmIChvbilcbiAgICAgICAgICAgIHByW2lkXSA9IDE7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBwcltpZF07XG4gICAgICAgIHN0b3JhZ2VbXCJlbGRIb3JzZVByb3RlY3RcIl0gPSBwcjtcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHsgLyogaWdub3JlICovIH1cbn07XG52YXIgZGVzdHJveVByb3h5TW91bnQgPSBmdW5jdGlvbiAocmlkZXJJZCkge1xuICAgIHZhciBwbSA9IHByb3h5TW91bnRzLmdldChyaWRlcklkKTtcbiAgICBpZiAoIXBtKVxuICAgICAgICByZXR1cm47XG4gICAgcHJveHlNb3VudHMuZGVsZXRlKHJpZGVySWQpO1xuICAgIHRyeSB7XG4gICAgICAgIHNldEhvcnNlUHJvdGVjdChwbS5wcm94eUlkLCBmYWxzZSk7IC8vIFNJRU1QUkUgZGVzcHJvdGVnZXIgYW50ZXMgZGUgYm9ycmFyIChldml0YSBodcOpcmZhbm8gcHJvdGVnaWRvKVxuICAgICAgICB2YXIgcmVmID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgocG0ucHJveHlJZCkpO1xuICAgICAgICBpZiAocmVmKSB7XG4gICAgICAgICAgICByZWYuZGlzYWJsZShmYWxzZSk7XG4gICAgICAgICAgICByZWYuZGVsZXRlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY2F0Y2ggKGUpIHsgLyogaWdub3JlICovIH1cbn07XG52YXIgUFJPWFlfR1JBQ0VfTVMgPSA3MDA7XG52YXIgUFJPWFlfVFRMX01TID0gNDAwMDsgLy8gamluZXRlIHF1ZSBkZWphIGRlIG1hbmRhciBtb3ZpbWllbnRvID4gVFRMIC0+IHN1IHByb3h5IHNlIGJhcnJlXG52YXIgbGFzdFByb3h5U3dlZXAgPSAwO1xuLy8gTGltcGllemEgaW5tZWRpYXRhIHBvciBqaW5ldGU7IGxhIGxsYW1hIEZvcm1WaWV3LmRlc3Ryb3koKSBhbCByZW1vdmVyIGFsIGFjdG9yIHJlbW90byAoY3VicmVcbi8vIHNhbGlyIGRlbCB3b3JsZFZpZXcgLyBjYW1iaW8gZGUgY2VsZGEgLyBkZXNjb25leGnDs24gc2luIHVuIHBhcXVldGUgZmluYWwgZGUgZGVzbW9udGFqZSkuXG5leHBvcnQgdmFyIGRlc3Ryb3lQcm94eU1vdW50Rm9yUmlkZXIgPSBmdW5jdGlvbiAocmlkZXJJZCkge1xuICAgIGRlc3Ryb3lQcm94eU1vdW50KHJpZGVySWQpO1xufTtcbi8vIEJhcnJpZG8gdGhyb3R0bGVkIGRlIHByb3hpZXMgaHXDqXJmYW5vczogY2F0Y2gtYWxsIHNpIGVsIGppbmV0ZSBkZXNhcGFyZWNlIHNpbiBkZXNtb250YXIgeSBzaW5cbi8vIHF1ZSBGb3JtVmlldy5kZXN0cm95IGxvIGxpbXBpZS4gU2UgZGlzcGFyYSBkZXNkZSBjdWFscXVpZXIgYXBwbHlNb3ZlbWVudCAoaGF5IG1vdmltaWVudG8gc2llbXByZVxuLy8gcXVlIGhheWEgYWxnw7puIHJlbW90byBlbiBlc2NlbmEpLlxudmFyIHN3ZWVwU3RhbGVQcm94aWVzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBub3cgPSBEYXRlLm5vdygpO1xuICAgIGlmIChub3cgLSBsYXN0UHJveHlTd2VlcCA8IDEwMDApXG4gICAgICAgIHJldHVybjtcbiAgICBsYXN0UHJveHlTd2VlcCA9IG5vdztcbiAgICBwcm94eU1vdW50cy5mb3JFYWNoKGZ1bmN0aW9uIChwbSwgcmlkZXJJZCkge1xuICAgICAgICBpZiAobm93IC0gcG0ubGFzdFNlZW5NcyA+IFBST1hZX1RUTF9NUylcbiAgICAgICAgICAgIGRlc3Ryb3lQcm94eU1vdW50KHJpZGVySWQpO1xuICAgIH0pO1xufTtcbmV4cG9ydCB2YXIgYXBwbHlNb3ZlbWVudCA9IGZ1bmN0aW9uIChyZWZyLCBtLCBpc015Q2xvbmUpIHtcbiAgICBzd2VlcFN0YWxlUHJveGllcygpO1xuICAgIGlmICh0ZWxlcG9ydElmTmVlZChyZWZyLCBtKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBtb3VudEFjID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICBpZiAobW91bnRBYykge1xuICAgICAgICB2YXIgcmlkZXJJZCA9IHJlZnIuZ2V0Rm9ybUlEKCk7XG4gICAgICAgIHZhciByZXFCYXNlID0gKG0udmVoaWNsZUZvcm1JZCAhPT0gdW5kZWZpbmVkICYmIG0udmVoaWNsZUZvcm1JZCAhPT0gbnVsbCkgPyAobS52ZWhpY2xlRm9ybUlkID4+PiAwKSA6IDA7XG4gICAgICAgIGlmIChyZXFCYXNlID4gMCAmJiBBTExPV0VEX0hPUlNFX0JBU0VTLmhhcyhyZXFCYXNlKSkge1xuICAgICAgICAgICAgdmFyIGJhc2VJZCA9IHJlcUJhc2U7XG4gICAgICAgICAgICB2YXIgcG0gPSBwcm94eU1vdW50cy5nZXQocmlkZXJJZCk7XG4gICAgICAgICAgICAvLyBDYW1iaW8gZGUgbW9udHVyYSAtPiBkZXNtb250YXIgYWwgamluZXRlIGRlbCBwcm94eSB2aWVqbywgZGVzY2FydGFybG8geSBjcmVhciB1bm8gbnVldm8uXG4gICAgICAgICAgICBpZiAocG0gJiYgcG0uYmFzZUlkICE9PSBiYXNlSWQpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobW91bnRBYy5pc09uTW91bnQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdW50QWMuZGlzbW91bnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsgLyogaWdub3JlICovIH1cbiAgICAgICAgICAgICAgICBkZXN0cm95UHJveHlNb3VudChyaWRlcklkKTtcbiAgICAgICAgICAgICAgICBwbSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcG0pIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYmFzZSA9IEdhbWUuZ2V0Rm9ybUV4KGJhc2VJZCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm94eSA9IGJhc2UgPyBtb3VudEFjLnBsYWNlQXRNZShiYXNlLCAxLCB0cnVlLCBmYWxzZSkgOiBudWxsO1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJveHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm94eUlkID0gcHJveHkuZ2V0Rm9ybUlEKCkgPj4+IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRIb3JzZVByb3RlY3QocHJveHlJZCwgdHJ1ZSk7IC8vIHF1ZSBlbCBXb3JsZENsZWFuZXIgZGVsIG9ic2VydmFkb3Igbm8gbG8gYm9ycmVcbiAgICAgICAgICAgICAgICAgICAgICAgIHBtID0geyBwcm94eUlkOiBwcm94eUlkLCBiYXNlSWQ6IGJhc2VJZCwgbGFzdFNlZW5NczogRGF0ZS5ub3coKSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJveHlNb3VudHMuc2V0KHJpZGVySWQsIHBtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkgeyAvKiByZWludGVudGFyIGVsIHByw7N4aW1vIGZyYW1lICovIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwbSkge1xuICAgICAgICAgICAgICAgIHZhciBwcm94eVJlZiA9IE9iamVjdFJlZmVyZW5jZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHBtLnByb3h5SWQpKTtcbiAgICAgICAgICAgICAgICBpZiAoIXByb3h5UmVmKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEVsIHByb3h5IHNlIHBlcmRpw7MgKGJvcnJhZG8gcG9yIGNsZWFudXAvY2VsZGEvcmFjZSkuIEVsIGVzdGFkbyBkZSBtb250YSBkZWwgZW5naW5lIHB1ZWRlXG4gICAgICAgICAgICAgICAgICAgIC8vIHNvYnJldml2aXIgYWwgcmVmIGJvcnJhZG8gLT4gZGVzbW9udGFyIGFsIGppbmV0ZSBlIGludmFsaWRhciAoZGVzdHJveVByb3h5TW91bnQgcXVpdGFcbiAgICAgICAgICAgICAgICAgICAgLy8gZWxkSG9yc2VQcm90ZWN0ICsgTWFwOyBOTyBzZSByZWZyZXNjw7MgbGFzdFNlZW5NcykuIEVsIHByw7N4aW1vIHBhcXVldGUgY3JlYSB1bm8gbnVldm8uXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobW91bnRBYy5pc09uTW91bnQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb3VudEFjLmRpc21vdW50KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsgLyogaWdub3JlICovIH1cbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVByb3h5TW91bnQocmlkZXJJZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwbS5sYXN0U2Vlbk1zID0gRGF0ZS5ub3coKTsgLy8gc29sbyByZWZyZXNjYXIgY29uIHByb3h5IFbDgUxJRE8gKHNpIG5vLCBlbCBUVEwgbnVuY2EgYmFycmVyw61hKVxuICAgICAgICAgICAgICAgICAgICAvLyDCv01vbnRhZG8gZW4gRVNURSBwcm94eSAobm8gZW4gdW5vIHZpZWpvL2JvcnJhZG8pPyBFbCBlc3RhZG8gZGUgbW9udGEgZGVsIGVuZ2luZSBwdWVkZVxuICAgICAgICAgICAgICAgICAgICAvLyBzb2JyZXZpdmlyIGFsIE1hcDsgdmVyaWZpY2Ftb3MgY29uIGxhIGZ1cm5pdHVyZSBBQ1RVQUwgeSBSRS1CSU5EZWFtb3Mgc2kgbm8gY29pbmNpZGUuXG4gICAgICAgICAgICAgICAgICAgIHZhciBjdXIgPSBtb3VudEFjLmdldEZ1cm5pdHVyZVJlZmVyZW5jZSgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgb25UaGlzUHJveHkgPSAhIWN1ciAmJiAoY3VyLmdldEZvcm1JRCgpID4+PiAwKSA9PT0gcG0ucHJveHlJZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFvblRoaXNQcm94eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb3VudEFjLnNldFZlaGljbGUocHJveHlSZWYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsgLyogaWdub3JlICovIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVUbyhwcm94eVJlZiwgbSk7IC8vIHBlZ2FyIGVsIHByb3h5IGEgbGEgcG9zIChmbHVpZGEpIGRlbCBqaW5ldGVcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFmdGVyID0gbW91bnRBYy5nZXRGdXJuaXR1cmVSZWZlcmVuY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbmZpcm1lZCA9ICEhYWZ0ZXIgJiYgKGFmdGVyLmdldEZvcm1JRCgpID4+PiAwKSA9PT0gcG0ucHJveHlJZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpcm1lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9udGFkbyBlbiBlbCBwcm94eSBBQ1RVQUw6IGFwbGljYXIgc29sbyBsbyBuby1wb3NpY2lvbmFsIChhbCBqaW5ldGUgbG8gbGxldmEgZWwgcHJveHkpIHkgc2FsaXIuXG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVdlYXBEcmF3bihtb3VudEFjLCBtLmlzV2VhcERyYXduKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5SGVhbHRoUGVyY2VudGFnZShtb3VudEFjLCBtLmhlYWx0aFBlcmNlbnRhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgU3BBcGlJbnRlcmFjdG9yLmdldENvbnRyb2xsZXJJbnN0YW5jZSgpLmVtaXR0ZXIuZW1pdChcImFwcGx5RGVhdGhTdGF0ZUV2ZW50XCIsIHsgYWN0b3I6IG1vdW50QWMsIGlzRGVhZDogbS5pc0RlYWQgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIE5PIHNlZ3VpciBhbCBwYXRoIG5vcm1hbCBkZSBtb3ZpbWllbnRvXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gQcO6biBubyBlbmdhbmNow7MgZW4gZWwgcHJveHkgYWN0dWFsICgzRCBubyBsaXN0byAvIHJlc2VhdCBlbiBjdXJzbyk6IE5PIHJldHVybiAtPiBtb3ZlciBhbFxuICAgICAgICAgICAgICAgICAgICAvLyBqaW5ldGUgcG9yIGVsIHBhdGggbm9ybWFsIGVzdGUgZnJhbWUgeSByZWludGVudGFyIGVsIHByw7N4aW1vLiBFdml0YSBjb25nZWxhcmxvLlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFByb3h5IGHDum4gbm8gbGlzdG8gKHJhY2Ugc3Bhd24pOiBOTyBjb25nZWxhciAtPiBjYWVyIGFsIG1vdmltaWVudG8gbm9ybWFsIGRlbCBqaW5ldGUgeSByZWludGVudGFyLlxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU2luIG1vbnR1cmEgRVNURSBwYXF1ZXRlOiB2ZW50YW5hIGRlIGdyYWNpYSBwYXJhIG5vIGRlc21vbnRhciBwb3IgMSBwYXF1ZXRlIHBlcmRpZG8vcmVvcmRlbmFkby5cbiAgICAgICAgICAgIHZhciBwbSA9IHByb3h5TW91bnRzLmdldChyaWRlcklkKTtcbiAgICAgICAgICAgIGlmIChwbSkge1xuICAgICAgICAgICAgICAgIGlmIChEYXRlLm5vdygpIC0gcG0ubGFzdFNlZW5NcyA8PSBQUk9YWV9HUkFDRV9NUykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJveHlSZWYgPSBPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm1FeChwbS5wcm94eUlkKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm94eVJlZiAmJiBtb3VudEFjLmlzT25Nb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVUbyhwcm94eVJlZiwgbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVdlYXBEcmF3bihtb3VudEFjLCBtLmlzV2VhcERyYXduKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5SGVhbHRoUGVyY2VudGFnZShtb3VudEFjLCBtLmhlYWx0aFBlcmNlbnRhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgU3BBcGlJbnRlcmFjdG9yLmdldENvbnRyb2xsZXJJbnN0YW5jZSgpLmVtaXR0ZXIuZW1pdChcImFwcGx5RGVhdGhTdGF0ZUV2ZW50XCIsIHsgYWN0b3I6IG1vdW50QWMsIGlzRGVhZDogbS5pc0RlYWQgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIGRlbnRybyBkZSBsYSBncmFjaWEgeSBhw7puIG1vbnRhZG86IGJyaWRnZSBkZWwgcGFxdWV0ZSBmYWx0YW50ZSAoc2luIGZsaWNrZXIpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gc2kgeWEgbm8gZXN0w6EgbW9udGFkbywgY2FlciBhbCBtb3ZpbWllbnRvIG5vcm1hbCAobm8gY29uZ2VsYXIpOyBzZSBsaW1waWEgYWwgZXhwaXJhciBsYSBncmFjaWFcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gR3JhY2lhIGV4cGlyYWRhIC0+IGRlc21vbnRhciB5IGxpbXBpYXIgZWwgcHJveHkuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vdW50QWMuaXNPbk1vdW50KCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3VudEFjLmRpc21vdW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7IC8qIGlnbm9yZSAqLyB9XG4gICAgICAgICAgICAgICAgZGVzdHJveVByb3h5TW91bnQocmlkZXJJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gWiBheGlzIGlzbid0IHVzZWZ1bCBoZXJlXG4gICAgdmFyIGFjWCA9IHJlZnIuZ2V0UG9zaXRpb25YKCk7XG4gICAgdmFyIGFjWSA9IHJlZnIuZ2V0UG9zaXRpb25ZKCk7XG4gICAgdmFyIGxhZ1VuaXRzTm9aID0gTWF0aC5yb3VuZChNYXRoLnNxcnQoc3FyKG0ucG9zWzBdIC0gYWNYKSArIHNxcihtLnBvc1sxXSAtIGFjWSkpKTtcbiAgICBpZiAoaXNNeUNsb25lID09PSB0cnVlKSB7XG4gICAgICAgIFNwQXBpSW50ZXJhY3Rvci5nZXRDb250cm9sbGVySW5zdGFuY2UoKS5lbWl0dGVyLmVtaXQoXCJuZXdMb2NhbExhZ1ZhbHVlQ2FsY3VsYXRlZFwiLCB7IGxhZ1VuaXRzTm9aOiBsYWdVbml0c05vWiB9KTtcbiAgICB9XG4gICAgdHJhbnNsYXRlVG8ocmVmciwgbSk7XG4gICAgdmFyIGFjID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICBpZiAoIWFjKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGxvb2tBdCA9IG51bGw7XG4gICAgaWYgKG0ubG9va0F0KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb29rQXQgPSBHYW1lLmZpbmRDbG9zZXN0QWN0b3IobS5sb29rQXRbMF0sIG0ubG9va0F0WzFdLCBtLmxvb2tBdFsyXSwgMTI4KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9va0F0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAobG9va0F0KSB7XG4gICAgICAgIGFjLnNldEhlYWRUcmFja2luZyh0cnVlKTtcbiAgICAgICAgYWMuc2V0TG9va0F0KGxvb2tBdCwgZmFsc2UpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYWMuc2V0SGVhZFRyYWNraW5nKGZhbHNlKTtcbiAgICB9XG4gICAgLy8gYWMuc3RvcENvbWJhdCgpO1xuICAgIGFjLmJsb2NrQWN0aXZhdGlvbih0cnVlKTtcbiAgICBrZWVwT2Zmc2V0RnJvbUFjdG9yKGFjLCBtKTtcbiAgICBhcHBseVNwcmludGluZyhhYywgbS5ydW5Nb2RlID09PSBcIlNwcmludGluZ1wiKTtcbiAgICBhcHBseUJsb2NraW5nKGFjLCBtKTtcbiAgICBhcHBseVNuZWFraW5nKGFjLCBtLmlzU25lYWtpbmcpO1xuICAgIGFwcGx5V2VhcERyYXduKGFjLCBtLmlzV2VhcERyYXduKTtcbiAgICBhcHBseUhlYWx0aFBlcmNlbnRhZ2UoYWMsIG0uaGVhbHRoUGVyY2VudGFnZSk7XG4gICAgU3BBcGlJbnRlcmFjdG9yLmdldENvbnRyb2xsZXJJbnN0YW5jZSgpLmVtaXR0ZXIuZW1pdChcImFwcGx5RGVhdGhTdGF0ZUV2ZW50XCIsIHsgYWN0b3I6IGFjLCBpc0RlYWQ6IG0uaXNEZWFkIH0pO1xufTtcbnZhciBrZWVwT2Zmc2V0RnJvbUFjdG9yID0gZnVuY3Rpb24gKGFjLCBtKSB7XG4gICAgdmFyIG9mZnNldEFuZ2xlID0gbS5yb3RbMl0gLSBhYy5nZXRBbmdsZVooKTtcbiAgICBpZiAoTWF0aC5hYnMob2Zmc2V0QW5nbGUpIDwgNSkge1xuICAgICAgICBvZmZzZXRBbmdsZSA9IDA7XG4gICAgfVxuICAgIGlmIChtLnJ1bk1vZGUgPT09IFwiU3RhbmRpbmdcIikge1xuICAgICAgICByZXR1cm4gYWMua2VlcE9mZnNldEZyb21BY3RvcihhYywgMCwgMCwgMCwgMCwgMCwgb2Zmc2V0QW5nbGUsIDEsIDEpO1xuICAgIH1cbiAgICB2YXIgb2Zmc2V0ID0gW1xuICAgICAgICAzICogTWF0aC5zaW4oKG0uZGlyZWN0aW9uIC8gMTgwKSAqIE1hdGguUEkpLFxuICAgICAgICAzICogTWF0aC5jb3MoKG0uZGlyZWN0aW9uIC8gMTgwKSAqIE1hdGguUEkpLFxuICAgICAgICBnZXRPZmZzZXRaKG0ucnVuTW9kZSksXG4gICAgXTtcbiAgICBhYy5rZWVwT2Zmc2V0RnJvbUFjdG9yKGFjLCBvZmZzZXRbMF0sIG9mZnNldFsxXSwgb2Zmc2V0WzJdLCAwLCAwLCBvZmZzZXRBbmdsZSwgbS5ydW5Nb2RlID09PSBcIldhbGtpbmdcIiA/IDIwNDggOiAxLCAxKTtcbn07XG52YXIgZ2V0T2Zmc2V0WiA9IGZ1bmN0aW9uIChydW5Nb2RlKSB7XG4gICAgc3dpdGNoIChydW5Nb2RlKSB7XG4gICAgICAgIGNhc2UgXCJXYWxraW5nXCI6XG4gICAgICAgICAgICByZXR1cm4gLTUxMjtcbiAgICAgICAgY2FzZSBcIlJ1bm5pbmdcIjpcbiAgICAgICAgICAgIHJldHVybiAtMTAyNDtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG59O1xudmFyIGFwcGx5U3ByaW50aW5nID0gZnVuY3Rpb24gKGFjLCBpc1NwcmludGluZykge1xuICAgIGlmIChhYy5pc1NwcmludGluZygpICE9IGlzU3ByaW50aW5nKSB7XG4gICAgICAgIERlYnVnLnNlbmRBbmltYXRpb25FdmVudChhYywgaXNTcHJpbnRpbmcgPyBcIlNwcmludFN0YXJ0XCIgOiBcIlNwcmludFN0b3BcIik7XG4gICAgfVxufTtcbnZhciBhcHBseUJsb2NraW5nID0gZnVuY3Rpb24gKGFjLCBtKSB7XG4gICAgaWYgKGFjLmdldEFuaW1hdGlvblZhcmlhYmxlQm9vbChcIklzQmxvY2tpbmdcIikgIT0gbS5pc0Jsb2NraW5nKSB7XG4gICAgICAgIERlYnVnLnNlbmRBbmltYXRpb25FdmVudChhYywgbS5pc0Jsb2NraW5nID8gXCJCbG9ja1N0YXJ0XCIgOiBcIkJsb2NrU3RvcFwiKTtcbiAgICAgICAgRGVidWcuc2VuZEFuaW1hdGlvbkV2ZW50KGFjLCBtLmlzU25lYWtpbmcgPyBcIlNuZWFrU3RhcnRcIiA6IFwiU25lYWtTdG9wXCIpO1xuICAgIH1cbn07XG52YXIgYXBwbHlTbmVha2luZyA9IGZ1bmN0aW9uIChhYywgaXNTbmVha2luZykge1xuICAgIHZhciBjdXJyZW50SXNTbmVha2luZyA9IGFjLmlzU25lYWtpbmcoKSB8fCBhYy5nZXRBbmltYXRpb25WYXJpYWJsZUJvb2woXCJJc1NuZWFraW5nXCIpO1xuICAgIGlmIChjdXJyZW50SXNTbmVha2luZyAhPSBpc1NuZWFraW5nKSB7XG4gICAgICAgIERlYnVnLnNlbmRBbmltYXRpb25FdmVudChhYywgaXNTbmVha2luZyA/IFwiU25lYWtTdGFydFwiIDogXCJTbmVha1N0b3BcIik7XG4gICAgfVxufTtcbmV4cG9ydCB2YXIgYXBwbHlXZWFwRHJhd24gPSBmdW5jdGlvbiAoYWMsIGlzV2VhcERyYXduKSB7XG4gICAgaWYgKGFjLmlzV2VhcG9uRHJhd24oKSAhPT0gaXNXZWFwRHJhd24pIHtcbiAgICAgICAgVEVTTW9kUGxhdGZvcm0uc2V0V2VhcG9uRHJhd25Nb2RlKGFjLCBpc1dlYXBEcmF3biA/IDEgOiAwKTtcbiAgICB9XG59O1xudmFyIGFwcGx5SGVhbHRoUGVyY2VudGFnZSA9IGZ1bmN0aW9uIChhYywgaGVhbHRoUGVyY2VudGFnZSkge1xuICAgIHZhciBjdXJyZW50UGVyY2VudGFnZSA9IGFjLmdldEFjdG9yVmFsdWVQZXJjZW50YWdlKCdoZWFsdGgnKTtcbiAgICBpZiAoY3VycmVudFBlcmNlbnRhZ2UgPT09IGhlYWx0aFBlcmNlbnRhZ2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgY3VycmVudE1heCA9IGFjLmdldEJhc2VBY3RvclZhbHVlKCdoZWFsdGgnKTtcbiAgICB2YXIgZGVsdGFQZXJjZW50YWdlID0gaGVhbHRoUGVyY2VudGFnZSAtIGN1cnJlbnRQZXJjZW50YWdlO1xuICAgIHZhciBrID0gMC4yNTtcbiAgICBpZiAoZGVsdGFQZXJjZW50YWdlID4gMCkge1xuICAgICAgICBhYy5yZXN0b3JlQWN0b3JWYWx1ZSgnaGVhbHRoJywgZGVsdGFQZXJjZW50YWdlICogY3VycmVudE1heCAqIGspO1xuICAgIH1cbiAgICBlbHNlIGlmIChkZWx0YVBlcmNlbnRhZ2UgPCAwKSB7XG4gICAgICAgIGFjLmRhbWFnZUFjdG9yVmFsdWUoJ2hlYWx0aCcsIGRlbHRhUGVyY2VudGFnZSAqIGN1cnJlbnRNYXggKiBrKTtcbiAgICB9XG59O1xuLy8gVXNlIGdsb2JhbCB0ZW1wIHZhciB0byBhdm9pZCBhbGxvY2F0aW9uIG9mIGFuIGFycmF5IG9uIGVhY2ggdHJhbnNsYXRlVG9cbnZhciBnVGVtcFRhcmdldFBvcyA9IFswLCAwLCAwXTtcbnZhciB0cmFuc2xhdGVUbyA9IGZ1bmN0aW9uIChyZWZyLCBtKSB7XG4gICAgdmFyIF9hO1xuICAgIHZhciB0aW1lID0gMC4yO1xuICAgIGlmIChtLmlzSW5KdW1wU3RhdGUgfHwgbS5ydW5Nb2RlICE9PSBcIlN0YW5kaW5nXCIpIHtcbiAgICAgICAgdGltZSA9IDAuMjtcbiAgICB9XG4gICAgLy8gTG9jYWwgbGFnIGNvbXBlbnNhdGlvblxuICAgIC8vIFRPRE86IFJlbW92ZSBcInx8IDBcIiBoYWNrIChhZGRlZCB0byBzdXBwb3J0IG9sZCBNcENsaWVudFBsdWdpbilcbiAgICB2YXIgZGlzdGFuY2VBZGQgPSAobS5zcGVlZCB8fCAwKSAqIHRpbWU7XG4gICAgdmFyIGRpcmVjdGlvbiA9IG0ucm90WzJdICsgbS5kaXJlY3Rpb247XG4gICAgZ1RlbXBUYXJnZXRQb3NbMF0gPSBtLnBvc1swXTtcbiAgICBnVGVtcFRhcmdldFBvc1sxXSA9IG0ucG9zWzFdO1xuICAgIGdUZW1wVGFyZ2V0UG9zWzJdID0gbS5wb3NbMl07XG4gICAgLy8gV2UgZG8gbm90IHdhbnQgdG8gYWRkIHBvcyBpbiBjYXNlIG9mIHN0YW5kaW5nLWp1bXBpbmdcbiAgICBpZiAobS5ydW5Nb2RlICE9PSBcIlN0YW5kaW5nXCIpIHtcbiAgICAgICAgZ1RlbXBUYXJnZXRQb3NbMF0gKz0gTWF0aC5zaW4oZGlyZWN0aW9uIC8gMTgwICogTWF0aC5QSSkgKiBkaXN0YW5jZUFkZDtcbiAgICAgICAgZ1RlbXBUYXJnZXRQb3NbMV0gKz0gTWF0aC5jb3MoZGlyZWN0aW9uIC8gMTgwICogTWF0aC5QSSkgKiBkaXN0YW5jZUFkZDtcbiAgICB9XG4gICAgdmFyIHJlZnJSZWFsUG9zID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0UG9zKHJlZnIpO1xuICAgIHZhciBkaXN0YW5jZSA9IE9iamVjdFJlZmVyZW5jZUV4LmdldERpc3RhbmNlKHJlZnJSZWFsUG9zLCBnVGVtcFRhcmdldFBvcyk7XG4gICAgdmFyIHNwZWVkID0gZGlzdGFuY2UgLyB0aW1lO1xuICAgIHZhciBhbmdsZURpZmYgPSBNYXRoLmFicyhtLnJvdFsyXSAtIHJlZnIuZ2V0QW5nbGVaKCkpO1xuICAgIGlmIChtLnJ1bk1vZGUgIT09IFwiU3RhbmRpbmdcIiB8fFxuICAgICAgICBtLmlzSW5KdW1wU3RhdGUgfHxcbiAgICAgICAgT2JqZWN0UmVmZXJlbmNlRXguZ2V0RGlzdGFuY2VOb1oocmVmclJlYWxQb3MsIGdUZW1wVGFyZ2V0UG9zKSA+IDggfHxcbiAgICAgICAgYW5nbGVEaWZmID4gODAgfHxcbiAgICAgICAgKChfYSA9IEFjdG9yLmZyb20ocmVmcikpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRTaXRTdGF0ZSgpKSA9PT0gMykge1xuICAgICAgICB2YXIgYWN0b3IgPSBBY3Rvci5mcm9tKHJlZnIpO1xuICAgICAgICBpZiAoYWN0b3IgJiYgYWN0b3IuZ2V0QWN0b3JWYWx1ZShcIlZhcmlhYmxlMTBcIikgPCAtOTk5KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFhY3RvciB8fCAhYWN0b3IuaXNEZWFkKCkpIHtcbiAgICAgICAgICAgIHJlZnIudHJhbnNsYXRlVG8oZ1RlbXBUYXJnZXRQb3NbMF0sIGdUZW1wVGFyZ2V0UG9zWzFdLCBnVGVtcFRhcmdldFBvc1syXSwgbS5yb3RbMF0sIG0ucm90WzFdLCBtLnJvdFsyXSwgc3BlZWQsIDApO1xuICAgICAgICB9XG4gICAgfVxufTtcbnZhciB0ZWxlcG9ydElmTmVlZCA9IGZ1bmN0aW9uIChyZWZyLCBtKSB7XG4gICAgaWYgKGlzSW5EaWZmZXJlbnRXb3JsZE9yQ2VsbChyZWZyLCBtLndvcmxkT3JDZWxsKSB8fFxuICAgICAgICAoIXJlZnIuaXMzRExvYWRlZCgpICYmIGlzSW5EaWZmZXJlbnRFeHRlcmlvckNlbGwocmVmciwgbS5wb3MpKSkge1xuICAgICAgICB0aHJvdyBuZXcgUmVzcGF3bk5lZWRlZEVycm9yKFwibmVlZHMgdG8gYmUgcmVzcGF3bmVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xudmFyIGNlbGxXaWR0aCA9IDQwOTY7XG52YXIgaXNJbkRpZmZlcmVudEV4dGVyaW9yQ2VsbCA9IGZ1bmN0aW9uIChyZWZyLCBwb3MpIHtcbiAgICB2YXIgY3VycmVudFBvcyA9IE9iamVjdFJlZmVyZW5jZUV4LmdldFBvcyhyZWZyKTtcbiAgICB2YXIgcGxheWVyUG9zID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0UG9zKEdhbWUuZ2V0UGxheWVyKCkpO1xuICAgIHZhciB0YXJnZXREaXN0YW5jZVRvUGxheWVyID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0RGlzdGFuY2UocGxheWVyUG9zLCBwb3MpO1xuICAgIHZhciBjdXJyZW50RGlzdGFuY2VUb1BsYXllciA9IE9iamVjdFJlZmVyZW5jZUV4LmdldERpc3RhbmNlKHBsYXllclBvcywgY3VycmVudFBvcyk7XG4gICAgcmV0dXJuIGN1cnJlbnREaXN0YW5jZVRvUGxheWVyID4gY2VsbFdpZHRoICYmIHRhcmdldERpc3RhbmNlVG9QbGF5ZXIgPD0gY2VsbFdpZHRoO1xufTtcbnZhciBpc0luRGlmZmVyZW50V29ybGRPckNlbGwgPSBmdW5jdGlvbiAocmVmciwgd29ybGRPckNlbGwpIHtcbiAgICByZXR1cm4gd29ybGRPckNlbGwgIT09IE9iamVjdFJlZmVyZW5jZUV4LmdldFdvcmxkT3JDZWxsKHJlZnIpO1xufTtcbiIsImltcG9ydCB7IEFjdG9yLCBURVNNb2RQbGF0Zm9ybSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgT2JqZWN0UmVmZXJlbmNlRXggfSBmcm9tICcuLi9leHRlbnNpb25zL29iamVjdFJlZmVyZW5jZUV4JztcbnZhciBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGxheWVyQ2hhcmFjdGVyU3BlZWRDYWxjdWxhdG9yKCkge1xuICAgIH1cbiAgICBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3Iuc2F2ZVBvc2l0aW9uID0gZnVuY3Rpb24gKHBvcywgd29ybGRPckNlbGwpIHtcbiAgICAgICAgdGhpcy5sYXN0UGNQb3MgPSBwb3M7XG4gICAgICAgIHRoaXMubGFzdFBjUG9zQ2hlY2sgPSBEYXRlLm5vdygpO1xuICAgICAgICB0aGlzLmxhc3RQY1dvcmxkT3JDZWxsID0gd29ybGRPckNlbGw7XG4gICAgfTtcbiAgICBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3IuZ2V0U3BlZWQgPSBmdW5jdGlvbiAoY3VycmVudFBvcywgd29ybGRPckNlbGwpIHtcbiAgICAgICAgaWYgKHRoaXMubGFzdFBjUG9zQ2hlY2sgPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdGltZURlbHRhU2VjID0gKERhdGUubm93KCkgLSB0aGlzLmxhc3RQY1Bvc0NoZWNrKSAvIDEwMDA7XG4gICAgICAgIGlmICh0aW1lRGVsdGFTZWMgPiA1KVxuICAgICAgICAgICAgcmV0dXJuIDA7IC8vIFRvbyBpbmFjY3VyYXRlXG4gICAgICAgIGlmICh0aW1lRGVsdGFTZWMgPT09IDApXG4gICAgICAgICAgICByZXR1cm4gMDsgLy8gRGl2aXNpb24gYnkgemVyb1xuICAgICAgICBpZiAod29ybGRPckNlbGwgIT09IHRoaXMubGFzdFBjV29ybGRPckNlbGwpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkaXN0YW5jZSA9IE9iamVjdFJlZmVyZW5jZUV4LmdldERpc3RhbmNlKGN1cnJlbnRQb3MsIHRoaXMubGFzdFBjUG9zKTtcbiAgICAgICAgcmV0dXJuIGRpc3RhbmNlIC8gdGltZURlbHRhU2VjO1xuICAgIH07XG4gICAgUGxheWVyQ2hhcmFjdGVyU3BlZWRDYWxjdWxhdG9yLmxhc3RQY1BvcyA9IFswLCAwLCAwXTtcbiAgICBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3IubGFzdFBjUG9zQ2hlY2sgPSAtMTtcbiAgICBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3IubGFzdFBjV29ybGRPckNlbGwgPSAwO1xuICAgIHJldHVybiBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3I7XG59KCkpO1xuZXhwb3J0IHZhciBnZXRNb3ZlbWVudCA9IGZ1bmN0aW9uIChyZWZyLCBmb3JtKSB7XG4gICAgdmFyIF9hO1xuICAgIHZhciBhYyA9IEFjdG9yLmZyb20ocmVmcik7XG4gICAgLy8gSXQgaXMgcnVubmluZyBmb3IgT2JqZWN0UmVmZXJlbmNlcyBiZWNhdXNlIFN0YW5kaW5nXG4gICAgLy8gRG9lc24ndCBsZWFkIHRvIHRyYW5zbGF0ZVRvIGNhbGxcbiAgICB2YXIgcnVuTW9kZSA9IGFjID8gZ2V0UnVuTW9kZShhYykgOiBcIlJ1bm5pbmdcIjtcbiAgICB2YXIgaGVhbHRoUGVyY2VudGFnZSA9IGFjICYmIGFjLmdldEFjdG9yVmFsdWVQZXJjZW50YWdlKFwiaGVhbHRoXCIpO1xuICAgIGlmIChhYyAmJiBhYy5pc0RlYWQoKSkge1xuICAgICAgICBoZWFsdGhQZXJjZW50YWdlID0gMDtcbiAgICB9XG4gICAgdmFyIGxvb2tBdCA9IHVuZGVmaW5lZDtcbiAgICBpZiAocmVmci5nZXRGb3JtSUQoKSAhPT0gMHgxNCkge1xuICAgICAgICB2YXIgY29tYmF0VGFyZ2V0ID0gYWMgPT09IG51bGwgfHwgYWMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGFjLmdldENvbWJhdFRhcmdldCgpO1xuICAgICAgICBpZiAoY29tYmF0VGFyZ2V0KSB7XG4gICAgICAgICAgICBsb29rQXQgPSBbXG4gICAgICAgICAgICAgICAgY29tYmF0VGFyZ2V0LmdldFBvc2l0aW9uWCgpLFxuICAgICAgICAgICAgICAgIGNvbWJhdFRhcmdldC5nZXRQb3NpdGlvblkoKSxcbiAgICAgICAgICAgICAgICBjb21iYXRUYXJnZXQuZ2V0UG9zaXRpb25aKCksXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgfVxuICAgIHZhciBwb3MgPSBPYmplY3RSZWZlcmVuY2VFeC5nZXRQb3MocmVmcik7XG4gICAgdmFyIHNwZWVkO1xuICAgIGlmIChyZWZyLmdldEZvcm1JRCgpICE9PSAweDE0KSB7XG4gICAgICAgIHNwZWVkID0gcmVmci5nZXRBbmltYXRpb25WYXJpYWJsZUZsb2F0KFwiU3BlZWRTYW1wbGVkXCIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gUmVhbCBwbGF5ZXJzIG9mdGVuIHJ1biBpbnRvIHRoZSB3YWxsLlxuICAgICAgICAvLyBXZSBuZWVkIHRvIGhhdmUgemVybyBzcGVlZCBpbiB0aGlzIGNhc2UuIFNwZWVkU2FtcGxlZCBkb2Vzbid0IGhlbHBcbiAgICAgICAgdmFyIHcgPSBPYmplY3RSZWZlcmVuY2VFeC5nZXRXb3JsZE9yQ2VsbChyZWZyKTtcbiAgICAgICAgc3BlZWQgPSBQbGF5ZXJDaGFyYWN0ZXJTcGVlZENhbGN1bGF0b3IuZ2V0U3BlZWQocG9zLCB3KTtcbiAgICAgICAgUGxheWVyQ2hhcmFjdGVyU3BlZWRDYWxjdWxhdG9yLnNhdmVQb3NpdGlvbihwb3MsIHcpO1xuICAgICAgICAvLyBJdCdzIHVucmVhbGlzdGljIHNwZWVkLiBJdCBzdGlsbCBtYXkgaGFwcGVuIGR1ZSB0byB0ZWxlcG9ydHNcbiAgICAgICAgaWYgKHNwZWVkID4gMjAwMCkge1xuICAgICAgICAgICAgc3BlZWQgPSAwO1xuICAgICAgICB9XG4gICAgfVxuICAgIHZhciB3b3JsZE9yQ2VsbCA9IHJlZnIuZ2V0V29ybGRTcGFjZSgpIHx8IHJlZnIuZ2V0UGFyZW50Q2VsbCgpO1xuICAgIC8vIEVsZGVydmFsZSBQYXJ0ZSAyIChPcGNpw7NuIEQsIFBST1RPVElQTyk6IHNpIEVTVEUganVnYWRvciBsb2NhbCBlc3TDoSBtb250YWRvIChzdSBjYWJhbGxvXG4gICAgLy8gQ0xJRU5ULUxPQ0FMIGRlIGxhIFBhcnRlIDEpLCByZXBvcnRhbW9zIGVsIEJBU0UgaWQgZGVsIGNhYmFsbG8gKGZvcm1pZCBiYXNlLCB1bml2ZXJzYWwgZW5cbiAgICAvLyB0b2RvcyBsb3MgY2xpZW50ZXMpLiBDYWRhIG9ic2VydmFkb3Igc3Bhd25lYSBzdSBQUk9QSU8gY2FiYWxsbyBsb2NhbCBjb24gZXNlIGJhc2UgeSBub3Mgc2llbnRhXG4gICAgLy8gZW5jaW1hLiBSZXVzYW1vcyBlbCBjYW1wbyB2ZWhpY2xlRm9ybUlkIGNvbW8gXCJiYXNlSWRcIiBTT0xPIGVuIGVsIHByb3RvdGlwbzsgZWwgY29uc3VtaWRvciBlblxuICAgIC8vIG1vdmVtZW50QXBwbHkgbG8gaW50ZXJwcmV0YSBhc8OtLiAoRWwgZGlzZcOxbyBmaW5hbCB1c2Fyw6EgdW4gY2FtcG8gbW91bnRlZEJhc2VJZCBwcm9waW8uKVxuICAgIHZhciB2ZWhpY2xlRm9ybUlkID0gdW5kZWZpbmVkO1xuICAgIGlmIChhYyAmJiByZWZyLmdldEZvcm1JRCgpID09PSAweDE0ICYmIGFjLmlzT25Nb3VudCgpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBMYSBtb250dXJhIEFDVFVBTCAoZWwgY2FiYWxsbyBjdWVudGEgY29tbyBmdXJuaXR1cmUpIC0+IG3DoXMgZmlhYmxlIHF1ZVxuICAgICAgICAgICAgLy8gZ2V0UGxheWVyc0xhc3RSaWRkZW5Ib3JzZSAocXVlIHB1ZWRlIHF1ZWRhciBzdGFsZSB0cmFzIGNhbWJpYXIgZGUgbW9udHVyYSkuXG4gICAgICAgICAgICB2YXIgbW91bnQgPSBhYy5nZXRGdXJuaXR1cmVSZWZlcmVuY2UoKTtcbiAgICAgICAgICAgIHZhciBiYXNlID0gbW91bnQgPyBtb3VudC5nZXRCYXNlT2JqZWN0KCkgOiBudWxsO1xuICAgICAgICAgICAgaWYgKGJhc2UpIHtcbiAgICAgICAgICAgICAgICB2YXIgYmFzZUlkID0gYmFzZS5nZXRGb3JtSUQoKSA+Pj4gMDtcbiAgICAgICAgICAgICAgICBpZiAoYmFzZUlkID4gMClcbiAgICAgICAgICAgICAgICAgICAgdmVoaWNsZUZvcm1JZCA9IGJhc2VJZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdmVoaWNsZUZvcm1JZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB3b3JsZE9yQ2VsbDogKHdvcmxkT3JDZWxsID09PSBudWxsIHx8IHdvcmxkT3JDZWxsID09PSB2b2lkIDAgPyB2b2lkIDAgOiB3b3JsZE9yQ2VsbC5nZXRGb3JtSUQoKSkgfHwgMCxcbiAgICAgICAgcG9zOiBwb3MsXG4gICAgICAgIHJvdDogW3JlZnIuZ2V0QW5nbGVYKCksIHJlZnIuZ2V0QW5nbGVZKCksIHJlZnIuZ2V0QW5nbGVaKCldLFxuICAgICAgICBydW5Nb2RlOiBydW5Nb2RlLFxuICAgICAgICBkaXJlY3Rpb246IHJ1bk1vZGUgIT09IFwiU3RhbmRpbmdcIlxuICAgICAgICAgICAgPyAzNjAgKiByZWZyLmdldEFuaW1hdGlvblZhcmlhYmxlRmxvYXQoXCJEaXJlY3Rpb25cIilcbiAgICAgICAgICAgIDogMCxcbiAgICAgICAgaXNJbkp1bXBTdGF0ZTogISEoYWMgJiYgYWMuZ2V0QW5pbWF0aW9uVmFyaWFibGVCb29sKFwiYkluSnVtcFN0YXRlXCIpKSxcbiAgICAgICAgaXNTbmVha2luZzogISEoYWMgJiYgaXNTbmVha2luZyhhYykpLFxuICAgICAgICBpc0Jsb2NraW5nOiAhIShhYyAmJiBhYy5nZXRBbmltYXRpb25WYXJpYWJsZUJvb2woXCJJc0Jsb2NraW5nXCIpKSxcbiAgICAgICAgaXNXZWFwRHJhd246ICEhKGFjICYmIGFjLmlzV2VhcG9uRHJhd24oKSksXG4gICAgICAgIGlzRGVhZDogKChfYSA9IGZvcm0gPT09IG51bGwgfHwgZm9ybSA9PT0gdm9pZCAwID8gdm9pZCAwIDogZm9ybS5pc0RlYWQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGZhbHNlKSB8fCAhIShhYyAmJiBhYy5pc0RlYWQoKSksXG4gICAgICAgIGhlYWx0aFBlcmNlbnRhZ2U6IGhlYWx0aFBlcmNlbnRhZ2UgfHwgMCxcbiAgICAgICAgbG9va0F0OiBsb29rQXQsXG4gICAgICAgIHNwZWVkOiBzcGVlZCxcbiAgICAgICAgdmVoaWNsZUZvcm1JZDogdmVoaWNsZUZvcm1JZFxuICAgIH07XG59O1xudmFyIGlzU25lYWtpbmcgPSBmdW5jdGlvbiAoYWMpIHtcbiAgICByZXR1cm4gYWMuaXNTbmVha2luZygpIHx8IGFjLmdldEFuaW1hdGlvblZhcmlhYmxlQm9vbChcIklzU25lYWtpbmdcIik7XG59O1xudmFyIGdldFJ1bk1vZGUgPSBmdW5jdGlvbiAoYWMpIHtcbiAgICBpZiAoYWMuaXNTcHJpbnRpbmcoKSkge1xuICAgICAgICByZXR1cm4gXCJTcHJpbnRpbmdcIjtcbiAgICB9XG4gICAgdmFyIHNwZWVkID0gYWMuZ2V0QW5pbWF0aW9uVmFyaWFibGVGbG9hdChcIlNwZWVkU2FtcGxlZFwiKTtcbiAgICBpZiAoIXNwZWVkKSB7XG4gICAgICAgIHJldHVybiBcIlN0YW5kaW5nXCI7XG4gICAgfVxuICAgIHZhciBmdXJuaXR1cmUgPSBhYy5nZXRGdXJuaXR1cmVSZWZlcmVuY2UoKTtcbiAgICBpZiAoZnVybml0dXJlICE9PSBudWxsKVxuICAgICAgICByZXR1cm4gXCJTdGFuZGluZ1wiOyAvLyBUT0RPOiBTaXR0aW5nP1xuICAgIHZhciBpc1J1bm5pbmcgPSB0cnVlO1xuICAgIGlmIChhYy5nZXRGb3JtSUQoKSA9PSAweDE0KSB7XG4gICAgICAgIGlmICghVEVTTW9kUGxhdGZvcm0uaXNQbGF5ZXJSdW5uaW5nRW5hYmxlZCgpIHx8IHNwZWVkIDwgMTUwKVxuICAgICAgICAgICAgaXNSdW5uaW5nID0gZmFsc2U7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZiAoIWFjLmlzUnVubmluZygpIHx8IHNwZWVkIDwgMTUwKSB7XG4gICAgICAgICAgICBpc1J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYWMuZ2V0QW5pbWF0aW9uVmFyaWFibGVGbG9hdChcIklzQmxvY2tpbmdcIikpIHtcbiAgICAgICAgaXNSdW5uaW5nID0gaXNTbmVha2luZyhhYyk7XG4gICAgfVxuICAgIHZhciBjYXJyeVdlaWdodCA9IGFjLmdldEFjdG9yVmFsdWUoXCJDYXJyeVdlaWdodFwiKTtcbiAgICB2YXIgdG90YWxJdGVtV2VpZ2h0ID0gYWMuZ2V0VG90YWxJdGVtV2VpZ2h0KCk7XG4gICAgaWYgKGNhcnJ5V2VpZ2h0IDwgdG90YWxJdGVtV2VpZ2h0KSB7XG4gICAgICAgIGlzUnVubmluZyA9IGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gaXNSdW5uaW5nID8gXCJSdW5uaW5nXCIgOiBcIldhbGtpbmdcIjtcbn07XG4iLCJpbXBvcnQgeyBHYW1lLCBTcGVsbCwgcHJpbnRDb25zb2xlIH0gZnJvbSAnc2t5cmltUGxhdGZvcm0nO1xuZXhwb3J0IHZhciByZW1vdmVBbGxTcGVsbHMgPSBmdW5jdGlvbiAoYWN0b3IpIHtcbiAgICB2YXIgc3BlbGxUb1JlbW92ZSA9IG5ldyBBcnJheSgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWN0b3IuZ2V0U3BlbGxDb3VudCgpOyBpKyspIHtcbiAgICAgICAgdmFyIHNwZWxsID0gYWN0b3IuZ2V0TnRoU3BlbGwoaSk7XG4gICAgICAgIGlmIChzcGVsbCkge1xuICAgICAgICAgICAgc3BlbGxUb1JlbW92ZS5wdXNoKHNwZWxsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBfaSA9IDAsIHNwZWxsVG9SZW1vdmVfMSA9IHNwZWxsVG9SZW1vdmU7IF9pIDwgc3BlbGxUb1JlbW92ZV8xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc3BlbGwgPSBzcGVsbFRvUmVtb3ZlXzFbX2ldO1xuICAgICAgICB2YXIgcmVtb3ZlUmVzdWx0ID0gYWN0b3IucmVtb3ZlU3BlbGwoc3BlbGwpO1xuICAgICAgICBwcmludENvbnNvbGUoXCJyZW1vdmVSZXN1bHQ6IFwiLmNvbmNhdChyZW1vdmVSZXN1bHQsIFwiLCBzcGVsbElkVG9SZW1vdmU6IFwiKS5jb25jYXQoc3BlbGxcbiAgICAgICAgICAgIC5nZXRGb3JtSUQoKVxuICAgICAgICAgICAgLnRvU3RyaW5nKDE2KSwgXCIsIHNwZWxsTmFtZTogXCIpLmNvbmNhdChzcGVsbC5nZXROYW1lKCkpKTtcbiAgICB9XG59O1xuZXhwb3J0IHZhciBsZWFyblNwZWxscyA9IGZ1bmN0aW9uIChhY3Rvciwgc3BlbGxzSWRzKSB7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBzcGVsbHNJZHNfMSA9IHNwZWxsc0lkczsgX2kgPCBzcGVsbHNJZHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHNwZWxsSWQgPSBzcGVsbHNJZHNfMVtfaV07XG4gICAgICAgIHZhciBzcGVsbCA9IFNwZWxsLmZyb20oR2FtZS5nZXRGb3JtRXgoc3BlbGxJZCkpO1xuICAgICAgICBpZiAoc3BlbGwpIHtcbiAgICAgICAgICAgIHZhciBhZGRSZXN1bHQgPSBhY3Rvci5hZGRTcGVsbChzcGVsbCwgZmFsc2UpO1xuICAgICAgICAgICAgcHJpbnRDb25zb2xlKFwiYWRkUmVzdWx0OiBcIi5jb25jYXQoYWRkUmVzdWx0LCBcIiwgc3BlbGxJZFRvTGVhcm46IFwiKS5jb25jYXQoc3BlbGxcbiAgICAgICAgICAgICAgICAuZ2V0Rm9ybUlEKClcbiAgICAgICAgICAgICAgICAudG9TdHJpbmcoMTYpLCBcIiwgc3BlbGxOYW1lOiBcIikuY29uY2F0KHNwZWxsLmdldE5hbWUoKSkpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsImltcG9ydCB7IFV0aWxpdHksIERlYnVnLCBnZXRQbGF0Zm9ybVZlcnNpb24sIG9uLCBHYW1lLCBVaSB9IGZyb20gJ3NreXJpbVBsYXRmb3JtJztcbmV4cG9ydCB2YXIgcmVxdWlyZWRWZXJzaW9uID0gJzIuOS4wJztcbnZhciByZWFsVmVyc2lvbiA9IHR5cGVvZiBnZXRQbGF0Zm9ybVZlcnNpb24gPT09ICdmdW5jdGlvbicgPyBnZXRQbGF0Zm9ybVZlcnNpb24oKSA6ICd1bmtub3duJztcbi8vIFRPRE86IG5vIG9uZSBhY3R1YWxseSBjYWxscyB0aGlzIGZ1bmN0aW9uLiBtYWtlIGEgc2VydmljZVxuZXhwb3J0IHZhciB2ZXJpZnlWZXJzaW9uID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghcmVxdWlyZWRWZXJzaW9uLmluY2x1ZGVzKHJlYWxWZXJzaW9uKSkge1xuICAgICAgICBEZWJ1Zy5tZXNzYWdlQm94KFwiWW91IG5lZWQgdG8gaGF2ZSBvbiBvZiB0aG9zZSBTa3lyaW1QbGF0Zm9ybSB2ZXJzaW9ucyBcIi5jb25jYXQoSlNPTi5zdHJpbmdpZnkocmVxdWlyZWRWZXJzaW9uKSwgXCIgdG8gam9pbiB0aGlzIHNlcnZlci4gWW91ciBjdXJyZW50IHZlcnNpb24gaXMgXCIpLmNvbmNhdChyZWFsVmVyc2lvbikpO1xuICAgICAgICBVdGlsaXR5LndhaXRNZW51TW9kZSgwLjUpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb24oJ3VwZGF0ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIVVpLmlzTWVudU9wZW4oJ01lc3NhZ2VCb3hNZW51JykpIHtcbiAgICAgICAgICAgICAgICAgICAgR2FtZS5xdWl0VG9NYWluTWVudSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiaW1wb3J0IHsgQWN0b3IsIEFjdG9yQmFzZSwgY3JlYXRlVGV4dCwgZGVzdHJveVRleHQsIEdhbWUsIEtleXdvcmQsIE5ldEltbWVyc2UsIE9iamVjdFJlZmVyZW5jZSwgb25jZSwgcHJpbnRDb25zb2xlLCBzZXRUZXh0UG9zLCBzZXRUZXh0U2l6ZSwgc3RvcmFnZSwgVEVTTW9kUGxhdGZvcm0sIFV0aWxpdHksIHdvcmxkUG9pbnRUb1NjcmVlblBvaW50IH0gZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG5pbXBvcnQgeyBzZXREZWZhdWx0QW5pbXNEaXNhYmxlZCwgYXBwbHlBbmltYXRpb24gfSBmcm9tIFwiLi4vc3luYy9hbmltYXRpb25cIjtcbmltcG9ydCB7IGFwcGx5QXBwZWFyYW5jZSB9IGZyb20gXCIuLi9zeW5jL2FwcGVhcmFuY2VcIjtcbmltcG9ydCB7IGlzQmFkTWVudVNob3duLCBhcHBseUVxdWlwbWVudCB9IGZyb20gXCIuLi9zeW5jL2VxdWlwbWVudFwiO1xuaW1wb3J0IHsgUmVzcGF3bk5lZWRlZEVycm9yIH0gZnJvbSBcIi4uL2xpYi9lcnJvcnNcIjtcbmltcG9ydCB7IGFwcGx5TW92ZW1lbnQsIGRlc3Ryb3lQcm94eU1vdW50Rm9yUmlkZXIgfSBmcm9tIFwiLi4vc3luYy9tb3ZlbWVudEFwcGx5XCI7XG5pbXBvcnQgeyBTcGF3blByb2Nlc3MgfSBmcm9tIFwiLi9zcGF3blByb2Nlc3NcIjtcbmltcG9ydCB7IE9iamVjdFJlZmVyZW5jZUV4IH0gZnJvbSBcIi4uL2V4dGVuc2lvbnMvb2JqZWN0UmVmZXJlbmNlRXhcIjtcbmltcG9ydCB7IFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIgfSBmcm9tIFwiLi9wbGF5ZXJDaGFyYWN0ZXJEYXRhSG9sZGVyXCI7XG5pbXBvcnQgeyBnZXRNb3ZlbWVudCB9IGZyb20gXCIuLi9zeW5jL21vdmVtZW50R2V0XCI7XG5pbXBvcnQgeyBsYXN0VHJ5SG9zdCwgdHJ5SG9zdCB9IGZyb20gXCIuL2hvc3RBdHRlbXB0c1wiO1xuaW1wb3J0IHsgTW9kZWxBcHBseVV0aWxzIH0gZnJvbSBcIi4vbW9kZWxBcHBseVV0aWxzXCI7XG5pbXBvcnQgeyBsb2NhbElkVG9SZW1vdGVJZCB9IGZyb20gXCIuL3dvcmxkVmlld01pc2NcIjtcbmltcG9ydCB7IFNwQXBpSW50ZXJhY3RvciB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zcEFwaUludGVyYWN0b3JcIjtcbmltcG9ydCB7IFdvcmxkQ2xlYW5lclNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvc2VydmljZXMvd29ybGRDbGVhbmVyU2VydmljZVwiO1xuaW1wb3J0IHsgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL3NlcnZpY2VzL2dhbWVtb2RlVXBkYXRlU2VydmljZVwiO1xudmFyIF9zY3JlZW5SZXNvbHV0aW9uO1xuZXhwb3J0IHZhciBnZXRTY3JlZW5SZXNvbHV0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghX3NjcmVlblJlc29sdXRpb24pIHtcbiAgICAgICAgX3NjcmVlblJlc29sdXRpb24gPSB7XG4gICAgICAgICAgICB3aWR0aDogVXRpbGl0eS5nZXRJTklJbnQoXCJpU2l6ZSBXOkRpc3BsYXlcIiksXG4gICAgICAgICAgICBoZWlnaHQ6IFV0aWxpdHkuZ2V0SU5JSW50KFwiaVNpemUgSDpEaXNwbGF5XCIpLFxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gX3NjcmVlblJlc29sdXRpb247XG59O1xudmFyIEZvcm1WaWV3ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZvcm1WaWV3KHJlbW90ZVJlZnJJZCkge1xuICAgICAgICB0aGlzLnJlbW90ZVJlZnJJZCA9IHJlbW90ZVJlZnJJZDtcbiAgICAgICAgdGhpcy5sYXN0SGFydmVzdGVkQXBwbHkgPSAwO1xuICAgICAgICB0aGlzLmxhc3RPcGVuQXBwbHkgPSAwO1xuICAgICAgICB0aGlzLmlzU2V0Tm9kZVRleHR1cmVTZXRBcHBsaWVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNTZXROb2RlU2NhbGVBcHBsaWVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVmcklkID0gMDtcbiAgICAgICAgdGhpcy5yZWFkeSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFuaW1TdGF0ZSA9IHRoaXMuZ2V0RGVmYXVsdEFuaW1TdGF0ZSgpO1xuICAgICAgICB0aGlzLm1vdlN0YXRlID0ge1xuICAgICAgICAgICAgbGFzdE51bUNoYW5nZXM6IDAsXG4gICAgICAgICAgICBsYXN0QXBwbHk6IDAsXG4gICAgICAgICAgICBsYXN0UmVob3N0OiAwLFxuICAgICAgICAgICAgZXZlckFwcGxpZWQ6IGZhbHNlLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFwcGVhcmFuY2VTdGF0ZSA9IHRoaXMuZ2V0RGVmYXVsdEFwcGVhcmFuY2VTdGF0ZSgpO1xuICAgICAgICB0aGlzLmVxU3RhdGUgPSB0aGlzLmdldERlZmF1bHRFcXVpcFN0YXRlKCk7XG4gICAgICAgIHRoaXMuYXBwZWFyYW5jZUJhc2VkQmFzZUlkID0gMDtcbiAgICAgICAgdGhpcy5sZXZlbGVkQmFzZUlkID0gMDtcbiAgICAgICAgdGhpcy5pc09uU2NyZWVuID0gZmFsc2U7XG4gICAgICAgIHRoaXMubGFzdFBjV29ybGRPckNlbGwgPSAwO1xuICAgICAgICB0aGlzLmxhc3RXb3JsZE9yQ2VsbCA9IDA7XG4gICAgICAgIHRoaXMuc3Bhd25Nb21lbnQgPSAwO1xuICAgICAgICB0aGlzLndhc0hvc3RlZEJ5T3RoZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7fTtcbiAgICAgICAgdGhpcy5sb2NhbEltbW9ydGFsID0gZmFsc2U7XG4gICAgICAgIHRoaXMudGV4dE5hbWVJZCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgRm9ybVZpZXcucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChtb2RlbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lLCBfZiwgX2csIF9oO1xuICAgICAgICAvLyBPdGhlciBwbGF5ZXJzIG11dGF0ZSBpbnRvIFBDIGNsb25lcyB3aGVuIG1vdmluZyB0byBhbm90aGVyIGxvY2F0aW9uXG4gICAgICAgIGlmIChtb2RlbC5tb3ZlbWVudCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmxhc3RXb3JsZE9yQ2VsbClcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RXb3JsZE9yQ2VsbCA9IG1vZGVsLm1vdmVtZW50LndvcmxkT3JDZWxsO1xuICAgICAgICAgICAgaWYgKHRoaXMubGFzdFdvcmxkT3JDZWxsICE9PSBtb2RlbC5tb3ZlbWVudC53b3JsZE9yQ2VsbCkge1xuICAgICAgICAgICAgICAgIHByaW50Q29uc29sZShcIlsxXSB3b3JsZE9yQ2VsbCBjaGFuZ2VkLCBkZXN0cm95aW5nIEZvcm1WaWV3IFwiLmNvbmNhdCh0aGlzLmxhc3RXb3JsZE9yQ2VsbC50b1N0cmluZygxNiksIFwiID0+IFwiKS5jb25jYXQobW9kZWwubW92ZW1lbnQud29ybGRPckNlbGwudG9TdHJpbmcoMTYpKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0V29ybGRPckNlbGwgPSBtb2RlbC5tb3ZlbWVudC53b3JsZE9yQ2VsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZnJJZCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5hcHBlYXJhbmNlQmFzZWRCYXNlSWQgPSAwO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBEb24ndCBzcGF3biBkZWFkIGFjdG9ycyBpZiBub3QgYWxyZWFkeVxuICAgICAgICBpZiAobW9kZWwuaXNEZWFkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWZySWQgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gUGxheWVycyB3aXRoIGRpZmZlcmVudCB3b3JsZE9yQ2VsbCBzaG91bGQgYmUgaW52aXNpYmxlXG4gICAgICAgIGlmIChtb2RlbC5tb3ZlbWVudCkge1xuICAgICAgICAgICAgdmFyIHdvcmxkT3JDZWxsID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0V29ybGRPckNlbGwoR2FtZS5nZXRQbGF5ZXIoKSk7XG4gICAgICAgICAgICBpZiAod29ybGRPckNlbGwgIT09IDAgJiZcbiAgICAgICAgICAgICAgICBtb2RlbC5tb3ZlbWVudC53b3JsZE9yQ2VsbCAhPT0gd29ybGRPckNlbGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZnJJZCA9IDA7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEFwcGx5IGFwcGVhcmFuY2UgYmVmb3JlIGJhc2UgZm9ybSBzZWxlY3Rpb24gdG8gcHJldmVudCBkb3VibGUtc3Bhd25cbiAgICAgICAgaWYgKG1vZGVsLmFwcGVhcmFuY2UgfHwgKCFtb2RlbC5hcHBlYXJhbmNlICYmIHRoaXMuYXBwZWFyYW5jZVN0YXRlLmFwcGVhcmFuY2UpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZVN0YXRlLmFwcGVhcmFuY2UgfHxcbiAgICAgICAgICAgICAgICBtb2RlbC5udW1BcHBlYXJhbmNlQ2hhbmdlcyAhPT0gdGhpcy5hcHBlYXJhbmNlU3RhdGUubGFzdE51bUNoYW5nZXMpIHtcbiAgICAgICAgICAgICAgICAvLyBCb3RoIG5vbi1udWxsXG4gICAgICAgICAgICAgICAgaWYgKG1vZGVsLmFwcGVhcmFuY2UgJiYgdGhpcy5hcHBlYXJhbmNlU3RhdGUuYXBwZWFyYW5jZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbW9kZWxBcHBlYXJhbmNlQ29weSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkobW9kZWwuYXBwZWFyYW5jZSkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3RhdGVBcHBlYXJhbmNlQ29weSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5hcHBlYXJhbmNlU3RhdGUuYXBwZWFyYW5jZSkpO1xuICAgICAgICAgICAgICAgICAgICBtb2RlbEFwcGVhcmFuY2VDb3B5Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZUFwcGVhcmFuY2VDb3B5Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXF1YWxXaXRob3V0TmFtZXMgPSBKU09OLnN0cmluZ2lmeShtb2RlbEFwcGVhcmFuY2VDb3B5KSA9PT0gSlNPTi5zdHJpbmdpZnkoc3RhdGVBcHBlYXJhbmNlQ29weSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcXVhbFdpdGhvdXROYW1lcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hhbmdlIG5hbWUgaW5wbGFjZVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlZnJfMSA9IE9iamVjdFJlZmVyZW5jZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHRoaXMucmVmcklkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAoX2EgPSByZWZyXzEgPT09IG51bGwgfHwgcmVmcl8xID09PSB2b2lkIDAgPyB2b2lkIDAgOiByZWZyXzEuZ2V0QmFzZU9iamVjdCgpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Euc2V0TmFtZShtb2RlbC5hcHBlYXJhbmNlLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVmcl8xID09PSBudWxsIHx8IHJlZnJfMSA9PT0gdm9pZCAwID8gdm9pZCAwIDogcmVmcl8xLnNldERpc3BsYXlOYW1lKG1vZGVsLmFwcGVhcmFuY2UubmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvL3ByaW50Q29uc29sZShcIkFwcGVhcmFuY2UgdXBkYXRlZCwgY2hhbmdpbmcgbmFtZSBpbnBsYWNlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9yY2UgcmUtYXBwbHkgYXBwZWFyYW5jZSBvbiB0aGUgbmV4dCBnZXRBcHBlYXJhbmNlQmFzZWRCYXNlIGNhbGxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXBwZWFyYW5jZUJhc2VkQmFzZUlkID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vcHJpbnRDb25zb2xlKFwiQXBwZWFyYW5jZSB1cGRhdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBGb3JjZSByZS1hcHBseSBhcHBlYXJhbmNlIG9uIHRoZSBuZXh0IGdldEFwcGVhcmFuY2VCYXNlZEJhc2UgY2FsbFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFwcGVhcmFuY2VCYXNlZEJhc2VJZCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIC8vcHJpbnRDb25zb2xlKFwiQXBwZWFyYW5jZSB1cGRhdGVkXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmFwcGVhcmFuY2VTdGF0ZS5hcHBlYXJhbmNlID0gbW9kZWwuYXBwZWFyYW5jZSB8fCBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuYXBwZWFyYW5jZVN0YXRlLmxhc3ROdW1DaGFuZ2VzID0gbW9kZWwubnVtQXBwZWFyYW5jZUNoYW5nZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlZklkID0gbW9kZWwucmVmcklkICYmIG1vZGVsLnJlZnJJZCA8IDB4ZmYwMDAwMDAgPyBtb2RlbC5yZWZySWQgOiB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChyZWZJZCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVmcklkICE9PSByZWZJZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVmcklkID0gbW9kZWwucmVmcklkO1xuICAgICAgICAgICAgICAgIHRoaXMucmVhZHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciByZWZyXzIgPSBPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm1FeCh0aGlzLnJlZnJJZCkpO1xuICAgICAgICAgICAgICAgIGlmIChyZWZyXzIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJhc2UgPSByZWZyXzIuZ2V0QmFzZU9iamVjdCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0UmVmZXJlbmNlRXguZGVhbFdpdGhSZWYocmVmcl8yLCBiYXNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciB0ZW1wbGF0ZUNoYWluID0gbW9kZWwudGVtcGxhdGVDaGFpbjtcbiAgICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIHBsYWNlIGZvciByYW5kb20vbGV2ZWxpbmcgaW4gMS1zaXplZCBjaGFpblxuICAgICAgICAgICAgLy8gSnVzdCBzcGF3biBhbiBOUEMsIGRvIG5vdCBnZW5lcmF0ZSBhIHRlbXBvcmFyeSBURVNOUEMgZm9ybVxuICAgICAgICAgICAgaWYgKCh0ZW1wbGF0ZUNoYWluID09PSBudWxsIHx8IHRlbXBsYXRlQ2hhaW4gPT09IHZvaWQgMCA/IHZvaWQgMCA6IHRlbXBsYXRlQ2hhaW4ubGVuZ3RoKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlQ2hhaW4gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUT0RPOiBnZXRMZXZlbGVkQmFzZSBjcmFzaGVzIHRvbyBvZnRlbiBBVE1cbiAgICAgICAgICAgIHZhciBiYXNlID0gbnVsbDsgLy9HYW1lLmdldEZvcm1FeCh0aGlzLmdldExldmVsZWRCYXNlKHRlbXBsYXRlQ2hhaW4pKTtcbiAgICAgICAgICAgIGlmIChiYXNlID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYmFzZSA9IEdhbWUuZ2V0Rm9ybUV4KG1vZGVsLmJhc2VJZCB8fCBOYU4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJhc2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBiYXNlID0gR2FtZS5nZXRGb3JtRXgodGhpcy5nZXRBcHBlYXJhbmNlQmFzZWRCYXNlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJhc2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmVmcl8zID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgodGhpcy5yZWZySWQpKTtcbiAgICAgICAgICAgIHZhciByZXNwYXduUmVxdWlyZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICghcmVmcl8zKSB7XG4gICAgICAgICAgICAgICAgcmVzcGF3blJlcXVpcmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFyZWZyXzMuZ2V0QmFzZU9iamVjdCgpKSB7XG4gICAgICAgICAgICAgICAgcmVzcGF3blJlcXVpcmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJlZnJfMy5nZXRCYXNlT2JqZWN0KCkuZ2V0Rm9ybUlEKCkgIT09IGJhc2UuZ2V0Rm9ybUlEKCkpIHtcbiAgICAgICAgICAgICAgICByZXNwYXduUmVxdWlyZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3Bhd25SZXF1aXJlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIHZhciBwbGF5ZXJfMSA9IEdhbWUuZ2V0UGxheWVyKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNwYXduTWV0aG9kT3JpZ2luYWwgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNwYXduOiBmdW5jdGlvbiAoYmFzZUZvcm0sIF9zcGF3blBvc2l0aW9uLCBfc3Bhd25Sb3RhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBsYXllcl8xLnBsYWNlQXRNZShiYXNlRm9ybSwgMSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHRyaWdnZXJTcGF3blByb2Nlc3M6IGZ1bmN0aW9uIChzcGF3bmluZ1JlZnIsIHNwYXduUG9zaXRpb24sIGFwcGVhcmFuY2UsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgU3Bhd25Qcm9jZXNzKGFwcGVhcmFuY2UsIHNwYXduUG9zaXRpb24sIHNwYXduaW5nUmVmci5nZXRGb3JtSUQoKSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB2YXIgc3Bhd25NZXRob2RTdHViID0ge1xuICAgICAgICAgICAgICAgICAgICBzcGF3bjogZnVuY3Rpb24gKGJhc2VGb3JtLCBzcGF3blBvc2l0aW9uLCBzcGF3blJvdGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IHN0b3JhZ2VbXCJmb3JtVmlld0Z1bmMxXCJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlZiA9IGYoYmFzZUZvcm0sIHNwYXduUG9zaXRpb24sIHNwYXduUm90YXRpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlZjtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlclNwYXduUHJvY2VzczogZnVuY3Rpb24gKHNwYXduaW5nUmVmciwgc3Bhd25Qb3NpdGlvbiwgYXBwZWFyYW5jZSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmID0gc3RvcmFnZVtcImZvcm1WaWV3RnVuYzJcIl07XG4gICAgICAgICAgICAgICAgICAgICAgICBmKHNwYXduaW5nUmVmciwgc3Bhd25Qb3NpdGlvbiwgYXBwZWFyYW5jZSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB2YXIgc3Bhd25Vc2luZ1N0dWJNZXRob2QgPSBiYXNlLmdldFR5cGUoKSA9PT0gNDMgLyogRm9ybVR5cGUuTlBDICovXG4gICAgICAgICAgICAgICAgICAgICYmICF0aGlzLmFwcGVhcmFuY2VTdGF0ZS5hcHBlYXJhbmNlXG4gICAgICAgICAgICAgICAgICAgICYmIHN0b3JhZ2VbXCJmb3JtVmlld0Z1bmMxU2V0XCJdID09PSB0cnVlXG4gICAgICAgICAgICAgICAgICAgICYmIHN0b3JhZ2VbXCJmb3JtVmlld0Z1bmMyU2V0XCJdID09PSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBzcGF3bk1ldGhvZCA9IHNwYXduVXNpbmdTdHViTWV0aG9kID8gc3Bhd25NZXRob2RTdHViIDogc3Bhd25NZXRob2RPcmlnaW5hbDtcbiAgICAgICAgICAgICAgICBpZiAobW9kZWwubW92ZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmcl8zID0gc3Bhd25NZXRob2Quc3Bhd24oYmFzZSwgbW9kZWwubW92ZW1lbnQucG9zLCBtb2RlbC5tb3ZlbWVudC5yb3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcHJpbnRDb25zb2xlKFwibW9kZWwubW92ZW1lbnQgd2FzIFwiICsgbW9kZWwubW92ZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0ge307XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMud2FzSG9zdGVkQnlPdGhlcjtcbiAgICAgICAgICAgICAgICBpZiAoYmFzZS5nZXRUeXBlKCkgIT09IDQzIC8qIEZvcm1UeXBlLk5QQyAqLykge1xuICAgICAgICAgICAgICAgICAgICByZWZyXzMgPT09IG51bGwgfHwgcmVmcl8zID09PSB2b2lkIDAgPyB2b2lkIDAgOiByZWZyXzMuc2V0QW5nbGUoKChfYiA9IG1vZGVsLm1vdmVtZW50KSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iucm90WzBdKSB8fCAwLCAoKF9jID0gbW9kZWwubW92ZW1lbnQpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5yb3RbMV0pIHx8IDAsICgoX2QgPSBtb2RlbC5tb3ZlbWVudCkgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLnJvdFsyXSkgfHwgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmFjZSA9IChfZiA9IChfZSA9IEFjdG9yLmZyb20ocmVmcl8zKSkgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLmdldFJhY2UoKSkgPT09IG51bGwgfHwgX2YgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9mLmdldEZvcm1JRCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZHJhdWdyUmFjZSA9IDB4ZDUzO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZmFsbWVyUmFjZSA9IDB4MTMxZjQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGF1cnVzUmFjZSA9IDB4MTMxZWI7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmcm9zdGJpdGVTcGlkZXJSYWNlR2lhbnQgPSAweDRlNTA3O1xuICAgICAgICAgICAgICAgICAgICB2YXIgZnJvc3RiaXRlU3BpZGVyUmFjZUxhcmdlID0gMHg1MzQ3NztcbiAgICAgICAgICAgICAgICAgICAgdmFyIGR3YXJ2ZW5DZW50dXJpb25SYWNlID0gMHgxMzFmMTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGR3YXJ2ZW5TcGhlcmVSYWNlID0gMHgxMzFmMjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGR3YXJ2ZW5TcGlkZXJSYWNlID0gMHgxMzFmMztcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNwcmlnZ2FuUmFjZSA9IDB4MjAxM2I3NztcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNwcmlnZ2FuUmFjZTIgPSAweGYzOTAzO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3ByaWdnYW5SYWNlMyA9IDB4MTMyMDQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzcHJpZ2dhblJhY2U0ID0gMHg0MDFiNjQ0O1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3ByaWdnYW5SYWNlNSA9IDB4OWFhNDQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3b2xmUmFjZSA9IDB4MTMyMGE7XG4gICAgICAgICAgICAgICAgICAgIC8vIHBvdGVudGlhbCBtYXN0ZXJhbWJ1c2hzY3JpcHRcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJhY2UgPT09IGRyYXVnclJhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHJhY2UgPT09IGZhbG1lclJhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHJhY2UgPT09IGNoYXVydXNSYWNlXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSBmcm9zdGJpdGVTcGlkZXJSYWNlR2lhbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHJhY2UgPT09IGZyb3N0Yml0ZVNwaWRlclJhY2VMYXJnZVxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgcmFjZSA9PT0gZHdhcnZlbkNlbnR1cmlvblJhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHJhY2UgPT09IGR3YXJ2ZW5TcGhlcmVSYWNlXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSBkd2FydmVuU3BpZGVyUmFjZVxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgcmFjZSA9PT0gc3ByaWdnYW5SYWNlXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSBzcHJpZ2dhblJhY2UyXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSBzcHJpZ2dhblJhY2UzXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSBzcHJpZ2dhblJhY2U0XG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSBzcHJpZ2dhblJhY2U1XG4gICAgICAgICAgICAgICAgICAgICAgICB8fCByYWNlID09PSB3b2xmUmFjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgKF9nID0gQWN0b3IuZnJvbShyZWZyXzMpKSA9PT0gbnVsbCB8fCBfZyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2cuc2V0QWN0b3JWYWx1ZShcIkFnZ3Jlc3Npb25cIiwgMik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlZnJfMyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBTcEFwaUludGVyYWN0b3IuZ2V0Q29udHJvbGxlckluc3RhbmNlKCkubG9va3VwTGlzdGVuZXIoV29ybGRDbGVhbmVyU2VydmljZSkubW9kV2NQcm90ZWN0aW9uKHJlZnJfMy5nZXRGb3JtSUQoKSwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFRPRE86IHJlc2V0IGFsbCBzdGF0ZXM/XG4gICAgICAgICAgICAgICAgdGhpcy5lcVN0YXRlID0gdGhpcy5nZXREZWZhdWx0RXF1aXBTdGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuYW5pbVN0YXRlID0gdGhpcy5nZXREZWZhdWx0QW5pbVN0YXRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBzcGF3blBvcyA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICBpZiAobW9kZWwubW92ZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3Bhd25Qb3MgPSBtb2RlbC5tb3ZlbWVudC5wb3M7XG4gICAgICAgICAgICAgICAgICAgIC8vIHByaW50Q29uc29sZShcIlNwYXduIE5QQyBhdCBtb3ZlbWVudC5wb3NcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzcGF3blBvcyA9IE9iamVjdFJlZmVyZW5jZUV4LmdldFBvcyhHYW1lLmdldFBsYXllcigpKTtcbiAgICAgICAgICAgICAgICAgICAgcHJpbnRDb25zb2xlKFwiU3Bhd24gTlBDIGF0IHBsYXllciBwb3NcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZWZyXzMpIHtcbiAgICAgICAgICAgICAgICAgICAgc3Bhd25NZXRob2QudHJpZ2dlclNwYXduUHJvY2VzcyhyZWZyXzMsIHNwYXduUG9zLCBtb2RlbC5hcHBlYXJhbmNlIHx8IG51bGwsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnJlYWR5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNwYXduTW9tZW50ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwcmludENvbnNvbGUoXCJVbmFibGUgdG8gdHJpZ2dlclNwYXduUHJvY2VzcyBmb3IgbnVsbCByZWZyXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobW9kZWwuYXBwZWFyYW5jZSAmJiBtb2RlbC5hcHBlYXJhbmNlLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmcl8zID09PSBudWxsIHx8IHJlZnJfMyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcmVmcl8zLnNldERpc3BsYXlOYW1lKFwiXCIgKyBtb2RlbC5hcHBlYXJhbmNlLm5hbWUsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAoX2ggPSBBY3Rvci5mcm9tKHJlZnJfMykpID09PSBudWxsIHx8IF9oID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfaC5zZXRBY3RvclZhbHVlKFwiYXR0YWNrRGFtYWdlTXVsdFwiLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVmcklkID0gcmVmcl8zLmdldEZvcm1JRCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5yZWFkeSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZWZyID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgodGhpcy5yZWZySWQpKTtcbiAgICAgICAgaWYgKHJlZnIpIHtcbiAgICAgICAgICAgIHZhciBhY3RvciA9IEFjdG9yLmZyb20ocmVmcik7XG4gICAgICAgICAgICBpZiAoYWN0b3IgJiYgIXRoaXMubG9jYWxJbW1vcnRhbCkge1xuICAgICAgICAgICAgICAgIGFjdG9yLnN0YXJ0RGVmZXJyZWRLaWxsKCk7XG4gICAgICAgICAgICAgICAgYWN0b3Iuc2V0QWN0b3JWYWx1ZShcImhlYWx0aFwiLCAxMDAwMDAwKTtcbiAgICAgICAgICAgICAgICBhY3Rvci5zZXRBY3RvclZhbHVlKFwibWFnaWNrYVwiLCAxMDAwMDAwKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsSW1tb3J0YWwgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hcHBseUFsbChyZWZyLCBtb2RlbCk7XG4gICAgICAgICAgICB2YXIgZ2FtZW1vZGVVcGRhdGVTZXJ2aWNlID0gU3BBcGlJbnRlcmFjdG9yLmdldENvbnRyb2xsZXJJbnN0YW5jZSgpLmxvb2t1cExpc3RlbmVyKEdhbWVtb2RlVXBkYXRlU2VydmljZSk7XG4gICAgICAgICAgICBnYW1lbW9kZVVwZGF0ZVNlcnZpY2UudXBkYXRlTmVpZ2hib3IocmVmciwgbW9kZWwsIHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBGb3JtVmlldy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pc09uU2NyZWVuID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc3Bhd25Nb21lbnQgPSAwO1xuICAgICAgICB2YXIgcmVmcklkID0gdGhpcy5yZWZySWQ7XG4gICAgICAgIG9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZGVzdHJveVByb3h5TW91bnRGb3JSaWRlcihyZWZySWQpOyAvLyBFbGRlcnZhbGUgUDI6IGxpbXBpYXIgZWwgY2FiYWxsby1wcm94eSBsb2NhbCBkZSBlc3RlIGppbmV0ZVxuICAgICAgICAgICAgaWYgKHJlZnJJZCA+PSAweGZmMDAwMDAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlZnIgPSBPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm1FeChyZWZySWQpKTtcbiAgICAgICAgICAgICAgICBpZiAocmVmcikge1xuICAgICAgICAgICAgICAgICAgICByZWZyLmRlbGV0ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBTcEFwaUludGVyYWN0b3IuZ2V0Q29udHJvbGxlckluc3RhbmNlKCkubG9va3VwTGlzdGVuZXIoV29ybGRDbGVhbmVyU2VydmljZSkubW9kV2NQcm90ZWN0aW9uKHJlZnJJZCwgLTEpO1xuICAgICAgICAgICAgICAgIHZhciBhYyA9IEFjdG9yLmZyb20ocmVmcik7XG4gICAgICAgICAgICAgICAgaWYgKGFjKSB7XG4gICAgICAgICAgICAgICAgICAgIFRFU01vZFBsYXRmb3JtLnNldFdlYXBvbkRyYXduTW9kZShhYywgLTEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubG9jYWxJbW1vcnRhbCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlbW92ZU5pY2tuYW1lKCk7XG4gICAgfTtcbiAgICBGb3JtVmlldy5wcm90b3R5cGUuYXBwbHlBbGwgPSBmdW5jdGlvbiAocmVmciwgbW9kZWwpIHtcbiAgICAgICAgdmFyIF9hLCBfYiwgX2M7XG4gICAgICAgIHZhciBmb3JjZWRXZWFwRHJhd24gPSBudWxsO1xuICAgICAgICBpZiAoUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci5nZXRDcm9zc2hhaXJSZWZJZCgpID09PSB0aGlzLnJlZnJJZCkge1xuICAgICAgICAgICAgdGhpcy5sYXN0SGFydmVzdGVkQXBwbHkgPSAwO1xuICAgICAgICAgICAgdGhpcy5sYXN0T3BlbkFwcGx5ID0gMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYgKG5vdyAtIHRoaXMubGFzdEhhcnZlc3RlZEFwcGx5ID4gNjY2KSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RIYXJ2ZXN0ZWRBcHBseSA9IG5vdztcbiAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsSXNIYXJ2ZXN0ZWQocmVmciwgISFtb2RlbC5pc0hhcnZlc3RlZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vdyAtIHRoaXMubGFzdE9wZW5BcHBseSA+IDEzMykge1xuICAgICAgICAgICAgdGhpcy5sYXN0T3BlbkFwcGx5ID0gbm93O1xuICAgICAgICAgICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJc09wZW4ocmVmciwgISFtb2RlbC5pc09wZW4pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc1NldE5vZGVTY2FsZUFwcGxpZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaXNTZXROb2RlU2NhbGVBcHBsaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsTm9kZVNjYWxlKHJlZnIsIG1vZGVsLnNldE5vZGVTY2FsZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmlzU2V0Tm9kZVRleHR1cmVTZXRBcHBsaWVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzU2V0Tm9kZVRleHR1cmVTZXRBcHBsaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsTm9kZVRleHR1cmVTZXQocmVmciwgbW9kZWwuc2V0Tm9kZVRleHR1cmVTZXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtb2RlbC5pbnZlbnRvcnkgJiZcbiAgICAgICAgICAgIFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIuZ2V0Q3Jvc3NoYWlyUmVmSWQoKSA9PSB0aGlzLnJlZnJJZCAmJlxuICAgICAgICAgICAgIWlzQmFkTWVudVNob3duKCkpIHtcbiAgICAgICAgICAgIC8vIERvIG5vdCBsZXQgYWN0b3JzIGJyZWFraW5nIHRoZWlyIGVxdWlwbWVudCB2aWEgaW52ZW50b3J5IGFwcGx5XG4gICAgICAgICAgICAvLyBIb3dldmVyLCBhY3R1YWxseSwgYWN0b3JzIGRvIG5vdCBoYXZlIGludmVudG9yeSBpbiB0aGVpciBtb2RlbHNcbiAgICAgICAgICAgIC8vIEV4Y2VwdCB5b3VyIGNsb25lLlxuICAgICAgICAgICAgaWYgKCFBY3Rvci5mcm9tKHJlZnIpKSB7XG4gICAgICAgICAgICAgICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJbnZlbnRvcnkocmVmciwgbW9kZWwuaW52ZW50b3J5KTtcbiAgICAgICAgICAgICAgICBtb2RlbC5pbnZlbnRvcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1vZGVsLmFuaW1hdGlvbikge1xuICAgICAgICAgICAgaWYgKG1vZGVsLmFuaW1hdGlvbi5hbmltRXZlbnROYW1lID09PSBcIlNreW1wRmFrZVVuZXF1aXBcIikge1xuICAgICAgICAgICAgICAgIGZvcmNlZFdlYXBEcmF3biA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobW9kZWwuYW5pbWF0aW9uLmFuaW1FdmVudE5hbWUgPT09IFwiU2t5bXBGYWtlRXF1aXBcIikge1xuICAgICAgICAgICAgICAgIGZvcmNlZFdlYXBEcmF3biA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogbWFrZSBob3N0IHNlcnZpY2VcbiAgICAgICAgdmFyIGhvc3RlZCA9IHN0b3JhZ2VbJ2hvc3RlZCddO1xuICAgICAgICB2YXIgYWxyZWFkeUhvc3RlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShob3N0ZWQpKSB7XG4gICAgICAgICAgICB2YXIgcmVtb3RlSWQgPSBsb2NhbElkVG9SZW1vdGVJZCh0aGlzLnJlZnJJZCk7XG4gICAgICAgICAgICBpZiAoaG9zdGVkLmluY2x1ZGVzKHJlbW90ZUlkKSB8fCBob3N0ZWQuaW5jbHVkZXMocmVtb3RlSWQgKyAweDEwMDAwMDAwMCkpIHtcbiAgICAgICAgICAgICAgICBhbHJlYWR5SG9zdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzZXREZWZhdWx0QW5pbXNEaXNhYmxlZCh0aGlzLnJlZnJJZCwgYWxyZWFkeUhvc3RlZCA/IGZhbHNlIDogdHJ1ZSk7XG4gICAgICAgIGlmIChhbHJlYWR5SG9zdGVkKSB7XG4gICAgICAgICAgICAoX2EgPSBBY3Rvci5mcm9tKHJlZnIpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY2xlYXJLZWVwT2Zmc2V0RnJvbUFjdG9yKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1vZGVsLm1vdmVtZW50KSB7XG4gICAgICAgICAgICB2YXIgYWMgPSBBY3Rvci5mcm9tKHJlZnIpO1xuICAgICAgICAgICAgaWYgKHRoaXMubW92U3RhdGUubGFzdEFwcGx5ICYmXG4gICAgICAgICAgICAgICAgRGF0ZS5ub3coKSAtIHRoaXMubW92U3RhdGUubGFzdEFwcGx5ID4gMTUwMCkge1xuICAgICAgICAgICAgICAgIGlmIChEYXRlLm5vdygpIC0gdGhpcy5tb3ZTdGF0ZS5sYXN0UmVob3N0ID4gMTAwMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1vdlN0YXRlLmxhc3RSZWhvc3QgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVtb3RlSWQgPSB0aGlzLnJlbW90ZVJlZnJJZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFjICYmIGFjLmlzM0RMb2FkZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cnlIb3N0SWZOZWVkKGFjLCByZW1vdGVJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmludENvbnNvbGUoXCJ0cnlIb3N0SWZOZWVkIC0gcmVhc29uOiBub3Qgc2VlaW5nIG1vdmVtZW50IGZvciBsb25nIHRpbWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoK21vZGVsLm51bU1vdmVtZW50Q2hhbmdlcyAhPT1cbiAgICAgICAgICAgICAgICB0aGlzLm1vdlN0YXRlLmxhc3ROdW1DaGFuZ2VzIHx8XG4gICAgICAgICAgICAgICAgRGF0ZS5ub3coKSAtIHRoaXMubW92U3RhdGUubGFzdEFwcGx5ID4gMjAwMCkge1xuICAgICAgICAgICAgICAgIHRoaXMubW92U3RhdGUubGFzdEFwcGx5ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICBpZiAobW9kZWwuaXNIb3N0ZWRCeU90aGVyIHx8ICF0aGlzLm1vdlN0YXRlLmV2ZXJBcHBsaWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBiYWNrdXAgPSBtb2RlbC5tb3ZlbWVudC5pc1dlYXBEcmF3bjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvcmNlZFdlYXBEcmF3biA9PT0gdHJ1ZSB8fCBmb3JjZWRXZWFwRHJhd24gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlbC5tb3ZlbWVudC5pc1dlYXBEcmF3biA9IGZvcmNlZFdlYXBEcmF3bjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlNb3ZlbWVudChyZWZyLCBtb2RlbC5tb3ZlbWVudCwgISFtb2RlbC5pc015Q2xvbmUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFJlc3Bhd25OZWVkZWRFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGFzdFdvcmxkT3JDZWxsID0gbW9kZWwubW92ZW1lbnQud29ybGRPckNlbGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWZySWQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXBwZWFyYW5jZUJhc2VkQmFzZUlkID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG1vZGVsLm1vdmVtZW50LmlzV2VhcERyYXduID0gYmFja3VwO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1vdlN0YXRlLmxhc3ROdW1DaGFuZ2VzID0gK21vZGVsLm51bU1vdmVtZW50Q2hhbmdlcztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZTdGF0ZS5ldmVyQXBwbGllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVtb3RlSWQgPSB0aGlzLnJlbW90ZVJlZnJJZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFjICYmIHJlbW90ZUlkICYmIGFjLmlzM0RMb2FkZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWMuY2xlYXJLZWVwT2Zmc2V0RnJvbUFjdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBtYWtlIGhvc3Qgc2VydmljZVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhvc3RlZF8xID0gc3RvcmFnZVsnaG9zdGVkJ107XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWxyZWFkeUhvc3RlZF8xID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShob3N0ZWRfMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVtb3RlSWRfMSA9IGxvY2FsSWRUb1JlbW90ZUlkKGFjLmdldEZvcm1JRCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaG9zdGVkXzEuaW5jbHVkZXMocmVtb3RlSWRfMSkgfHwgaG9zdGVkXzEuaW5jbHVkZXMocmVtb3RlSWRfMSArIDB4MTAwMDAwMDAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHJlYWR5SG9zdGVkXzEgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWxyZWFkeUhvc3RlZF8xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudHJ5SG9zdElmTmVlZChhYywgcmVtb3RlSWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByZXZpb3VzbHksIHdlIGRpZCB0aGlzIGNsZWFudXAgb24gZWFjaCB1cGRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IEkgZ3Vlc3MgaXQncyB0b28gZXhwZW5zaXZlIGFuZCBjYW4gcG9zc2libHkgaHVydCBGUFNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVEVTTW9kUGxhdGZvcm0uc2V0V2VhcG9uRHJhd25Nb2RlKGFjLCAtMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChyZWZyLmlzM0RMb2FkZWQoKSkge1xuICAgICAgICAgICAgaWYgKG1vZGVsLmFuaW1hdGlvbikge1xuICAgICAgICAgICAgICAgIGFwcGx5QW5pbWF0aW9uKHJlZnIsIG1vZGVsLmFuaW1hdGlvbiwgdGhpcy5hbmltU3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVXNlIHRoZW0gb25seSBvbmNlLCBmb3Igc3Bhd25pbmcgYWN0b3JzIHdpdGggY29ycmVjdCBhbmltYXRpb25zXG4gICAgICAgICAgICB0aGlzLmFuaW1TdGF0ZS51c2VBbmltT3ZlcnJpZGVzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1vZGVsLmFwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgIHZhciBhY3RvciA9IEFjdG9yLmZyb20ocmVmcik7XG4gICAgICAgICAgICBpZiAoYWN0b3IgJiYgIVBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIuaXNJbkp1bXBTdGF0ZSgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIuZ2V0V29ybGRPckNlbGwoKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sYXN0UGNXb3JsZE9yQ2VsbCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci5nZXRXb3JsZE9yQ2VsbCgpICE9PSB0aGlzLmxhc3RQY1dvcmxkT3JDZWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWRyYXcgdGludHMgaWYgUEMgd29ybGQvY2VsbCBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzT25TY3JlZW4gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxhc3RQY1dvcmxkT3JDZWxsID0gUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci5nZXRXb3JsZE9yQ2VsbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaGVhZFBvcyA9IFtcbiAgICAgICAgICAgICAgICAgICAgTmV0SW1tZXJzZS5nZXROb2RlV29ybGRQb3NpdGlvblgoYWN0b3IsIFwiTlBDIEhlYWQgW0hlYWRdXCIsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgTmV0SW1tZXJzZS5nZXROb2RlV29ybGRQb3NpdGlvblkoYWN0b3IsIFwiTlBDIEhlYWQgW0hlYWRdXCIsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgTmV0SW1tZXJzZS5nZXROb2RlV29ybGRQb3NpdGlvblooYWN0b3IsIFwiTlBDIEhlYWQgW0hlYWRdXCIsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgIHZhciBzY3JlZW5Qb2ludCA9IHdvcmxkUG9pbnRUb1NjcmVlblBvaW50KGhlYWRQb3MpWzBdO1xuICAgICAgICAgICAgICAgIHZhciBpc09uU2NyZWVuID0gc2NyZWVuUG9pbnRbMF0gPiAwICYmXG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblBvaW50WzFdID4gMCAmJlxuICAgICAgICAgICAgICAgICAgICBzY3JlZW5Qb2ludFsyXSA+IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgc2NyZWVuUG9pbnRbMF0gPCAxICYmXG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblBvaW50WzFdIDwgMSAmJlxuICAgICAgICAgICAgICAgICAgICBzY3JlZW5Qb2ludFsyXSA8IDE7XG4gICAgICAgICAgICAgICAgaWYgKGlzT25TY3JlZW4gIT0gdGhpcy5pc09uU2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNPblNjcmVlbiA9IGlzT25TY3JlZW47XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc09uU2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rvci5xdWV1ZU5pTm9kZVVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgR2FtZS5nZXRQbGF5ZXIoKS5xdWV1ZU5pTm9kZVVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtb2RlbC5lcXVpcG1lbnQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmVxU3RhdGUubGFzdE51bUNoYW5nZXMgIT09IG1vZGVsLmVxdWlwbWVudC5udW1DaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBkbyBub3QgYmxvY2sgaW52ZW50b3J5IGhlcmUsIHdlIHdpbGwgYmUgYWJsZSB0byByZXByb2R1Y2UgdGhlIGJ1ZzpcbiAgICAgICAgICAgICAgICAvLyAxLiBQbGFjZSB+OTAgYm90cyBhbmQgZm9yY2UgdGhlbSB0byByZWVxdWlwIGlyb24gc3dvcmRzIHRvIHRoZSBsZWZ0IGhhbmQgKHJhdGUgc2hvdWxkIGJlIH41MG1zKVxuICAgICAgICAgICAgICAgIC8vIDIuIE9wZW4geW91ciBpbnZlbnRvcnkgYW5kIHJlZXF1aXAgZGlmZmVyZW50IGl0ZW1zIGZhc3RcbiAgICAgICAgICAgICAgICAvLyAzLiBBZnRlciAxLTIgbWludXRlcyBjbG9zZSB5b3VyIGludmVudG9yeSBhbmQgc2VlIHRoYXQgSFVEIGRpc2FwcGVhcmVkXG4gICAgICAgICAgICAgICAgaWYgKGFjICYmXG4gICAgICAgICAgICAgICAgICAgICFpc0JhZE1lbnVTaG93bigpICYmXG4gICAgICAgICAgICAgICAgICAgIERhdGUubm93KCkgLSB0aGlzLmVxU3RhdGUubGFzdEVxTW9tZW50ID4gNTAwICYmXG4gICAgICAgICAgICAgICAgICAgIERhdGUubm93KCkgLSB0aGlzLnNwYXduTW9tZW50ID4gLTEgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zcGF3bk1vbWVudCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy9pZiAodGhpcy5zcGF3bk1vbWVudCA+IDAgJiYgRGF0ZS5ub3coKSAtIHRoaXMuc3Bhd25Nb21lbnQgPiA1MDAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcHBseUVxdWlwbWVudChhYywgbW9kZWwuZXF1aXBtZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lcVN0YXRlLmxhc3ROdW1DaGFuZ2VzID0gbW9kZWwuZXF1aXBtZW50Lm51bUNoYW5nZXM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lcVN0YXRlLmxhc3RFcU1vbWVudCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgIC8vfVxuICAgICAgICAgICAgICAgICAgICAvL2NvbnN0IHJlczogYm9vbGVhbiA9IGFwcGx5RXF1aXBtZW50KGFjLCBtb2RlbC5lcXVpcG1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAvL2lmIChyZXMpIHRoaXMuZXFTdGF0ZS5sYXN0TnVtQ2hhbmdlcyA9IG1vZGVsLmVxdWlwbWVudC5udW1DaGFuZ2VzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoRm9ybVZpZXcuaXNEaXNwbGF5aW5nTmlja25hbWVzICYmIHRoaXMucmVmcklkICYmICgoX2IgPSBtb2RlbC5hcHBlYXJhbmNlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IubmFtZSkpIHtcbiAgICAgICAgICAgIHZhciBoZWFkUGFydCA9IFwiTlBDIEhlYWQgW0hlYWRdXCI7XG4gICAgICAgICAgICB2YXIgbWF4Tmlja25hbWVEcmF3RGlzdGFuY2UgPSAxMDAwO1xuICAgICAgICAgICAgdmFyIHBsYXllckFjdG9yID0gR2FtZS5nZXRQbGF5ZXIoKTtcbiAgICAgICAgICAgIHZhciBpc1Zpc2libGVCeVBsYXllciA9ICEoKF9jID0gbW9kZWwubW92ZW1lbnQpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5pc1NuZWFraW5nKVxuICAgICAgICAgICAgICAgICYmIHBsYXllckFjdG9yLmdldERpc3RhbmNlKHJlZnIpIDw9IG1heE5pY2tuYW1lRHJhd0Rpc3RhbmNlXG4gICAgICAgICAgICAgICAgJiYgcGxheWVyQWN0b3IuaGFzTE9TKHJlZnIpXG4gICAgICAgICAgICAgICAgJiYgIXRoaXMuaXNTd2VldEhpZGVQZXJzb24ocmVmcik7XG4gICAgICAgICAgICBpZiAoaXNWaXNpYmxlQnlQbGF5ZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgaGVhZFNjcmVlblBvcyA9IHdvcmxkUG9pbnRUb1NjcmVlblBvaW50KFtcbiAgICAgICAgICAgICAgICAgICAgTmV0SW1tZXJzZS5nZXROb2RlV29ybGRQb3NpdGlvblgocmVmciwgaGVhZFBhcnQsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgTmV0SW1tZXJzZS5nZXROb2RlV29ybGRQb3NpdGlvblkocmVmciwgaGVhZFBhcnQsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgTmV0SW1tZXJzZS5nZXROb2RlV29ybGRQb3NpdGlvbloocmVmciwgaGVhZFBhcnQsIGZhbHNlKSArIDMyXG4gICAgICAgICAgICAgICAgXSlbMF07XG4gICAgICAgICAgICAgICAgdmFyIHJlc29sdXRpb24gPSBnZXRTY3JlZW5SZXNvbHV0aW9uKCk7XG4gICAgICAgICAgICAgICAgdmFyIHRleHRYUG9zID0gTWF0aC5yb3VuZChoZWFkU2NyZWVuUG9zWzBdICogcmVzb2x1dGlvbi53aWR0aCk7XG4gICAgICAgICAgICAgICAgdmFyIHRleHRZUG9zID0gTWF0aC5yb3VuZCgoMSAtIGhlYWRTY3JlZW5Qb3NbMV0pICogcmVzb2x1dGlvbi5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy50ZXh0TmFtZUlkICYmIGhlYWRTY3JlZW5Qb3NbMl0gPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dE5hbWVJZCA9IGNyZWF0ZVRleHQodGV4dFhQb3MsIHRleHRZUG9zLCByZWZyLmdldERpc3BsYXlOYW1lKCksIFsxLCAxLCAxLCAwLjhdKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGV4dFNpemUodGhpcy50ZXh0TmFtZUlkLCAwLjUpO1xuICAgICAgICAgICAgICAgICAgICBTcEFwaUludGVyYWN0b3IuZ2V0Q29udHJvbGxlckluc3RhbmNlKCkuZW1pdHRlci5lbWl0KFwibmlja25hbWVDcmVhdGVcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlUmVmcklkOiB0aGlzLmdldFJlbW90ZVJlZnJJZCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dElkOiB0aGlzLnRleHROYW1lSWRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVsZXRlTmlja25hbWUgPSBoZWFkU2NyZWVuUG9zWzJdIDwgMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRlbGV0ZU5pY2tuYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZU5pY2tuYW1lKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudGV4dE5hbWVJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGV4dFBvcyh0aGlzLnRleHROYW1lSWQsIHRleHRYUG9zLCB0ZXh0WVBvcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZU5pY2tuYW1lKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZU5pY2tuYW1lKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZvcm1WaWV3LnByb3RvdHlwZS5pc1N3ZWV0SGlkZVBlcnNvbiA9IGZ1bmN0aW9uIChyZWZyKSB7XG4gICAgICAgIHZhciBhY3RvciA9IEFjdG9yLmZyb20ocmVmcik7XG4gICAgICAgIGlmICghYWN0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIga2V5d29yZCA9IEtleXdvcmQuZ2V0S2V5d29yZCgnU3dlZXRIaWRlUGVyc29uJyk7XG4gICAgICAgIHJldHVybiBhY3Rvci53b3JuSGFzS2V5d29yZChrZXl3b3JkKTtcbiAgICB9O1xuICAgIEZvcm1WaWV3LnByb3RvdHlwZS5yZW1vdmVOaWNrbmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMudGV4dE5hbWVJZCkge1xuICAgICAgICAgICAgU3BBcGlJbnRlcmFjdG9yLmdldENvbnRyb2xsZXJJbnN0YW5jZSgpLmVtaXR0ZXIuZW1pdChcIm5pY2tuYW1lRGVzdHJveVwiLCB7XG4gICAgICAgICAgICAgICAgcmVtb3RlUmVmcklkOiB0aGlzLmdldFJlbW90ZVJlZnJJZCgpLFxuICAgICAgICAgICAgICAgIHRleHRJZDogdGhpcy50ZXh0TmFtZUlkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlc3Ryb3lUZXh0KHRoaXMudGV4dE5hbWVJZCk7XG4gICAgICAgICAgICB0aGlzLnRleHROYW1lSWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZvcm1WaWV3LnByb3RvdHlwZS5nZXRBcHBlYXJhbmNlQmFzZWRCYXNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYmFzZSA9IEFjdG9yQmFzZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHRoaXMuYXBwZWFyYW5jZUJhc2VkQmFzZUlkKSk7XG4gICAgICAgIGlmICghYmFzZSAmJiB0aGlzLmFwcGVhcmFuY2VTdGF0ZS5hcHBlYXJhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLmFwcGVhcmFuY2VCYXNlZEJhc2VJZCA9IGFwcGx5QXBwZWFyYW5jZSh0aGlzLmFwcGVhcmFuY2VTdGF0ZS5hcHBlYXJhbmNlKS5nZXRGb3JtSUQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5hcHBlYXJhbmNlQmFzZWRCYXNlSWQ7XG4gICAgfTtcbiAgICBGb3JtVmlldy5wcm90b3R5cGUuZ2V0TGV2ZWxlZEJhc2UgPSBmdW5jdGlvbiAodGVtcGxhdGVDaGFpbikge1xuICAgICAgICBpZiAodGVtcGxhdGVDaGFpbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3RyID0gdGVtcGxhdGVDaGFpbi5qb2luKCcsJyk7XG4gICAgICAgIGlmICh0aGlzLmxldmVsZWRCYXNlSWQgPT09IDApIHtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIHZhciBsZXZlbGVkQmFzZSA9IFRFU01vZFBsYXRmb3JtLmV2YWx1YXRlTGV2ZWxlZE5wYyhzdHIpO1xuICAgICAgICAgICAgaWYgKCFsZXZlbGVkQmFzZSkge1xuICAgICAgICAgICAgICAgIHByaW50Q29uc29sZShcIkZhaWxlZCB0byBldmFsdWF0ZSBsZXZlbGVkIG5wY1wiLCBzdHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5sZXZlbGVkQmFzZUlkID0gKGxldmVsZWRCYXNlID09PSBudWxsIHx8IGxldmVsZWRCYXNlID09PSB2b2lkIDAgPyB2b2lkIDAgOiBsZXZlbGVkQmFzZS5nZXRGb3JtSUQoKSkgfHwgMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5sZXZlbGVkQmFzZUlkO1xuICAgIH07XG4gICAgRm9ybVZpZXcucHJvdG90eXBlLmdldERlZmF1bHRFcXVpcFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyBsYXN0TnVtQ2hhbmdlczogMCwgbGFzdEVxTW9tZW50OiAwIH07XG4gICAgfTtcbiAgICA7XG4gICAgRm9ybVZpZXcucHJvdG90eXBlLmdldERlZmF1bHRBcHBlYXJhbmNlU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7IGxhc3ROdW1DaGFuZ2VzOiAwLCBhcHBlYXJhbmNlOiBudWxsIH07XG4gICAgfTtcbiAgICA7XG4gICAgRm9ybVZpZXcucHJvdG90eXBlLmdldERlZmF1bHRBbmltU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7IGxhc3ROdW1DaGFuZ2VzOiAwLCB1c2VBbmltT3ZlcnJpZGVzOiB0cnVlIH07XG4gICAgfTtcbiAgICA7XG4gICAgRm9ybVZpZXcucHJvdG90eXBlLnRyeUhvc3RJZk5lZWQgPSBmdW5jdGlvbiAoYWMsIHJlbW90ZUlkKSB7XG4gICAgICAgIHZhciBsYXN0ID0gbGFzdFRyeUhvc3RbcmVtb3RlSWRdO1xuICAgICAgICBpZiAoIWxhc3QgfHwgRGF0ZS5ub3coKSAtIGxhc3QgPj0gMTAwMCkge1xuICAgICAgICAgICAgbGFzdFRyeUhvc3RbcmVtb3RlSWRdID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIGlmIChnZXRNb3ZlbWVudChhYykud29ybGRPckNlbGwgPT09XG4gICAgICAgICAgICAgICAgZ2V0TW92ZW1lbnQoR2FtZS5nZXRQbGF5ZXIoKSkud29ybGRPckNlbGwpIHtcbiAgICAgICAgICAgICAgICB0cnlIb3N0KHJlbW90ZUlkKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICA7XG4gICAgRm9ybVZpZXcucHJvdG90eXBlLmdldExvY2FsUmVmcklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWZySWQ7XG4gICAgfTtcbiAgICBGb3JtVmlldy5wcm90b3R5cGUuZ2V0UmVtb3RlUmVmcklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZW1vdGVSZWZySWQ7XG4gICAgfTtcbiAgICBGb3JtVmlldy5pc0Rpc3BsYXlpbmdOaWNrbmFtZXMgPSB0cnVlO1xuICAgIHJldHVybiBGb3JtVmlldztcbn0oKSk7XG5leHBvcnQgeyBGb3JtVmlldyB9O1xuIiwiaW1wb3J0IHsgRm9ybVZpZXcgfSBmcm9tIFwiLi9mb3JtVmlld1wiO1xuaW1wb3J0IHsgU3BBcGlJbnRlcmFjdG9yIH0gZnJvbSBcIi4uL3NlcnZpY2VzL3NwQXBpSW50ZXJhY3RvclwiO1xuaW1wb3J0IHsgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL3NlcnZpY2VzL2dhbWVtb2RlVXBkYXRlU2VydmljZVwiO1xudmFyIEZvcm1WaWV3QXJyYXkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRm9ybVZpZXdBcnJheSgpIHtcbiAgICAgICAgdGhpcy5mb3JtVmlld3MgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG4gICAgRm9ybVZpZXdBcnJheS5wcm90b3R5cGUudXBkYXRlRm9ybSA9IGZ1bmN0aW9uIChmb3JtLCBpKSB7XG4gICAgICAgIHZhciB2aWV3ID0gdGhpcy5mb3JtVmlld3NbaV07XG4gICAgICAgIGlmICghdmlldykge1xuICAgICAgICAgICAgdGhpcy5mb3JtVmlld3NbaV0gPSBuZXcgRm9ybVZpZXcoZm9ybS5yZWZySWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmlldy51cGRhdGUoZm9ybSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZvcm1WaWV3QXJyYXkucHJvdG90eXBlLmRlc3Ryb3lGb3JtID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgdmFyIGZvcm1WaWV3ID0gdGhpcy5mb3JtVmlld3NbaV07XG4gICAgICAgIGlmIChmb3JtVmlldyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZm9ybVZpZXcuZGVzdHJveSgpO1xuICAgICAgICB0aGlzLmZvcm1WaWV3c1tpXSA9IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIEZvcm1WaWV3QXJyYXkucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uIChuZXdTaXplKSB7XG4gICAgICAgIGlmICh0aGlzLmZvcm1WaWV3cy5sZW5ndGggPiBuZXdTaXplKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm1WaWV3cy5zbGljZShuZXdTaXplKS5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2ICYmIHYuZGVzdHJveSgpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvcm1WaWV3cy5sZW5ndGggPSBuZXdTaXplO1xuICAgIH07XG4gICAgRm9ybVZpZXdBcnJheS5wcm90b3R5cGUudXBkYXRlQWxsID0gZnVuY3Rpb24gKG1vZGVsLCBzaG93TWUsIGlzQ2xvbmVWaWV3KSB7XG4gICAgICAgIHZhciBnYW1lbW9kZVVwZGF0ZVNlcnZpY2UgPSBTcEFwaUludGVyYWN0b3IuZ2V0Q29udHJvbGxlckluc3RhbmNlKCkubG9va3VwTGlzdGVuZXIoR2FtZW1vZGVVcGRhdGVTZXJ2aWNlKTtcbiAgICAgICAgZ2FtZW1vZGVVcGRhdGVTZXJ2aWNlLnNldEZvcm1WaWV3QXJyYXkodGhpcyk7XG4gICAgICAgIHZhciBmb3JtcyA9IG1vZGVsLmZvcm1zO1xuICAgICAgICB2YXIgbiA9IGZvcm1zLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgIHZhciBmb3JtID0gZm9ybXNbaV07XG4gICAgICAgICAgICBpZiAoIWZvcm0gfHwgKG1vZGVsLnBsYXllckNoYXJhY3RlckZvcm1JZHggPT09IGkgJiYgIXNob3dNZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3lGb3JtKGkpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlYWxQb3MgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0ID0gbW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeCA9PT0gaSB8fCBpc0Nsb25lVmlldztcbiAgICAgICAgICAgIGlmIChvZmZzZXQgJiYgZm9ybS5tb3ZlbWVudCkge1xuICAgICAgICAgICAgICAgIHJlYWxQb3MgPSBmb3JtLm1vdmVtZW50LnBvcztcbiAgICAgICAgICAgICAgICBmb3JtLm1vdmVtZW50LnBvcyA9IFtcbiAgICAgICAgICAgICAgICAgICAgcmVhbFBvc1swXSArIDEyOCxcbiAgICAgICAgICAgICAgICAgICAgcmVhbFBvc1sxXSArIDEyOCxcbiAgICAgICAgICAgICAgICAgICAgcmVhbFBvc1syXSxcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzQ2xvbmVWaWV3KSB7XG4gICAgICAgICAgICAgICAgLy8gUHJldmVudCB1c2luZyB0aGUgc2FtZSByZWZyIGJ5IG5vcm1hbCBhbmQgY2xvbmUgdmlld3NcbiAgICAgICAgICAgICAgICBpZiAoIWZvcm0ucmVmcklkIHx8IGZvcm0ucmVmcklkID49IDB4ZmYwMDAwMDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJhY2t1cCA9IGZvcm0uaXNIb3N0ZWRCeU90aGVyO1xuICAgICAgICAgICAgICAgICAgICBmb3JtLmlzSG9zdGVkQnlPdGhlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IEV4cGxhaW4gd2h5IGRvIG5vdCBHYW1lbW9kZUFwaVN1cHBvcnQuc2V0SShpKTsgaGVyZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUZvcm0oZm9ybSwgaSk7XG4gICAgICAgICAgICAgICAgICAgIGZvcm0uaXNIb3N0ZWRCeU90aGVyID0gYmFja3VwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdhbWVtb2RlVXBkYXRlU2VydmljZS5zZXRJKGkpO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRm9ybShmb3JtLCBpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvZmZzZXQgJiYgZm9ybS5tb3ZlbWVudCAmJiByZWFsUG9zKSB7XG4gICAgICAgICAgICAgICAgZm9ybS5tb3ZlbWVudC5wb3MgPSByZWFsUG9zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBGb3JtVmlld0FycmF5LnByb3RvdHlwZS5zeW5jRm9ybVZpZXcgPSBmdW5jdGlvbiAobW9kZWwsIHNob3dNZSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vZGVsLmZvcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBpZiAoIW1vZGVsLmZvcm1zW2ldIHx8IChtb2RlbC5wbGF5ZXJDaGFyYWN0ZXJGb3JtSWR4ID09PSBpICYmICFzaG93TWUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXN0cm95Rm9ybShpKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRm9ybVZpZXdBcnJheS5wcm90b3R5cGUuZ2V0UmVtb3RlUmVmcklkID0gZnVuY3Rpb24gKGNsaWVudHNpZGVSZWZySWQpIHtcbiAgICAgICAgaWYgKGNsaWVudHNpZGVSZWZySWQgPCAweGZmMDAwMDAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBmdW5jdGlvbiBpcyBvbmx5IGZvciAweGZmIGZvcm1zXCIpO1xuICAgICAgICB2YXIgZm9ybVZpZXcgPSB0aGlzLmZvcm1WaWV3cy5maW5kKGZ1bmN0aW9uIChmb3JtVmlldykge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1WaWV3ICYmIGZvcm1WaWV3LmdldExvY2FsUmVmcklkKCkgPT09IGNsaWVudHNpZGVSZWZySWQ7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZm9ybVZpZXcgPyBmb3JtVmlldy5nZXRSZW1vdGVSZWZySWQoKSA6IDA7XG4gICAgfTtcbiAgICBGb3JtVmlld0FycmF5LnByb3RvdHlwZS5nZXRMb2NhbFJlZnJJZCA9IGZ1bmN0aW9uIChyZW1vdGVSZWZySWQpIHtcbiAgICAgICAgaWYgKHJlbW90ZVJlZnJJZCA8IDB4ZmYwMDAwMDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGZ1bmN0aW9uIGlzIG9ubHkgZm9yIDB4ZmYgZm9ybXNcIik7XG4gICAgICAgIHZhciBmb3JtVmlldyA9IHRoaXMuZm9ybVZpZXdzLmZpbmQoZnVuY3Rpb24gKGZvcm1WaWV3KSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybVZpZXcgJiYgZm9ybVZpZXcuZ2V0UmVtb3RlUmVmcklkKCkgPT09IHJlbW90ZVJlZnJJZDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmb3JtVmlldyA/IGZvcm1WaWV3LmdldExvY2FsUmVmcklkKCkgOiAwO1xuICAgIH07XG4gICAgRm9ybVZpZXdBcnJheS5wcm90b3R5cGUuZ2V0TnRoRm9ybVZpZXcgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb3JtVmlld3NbaV07XG4gICAgfTtcbiAgICBGb3JtVmlld0FycmF5LnByb3RvdHlwZS5nZXRGb3JtVmlld3NBcnJheUxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybVZpZXdzLmxlbmd0aDtcbiAgICB9O1xuICAgIHJldHVybiBGb3JtVmlld0FycmF5O1xufSgpKTtcbmV4cG9ydCB7IEZvcm1WaWV3QXJyYXkgfTtcbiIsImltcG9ydCB7IHN0b3JhZ2UgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbnN0b3JhZ2VbXCJob3N0QXR0ZW1wdHNcIl0gPSBbXTtcbmV4cG9ydCB2YXIgdHJ5SG9zdCA9IGZ1bmN0aW9uICh0YXJnZXRSZW1vdGVJZCkge1xuICAgIHN0b3JhZ2VbXCJob3N0QXR0ZW1wdHNcIl0ucHVzaCh0YXJnZXRSZW1vdGVJZCk7XG59O1xuZXhwb3J0IHZhciBuZXh0SG9zdEF0dGVtcHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGFyciA9IHN0b3JhZ2VbXCJob3N0QXR0ZW1wdHNcIl07XG4gICAgaWYgKGFyci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIGFyci5zaGlmdCgpO1xufTtcbmV4cG9ydCB2YXIgbGFzdFRyeUhvc3QgPSB7fTtcbiIsImltcG9ydCB7IE9iamVjdFJlZmVyZW5jZSwgR2FtZSwgVGV4dHVyZVNldCwgTmV0SW1tZXJzZSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgYXBwbHlJbnZlbnRvcnkgfSBmcm9tIFwiLi4vc3luYy9pbnZlbnRvcnlcIjtcbmltcG9ydCB7IGxvZ0Vycm9yLCBsb2dUcmFjZSB9IGZyb20gXCIuLi9sb2dnaW5nXCI7XG4vLyBGb3IgMHhmZjAwMDAwMCsgdXNlZCBmcm9tIEZvcm1WaWV3XG4vLyBGb3Igb2JqZWN0cyBmcm9tIG1hc3RlciBmaWxlcyB1c2VkIGRpcmVjdGx5IGZyb20gcmVtb3RlU2VydmVyLnRzXG52YXIgTW9kZWxBcHBseVV0aWxzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE1vZGVsQXBwbHlVdGlscygpIHtcbiAgICB9XG4gICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJbnZlbnRvcnkgPSBmdW5jdGlvbiAocmVmciwgaW52ZW50b3J5KSB7XG4gICAgICAgIGFwcGx5SW52ZW50b3J5KHJlZnIsIGludmVudG9yeSwgZmFsc2UsIHRydWUpO1xuICAgIH07XG4gICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJc09wZW4gPSBmdW5jdGlvbiAocmVmciwgaXNPcGVuKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgcmVmci5zZXRPcGVuKGlzT3Blbik7XG4gICAgICAgIC8vIFNlZSBhbHNvIG9iamVjdFJlZmVyZW5jZUV4LnRzXG4gICAgICAgIHZhciBjYXZlR1NlY3JldERvb3IwMSA9IDB4NmY3MDM7XG4gICAgICAgIC8vIFRPRE86IGFkZCBtb3JlIGFjdGl2YXRvcnMgdG8gc3VwcG9ydCBtb3JlIGNlbGxzXG4gICAgICAgIHZhciBwYXJlbnRBY3RpdmF0b3JJZCA9IDB4NDYwY2E7XG4gICAgICAgIGlmICgoKF9hID0gcmVmci5nZXRCYXNlT2JqZWN0KCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRGb3JtSUQoKSkgPT09IGNhdmVHU2VjcmV0RG9vcjAxKSB7XG4gICAgICAgICAgICB2YXIgb3Blbk9yT3BlbmluZyA9IFsxLCAyXS5pbmNsdWRlcyhyZWZyLmdldE9wZW5TdGF0ZSgpKTtcbiAgICAgICAgICAgIGlmIChvcGVuT3JPcGVuaW5nKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc09wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmci5hY3RpdmF0ZShPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm0ocGFyZW50QWN0aXZhdG9ySWQpKSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghb3Blbk9yT3BlbmluZykge1xuICAgICAgICAgICAgICAgIGlmIChpc09wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmci5hY3RpdmF0ZShPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm0ocGFyZW50QWN0aXZhdG9ySWQpKSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJc0Rpc2FibGVkID0gZnVuY3Rpb24gKHJlZnIsIGRpc2FibGVkKSB7XG4gICAgICAgIHZhciB3YXNEaXNhYmxlZCA9IHJlZnIuaXNEaXNhYmxlZCgpO1xuICAgICAgICBpZiAod2FzRGlzYWJsZWQgPT0gZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHJlZnIuZGlzYWJsZShmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZWZyLmVuYWJsZSh0cnVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxJc0hhcnZlc3RlZCA9IGZ1bmN0aW9uIChyZWZyLCBpc0hhcnZlc3RlZCkge1xuICAgICAgICB2YXIgYmFzZSA9IHJlZnIuZ2V0QmFzZU9iamVjdCgpO1xuICAgICAgICBpZiAoYmFzZSkge1xuICAgICAgICAgICAgdmFyIHQgPSBiYXNlLmdldFR5cGUoKTtcbiAgICAgICAgICAgIGlmICh0ID09IDM4IC8qIEZvcm1UeXBlLlRyZWUgKi8gfHwgdCA9PSAzOSAvKiBGb3JtVHlwZS5GbG9yYSAqLykge1xuICAgICAgICAgICAgICAgIHZhciB3YXNIYXJ2ZXN0ZWQgPSByZWZyLmlzSGFydmVzdGVkKCk7XG4gICAgICAgICAgICAgICAgaWYgKGlzSGFydmVzdGVkICE9IHdhc0hhcnZlc3RlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYWMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNIYXJ2ZXN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMjA7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjID0gR2FtZS5maW5kUmFuZG9tQWN0b3IocmVmci5nZXRQb3NpdGlvblgoKSwgcmVmci5nZXRQb3NpdGlvblkoKSwgcmVmci5nZXRQb3NpdGlvblooKSwgMTAwMDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYyAmJiBhYy5nZXRGb3JtSUQoKSAhPT0gMHgxNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzSGFydmVzdGVkICYmIGFjICYmIGFjLmdldEZvcm1JRCgpICE9PSAweDE0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyLmFjdGl2YXRlKGFjLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZnIuc2V0SGFydmVzdGVkKGlzSGFydmVzdGVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpZF8xID0gcmVmci5nZXRGb3JtSUQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZnIuZGlzYWJsZShmYWxzZSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3RvcmVkUmVmciA9IE9iamVjdFJlZmVyZW5jZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KGlkXzEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdG9yZWRSZWZyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RvcmVkUmVmci5lbmFibGUoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHdhc0hhcnZlc3RlZCA9IHJlZnIuaXNEaXNhYmxlZCgpO1xuICAgICAgICAgICAgICAgIGlmIChpc0hhcnZlc3RlZCAhPSB3YXNIYXJ2ZXN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzSGFydmVzdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWRfMiA9IHJlZnIuZ2V0Rm9ybUlEKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyLmRpc2FibGUoZmFsc2UpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN0b3JlZFJlZnIgPSBPYmplY3RSZWZlcmVuY2UuZnJvbShHYW1lLmdldEZvcm1FeChpZF8yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3RvcmVkUmVmciAmJiAhcmVzdG9yZWRSZWZyLmlzRGlzYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0b3JlZFJlZnIuZGVsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW9uIHRha2VzIHRpbWUsIHNvIGluIHByYWN0aWNlIHRoaXMgd291bGQgYmUgY2FsbGVkIGEgbG90IG9mIHRpbWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyLmVuYWJsZSh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgTW9kZWxBcHBseVV0aWxzLmFwcGx5TW9kZWxOb2RlVGV4dHVyZVNldCA9IGZ1bmN0aW9uIChyZWZyLCBzZXROb2RlVGV4dHVyZVNldCkge1xuICAgICAgICBpZiAoc2V0Tm9kZVRleHR1cmVTZXQpIHtcbiAgICAgICAgICAgIHNldE5vZGVUZXh0dXJlU2V0LmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmlyc3RQZXJzb24gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgdGV4dHVyZVNldCA9IFRleHR1cmVTZXQuZnJvbShHYW1lLmdldEZvcm1FeChlbGVtZW50LnRleHR1cmVTZXRJZCkpO1xuICAgICAgICAgICAgICAgIGlmICh0ZXh0dXJlU2V0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIE5ldEltbWVyc2Uuc2V0Tm9kZVRleHR1cmVTZXQocmVmciwgZWxlbWVudC5ub2RlTmFtZSwgdGV4dHVyZVNldCwgZmlyc3RQZXJzb24pO1xuICAgICAgICAgICAgICAgICAgICBsb2dUcmFjZShcIk1vZGVsQXBwbHlVdGlsc1wiLCByZWZyLmdldEZvcm1JRCgpLnRvU3RyaW5nKDE2KSwgXCJBcHBsaWVkIHRleHR1cmUgc2V0XCIsIGVsZW1lbnQudGV4dHVyZVNldElkLnRvU3RyaW5nKDE2KSwgXCJ0b1wiLCBlbGVtZW50Lm5vZGVOYW1lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ0Vycm9yKFwiTW9kZWxBcHBseVV0aWxzXCIsIHJlZnIuZ2V0Rm9ybUlEKCkudG9TdHJpbmcoMTYpLCBcIkZhaWxlZCB0byBhcHBseSB0ZXh0dXJlIHNldFwiLCBlbGVtZW50LnRleHR1cmVTZXRJZC50b1N0cmluZygxNiksIFwidG9cIiwgZWxlbWVudC5ub2RlTmFtZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE1vZGVsQXBwbHlVdGlscy5hcHBseU1vZGVsTm9kZVNjYWxlID0gZnVuY3Rpb24gKHJlZnIsIHNldE5vZGVTY2FsZSkge1xuICAgICAgICBpZiAoc2V0Tm9kZVNjYWxlKSB7XG4gICAgICAgICAgICBzZXROb2RlU2NhbGUuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHZhciBmaXJzdFBlcnNvbiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIE5ldEltbWVyc2Uuc2V0Tm9kZVNjYWxlKHJlZnIsIGVsZW1lbnQubm9kZU5hbWUsIGVsZW1lbnQuc2NhbGUsIGZpcnN0UGVyc29uKTtcbiAgICAgICAgICAgICAgICBsb2dUcmFjZShcIk1vZGVsQXBwbHlVdGlsc1wiLCByZWZyLmdldEZvcm1JRCgpLnRvU3RyaW5nKDE2KSwgXCJBcHBsaWVkIG5vZGUgc2NhbGVcIiwgZWxlbWVudC5zY2FsZSwgXCJ0b1wiLCBlbGVtZW50Lm5vZGVOYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gTW9kZWxBcHBseVV0aWxzO1xufSgpKTtcbmV4cG9ydCB7IE1vZGVsQXBwbHlVdGlscyB9O1xuIiwiaW1wb3J0IHsgR2FtZSB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgT2JqZWN0UmVmZXJlbmNlRXggfSBmcm9tIFwiLi4vZXh0ZW5zaW9ucy9vYmplY3RSZWZlcmVuY2VFeFwiO1xudmFyIFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlcigpIHtcbiAgICB9XG4gICAgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci51cGRhdGVEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHZhciBwbGF5ZXIgPSBHYW1lLmdldFBsYXllcigpO1xuICAgICAgICBpZiAoIXBsYXllcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5KdW1wU3RhdGUgPSBwbGF5ZXIuZ2V0QW5pbWF0aW9uVmFyaWFibGVCb29sKFwiYkluSnVtcFN0YXRlXCIpO1xuICAgICAgICB0aGlzLndvcmxkT3JDZWxsID0gT2JqZWN0UmVmZXJlbmNlRXguZ2V0V29ybGRPckNlbGwocGxheWVyKTtcbiAgICAgICAgdGhpcy5jcm9zc2hhaXJSZWZJZCA9ICgoX2EgPSBHYW1lLmdldEN1cnJlbnRDcm9zc2hhaXJSZWYoKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldEZvcm1JRCgpKSB8fCAwO1xuICAgIH07XG4gICAgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci5pc0luSnVtcFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pbkp1bXBTdGF0ZTtcbiAgICB9O1xuICAgIFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIuZ2V0V29ybGRPckNlbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndvcmxkT3JDZWxsO1xuICAgIH07XG4gICAgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci5nZXRDcm9zc2hhaXJSZWZJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3Jvc3NoYWlyUmVmSWQ7XG4gICAgfTtcbiAgICBQbGF5ZXJDaGFyYWN0ZXJEYXRhSG9sZGVyLmluSnVtcFN0YXRlID0gZmFsc2U7XG4gICAgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci53b3JsZE9yQ2VsbCA9IDA7XG4gICAgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlci5jcm9zc2hhaXJSZWZJZCA9IDA7XG4gICAgcmV0dXJuIFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXI7XG59KCkpO1xuZXhwb3J0IHsgUGxheWVyQ2hhcmFjdGVyRGF0YUhvbGRlciB9O1xuIiwiaW1wb3J0IHsgT2JqZWN0UmVmZXJlbmNlLCBHYW1lLCBBY3RvciB9IGZyb20gXCJza3lyaW1QbGF0Zm9ybVwiO1xuaW1wb3J0IHsgYXBwbHlUaW50cyB9IGZyb20gXCIuLi9zeW5jL2FwcGVhcmFuY2VcIjtcbmltcG9ydCB7IE9iamVjdFJlZmVyZW5jZUV4IH0gZnJvbSBcIi4uL2V4dGVuc2lvbnMvb2JqZWN0UmVmZXJlbmNlRXhcIjtcbnZhciBTcGF3blByb2Nlc3MgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU3Bhd25Qcm9jZXNzKGFwcGVhcmFuY2UsIHBvcywgcmVmcklkLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICAgIHZhciByZWZyID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgocmVmcklkKSk7XG4gICAgICAgIGlmICghcmVmciB8fCByZWZyLmdldEZvcm1JRCgpICE9PSByZWZySWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZWZyLnNldFBvc2l0aW9uLmFwcGx5KHJlZnIsIHBvcykudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5lbmFibGUoYXBwZWFyYW5jZSwgcmVmcklkKTsgfSk7XG4gICAgfVxuICAgIFNwYXduUHJvY2Vzcy5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKGFwcGVhcmFuY2UsIHJlZnJJZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVmciA9IE9iamVjdFJlZmVyZW5jZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHJlZnJJZCkpO1xuICAgICAgICBpZiAoIXJlZnIgfHwgcmVmci5nZXRGb3JtSUQoKSAhPT0gcmVmcklkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFjID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICAgICAgaWYgKGFjICYmIGFwcGVhcmFuY2UpIHtcbiAgICAgICAgICAgIGFwcGx5VGludHMoYWMsIGFwcGVhcmFuY2UpO1xuICAgICAgICB9XG4gICAgICAgIHJlZnIuZW5hYmxlKGZhbHNlKS50aGVuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnJlc3VycmVjdChyZWZySWQpOyB9KTtcbiAgICB9O1xuICAgIFNwYXduUHJvY2Vzcy5wcm90b3R5cGUucmVzdXJyZWN0ID0gZnVuY3Rpb24gKHJlZnJJZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVmciA9IE9iamVjdFJlZmVyZW5jZS5mcm9tKEdhbWUuZ2V0Rm9ybUV4KHJlZnJJZCkpO1xuICAgICAgICBpZiAoIXJlZnIgfHwgcmVmci5nZXRGb3JtSUQoKSAhPT0gcmVmcklkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFjID0gQWN0b3IuZnJvbShyZWZyKTtcbiAgICAgICAgaWYgKGFjKSB7XG4gICAgICAgICAgICByZXR1cm4gYWMucmVzdXJyZWN0KCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIE9iamVjdFJlZmVyZW5jZUV4LmRlYWxXaXRoUmVmKHJlZnIsIHJlZnIuZ2V0QmFzZU9iamVjdCgpKTtcbiAgICAgICAgcmV0dXJuIHJlZnIuc2V0TW90aW9uVHlwZSg0IC8qIE1vdGlvblR5cGUuS2V5ZnJhbWVkICovLCB0cnVlKS50aGVuKHRoaXMuY2FsbGJhY2spO1xuICAgIH07XG4gICAgcmV0dXJuIFNwYXduUHJvY2Vzcztcbn0oKSk7XG5leHBvcnQgeyBTcGF3blByb2Nlc3MgfTtcbiIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBGb3JtVmlld0FycmF5IH0gZnJvbSAnLi9mb3JtVmlld0FycmF5JztcbmltcG9ydCB7IFBsYXllckNoYXJhY3RlckRhdGFIb2xkZXIgfSBmcm9tICcuL3BsYXllckNoYXJhY3RlckRhdGFIb2xkZXInO1xuaW1wb3J0IHsgQ2xpZW50TGlzdGVuZXIgfSBmcm9tICcuLi9zZXJ2aWNlcy9zZXJ2aWNlcy9jbGllbnRMaXN0ZW5lcic7XG5pbXBvcnQgeyBsb2dUcmFjZSB9IGZyb20gXCIuLi9sb2dnaW5nXCI7XG5pbXBvcnQgeyBTaW5nbGVQbGF5ZXJTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL3NlcnZpY2VzL3NpbmdsZVBsYXllclNlcnZpY2VcIjtcbmltcG9ydCB7IFJlbW90ZVNlcnZlciB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zZXJ2aWNlcy9yZW1vdGVTZXJ2ZXJcIjtcbnZhciBXb3JsZFZpZXcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFdvcmxkVmlldywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBXb3JsZFZpZXcoc3AsIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3AgPSBzcDtcbiAgICAgICAgX3RoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXI7XG4gICAgICAgIGNvbnRyb2xsZXIub24oXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25VcGRhdGUoKTsgfSk7XG4gICAgICAgIGNvbnRyb2xsZXIub25jZShcInVwZGF0ZVwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vbmNlVXBkYXRlKCk7IH0pO1xuICAgICAgICBfdGhpcy5zdGF0ZSA9IF90aGlzLm1ha2VFbXB0eVN0YXRlKCk7XG4gICAgICAgIHZhciBvbGRWaWV3ID0gX3RoaXMuc3Auc3RvcmFnZVtcInZpZXdcIl07XG4gICAgICAgIC8vIGNhbid0IHVzZSBpbnN0YW5jZW9mIGhlcmUgYmVjYXVzZSBlYWNoIGhvdCByZWxvYWQgY3JlYXRlcyBhIG5ldyBjbGFzc1xuICAgICAgICBfdGhpcy5vbGRWaWV3ID0gdHlwZW9mIG9sZFZpZXcgPT09IFwib2JqZWN0XCIgPyBvbGRWaWV3IDogdW5kZWZpbmVkO1xuICAgICAgICBfdGhpcy5zcC5zdG9yYWdlW1widmlld1wiXSA9IF90aGlzO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFdvcmxkVmlldy5wcm90b3R5cGUuZ2V0UmVtb3RlUmVmcklkID0gZnVuY3Rpb24gKGNsaWVudHNpZGVSZWZySWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGUuZm9ybVZpZXdzLmdldFJlbW90ZVJlZnJJZChjbGllbnRzaWRlUmVmcklkKTtcbiAgICB9O1xuICAgIFdvcmxkVmlldy5wcm90b3R5cGUuZ2V0TG9jYWxSZWZySWQgPSBmdW5jdGlvbiAocmVtb3RlUmVmcklkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmZvcm1WaWV3cy5nZXRMb2NhbFJlZnJJZChyZW1vdGVSZWZySWQpO1xuICAgIH07XG4gICAgV29ybGRWaWV3LnByb3RvdHlwZS5zeW5jRm9ybUFycmF5ID0gZnVuY3Rpb24gKG1vZGVsKSB7XG4gICAgICAgIHZhciBzZXR0aW5ncyA9IHRoaXMuc3Auc2V0dGluZ3M7XG4gICAgICAgIHZhciBzaG93TWUgPSBzZXR0aW5nc1snc2t5bXA1LWNsaWVudCddWydzaG93LW1lJ107XG4gICAgICAgIHRoaXMuc3RhdGUuZm9ybVZpZXdzLnN5bmNGb3JtVmlldyhtb2RlbCwgISFzaG93TWUpO1xuICAgIH07XG4gICAgV29ybGRWaWV3LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnN0YXRlLmZvcm1WaWV3cy5yZXNpemUoMCk7XG4gICAgICAgIHRoaXMuc3RhdGUuY2xvbmVGb3JtVmlld3MucmVzaXplKDApOyAvLyBSZWNlbnJseSBhZGRlZCwgbm90IHRlc3RlZCBpZiBpdCdzIG5lZWRlZFxuICAgICAgICB0aGlzLnN0YXRlID0gdGhpcy5tYWtlRW1wdHlTdGF0ZSgpO1xuICAgIH07XG4gICAgV29ybGRWaWV3LnByb3RvdHlwZS5nZXRGb3JtVmlld3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmZvcm1WaWV3cztcbiAgICB9O1xuICAgIFdvcmxkVmlldy5wcm90b3R5cGUub25VcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVzZXRBbGxGb3JtVmlld3NJZlBsYXllckNoYW5nZWRXb3JsZCgpO1xuICAgICAgICB2YXIgc2luZ2xlUGxheWVyU2VydmljZSA9IHRoaXMuY29udHJvbGxlci5sb29rdXBMaXN0ZW5lcihTaW5nbGVQbGF5ZXJTZXJ2aWNlKTtcbiAgICAgICAgaWYgKCFzaW5nbGVQbGF5ZXJTZXJ2aWNlLmlzU2luZ2xlUGxheWVyKSB7XG4gICAgICAgICAgICB2YXIgbW9kZWxTb3VyY2UgPSB0aGlzLmNvbnRyb2xsZXIubG9va3VwTGlzdGVuZXIoUmVtb3RlU2VydmVyKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlV29ybGQobW9kZWxTb3VyY2UuZ2V0V29ybGRNb2RlbCgpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgV29ybGRWaWV3LnByb3RvdHlwZS5vbmNlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5vbGRWaWV3KSB7XG4gICAgICAgICAgICB0aGlzLm9sZFZpZXcuZGVzdHJveSgpO1xuICAgICAgICAgICAgdGhpcy5vbGRWaWV3ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgbG9nVHJhY2UodGhpcywgJ1ByZXZpb3VzIFZpZXcgZGVzdHJveWVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53YWl0R2FtZVRpbWVBbmRBbGxvd0Zvcm1WaWV3VXBkYXRlKDEuMCk7XG4gICAgfTtcbiAgICBXb3JsZFZpZXcucHJvdG90eXBlLnJlc2V0QWxsRm9ybVZpZXdzSWZQbGF5ZXJDaGFuZ2VkV29ybGQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgICAgIHZhciBwYyA9IHRoaXMuc3AuR2FtZS5nZXRQbGF5ZXIoKTtcbiAgICAgICAgdmFyIHBjV29ybGRPckNlbGwgPSAocGMuZ2V0V29ybGRTcGFjZSgpIHx8IHBjLmdldFBhcmVudENlbGwoKSkuZ2V0Rm9ybUlEKCk7XG4gICAgICAgIGlmIChzdGF0ZS5wY1dvcmxkT3JDZWxsICE9PSBwY1dvcmxkT3JDZWxsKSB7XG4gICAgICAgICAgICBpZiAoc3RhdGUucGNXb3JsZE9yQ2VsbCkge1xuICAgICAgICAgICAgICAgIGxvZ1RyYWNlKHRoaXMsICdSZXNldCBhbGwgZm9ybSB2aWV3cycpO1xuICAgICAgICAgICAgICAgIHN0YXRlLmZvcm1WaWV3cy5yZXNpemUoMCk7XG4gICAgICAgICAgICAgICAgc3RhdGUuY2xvbmVGb3JtVmlld3MucmVzaXplKDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RhdGUucGNXb3JsZE9yQ2VsbCA9IHBjV29ybGRPckNlbGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFdvcmsgYXJvdW5kIHNob3dSYWNlTWVudSBpc3N1ZVxuICAgIC8vIERlZmF1bHQgbm9yZCBpbiBSYWNlIE1lbnUgd2lsbCBoYXZlIHZlcnkgdWdseSBmYWNlXG4gICAgLy8gSWYgb3RoZXIgcGxheWVycyBhcmUgc3Bhd25pbmcgd2hlbiB3ZSBzaG93IHRoaXMgbWVudVxuICAgIC8vIFRPRE86IHNlcGFyYXRlIGxpc3RlbmVyXG4gICAgV29ybGRWaWV3LnByb3RvdHlwZS53YWl0R2FtZVRpbWVBbmRBbGxvd0Zvcm1WaWV3VXBkYXRlID0gZnVuY3Rpb24gKHNlY29uZHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gV2FpdCAxcyBnYW1lIHRpbWUgKHRpbWUgc3BlbnQgaW4gUmFjZSBNZW51IGlzbid0IGNvdW50ZWQpXG4gICAgICAgIHRoaXMuc3AuVXRpbGl0eS53YWl0KHNlY29uZHMpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuc3RhdGUuYWxsb3dVcGRhdGUgPSB0cnVlO1xuICAgICAgICAgICAgbG9nVHJhY2UoX3RoaXMsICdVcGRhdGUgaXMgbm93IGFsbG93ZWQnKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBXb3JsZFZpZXcucHJvdG90eXBlLnNldEZvcm1WaWV3VXBkYXRlQWxsb3dlZCA9IGZ1bmN0aW9uIChhbGxvd2VkKSB7XG4gICAgICAgIHRoaXMuc3RhdGUuYWxsb3dVcGRhdGUgPSBhbGxvd2VkO1xuICAgICAgICBsb2dUcmFjZSh0aGlzLCAnVXBkYXRlIGlzIG5vdycsIGFsbG93ZWQgPyAnYWxsb3dlZCcgOiAnZGlzYWxsb3dlZCcpO1xuICAgIH07XG4gICAgV29ybGRWaWV3LnByb3RvdHlwZS51cGRhdGVXb3JsZCA9IGZ1bmN0aW9uIChtb2RlbCkge1xuICAgICAgICB2YXIgc2V0dGluZ3MgPSB0aGlzLnNwLnNldHRpbmdzO1xuICAgICAgICB2YXIgc3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgICAgICBpZiAoIXN0YXRlLmFsbG93VXBkYXRlKSB7XG4gICAgICAgICAgICBtb2RlbCA9IHtcbiAgICAgICAgICAgICAgICBmb3JtczogW10sXG4gICAgICAgICAgICAgICAgcGxheWVyQ2hhcmFjdGVyRm9ybUlkeDogbW9kZWwucGxheWVyQ2hhcmFjdGVyRm9ybUlkeCxcbiAgICAgICAgICAgICAgICBwbGF5ZXJDaGFyYWN0ZXJSZWZySWQ6IG1vZGVsLnBsYXllckNoYXJhY3RlclJlZnJJZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2tpcFVwZGF0ZXMgPSBzZXR0aW5nc1snc2t5bXA1LWNsaWVudCddWydza2lwVXBkYXRlcyddO1xuICAgICAgICAvLyBza2lwIDUwJSBvZiB1cGRhdGVzIGlmIHNwZWNpZmllZCBpbiB0aGUgc2V0dGluZ3NcbiAgICAgICAgc3RhdGUuY291bnRlciA9ICFzdGF0ZS5jb3VudGVyO1xuICAgICAgICBpZiAoc3RhdGUuY291bnRlciAmJiBza2lwVXBkYXRlcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRlLmZvcm1WaWV3cy5yZXNpemUobW9kZWwuZm9ybXMubGVuZ3RoKTtcbiAgICAgICAgdmFyIHNob3dNZSA9IHNldHRpbmdzWydza3ltcDUtY2xpZW50J11bJ3Nob3ctbWUnXTtcbiAgICAgICAgdmFyIHNob3dDbG9uZXMgPSBzZXR0aW5nc1snc2t5bXA1LWNsaWVudCddWydzaG93LWNsb25lcyddO1xuICAgICAgICBQbGF5ZXJDaGFyYWN0ZXJEYXRhSG9sZGVyLnVwZGF0ZURhdGEoKTtcbiAgICAgICAgc3RhdGUuZm9ybVZpZXdzLnVwZGF0ZUFsbChtb2RlbCwgISFzaG93TWUsIGZhbHNlKTtcbiAgICAgICAgaWYgKHNob3dDbG9uZXMpIHtcbiAgICAgICAgICAgIHN0YXRlLmNsb25lRm9ybVZpZXdzLnVwZGF0ZUFsbChtb2RlbCwgZmFsc2UsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3RhdGUuY2xvbmVGb3JtVmlld3MucmVzaXplKDApO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBXb3JsZFZpZXcucHJvdG90eXBlLm1ha2VFbXB0eVN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZm9ybVZpZXdzOiBuZXcgRm9ybVZpZXdBcnJheSgpLFxuICAgICAgICAgICAgY2xvbmVGb3JtVmlld3M6IG5ldyBGb3JtVmlld0FycmF5KCksXG4gICAgICAgICAgICBhbGxvd1VwZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICBwY1dvcmxkT3JDZWxsOiAwLFxuICAgICAgICAgICAgY291bnRlcjogZmFsc2UsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gV29ybGRWaWV3O1xufShDbGllbnRMaXN0ZW5lcikpO1xuZXhwb3J0IHsgV29ybGRWaWV3IH07XG4iLCJpbXBvcnQgeyBHYW1lLCBPYmplY3RSZWZlcmVuY2UsIHN0b3JhZ2UgfSBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IFNwQXBpSW50ZXJhY3RvciB9IGZyb20gJy4uL3NlcnZpY2VzL3NwQXBpSW50ZXJhY3Rvcic7XG5pbXBvcnQgeyBSZW1vdGVTZXJ2ZXIgfSBmcm9tIFwiLi4vc2VydmljZXMvc2VydmljZXMvcmVtb3RlU2VydmVyXCI7XG5leHBvcnQgdmFyIGdldFZpZXdGcm9tU3RvcmFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzID0gc3RvcmFnZVtcInZpZXdcIl07XG4gICAgLy8gY2FuJ3QgdXNlIGluc3RhbmNlb2YgaGVyZSBiZWNhdXNlIGVhY2ggaG90IHJlbG9hZCBjcmVhdGVzIGEgbmV3IGNsYXNzXG4gICAgaWYgKHR5cGVvZiByZXMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbn07XG5leHBvcnQgdmFyIGxvY2FsSWRUb1JlbW90ZUlkID0gZnVuY3Rpb24gKGxvY2FsRm9ybUlkLCBuZXdDYXN0KSB7XG4gICAgaWYgKG5ld0Nhc3QgPT09IHZvaWQgMCkgeyBuZXdDYXN0ID0gZmFsc2U7IH1cbiAgICBpZiAobmV3Q2FzdCAmJiBsb2NhbEZvcm1JZCA9PSAweDE0KSB7XG4gICAgICAgIHJldHVybiBTcEFwaUludGVyYWN0b3IuZ2V0Q29udHJvbGxlckluc3RhbmNlKCkubG9va3VwTGlzdGVuZXIoUmVtb3RlU2VydmVyKS5nZXRNeVJlbW90ZVJlZnJJZCgpO1xuICAgIH1cbiAgICBpZiAobG9jYWxGb3JtSWQgPj0gMHhmZjAwMDAwMCkge1xuICAgICAgICB2YXIgdmlldyA9IGdldFZpZXdGcm9tU3RvcmFnZSgpO1xuICAgICAgICBpZiAoIXZpZXcpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIGxvY2FsRm9ybUlkID0gdmlldy5nZXRSZW1vdGVSZWZySWQobG9jYWxGb3JtSWQpO1xuICAgICAgICBpZiAoIWxvY2FsRm9ybUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICAvLyBzZXJ2ZXJzaWRlIGlkcyBhcmUgNjRiaXRcbiAgICAgICAgaWYgKGxvY2FsRm9ybUlkID49IDB4MTAwMDAwMDAwKSB7XG4gICAgICAgICAgICBsb2NhbEZvcm1JZCAtPSAweDEwMDAwMDAwMDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbG9jYWxGb3JtSWQ7XG59O1xuZXhwb3J0IHZhciByZW1vdGVJZFRvTG9jYWxJZCA9IGZ1bmN0aW9uIChyZW1vdGVGb3JtSWQpIHtcbiAgICBpZiAocmVtb3RlRm9ybUlkID49IDB4ZmYwMDAwMDApIHtcbiAgICAgICAgdmFyIHZpZXcgPSBnZXRWaWV3RnJvbVN0b3JhZ2UoKTtcbiAgICAgICAgaWYgKCF2aWV3KSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICByZW1vdGVGb3JtSWQgPSB2aWV3LmdldExvY2FsUmVmcklkKHJlbW90ZUZvcm1JZCk7XG4gICAgICAgIGlmICghcmVtb3RlRm9ybUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVtb3RlRm9ybUlkO1xufTtcbmV4cG9ydCB2YXIgZ2V0T2JqZWN0UmVmZXJlbmNlID0gZnVuY3Rpb24gKGkpIHtcbiAgICB2YXIgdmlldyA9IGdldFZpZXdGcm9tU3RvcmFnZSgpO1xuICAgIGlmICh2aWV3KSB7XG4gICAgICAgIHZhciBmb3JtVmlldyA9IHZpZXcuZ2V0Rm9ybVZpZXdzKCkuZ2V0TnRoRm9ybVZpZXcoaSk7XG4gICAgICAgIGlmIChmb3JtVmlldykge1xuICAgICAgICAgICAgdmFyIHJlZnJJZCA9IGZvcm1WaWV3LmdldExvY2FsUmVmcklkKCk7XG4gICAgICAgICAgICBpZiAocmVmcklkID4gMCkge1xuICAgICAgICAgICAgICAgIHZhciByZWZyID0gT2JqZWN0UmVmZXJlbmNlLmZyb20oR2FtZS5nZXRGb3JtRXgocmVmcklkKSk7XG4gICAgICAgICAgICAgICAgaWYgKHJlZnIgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlZnI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImNyeXB0b1wiKTsiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJmc1wiKTsiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJpbnNwZWN0b3JcIik7IiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwibm9kZTpjcnlwdG9cIik7IiwibW9kdWxlLmV4cG9ydHMgPSBza3lyaW1QbGF0Zm9ybTsiLCJpbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJy4vaW5kZXguanMnXG5cbmV4cG9ydCB7IEV2ZW50RW1pdHRlciB9XG5leHBvcnQgZGVmYXVsdCBFdmVudEVtaXR0ZXJcbiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgeyBHYW1lLCBVdGlsaXR5LCBvbmNlIH0gZnJvbSBcInNreXJpbVBsYXRmb3JtXCI7XG5pbXBvcnQgeyBTa3ltcENsaWVudCB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL3NreW1wQ2xpZW50XCI7XG5pbXBvcnQgKiBhcyBzcCBmcm9tIFwic2t5cmltUGxhdGZvcm1cIjtcbmltcG9ydCB7IEJsb2NrUGFweXJ1c0V2ZW50c1NlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL3NlcnZpY2VzL2Jsb2NrUGFweXJ1c0V2ZW50c1NlcnZpY2UnO1xuaW1wb3J0IHsgRW5mb3JjZUxpbWl0YXRpb25zU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvc2VydmljZXMvZW5mb3JjZUxpbWl0YXRpb25zU2VydmljZSc7XG5pbXBvcnQgeyBMb2FkR2FtZVNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL3NlcnZpY2VzL2xvYWRHYW1lU2VydmljZSc7XG5pbXBvcnQgeyBTZW5kSW5wdXRzU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvc2VydmljZXMvc2VuZElucHV0c1NlcnZpY2UnO1xuaW1wb3J0IHsgU2luZ2xlUGxheWVyU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvc2VydmljZXMvc2luZ2xlUGxheWVyU2VydmljZSc7XG5pbXBvcnQgeyBTcEFwaUludGVyYWN0b3IgfSBmcm9tICcuL3NlcnZpY2VzL3NwQXBpSW50ZXJhY3Rvcic7XG5pbXBvcnQgeyBUaW1lU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL3RpbWVTZXJ2aWNlXCI7XG5pbXBvcnQgeyBTcFZlcnNpb25DaGVja1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9zcFZlcnNpb25DaGVja1NlcnZpY2VcIjtcbmltcG9ydCB7IENvbnNvbGVDb21tYW5kc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9jb25zb2xlQ29tbWFuZHNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBMYXN0SW52U2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2xhc3RJbnZTZXJ2aWNlXCI7XG5pbXBvcnQgeyBBY3RpdmF0aW9uU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2FjdGl2YXRpb25TZXJ2aWNlXCI7XG5pbXBvcnQgeyBDcmFmdFNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9jcmFmdFNlcnZpY2VcIjtcbmltcG9ydCB7IERyb3BJdGVtU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2Ryb3BJdGVtU2VydmljZVwiO1xuaW1wb3J0IHsgSGl0U2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2hpdFNlcnZpY2VcIjtcbmltcG9ydCB7IFJhZ2RvbGxTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvcmFnZG9sbFNlcnZpY2VcIjtcbmltcG9ydCB7IERlYXRoU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2RlYXRoU2VydmljZVwiO1xuaW1wb3J0IHsgQ29udGFpbmVyc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9jb250YWluZXJzU2VydmljZVwiO1xuaW1wb3J0IHsgTmV0d29ya2luZ1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9uZXR3b3JraW5nU2VydmljZVwiO1xuaW1wb3J0IHsgUmVtb3RlU2VydmVyIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvcmVtb3RlU2VydmVyXCI7XG5pbXBvcnQgeyBTcFNuaXBwZXRTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvc3BTbmlwcGV0U2VydmljZVwiO1xuaW1wb3J0IHsgU3dlZXRUYWZmeUR5bmFtaWNQZXJrc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9zd2VldFRhZmZ5RHluYW1pY1BlcmtzU2VydmljZVwiO1xuaW1wb3J0IHsgU3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvc3dlZXRUYWZmeVN3ZWV0Q2FudERyb3BTZXJ2aWNlXCI7XG5pbXBvcnQgeyBTd2VldFRhZmZ5U3RhdGljUGVya3NTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvc3dlZXRUYWZmeVN0YXRpY1BlcmtzU2VydmljZVwiO1xuaW1wb3J0IHsgRGlzYWJsZVNraWxsQWR2YW5jZVNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9kaXNhYmxlU2tpbGxBZHZhbmNlU2VydmljZVwiO1xuaW1wb3J0IHsgRGlzYWJsZUZhc3RUcmF2ZWxTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvZGlzYWJsZUZhc3RUcmF2ZWxTZXJ2aWNlXCI7XG5pbXBvcnQgeyBEaXNhYmxlRGlmZmljdWx0eVNlbGVjdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9kaXNhYmxlRGlmZmljdWx0eVNlbGVjdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFN3ZWV0VGFmZnlQbGF5ZXJDb21iYXRTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvc3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2VcIjtcbmltcG9ydCB7IFdvcmxkQ2xlYW5lclNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy93b3JsZENsZWFuZXJTZXJ2aWNlXCI7XG5pbXBvcnQgeyBTd2VldFRhZmZ5U2tpbGxNZW51U2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL3N3ZWV0VGFmZnlTa2lsbE1lbnVTZXJ2aWNlXCI7XG5pbXBvcnQgeyBMb2FkT3JkZXJWZXJpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvbG9hZE9yZGVyVmVyaWZpY2F0aW9uU2VydmljZVwiO1xuaW1wb3J0IHsgQnJvd3NlclNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9icm93c2VyU2VydmljZVwiO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9hdXRoU2VydmljZVwiO1xuaW1wb3J0IHsgTmV0SW5mb1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9uZXRJbmZvU2VydmljZVwiO1xuaW1wb3J0IHsgQW5pbURlYnVnU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2FuaW1EZWJ1Z1NlcnZpY2VcIjtcbmltcG9ydCB7IFRpbWVyc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy90aW1lcnNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBQbGF5ZXJCb3dTaG90U2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL3BsYXllckJvd1Nob3RTZXJ2aWNlXCI7XG5pbXBvcnQgeyBHYW1lbW9kZUV2ZW50U291cmNlU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2dhbWVtb2RlRXZlbnRTb3VyY2VTZXJ2aWNlXCI7XG5pbXBvcnQgeyBHYW1lbW9kZVVwZGF0ZVNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9nYW1lbW9kZVVwZGF0ZVNlcnZpY2VcIjtcbmltcG9ydCB7IEZyb250SG90UmVsb2FkU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL2Zyb250SG90UmVsb2FkU2VydmljZVwiO1xuaW1wb3J0IHsgQmxvY2tlZEFuaW1hdGlvbnNTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvYmxvY2tlZEFuaW1hdGlvbnNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBXb3JsZFZpZXcgfSBmcm9tIFwiLi92aWV3L3dvcmxkVmlld1wiO1xuaW1wb3J0IHsgS2V5Ym9hcmRFdmVudHNTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMva2V5Ym9hcmRFdmVudHNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBNYWdpY1N5bmNTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvbWFnaWNTeW5jU2VydmljZVwiO1xuaW1wb3J0IHsgUHJvZmlsaW5nU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL3Byb2ZpbGluZ1NlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlcnZpY2VzL3NldHRpbmdzU2VydmljZVwiO1xuaW1wb3J0IHsgU3dlZXRDYW1lcmFFbmZvcmNlbWVudFNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9zd2VldENhbWVyYUVuZm9yY2VtZW50U2VydmljZVwiO1xuaW1wb3J0IHsgU3dlZXRUYWZmeU5pY2tuYW1lc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9zd2VldFRhZmZ5Tmlja25hbWVzU2VydmljZVwiO1xuaW1wb3J0IHsgU2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VydmljZXMvc2VydmVySnNWZXJpZmljYXRpb25TZXJ2aWNlXCI7XG5pbXBvcnQgeyBTd2VldFRhZmZ5RXZhbFNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9zZXJ2aWNlcy9zd2VldFRhZmZ5RXZhbFNlcnZpY2VcIjtcbm9uY2UoXCJ1cGRhdGVcIiwgZnVuY3Rpb24gKCkge1xuICAgIFV0aWxpdHkuc2V0SU5JQm9vbChcImJBbHdheXNBY3RpdmU6R2VuZXJhbFwiLCB0cnVlKTtcbiAgICBHYW1lLnNldEdhbWVTZXR0aW5nSW50KFwiaURlYXRoRHJvcFdlYXBvbkNoYW5jZVwiLCAwKTtcbiAgICBVdGlsaXR5LnNldElOSUZsb2F0KFwiZkF1dG9WYW5pdHlNb2RlRGVsYXk6Q2FtZXJhXCIsIDM2MDApO1xufSk7XG52YXIgbWFpbiA9IGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICB2YXIgY29udHJvbGxlciA9IFNwQXBpSW50ZXJhY3Rvci5nZXRDb250cm9sbGVySW5zdGFuY2UoKTtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IFtcbiAgICAgICAgICAgIG5ldyBCbG9ja1BhcHlydXNFdmVudHNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBMb2FkR2FtZVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFNpbmdsZVBsYXllclNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IEVuZm9yY2VMaW1pdGF0aW9uc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFNlbmRJbnB1dHNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBTa3ltcENsaWVudChzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgVGltZVNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFNwVmVyc2lvbkNoZWNrU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgQ29uc29sZUNvbW1hbmRzU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgTGFzdEludlNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IEFjdGl2YXRpb25TZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBDcmFmdFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IERyb3BJdGVtU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgSGl0U2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgUmFnZG9sbFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IERlYXRoU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgQ29udGFpbmVyc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IE5ldHdvcmtpbmdTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBSZW1vdGVTZXJ2ZXIoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFNwU25pcHBldFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdzU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgU3dlZXRUYWZmeUR5bmFtaWNQZXJrc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFN3ZWV0VGFmZnlTdGF0aWNQZXJrc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFN3ZWV0VGFmZnlTd2VldENhbnREcm9wU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgU3dlZXRUYWZmeVBsYXllckNvbWJhdFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFN3ZWV0VGFmZnlTa2lsbE1lbnVTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBTd2VldENhbWVyYUVuZm9yY2VtZW50U2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgU3dlZXRUYWZmeUV2YWxTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBEaXNhYmxlU2tpbGxBZHZhbmNlU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgRGlzYWJsZUZhc3RUcmF2ZWxTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBEaXNhYmxlRGlmZmljdWx0eVNlbGVjdGlvblNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFdvcmxkQ2xlYW5lclNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IExvYWRPcmRlclZlcmlmaWNhdGlvblNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IEJyb3dzZXJTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBBdXRoU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgTmV0SW5mb1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IEFuaW1EZWJ1Z1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFRpbWVyc1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFBsYXllckJvd1Nob3RTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBHYW1lbW9kZUV2ZW50U291cmNlU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgR2FtZW1vZGVVcGRhdGVTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBGcm9udEhvdFJlbG9hZFNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IEJsb2NrZWRBbmltYXRpb25zU2VydmljZShzcCwgY29udHJvbGxlciksXG4gICAgICAgICAgICBuZXcgV29ybGRWaWV3KHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBLZXlib2FyZEV2ZW50c1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IE1hZ2ljU3luY1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFByb2ZpbGluZ1NlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpLFxuICAgICAgICAgICAgbmV3IFN3ZWV0VGFmZnlOaWNrbmFtZXNTZXJ2aWNlKHNwLCBjb250cm9sbGVyKSxcbiAgICAgICAgICAgIG5ldyBTZXJ2ZXJKc1ZlcmlmaWNhdGlvblNlcnZpY2Uoc3AsIGNvbnRyb2xsZXIpXG4gICAgICAgIF07XG4gICAgICAgIFNwQXBpSW50ZXJhY3Rvci5zZXR1cChsaXN0ZW5lcnMpO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICAvLyBUT0RPOiBoYW5kbGUgc2V0dXAgZmFpbHVyZS4gd2lsbCBvdXRwdXQgdG8gZ2FtZSBjb25zb2xlIGJ5IGRlZmF1bHRcbiAgICAgICAgdGhyb3cgZTtcbiAgICB9XG59O1xuLy8gWzE4LjA4LjIwMjNdXG4vLyBJIHNhdyBcImF0dGVtcHQgdG8gY2FsbCBob29rcy5hZGQgd2hpbGUgaW4gaG9vayBjb250ZXh0XCIgZXJyb3Jcbi8vIEknbSBub3Qgc3VyZSBpZiBpdCdzIGEgQysrIGJ1ZyBpbiBTa3lyaW1QbGF0Zm9ybSBvciBhbiBhcnRpZmFjdCBvZiB3ZWJwYWNrK2hvdHJlbG9hZFxuLy8gQnV0IGxldCdzIGZvciBub3cgZW5zdXJlIHRoYXQgXCJtYWluXCIgZXhlY3V0ZXMgaW5zaWRlIHRpY2sgY29udGV4dFxub25jZShcInRpY2tcIiwgbWFpbik7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=