silika-website/wwwroot/assets/vendor/libs/bootstrap-daterangepicker/bootstrap-daterangepicker.js

142 lines
182 KiB
JavaScript

/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("moment"), require("jQuery"));
else if(typeof define === 'function' && define.amd)
define(["moment", "jQuery"], factory);
else {
var a = typeof exports === 'object' ? factory(require("moment"), require("jQuery")) : factory(root["moment"], root["jQuery"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(self, function(__WEBPACK_EXTERNAL_MODULE_moment__, __WEBPACK_EXTERNAL_MODULE_jquery__) {
return /******/ (function() { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./libs/bootstrap-daterangepicker/bootstrap-daterangepicker.js":
/*!*********************************************************************!*\
!*** ./libs/bootstrap-daterangepicker/bootstrap-daterangepicker.js ***!
\*********************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var bootstrap_daterangepicker_daterangepicker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! bootstrap-daterangepicker/daterangepicker */ \"./node_modules/bootstrap-daterangepicker/daterangepicker.js\");\n/* harmony import */ var bootstrap_daterangepicker_daterangepicker__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(bootstrap_daterangepicker_daterangepicker__WEBPACK_IMPORTED_MODULE_0__);\n\n\n// Patch detect when weeks are shown\n\nvar fnDaterangepicker = $.fn.daterangepicker;\n$.fn.daterangepicker = function (options, callback) {\n fnDaterangepicker.call(this, options, callback);\n if (options && (options.showWeekNumbers || options.showISOWeekNumbers)) {\n this.each(function () {\n var instance = $(this).data('daterangepicker');\n console.log(instance);\n if (instance && instance.container) instance.container.addClass('with-week-numbers');\n });\n }\n return this;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9saWJzL2Jvb3RzdHJhcC1kYXRlcmFuZ2VwaWNrZXIvYm9vdHN0cmFwLWRhdGVyYW5nZXBpY2tlci5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7QUFBbUQ7O0FBRW5EOztBQUVBLElBQU1BLGlCQUFpQixHQUFHQyxDQUFDLENBQUNDLEVBQUUsQ0FBQ0MsZUFBZTtBQUU5Q0YsQ0FBQyxDQUFDQyxFQUFFLENBQUNDLGVBQWUsR0FBRyxVQUFVQyxPQUFPLEVBQUVDLFFBQVEsRUFBRTtFQUNsREwsaUJBQWlCLENBQUNNLElBQUksQ0FBQyxJQUFJLEVBQUVGLE9BQU8sRUFBRUMsUUFBUSxDQUFDO0VBRS9DLElBQUlELE9BQU8sS0FBS0EsT0FBTyxDQUFDRyxlQUFlLElBQUlILE9BQU8sQ0FBQ0ksa0JBQWtCLENBQUMsRUFBRTtJQUN0RSxJQUFJLENBQUNDLElBQUksQ0FBQyxZQUFZO01BQ3BCLElBQU1DLFFBQVEsR0FBR1QsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDVSxJQUFJLENBQUMsaUJBQWlCLENBQUM7TUFDaERDLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDSCxRQUFRLENBQUM7TUFDckIsSUFBSUEsUUFBUSxJQUFJQSxRQUFRLENBQUNJLFNBQVMsRUFBRUosUUFBUSxDQUFDSSxTQUFTLENBQUNDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQztJQUN0RixDQUFDLENBQUM7RUFDSjtFQUVBLE9BQU8sSUFBSTtBQUNiLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9WdWV4eS8uL2xpYnMvYm9vdHN0cmFwLWRhdGVyYW5nZXBpY2tlci9ib290c3RyYXAtZGF0ZXJhbmdlcGlja2VyLmpzP2RmZWQiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICdib290c3RyYXAtZGF0ZXJhbmdlcGlja2VyL2RhdGVyYW5nZXBpY2tlcic7XHJcblxyXG4vLyBQYXRjaCBkZXRlY3Qgd2hlbiB3ZWVrcyBhcmUgc2hvd25cclxuXHJcbmNvbnN0IGZuRGF0ZXJhbmdlcGlja2VyID0gJC5mbi5kYXRlcmFuZ2VwaWNrZXI7XHJcblxyXG4kLmZuLmRhdGVyYW5nZXBpY2tlciA9IGZ1bmN0aW9uIChvcHRpb25zLCBjYWxsYmFjaykge1xyXG4gIGZuRGF0ZXJhbmdlcGlja2VyLmNhbGwodGhpcywgb3B0aW9ucywgY2FsbGJhY2spO1xyXG5cclxuICBpZiAob3B0aW9ucyAmJiAob3B0aW9ucy5zaG93V2Vla051bWJlcnMgfHwgb3B0aW9ucy5zaG93SVNPV2Vla051bWJlcnMpKSB7XHJcbiAgICB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xyXG4gICAgICBjb25zdCBpbnN0YW5jZSA9ICQodGhpcykuZGF0YSgnZGF0ZXJhbmdlcGlja2VyJyk7XHJcbiAgICAgIGNvbnNvbGUubG9nKGluc3RhbmNlKTtcclxuICAgICAgaWYgKGluc3RhbmNlICYmIGluc3RhbmNlLmNvbnRhaW5lcikgaW5zdGFuY2UuY29udGFpbmVyLmFkZENsYXNzKCd3aXRoLXdlZWstbnVtYmVycycpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gdGhpcztcclxufTtcclxuIl0sIm5hbWVzIjpbImZuRGF0ZXJhbmdlcGlja2VyIiwiJCIsImZuIiwiZGF0ZXJhbmdlcGlja2VyIiwib3B0aW9ucyIsImNhbGxiYWNrIiwiY2FsbCIsInNob3dXZWVrTnVtYmVycyIsInNob3dJU09XZWVrTnVtYmVycyIsImVhY2giLCJpbnN0YW5jZSIsImRhdGEiLCJjb25zb2xlIiwibG9nIiwiY29udGFpbmVyIiwiYWRkQ2xhc3MiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./libs/bootstrap-daterangepicker/bootstrap-daterangepicker.js\n");
/***/ }),
/***/ "./node_modules/bootstrap-daterangepicker/daterangepicker.js":
/*!*******************************************************************!*\
!*** ./node_modules/bootstrap-daterangepicker/daterangepicker.js ***!
\*******************************************************************/
/***/ (function(module, exports, __webpack_require__) {
eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/**\r\n* @version: 3.1\r\n* @author: Dan Grossman http://www.dangrossman.info/\r\n* @copyright: Copyright (c) 2012-2019 Dan Grossman. All rights reserved.\r\n* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php\r\n* @website: http://www.daterangepicker.com/\r\n*/\r\n// Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js\r\n(function (root, factory) {\r\n if (true) {\r\n // AMD. Make globaly available as well\r\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! moment */ \"moment\"), __webpack_require__(/*! jquery */ \"jquery\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function (moment, jquery) {\r\n if (!jquery.fn) jquery.fn = {}; // webpack server rendering\r\n if (typeof moment !== 'function' && moment.hasOwnProperty('default')) moment = moment['default']\r\n return factory(moment, jquery);\r\n }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\r\n } else { var moment, jQuery; }\r\n}(this, function(moment, $) {\r\n var DateRangePicker = function(element, options, cb) {\r\n\r\n //default settings for options\r\n this.parentEl = 'body';\r\n this.element = $(element);\r\n this.startDate = moment().startOf('day');\r\n this.endDate = moment().endOf('day');\r\n this.minDate = false;\r\n this.maxDate = false;\r\n this.maxSpan = false;\r\n this.autoApply = false;\r\n this.singleDatePicker = false;\r\n this.showDropdowns = false;\r\n this.minYear = moment().subtract(100, 'year').format('YYYY');\r\n this.maxYear = moment().add(100, 'year').format('YYYY');\r\n this.showWeekNumbers = false;\r\n this.showISOWeekNumbers = false;\r\n this.showCustomRangeLabel = true;\r\n this.timePicker = false;\r\n this.timePicker24Hour = false;\r\n this.timePickerIncrement = 1;\r\n this.timePickerSeconds = false;\r\n this.linkedCalendars = true;\r\n this.autoUpdateInput = true;\r\n this.alwaysShowCalendars = false;\r\n this.ranges = {};\r\n\r\n this.opens = 'right';\r\n if (this.element.hasClass('pull-right'))\r\n this.opens = 'left';\r\n\r\n this.drops = 'down';\r\n if (this.element.hasClass('dropup'))\r\n this.drops = 'up';\r\n\r\n this.buttonClasses = 'btn btn-sm';\r\n this.applyButtonClasses = 'btn-primary';\r\n this.cancelButtonClasses = 'btn-default';\r\n\r\n this.locale = {\r\n direction: 'ltr',\r\n format: moment.localeData().longDateFormat('L'),\r\n separator: ' - ',\r\n applyLabel: 'Apply',\r\n cancelLabel: 'Cancel',\r\n weekLabel: 'W',\r\n customRangeLabel: 'Custom Range',\r\n daysOfWeek: moment.weekdaysMin(),\r\n monthNames: moment.monthsShort(),\r\n firstDay: moment.localeData().firstDayOfWeek()\r\n };\r\n\r\n this.callback = function() { };\r\n\r\n //some state information\r\n this.isShowing = false;\r\n this.leftCalendar = {};\r\n this.rightCalendar = {};\r\n\r\n //custom options from user\r\n if (typeof options !== 'object' || options === null)\r\n options = {};\r\n\r\n //allow setting options with data attributes\r\n //data-api options will be overwritten with custom javascript options\r\n options = $.extend(this.element.data(), options);\r\n\r\n //html template for the picker UI\r\n if (typeof options.template !== 'string' && !(options.template instanceof $))\r\n options.template =\r\n '<div class=\"daterangepicker\">' +\r\n '<div class=\"ranges\"></div>' +\r\n '<div class=\"drp-calendar left\">' +\r\n '<div class=\"calendar-table\"></div>' +\r\n '<div class=\"calendar-time\"></div>' +\r\n '</div>' +\r\n '<div class=\"drp-calendar right\">' +\r\n '<div class=\"calendar-table\"></div>' +\r\n '<div class=\"calendar-time\"></div>' +\r\n '</div>' +\r\n '<div class=\"drp-buttons\">' +\r\n '<span class=\"drp-selected\"></span>' +\r\n '<button class=\"cancelBtn\" type=\"button\"></button>' +\r\n '<button class=\"applyBtn\" disabled=\"disabled\" type=\"button\"></button> ' +\r\n '</div>' +\r\n '</div>';\r\n\r\n this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\r\n this.container = $(options.template).appendTo(this.parentEl);\r\n\r\n //\r\n // handle all the possible options overriding defaults\r\n //\r\n\r\n if (typeof options.locale === 'object') {\r\n\r\n if (typeof options.locale.direction === 'string')\r\n this.locale.direction = options.locale.direction;\r\n\r\n if (typeof options.locale.format === 'string')\r\n this.locale.format = options.locale.format;\r\n\r\n if (typeof options.locale.separator === 'string')\r\n this.locale.separator = options.locale.separator;\r\n\r\n if (typeof options.locale.daysOfWeek === 'object')\r\n this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\r\n\r\n if (typeof options.locale.monthNames === 'object')\r\n this.locale.monthNames = options.locale.monthNames.slice();\r\n\r\n if (typeof options.locale.firstDay === 'number')\r\n this.locale.firstDay = options.locale.firstDay;\r\n\r\n if (typeof options.locale.applyLabel === 'string')\r\n this.locale.applyLabel = options.locale.applyLabel;\r\n\r\n if (typeof options.locale.cancelLabel === 'string')\r\n this.locale.cancelLabel = options.locale.cancelLabel;\r\n\r\n if (typeof options.locale.weekLabel === 'string')\r\n this.locale.weekLabel = options.locale.weekLabel;\r\n\r\n if (typeof options.locale.customRangeLabel === 'string'){\r\n //Support unicode chars in the custom range name.\r\n var elem = document.createElement('textarea');\r\n elem.innerHTML = options.locale.customRangeLabel;\r\n var rangeHtml = elem.value;\r\n this.locale.customRangeLabel = rangeHtml;\r\n }\r\n }\r\n this.container.addClass(this.locale.direction);\r\n\r\n if (typeof options.startDate === 'string')\r\n this.startDate = moment(options.startDate, this.locale.format);\r\n\r\n if (typeof options.endDate === 'string')\r\n this.endDate = moment(options.endDate, this.locale.format);\r\n\r\n if (typeof options.minDate === 'string')\r\n this.minDate = moment(options.minDate, this.locale.format);\r\n\r\n if (typeof options.maxDate === 'string')\r\n this.maxDate = moment(options.maxDate, this.locale.format);\r\n\r\n if (typeof options.startDate === 'object')\r\n this.startDate = moment(options.startDate);\r\n\r\n if (typeof options.endDate === 'object')\r\n this.endDate = moment(options.endDate);\r\n\r\n if (typeof options.minDate === 'object')\r\n this.minDate = moment(options.minDate);\r\n\r\n if (typeof options.maxDate === 'object')\r\n this.maxDate = moment(options.maxDate);\r\n\r\n // sanity check for bad options\r\n if (this.minDate && this.startDate.isBefore(this.minDate))\r\n this.startDate = this.minDate.clone();\r\n\r\n // sanity check for bad options\r\n if (this.maxDate && this.endDate.isAfter(this.maxDate))\r\n this.endDate = this.maxDate.clone();\r\n\r\n if (typeof options.applyButtonClasses === 'string')\r\n this.applyButtonClasses = options.applyButtonClasses;\r\n\r\n if (typeof options.applyClass === 'string') //backwards compat\r\n this.applyButtonClasses = options.applyClass;\r\n\r\n if (typeof options.cancelButtonClasses === 'string')\r\n this.cancelButtonClasses = options.cancelButtonClasses;\r\n\r\n if (typeof options.cancelClass === 'string') //backwards compat\r\n this.cancelButtonClasses = options.cancelClass;\r\n\r\n if (typeof options.maxSpan === 'object')\r\n this.maxSpan = options.maxSpan;\r\n\r\n if (typeof options.dateLimit === 'object') //backwards compat\r\n this.maxSpan = options.dateLimit;\r\n\r\n if (typeof options.opens === 'string')\r\n this.opens = options.opens;\r\n\r\n if (typeof options.drops === 'string')\r\n this.drops = options.drops;\r\n\r\n if (typeof options.showWeekNumbers === 'boolean')\r\n this.showWeekNumbers = options.showWeekNumbers;\r\n\r\n if (typeof options.showISOWeekNumbers === 'boolean')\r\n this.showISOWeekNumbers = options.showISOWeekNumbers;\r\n\r\n if (typeof options.buttonClasses === 'string')\r\n this.buttonClasses = options.buttonClasses;\r\n\r\n if (typeof options.buttonClasses === 'object')\r\n this.buttonClasses = options.buttonClasses.join(' ');\r\n\r\n if (typeof options.showDropdowns === 'boolean')\r\n this.showDropdowns = options.showDropdowns;\r\n\r\n if (typeof options.minYear === 'number')\r\n this.minYear = options.minYear;\r\n\r\n if (typeof options.maxYear === 'number')\r\n this.maxYear = options.maxYear;\r\n\r\n if (typeof options.showCustomRangeLabel === 'boolean')\r\n this.showCustomRangeLabel = options.showCustomRangeLabel;\r\n\r\n if (typeof options.singleDatePicker === 'boolean') {\r\n this.singleDatePicker = options.singleDatePicker;\r\n if (this.singleDatePicker)\r\n this.endDate = this.startDate.clone();\r\n }\r\n\r\n if (typeof options.timePicker === 'boolean')\r\n this.timePicker = options.timePicker;\r\n\r\n if (typeof options.timePickerSeconds === 'boolean')\r\n this.timePickerSeconds = options.timePickerSeconds;\r\n\r\n if (typeof options.timePickerIncrement === 'number')\r\n this.timePickerIncrement = options.timePickerIncrement;\r\n\r\n if (typeof options.timePicker24Hour === 'boolean')\r\n this.timePicker24Hour = options.timePicker24Hour;\r\n\r\n if (typeof options.autoApply === 'boolean')\r\n this.autoApply = options.autoApply;\r\n\r\n if (typeof options.autoUpdateInput === 'boolean')\r\n this.autoUpdateInput = options.autoUpdateInput;\r\n\r\n if (typeof options.linkedCalendars === 'boolean')\r\n this.linkedCalendars = options.linkedCalendars;\r\n\r\n if (typeof options.isInvalidDate === 'function')\r\n this.isInvalidDate = options.isInvalidDate;\r\n\r\n if (typeof options.isCustomDate === 'function')\r\n this.isCustomDate = options.isCustomDate;\r\n\r\n if (typeof options.alwaysShowCalendars === 'boolean')\r\n this.alwaysShowCalendars = options.alwaysShowCalendars;\r\n\r\n // update day names order to firstDay\r\n if (this.locale.firstDay != 0) {\r\n var iterator = this.locale.firstDay;\r\n while (iterator > 0) {\r\n this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\r\n iterator--;\r\n }\r\n }\r\n\r\n var start, end, range;\r\n\r\n //if no start/end dates set, check if an input element contains initial values\r\n if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\r\n if ($(this.element).is(':text')) {\r\n var val = $(this.element).val(),\r\n split = val.split(this.locale.separator);\r\n\r\n start = end = null;\r\n\r\n if (split.length == 2) {\r\n start = moment(split[0], this.locale.format);\r\n end = moment(split[1], this.locale.format);\r\n } else if (this.singleDatePicker && val !== \"\") {\r\n start = moment(val, this.locale.format);\r\n end = moment(val, this.locale.format);\r\n }\r\n if (start !== null && end !== null) {\r\n this.setStartDate(start);\r\n this.setEndDate(end);\r\n }\r\n }\r\n }\r\n\r\n if (typeof options.ranges === 'object') {\r\n for (range in options.ranges) {\r\n\r\n if (typeof options.ranges[range][0] === 'string')\r\n start = moment(options.ranges[range][0], this.locale.format);\r\n else\r\n start = moment(options.ranges[range][0]);\r\n\r\n if (typeof options.ranges[range][1] === 'string')\r\n end = moment(options.ranges[range][1], this.locale.format);\r\n else\r\n end = moment(options.ranges[range][1]);\r\n\r\n // If the start or end date exceed those allowed by the minDate or maxSpan\r\n // options, shorten the range to the allowable period.\r\n if (this.minDate && start.isBefore(this.minDate))\r\n start = this.minDate.clone();\r\n\r\n var maxDate = this.maxDate;\r\n if (this.maxSpan && maxDate && start.clone().add(this.maxSpan).isAfter(maxDate))\r\n maxDate = start.clone().add(this.maxSpan);\r\n if (maxDate && end.isAfter(maxDate))\r\n end = maxDate.clone();\r\n\r\n // If the end of the range is before the minimum or the start of the range is\r\n // after the maximum, don't display this range option at all.\r\n if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day'))\r\n || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day')))\r\n continue;\r\n\r\n //Support unicode chars in the range names.\r\n var elem = document.createElement('textarea');\r\n elem.innerHTML = range;\r\n var rangeHtml = elem.value;\r\n\r\n this.ranges[rangeHtml] = [start, end];\r\n }\r\n\r\n var list = '<ul>';\r\n for (range in this.ranges) {\r\n list += '<li data-range-key=\"' + range + '\">' + range + '</li>';\r\n }\r\n if (this.showCustomRangeLabel) {\r\n list += '<li data-range-key=\"' + this.locale.customRangeLabel + '\">' + this.locale.customRangeLabel + '</li>';\r\n }\r\n list += '</ul>';\r\n this.container.find('.ranges').prepend(list);\r\n }\r\n\r\n if (typeof cb === 'function') {\r\n this.callback = cb;\r\n }\r\n\r\n if (!this.timePicker) {\r\n this.startDate = this.startDate.startOf('day');\r\n this.endDate = this.endDate.endOf('day');\r\n this.container.find('.calendar-time').hide();\r\n }\r\n\r\n //can't be used together for now\r\n if (this.timePicker && this.autoApply)\r\n this.autoApply = false;\r\n\r\n if (this.autoApply) {\r\n this.container.addClass('auto-apply');\r\n }\r\n\r\n if (typeof options.ranges === 'object')\r\n this.container.addClass('show-ranges');\r\n\r\n if (this.singleDatePicker) {\r\n this.container.addClass('single');\r\n this.container.find('.drp-calendar.left').addClass('single');\r\n this.container.find('.drp-calendar.left').show();\r\n this.container.find('.drp-calendar.right').hide();\r\n if (!this.timePicker && this.autoApply) {\r\n this.container.addClass('auto-apply');\r\n }\r\n }\r\n\r\n if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) {\r\n this.container.addClass('show-calendar');\r\n }\r\n\r\n this.container.addClass('opens' + this.opens);\r\n\r\n //apply CSS classes and labels to buttons\r\n this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses);\r\n if (this.applyButtonClasses.length)\r\n this.container.find('.applyBtn').addClass(this.applyButtonClasses);\r\n if (this.cancelButtonClasses.length)\r\n this.container.find('.cancelBtn').addClass(this.cancelButtonClasses);\r\n this.container.find('.applyBtn').html(this.locale.applyLabel);\r\n this.container.find('.cancelBtn').html(this.locale.cancelLabel);\r\n\r\n //\r\n // event listeners\r\n //\r\n\r\n this.container.find('.drp-calendar')\r\n .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\r\n .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\r\n .on('mousedown.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\r\n .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this))\r\n .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this))\r\n .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this))\r\n .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this));\r\n\r\n this.container.find('.ranges')\r\n .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this));\r\n\r\n this.container.find('.drp-buttons')\r\n .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\r\n .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this));\r\n\r\n if (this.element.is('input') || this.element.is('button')) {\r\n this.element.on({\r\n 'click.daterangepicker': $.proxy(this.show, this),\r\n 'focus.daterangepicker': $.proxy(this.show, this),\r\n 'keyup.daterangepicker': $.proxy(this.elementChanged, this),\r\n 'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility\r\n });\r\n } else {\r\n this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\r\n this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this));\r\n }\r\n\r\n //\r\n // if attached to a text input, set the initial value\r\n //\r\n\r\n this.updateElement();\r\n\r\n };\r\n\r\n DateRangePicker.prototype = {\r\n\r\n constructor: DateRangePicker,\r\n\r\n setStartDate: function(startDate) {\r\n if (typeof startDate === 'string')\r\n this.startDate = moment(startDate, this.locale.format);\r\n\r\n if (typeof startDate === 'object')\r\n this.startDate = moment(startDate);\r\n\r\n if (!this.timePicker)\r\n this.startDate = this.startDate.startOf('day');\r\n\r\n if (this.timePicker && this.timePickerIncrement)\r\n this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);\r\n\r\n if (this.minDate && this.startDate.isBefore(this.minDate)) {\r\n this.startDate = this.minDate.clone();\r\n if (this.timePicker && this.timePickerIncrement)\r\n this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);\r\n }\r\n\r\n if (this.maxDate && this.startDate.isAfter(this.maxDate)) {\r\n this.startDate = this.maxDate.clone();\r\n if (this.timePicker && this.timePickerIncrement)\r\n this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);\r\n }\r\n\r\n if (!this.isShowing)\r\n this.updateElement();\r\n\r\n this.updateMonthsInView();\r\n },\r\n\r\n setEndDate: function(endDate) {\r\n if (typeof endDate === 'string')\r\n this.endDate = moment(endDate, this.locale.format);\r\n\r\n if (typeof endDate === 'object')\r\n this.endDate = moment(endDate);\r\n\r\n if (!this.timePicker)\r\n this.endDate = this.endDate.endOf('day');\r\n\r\n if (this.timePicker && this.timePickerIncrement)\r\n this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);\r\n\r\n if (this.endDate.isBefore(this.startDate))\r\n this.endDate = this.startDate.clone();\r\n\r\n if (this.maxDate && this.endDate.isAfter(this.maxDate))\r\n this.endDate = this.maxDate.clone();\r\n\r\n if (this.maxSpan && this.startDate.clone().add(this.maxSpan).isBefore(this.endDate))\r\n this.endDate = this.startDate.clone().add(this.maxSpan);\r\n\r\n this.previousRightTime = this.endDate.clone();\r\n\r\n this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));\r\n\r\n if (!this.isShowing)\r\n this.updateElement();\r\n\r\n this.updateMonthsInView();\r\n },\r\n\r\n isInvalidDate: function() {\r\n return false;\r\n },\r\n\r\n isCustomDate: function() {\r\n return false;\r\n },\r\n\r\n updateView: function() {\r\n if (this.timePicker) {\r\n this.renderTimePicker('left');\r\n this.renderTimePicker('right');\r\n if (!this.endDate) {\r\n this.container.find('.right .calendar-time select').prop('disabled', true).addClass('disabled');\r\n } else {\r\n this.container.find('.right .calendar-time select').prop('disabled', false).removeClass('disabled');\r\n }\r\n }\r\n if (this.endDate)\r\n this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));\r\n this.updateMonthsInView();\r\n this.updateCalendars();\r\n this.updateFormInputs();\r\n },\r\n\r\n updateMonthsInView: function() {\r\n if (this.endDate) {\r\n\r\n //if both dates are visible already, do nothing\r\n if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month &&\r\n (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))\r\n &&\r\n (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))\r\n ) {\r\n return;\r\n }\r\n\r\n this.leftCalendar.month = this.startDate.clone().date(2);\r\n if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) {\r\n this.rightCalendar.month = this.endDate.clone().date(2);\r\n } else {\r\n this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');\r\n }\r\n\r\n } else {\r\n if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) {\r\n this.leftCalendar.month = this.startDate.clone().date(2);\r\n this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');\r\n }\r\n }\r\n if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) {\r\n this.rightCalendar.month = this.maxDate.clone().date(2);\r\n this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month');\r\n }\r\n },\r\n\r\n updateCalendars: function() {\r\n\r\n if (this.timePicker) {\r\n var hour, minute, second;\r\n if (this.endDate) {\r\n hour = parseInt(this.container.find('.left .hourselect').val(), 10);\r\n minute = parseInt(this.container.find('.left .minuteselect').val(), 10);\r\n if (isNaN(minute)) {\r\n minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10);\r\n }\r\n second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;\r\n if (!this.timePicker24Hour) {\r\n var ampm = this.container.find('.left .ampmselect').val();\r\n if (ampm === 'PM' && hour < 12)\r\n hour += 12;\r\n if (ampm === 'AM' && hour === 12)\r\n hour = 0;\r\n }\r\n } else {\r\n hour = parseInt(this.container.find('.right .hourselect').val(), 10);\r\n minute = parseInt(this.container.find('.right .minuteselect').val(), 10);\r\n if (isNaN(minute)) {\r\n minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10);\r\n }\r\n second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;\r\n if (!this.timePicker24Hour) {\r\n var ampm = this.container.find('.right .ampmselect').val();\r\n if (ampm === 'PM' && hour < 12)\r\n hour += 12;\r\n if (ampm === 'AM' && hour === 12)\r\n hour = 0;\r\n }\r\n }\r\n this.leftCalendar.month.hour(hour).minute(minute).second(second);\r\n this.rightCalendar.month.hour(hour).minute(minute).second(second);\r\n }\r\n\r\n this.renderCalendar('left');\r\n this.renderCalendar('right');\r\n\r\n //highlight any predefined range matching the current start and end dates\r\n this.container.find('.ranges li').removeClass('active');\r\n if (this.endDate == null) return;\r\n\r\n this.calculateChosenLabel();\r\n },\r\n\r\n renderCalendar: function(side) {\r\n\r\n //\r\n // Build the matrix of dates that will populate the calendar\r\n //\r\n\r\n var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar;\r\n var month = calendar.month.month();\r\n var year = calendar.month.year();\r\n var hour = calendar.month.hour();\r\n var minute = calendar.month.minute();\r\n var second = calendar.month.second();\r\n var daysInMonth = moment([year, month]).daysInMonth();\r\n var firstDay = moment([year, month, 1]);\r\n var lastDay = moment([year, month, daysInMonth]);\r\n var lastMonth = moment(firstDay).subtract(1, 'month').month();\r\n var lastYear = moment(firstDay).subtract(1, 'month').year();\r\n var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\r\n var dayOfWeek = firstDay.day();\r\n\r\n //initialize a 6 rows x 7 columns array for the calendar\r\n var calendar = [];\r\n calendar.firstDay = firstDay;\r\n calendar.lastDay = lastDay;\r\n\r\n for (var i = 0; i < 6; i++) {\r\n calendar[i] = [];\r\n }\r\n\r\n //populate the calendar with date objects\r\n var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\r\n if (startDay > daysInLastMonth)\r\n startDay -= 7;\r\n\r\n if (dayOfWeek == this.locale.firstDay)\r\n startDay = daysInLastMonth - 6;\r\n\r\n var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]);\r\n\r\n var col, row;\r\n for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) {\r\n if (i > 0 && col % 7 === 0) {\r\n col = 0;\r\n row++;\r\n }\r\n calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second);\r\n curDate.hour(12);\r\n\r\n if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') {\r\n calendar[row][col] = this.minDate.clone();\r\n }\r\n\r\n if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') {\r\n calendar[row][col] = this.maxDate.clone();\r\n }\r\n\r\n }\r\n\r\n //make the calendar object available to hoverDate/clickDate\r\n if (side == 'left') {\r\n this.leftCalendar.calendar = calendar;\r\n } else {\r\n this.rightCalendar.calendar = calendar;\r\n }\r\n\r\n //\r\n // Display the calendar\r\n //\r\n\r\n var minDate = side == 'left' ? this.minDate : this.startDate;\r\n var maxDate = this.maxDate;\r\n var selected = side == 'left' ? this.startDate : this.endDate;\r\n var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'};\r\n\r\n var html = '<table class=\"table-condensed\">';\r\n html += '<thead>';\r\n html += '<tr>';\r\n\r\n // add empty cell for week number\r\n if (this.showWeekNumbers || this.showISOWeekNumbers)\r\n html += '<th></th>';\r\n\r\n if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {\r\n html += '<th class=\"prev available\"><span></span></th>';\r\n } else {\r\n html += '<th></th>';\r\n }\r\n\r\n var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\r\n\r\n if (this.showDropdowns) {\r\n var currentMonth = calendar[1][1].month();\r\n var currentYear = calendar[1][1].year();\r\n var maxYear = (maxDate && maxDate.year()) || (this.maxYear);\r\n var minYear = (minDate && minDate.year()) || (this.minYear);\r\n var inMinYear = currentYear == minYear;\r\n var inMaxYear = currentYear == maxYear;\r\n\r\n var monthHtml = '<select class=\"monthselect\">';\r\n for (var m = 0; m < 12; m++) {\r\n if ((!inMinYear || (minDate && m >= minDate.month())) && (!inMaxYear || (maxDate && m <= maxDate.month()))) {\r\n monthHtml += \"<option value='\" + m + \"'\" +\r\n (m === currentMonth ? \" selected='selected'\" : \"\") +\r\n \">\" + this.locale.monthNames[m] + \"</option>\";\r\n } else {\r\n monthHtml += \"<option value='\" + m + \"'\" +\r\n (m === currentMonth ? \" selected='selected'\" : \"\") +\r\n \" disabled='disabled'>\" + this.locale.monthNames[m] + \"</option>\";\r\n }\r\n }\r\n monthHtml += \"</select>\";\r\n\r\n var yearHtml = '<select class=\"yearselect\">';\r\n for (var y = minYear; y <= maxYear; y++) {\r\n yearHtml += '<option value=\"' + y + '\"' +\r\n (y === currentYear ? ' selected=\"selected\"' : '') +\r\n '>' + y + '</option>';\r\n }\r\n yearHtml += '</select>';\r\n\r\n dateHtml = monthHtml + yearHtml;\r\n }\r\n\r\n html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\r\n if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) {\r\n html += '<th class=\"next available\"><span></span></th>';\r\n } else {\r\n html += '<th></th>';\r\n }\r\n\r\n html += '</tr>';\r\n html += '<tr>';\r\n\r\n // add week number label\r\n if (this.showWeekNumbers || this.showISOWeekNumbers)\r\n html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\r\n\r\n $.each(this.locale.daysOfWeek, function(index, dayOfWeek) {\r\n html += '<th>' + dayOfWeek + '</th>';\r\n });\r\n\r\n html += '</tr>';\r\n html += '</thead>';\r\n html += '<tbody>';\r\n\r\n //adjust maxDate to reflect the maxSpan setting in order to\r\n //grey out end dates beyond the maxSpan\r\n if (this.endDate == null && this.maxSpan) {\r\n var maxLimit = this.startDate.clone().add(this.maxSpan).endOf('day');\r\n if (!maxDate || maxLimit.isBefore(maxDate)) {\r\n maxDate = maxLimit;\r\n }\r\n }\r\n\r\n for (var row = 0; row < 6; row++) {\r\n html += '<tr>';\r\n\r\n // add week number\r\n if (this.showWeekNumbers)\r\n html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\r\n else if (this.showISOWeekNumbers)\r\n html += '<td class=\"week\">' + calendar[row][0].isoWeek() + '</td>';\r\n\r\n for (var col = 0; col < 7; col++) {\r\n\r\n var classes = [];\r\n\r\n //highlight today's date\r\n if (calendar[row][col].isSame(new Date(), \"day\"))\r\n classes.push('today');\r\n\r\n //highlight weekends\r\n if (calendar[row][col].isoWeekday() > 5)\r\n classes.push('weekend');\r\n\r\n //grey out the dates in other months displayed at beginning and end of this calendar\r\n if (calendar[row][col].month() != calendar[1][1].month())\r\n classes.push('off', 'ends');\r\n\r\n //don't allow selection of dates before the minimum date\r\n if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day'))\r\n classes.push('off', 'disabled');\r\n\r\n //don't allow selection of dates after the maximum date\r\n if (maxDate && calendar[row][col].isAfter(maxDate, 'day'))\r\n classes.push('off', 'disabled');\r\n\r\n //don't allow selection of date if a custom function decides it's invalid\r\n if (this.isInvalidDate(calendar[row][col]))\r\n classes.push('off', 'disabled');\r\n\r\n //highlight the currently selected start date\r\n if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD'))\r\n classes.push('active', 'start-date');\r\n\r\n //highlight the currently selected end date\r\n if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD'))\r\n classes.push('active', 'end-date');\r\n\r\n //highlight dates in-between the selected dates\r\n if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)\r\n classes.push('in-range');\r\n\r\n //apply custom classes for this date\r\n var isCustom = this.isCustomDate(calendar[row][col]);\r\n if (isCustom !== false) {\r\n if (typeof isCustom === 'string')\r\n classes.push(isCustom);\r\n else\r\n Array.prototype.push.apply(classes, isCustom);\r\n }\r\n\r\n var cname = '', disabled = false;\r\n for (var i = 0; i < classes.length; i++) {\r\n cname += classes[i] + ' ';\r\n if (classes[i] == 'disabled')\r\n disabled = true;\r\n }\r\n if (!disabled)\r\n cname += 'available';\r\n\r\n html += '<td class=\"' + cname.replace(/^\\s+|\\s+$/g, '') + '\" data-title=\"' + 'r' + row + 'c' + col + '\">' + calendar[row][col].date() + '</td>';\r\n\r\n }\r\n html += '</tr>';\r\n }\r\n\r\n html += '</tbody>';\r\n html += '</table>';\r\n\r\n this.container.find('.drp-calendar.' + side + ' .calendar-table').html(html);\r\n\r\n },\r\n\r\n renderTimePicker: function(side) {\r\n\r\n // Don't bother updating the time picker if it's currently disabled\r\n // because an end date hasn't been clicked yet\r\n if (side == 'right' && !this.endDate) return;\r\n\r\n var html, selected, minDate, maxDate = this.maxDate;\r\n\r\n if (this.maxSpan && (!this.maxDate || this.startDate.clone().add(this.maxSpan).isBefore(this.maxDate)))\r\n maxDate = this.startDate.clone().add(this.maxSpan);\r\n\r\n if (side == 'left') {\r\n selected = this.startDate.clone();\r\n minDate = this.minDate;\r\n } else if (side == 'right') {\r\n selected = this.endDate.clone();\r\n minDate = this.startDate;\r\n\r\n //Preserve the time already selected\r\n var timeSelector = this.container.find('.drp-calendar.right .calendar-time');\r\n if (timeSelector.html() != '') {\r\n\r\n selected.hour(!isNaN(selected.hour()) ? selected.hour() : timeSelector.find('.hourselect option:selected').val());\r\n selected.minute(!isNaN(selected.minute()) ? selected.minute() : timeSelector.find('.minuteselect option:selected').val());\r\n selected.second(!isNaN(selected.second()) ? selected.second() : timeSelector.find('.secondselect option:selected').val());\r\n\r\n if (!this.timePicker24Hour) {\r\n var ampm = timeSelector.find('.ampmselect option:selected').val();\r\n if (ampm === 'PM' && selected.hour() < 12)\r\n selected.hour(selected.hour() + 12);\r\n if (ampm === 'AM' && selected.hour() === 12)\r\n selected.hour(0);\r\n }\r\n\r\n }\r\n\r\n if (selected.isBefore(this.startDate))\r\n selected = this.startDate.clone();\r\n\r\n if (maxDate && selected.isAfter(maxDate))\r\n selected = maxDate.clone();\r\n\r\n }\r\n\r\n //\r\n // hours\r\n //\r\n\r\n html = '<select class=\"hourselect\">';\r\n\r\n var start = this.timePicker24Hour ? 0 : 1;\r\n var end = this.timePicker24Hour ? 23 : 12;\r\n\r\n for (var i = start; i <= end; i++) {\r\n var i_in_24 = i;\r\n if (!this.timePicker24Hour)\r\n i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i);\r\n\r\n var time = selected.clone().hour(i_in_24);\r\n var disabled = false;\r\n if (minDate && time.minute(59).isBefore(minDate))\r\n disabled = true;\r\n if (maxDate && time.minute(0).isAfter(maxDate))\r\n disabled = true;\r\n\r\n if (i_in_24 == selected.hour() && !disabled) {\r\n html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\r\n } else if (disabled) {\r\n html += '<option value=\"' + i + '\" disabled=\"disabled\" class=\"disabled\">' + i + '</option>';\r\n } else {\r\n html += '<option value=\"' + i + '\">' + i + '</option>';\r\n }\r\n }\r\n\r\n html += '</select> ';\r\n\r\n //\r\n // minutes\r\n //\r\n\r\n html += ': <select class=\"minuteselect\">';\r\n\r\n for (var i = 0; i < 60; i += this.timePickerIncrement) {\r\n var padded = i < 10 ? '0' + i : i;\r\n var time = selected.clone().minute(i);\r\n\r\n var disabled = false;\r\n if (minDate && time.second(59).isBefore(minDate))\r\n disabled = true;\r\n if (maxDate && time.second(0).isAfter(maxDate))\r\n disabled = true;\r\n\r\n if (selected.minute() == i && !disabled) {\r\n html += '<option value=\"' + i + '\" selected=\"selected\">' + padded + '</option>';\r\n } else if (disabled) {\r\n html += '<option value=\"' + i + '\" disabled=\"disabled\" class=\"disabled\">' + padded + '</option>';\r\n } else {\r\n html += '<option value=\"' + i + '\">' + padded + '</option>';\r\n }\r\n }\r\n\r\n html += '</select> ';\r\n\r\n //\r\n // seconds\r\n //\r\n\r\n if (this.timePickerSeconds) {\r\n html += ': <select class=\"secondselect\">';\r\n\r\n for (var i = 0; i < 60; i++) {\r\n var padded = i < 10 ? '0' + i : i;\r\n var time = selected.clone().second(i);\r\n\r\n var disabled = false;\r\n if (minDate && time.isBefore(minDate))\r\n disabled = true;\r\n if (maxDate && time.isAfter(maxDate))\r\n disabled = true;\r\n\r\n if (selected.second() == i && !disabled) {\r\n html += '<option value=\"' + i + '\" selected=\"selected\">' + padded + '</option>';\r\n } else if (disabled) {\r\n html += '<option value=\"' + i + '\" disabled=\"disabled\" class=\"disabled\">' + padded + '</option>';\r\n } else {\r\n html += '<option value=\"' + i + '\">' + padded + '</option>';\r\n }\r\n }\r\n\r\n html += '</select> ';\r\n }\r\n\r\n //\r\n // AM/PM\r\n //\r\n\r\n if (!this.timePicker24Hour) {\r\n html += '<select class=\"ampmselect\">';\r\n\r\n var am_html = '';\r\n var pm_html = '';\r\n\r\n if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate))\r\n am_html = ' disabled=\"disabled\" class=\"disabled\"';\r\n\r\n if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate))\r\n pm_html = ' disabled=\"disabled\" class=\"disabled\"';\r\n\r\n if (selected.hour() >= 12) {\r\n html += '<option value=\"AM\"' + am_html + '>AM</option><option value=\"PM\" selected=\"selected\"' + pm_html + '>PM</option>';\r\n } else {\r\n html += '<option value=\"AM\" selected=\"selected\"' + am_html + '>AM</option><option value=\"PM\"' + pm_html + '>PM</option>';\r\n }\r\n\r\n html += '</select>';\r\n }\r\n\r\n this.container.find('.drp-calendar.' + side + ' .calendar-time').html(html);\r\n\r\n },\r\n\r\n updateFormInputs: function() {\r\n\r\n if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {\r\n this.container.find('button.applyBtn').prop('disabled', false);\r\n } else {\r\n this.container.find('button.applyBtn').prop('disabled', true);\r\n }\r\n\r\n },\r\n\r\n move: function() {\r\n var parentOffset = { top: 0, left: 0 },\r\n containerTop,\r\n drops = this.drops;\r\n\r\n var parentRightEdge = $(window).width();\r\n if (!this.parentEl.is('body')) {\r\n parentOffset = {\r\n top: this.parentEl.offset().top - this.parentEl.scrollTop(),\r\n left: this.parentEl.offset().left - this.parentEl.scrollLeft()\r\n };\r\n parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left;\r\n }\r\n\r\n switch (drops) {\r\n case 'auto':\r\n containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;\r\n if (containerTop + this.container.outerHeight() >= this.parentEl[0].scrollHeight) {\r\n containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;\r\n drops = 'up';\r\n }\r\n break;\r\n case 'up':\r\n containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;\r\n break;\r\n default:\r\n containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;\r\n break;\r\n }\r\n\r\n // Force the container to it's actual width\r\n this.container.css({\r\n top: 0,\r\n left: 0,\r\n right: 'auto'\r\n });\r\n var containerWidth = this.container.outerWidth();\r\n\r\n this.container.toggleClass('drop-up', drops == 'up');\r\n\r\n if (this.opens == 'left') {\r\n var containerRight = parentRightEdge - this.element.offset().left - this.element.outerWidth();\r\n if (containerWidth + containerRight > $(window).width()) {\r\n this.container.css({\r\n top: containerTop,\r\n right: 'auto',\r\n left: 9\r\n });\r\n } else {\r\n this.container.css({\r\n top: containerTop,\r\n right: containerRight,\r\n left: 'auto'\r\n });\r\n }\r\n } else if (this.opens == 'center') {\r\n var containerLeft = this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2\r\n - containerWidth / 2;\r\n if (containerLeft < 0) {\r\n this.container.css({\r\n top: containerTop,\r\n right: 'auto',\r\n left: 9\r\n });\r\n } else if (containerLeft + containerWidth > $(window).width()) {\r\n this.container.css({\r\n top: containerTop,\r\n left: 'auto',\r\n right: 0\r\n });\r\n } else {\r\n this.container.css({\r\n top: containerTop,\r\n left: containerLeft,\r\n right: 'auto'\r\n });\r\n }\r\n } else {\r\n var containerLeft = this.element.offset().left - parentOffset.left;\r\n if (containerLeft + containerWidth > $(window).width()) {\r\n this.container.css({\r\n top: containerTop,\r\n left: 'auto',\r\n right: 0\r\n });\r\n } else {\r\n this.container.css({\r\n top: containerTop,\r\n left: containerLeft,\r\n right: 'auto'\r\n });\r\n }\r\n }\r\n },\r\n\r\n show: function(e) {\r\n if (this.isShowing) return;\r\n\r\n // Create a click proxy that is private to this instance of datepicker, for unbinding\r\n this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this);\r\n\r\n // Bind global datepicker mousedown for hiding and\r\n $(document)\r\n .on('mousedown.daterangepicker', this._outsideClickProxy)\r\n // also support mobile devices\r\n .on('touchend.daterangepicker', this._outsideClickProxy)\r\n // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\r\n .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\r\n // and also close when focus changes to outside the picker (eg. tabbing between controls)\r\n .on('focusin.daterangepicker', this._outsideClickProxy);\r\n\r\n // Reposition the picker if the window is resized while it's open\r\n $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this));\r\n\r\n this.oldStartDate = this.startDate.clone();\r\n this.oldEndDate = this.endDate.clone();\r\n this.previousRightTime = this.endDate.clone();\r\n\r\n this.updateView();\r\n this.container.show();\r\n this.move();\r\n this.element.trigger('show.daterangepicker', this);\r\n this.isShowing = true;\r\n },\r\n\r\n hide: function(e) {\r\n if (!this.isShowing) return;\r\n\r\n //incomplete date selection, revert to last values\r\n if (!this.endDate) {\r\n this.startDate = this.oldStartDate.clone();\r\n this.endDate = this.oldEndDate.clone();\r\n }\r\n\r\n //if a new date range was selected, invoke the user callback function\r\n if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\r\n this.callback(this.startDate.clone(), this.endDate.clone(), this.chosenLabel);\r\n\r\n //if picker is attached to a text input, update it\r\n this.updateElement();\r\n\r\n $(document).off('.daterangepicker');\r\n $(window).off('.daterangepicker');\r\n this.container.hide();\r\n this.element.trigger('hide.daterangepicker', this);\r\n this.isShowing = false;\r\n },\r\n\r\n toggle: function(e) {\r\n if (this.isShowing) {\r\n this.hide();\r\n } else {\r\n this.show();\r\n }\r\n },\r\n\r\n outsideClick: function(e) {\r\n var target = $(e.target);\r\n // if the page is clicked anywhere except within the daterangerpicker/button\r\n // itself then call this.hide()\r\n if (\r\n // ie modal dialog fix\r\n e.type == \"focusin\" ||\r\n target.closest(this.element).length ||\r\n target.closest(this.container).length ||\r\n target.closest('.calendar-table').length\r\n ) return;\r\n this.hide();\r\n this.element.trigger('outsideClick.daterangepicker', this);\r\n },\r\n\r\n showCalendars: function() {\r\n this.container.addClass('show-calendar');\r\n this.move();\r\n this.element.trigger('showCalendar.daterangepicker', this);\r\n },\r\n\r\n hideCalendars: function() {\r\n this.container.removeClass('show-calendar');\r\n this.element.trigger('hideCalendar.daterangepicker', this);\r\n },\r\n\r\n clickRange: function(e) {\r\n var label = e.target.getAttribute('data-range-key');\r\n this.chosenLabel = label;\r\n if (label == this.locale.customRangeLabel) {\r\n this.showCalendars();\r\n } else {\r\n var dates = this.ranges[label];\r\n this.startDate = dates[0];\r\n this.endDate = dates[1];\r\n\r\n if (!this.timePicker) {\r\n this.startDate.startOf('day');\r\n this.endDate.endOf('day');\r\n }\r\n\r\n if (!this.alwaysShowCalendars)\r\n this.hideCalendars();\r\n this.clickApply();\r\n }\r\n },\r\n\r\n clickPrev: function(e) {\r\n var cal = $(e.target).parents('.drp-calendar');\r\n if (cal.hasClass('left')) {\r\n this.leftCalendar.month.subtract(1, 'month');\r\n if (this.linkedCalendars)\r\n this.rightCalendar.month.subtract(1, 'month');\r\n } else {\r\n this.rightCalendar.month.subtract(1, 'month');\r\n }\r\n this.updateCalendars();\r\n },\r\n\r\n clickNext: function(e) {\r\n var cal = $(e.target).parents('.drp-calendar');\r\n if (cal.hasClass('left')) {\r\n this.leftCalendar.month.add(1, 'month');\r\n } else {\r\n this.rightCalendar.month.add(1, 'month');\r\n if (this.linkedCalendars)\r\n this.leftCalendar.month.add(1, 'month');\r\n }\r\n this.updateCalendars();\r\n },\r\n\r\n hoverDate: function(e) {\r\n\r\n //ignore dates that can't be selected\r\n if (!$(e.target).hasClass('available')) return;\r\n\r\n var title = $(e.target).attr('data-title');\r\n var row = title.substr(1, 1);\r\n var col = title.substr(3, 1);\r\n var cal = $(e.target).parents('.drp-calendar');\r\n var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];\r\n\r\n //highlight the dates between the start date and the date being hovered as a potential end date\r\n var leftCalendar = this.leftCalendar;\r\n var rightCalendar = this.rightCalendar;\r\n var startDate = this.startDate;\r\n if (!this.endDate) {\r\n this.container.find('.drp-calendar tbody td').each(function(index, el) {\r\n\r\n //skip week numbers, only look at dates\r\n if ($(el).hasClass('week')) return;\r\n\r\n var title = $(el).attr('data-title');\r\n var row = title.substr(1, 1);\r\n var col = title.substr(3, 1);\r\n var cal = $(el).parents('.drp-calendar');\r\n var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];\r\n\r\n if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) {\r\n $(el).addClass('in-range');\r\n } else {\r\n $(el).removeClass('in-range');\r\n }\r\n\r\n });\r\n }\r\n\r\n },\r\n\r\n clickDate: function(e) {\r\n\r\n if (!$(e.target).hasClass('available')) return;\r\n\r\n var title = $(e.target).attr('data-title');\r\n var row = title.substr(1, 1);\r\n var col = title.substr(3, 1);\r\n var cal = $(e.target).parents('.drp-calendar');\r\n var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];\r\n\r\n //\r\n // this function needs to do a few things:\r\n // * alternate between selecting a start and end date for the range,\r\n // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date\r\n // * if autoapply is enabled, and an end date was chosen, apply the selection\r\n // * if single date picker mode, and time picker isn't enabled, apply the selection immediately\r\n // * if one of the inputs above the calendars was focused, cancel that manual input\r\n //\r\n\r\n if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start\r\n if (this.timePicker) {\r\n var hour = parseInt(this.container.find('.left .hourselect').val(), 10);\r\n if (!this.timePicker24Hour) {\r\n var ampm = this.container.find('.left .ampmselect').val();\r\n if (ampm === 'PM' && hour < 12)\r\n hour += 12;\r\n if (ampm === 'AM' && hour === 12)\r\n hour = 0;\r\n }\r\n var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);\r\n if (isNaN(minute)) {\r\n minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10);\r\n }\r\n var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;\r\n date = date.clone().hour(hour).minute(minute).second(second);\r\n }\r\n this.endDate = null;\r\n this.setStartDate(date.clone());\r\n } else if (!this.endDate && date.isBefore(this.startDate)) {\r\n //special case: clicking the same date for start/end,\r\n //but the time of the end date is before the start date\r\n this.setEndDate(this.startDate.clone());\r\n } else { // picking end\r\n if (this.timePicker) {\r\n var hour = parseInt(this.container.find('.right .hourselect').val(), 10);\r\n if (!this.timePicker24Hour) {\r\n var ampm = this.container.find('.right .ampmselect').val();\r\n if (ampm === 'PM' && hour < 12)\r\n hour += 12;\r\n if (ampm === 'AM' && hour === 12)\r\n hour = 0;\r\n }\r\n var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);\r\n if (isNaN(minute)) {\r\n minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10);\r\n }\r\n var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;\r\n date = date.clone().hour(hour).minute(minute).second(second);\r\n }\r\n this.setEndDate(date.clone());\r\n if (this.autoApply) {\r\n this.calculateChosenLabel();\r\n this.clickApply();\r\n }\r\n }\r\n\r\n if (this.singleDatePicker) {\r\n this.setEndDate(this.startDate);\r\n if (!this.timePicker && this.autoApply)\r\n this.clickApply();\r\n }\r\n\r\n this.updateView();\r\n\r\n //This is to cancel the blur event handler if the mouse was in one of the inputs\r\n e.stopPropagation();\r\n\r\n },\r\n\r\n calculateChosenLabel: function () {\r\n var customRange = true;\r\n var i = 0;\r\n for (var range in this.ranges) {\r\n if (this.timePicker) {\r\n var format = this.timePickerSeconds ? \"YYYY-MM-DD HH:mm:ss\" : \"YYYY-MM-DD HH:mm\";\r\n //ignore times when comparing dates if time picker seconds is not enabled\r\n if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) {\r\n customRange = false;\r\n this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');\r\n break;\r\n }\r\n } else {\r\n //ignore times when comparing dates if time picker is not enabled\r\n if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\r\n customRange = false;\r\n this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');\r\n break;\r\n }\r\n }\r\n i++;\r\n }\r\n if (customRange) {\r\n if (this.showCustomRangeLabel) {\r\n this.chosenLabel = this.container.find('.ranges li:last').addClass('active').attr('data-range-key');\r\n } else {\r\n this.chosenLabel = null;\r\n }\r\n this.showCalendars();\r\n }\r\n },\r\n\r\n clickApply: function(e) {\r\n this.hide();\r\n this.element.trigger('apply.daterangepicker', this);\r\n },\r\n\r\n clickCancel: function(e) {\r\n this.startDate = this.oldStartDate;\r\n this.endDate = this.oldEndDate;\r\n this.hide();\r\n this.element.trigger('cancel.daterangepicker', this);\r\n },\r\n\r\n monthOrYearChanged: function(e) {\r\n var isLeft = $(e.target).closest('.drp-calendar').hasClass('left'),\r\n leftOrRight = isLeft ? 'left' : 'right',\r\n cal = this.container.find('.drp-calendar.'+leftOrRight);\r\n\r\n // Month must be Number for new moment versions\r\n var month = parseInt(cal.find('.monthselect').val(), 10);\r\n var year = cal.find('.yearselect').val();\r\n\r\n if (!isLeft) {\r\n if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) {\r\n month = this.startDate.month();\r\n year = this.startDate.year();\r\n }\r\n }\r\n\r\n if (this.minDate) {\r\n if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) {\r\n month = this.minDate.month();\r\n year = this.minDate.year();\r\n }\r\n }\r\n\r\n if (this.maxDate) {\r\n if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) {\r\n month = this.maxDate.month();\r\n year = this.maxDate.year();\r\n }\r\n }\r\n\r\n if (isLeft) {\r\n this.leftCalendar.month.month(month).year(year);\r\n if (this.linkedCalendars)\r\n this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month');\r\n } else {\r\n this.rightCalendar.month.month(month).year(year);\r\n if (this.linkedCalendars)\r\n this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month');\r\n }\r\n this.updateCalendars();\r\n },\r\n\r\n timeChanged: function(e) {\r\n\r\n var cal = $(e.target).closest('.drp-calendar'),\r\n isLeft = cal.hasClass('left');\r\n\r\n var hour = parseInt(cal.find('.hourselect').val(), 10);\r\n var minute = parseInt(cal.find('.minuteselect').val(), 10);\r\n if (isNaN(minute)) {\r\n minute = parseInt(cal.find('.minuteselect option:last').val(), 10);\r\n }\r\n var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0;\r\n\r\n if (!this.timePicker24Hour) {\r\n var ampm = cal.find('.ampmselect').val();\r\n if (ampm === 'PM' && hour < 12)\r\n hour += 12;\r\n if (ampm === 'AM' && hour === 12)\r\n hour = 0;\r\n }\r\n\r\n if (isLeft) {\r\n var start = this.startDate.clone();\r\n start.hour(hour);\r\n start.minute(minute);\r\n start.second(second);\r\n this.setStartDate(start);\r\n if (this.singleDatePicker) {\r\n this.endDate = this.startDate.clone();\r\n } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) {\r\n this.setEndDate(start.clone());\r\n }\r\n } else if (this.endDate) {\r\n var end = this.endDate.clone();\r\n end.hour(hour);\r\n end.minute(minute);\r\n end.second(second);\r\n this.setEndDate(end);\r\n }\r\n\r\n //update the calendars so all clickable dates reflect the new time component\r\n this.updateCalendars();\r\n\r\n //update the form inputs above the calendars with the new time\r\n this.updateFormInputs();\r\n\r\n //re-render the time pickers because changing one selection can affect what's enabled in another\r\n this.renderTimePicker('left');\r\n this.renderTimePicker('right');\r\n\r\n },\r\n\r\n elementChanged: function() {\r\n if (!this.element.is('input')) return;\r\n if (!this.element.val().length) return;\r\n\r\n var dateString = this.element.val().split(this.locale.separator),\r\n start = null,\r\n end = null;\r\n\r\n if (dateString.length === 2) {\r\n start = moment(dateString[0], this.locale.format);\r\n end = moment(dateString[1], this.locale.format);\r\n }\r\n\r\n if (this.singleDatePicker || start === null || end === null) {\r\n start = moment(this.element.val(), this.locale.format);\r\n end = start;\r\n }\r\n\r\n if (!start.isValid() || !end.isValid()) return;\r\n\r\n this.setStartDate(start);\r\n this.setEndDate(end);\r\n this.updateView();\r\n },\r\n\r\n keydown: function(e) {\r\n //hide on tab or enter\r\n if ((e.keyCode === 9) || (e.keyCode === 13)) {\r\n this.hide();\r\n }\r\n\r\n //hide on esc and prevent propagation\r\n if (e.keyCode === 27) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n this.hide();\r\n }\r\n },\r\n\r\n updateElement: function() {\r\n if (this.element.is('input') && this.autoUpdateInput) {\r\n var newValue = this.startDate.format(this.locale.format);\r\n if (!this.singleDatePicker) {\r\n newValue += this.locale.separator + this.endDate.format(this.locale.format);\r\n }\r\n if (newValue !== this.element.val()) {\r\n this.element.val(newValue).trigger('change');\r\n }\r\n }\r\n },\r\n\r\n remove: function() {\r\n this.container.remove();\r\n this.element.off('.daterangepicker');\r\n this.element.removeData();\r\n }\r\n\r\n };\r\n\r\n $.fn.daterangepicker = function(options, callback) {\r\n var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options);\r\n this.each(function() {\r\n var el = $(this);\r\n if (el.data('daterangepicker'))\r\n el.data('daterangepicker').remove();\r\n el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback));\r\n });\r\n return this;\r\n };\r\n\r\n return DateRangePicker;\r\n\r\n}));\r\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLWRhdGVyYW5nZXBpY2tlci9kYXRlcmFuZ2VwaWNrZXIuanMuanMiLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSxJQUEwQztBQUNsRDtBQUNBLFFBQVEsaUNBQU8sQ0FBQywyQ0FBUSxFQUFFLDJDQUFRLENBQUMsbUNBQUU7QUFDckMsNENBQTRDO0FBQzVDO0FBQ0E7QUFDQSxTQUFTO0FBQUEsa0dBQUM7QUFDVixNQUFNLEtBQUssdUJBYU47QUFDTCxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QixPQUFPO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsUUFBUTtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMERBQTBELDhDQUE4QyxHQUFHO0FBQzNHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQyxRQUFRO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsY0FBYztBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsU0FBUztBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLFNBQVM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0Msb0JBQW9CO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQyxVQUFVO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QixRQUFRO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0MsUUFBUTtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGlDQUFpQyxpQkFBaUI7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsdUJBQXVCO0FBQ25GO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlFQUF5RSxlQUFlO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQjtBQUN0QjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0VBQXdFO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRDtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vVnVleHkvLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLWRhdGVyYW5nZXBpY2tlci9kYXRlcmFuZ2VwaWNrZXIuanM/ZWY3YyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuKiBAdmVyc2lvbjogMy4xXHJcbiogQGF1dGhvcjogRGFuIEdyb3NzbWFuIGh0dHA6Ly93d3cuZGFuZ3Jvc3NtYW4uaW5mby9cclxuKiBAY29weXJpZ2h0OiBDb3B5cmlnaHQgKGMpIDIwMTItMjAxOSBEYW4gR3Jvc3NtYW4uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiogQGxpY2Vuc2U6IExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS4gU2VlIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXHJcbiogQHdlYnNpdGU6IGh0dHA6Ly93d3cuZGF0ZXJhbmdlcGlja2VyLmNvbS9cclxuKi9cclxuLy8gRm9sbG93aW5nIHRoZSBVTUQgdGVtcGxhdGUgaHR0cHM6Ly9naXRodWIuY29tL3VtZGpzL3VtZC9ibG9iL21hc3Rlci90ZW1wbGF0ZXMvcmV0dXJuRXhwb3J0c0dsb2JhbC5qc1xyXG4oZnVuY3Rpb24gKHJvb3QsIGZhY3RvcnkpIHtcclxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcclxuICAgICAgICAvLyBBTUQuIE1ha2UgZ2xvYmFseSBhdmFpbGFibGUgYXMgd2VsbFxyXG4gICAgICAgIGRlZmluZShbJ21vbWVudCcsICdqcXVlcnknXSwgZnVuY3Rpb24gKG1vbWVudCwganF1ZXJ5KSB7XHJcbiAgICAgICAgICAgIGlmICghanF1ZXJ5LmZuKSBqcXVlcnkuZm4gPSB7fTsgLy8gd2VicGFjayBzZXJ2ZXIgcmVuZGVyaW5nXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbW9tZW50ICE9PSAnZnVuY3Rpb24nICYmIG1vbWVudC5oYXNPd25Qcm9wZXJ0eSgnZGVmYXVsdCcpKSBtb21lbnQgPSBtb21lbnRbJ2RlZmF1bHQnXVxyXG4gICAgICAgICAgICByZXR1cm4gZmFjdG9yeShtb21lbnQsIGpxdWVyeSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7XHJcbiAgICAgICAgLy8gTm9kZSAvIEJyb3dzZXJpZnlcclxuICAgICAgICAvL2lzb21vcnBoaWMgaXNzdWVcclxuICAgICAgICB2YXIgalF1ZXJ5ID0gKHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcpID8gd2luZG93LmpRdWVyeSA6IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAoIWpRdWVyeSkge1xyXG4gICAgICAgICAgICBqUXVlcnkgPSByZXF1aXJlKCdqcXVlcnknKTtcclxuICAgICAgICAgICAgaWYgKCFqUXVlcnkuZm4pIGpRdWVyeS5mbiA9IHt9O1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgbW9tZW50ID0gKHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5tb21lbnQgIT0gJ3VuZGVmaW5lZCcpID8gd2luZG93Lm1vbWVudCA6IHJlcXVpcmUoJ21vbWVudCcpO1xyXG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShtb21lbnQsIGpRdWVyeSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIEJyb3dzZXIgZ2xvYmFsc1xyXG4gICAgICAgIHJvb3QuZGF0ZXJhbmdlcGlja2VyID0gZmFjdG9yeShyb290Lm1vbWVudCwgcm9vdC5qUXVlcnkpO1xyXG4gICAgfVxyXG59KHRoaXMsIGZ1bmN0aW9uKG1vbWVudCwgJCkge1xyXG4gICAgdmFyIERhdGVSYW5nZVBpY2tlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIG9wdGlvbnMsIGNiKSB7XHJcblxyXG4gICAgICAgIC8vZGVmYXVsdCBzZXR0aW5ncyBmb3Igb3B0aW9uc1xyXG4gICAgICAgIHRoaXMucGFyZW50RWwgPSAnYm9keSc7XHJcbiAgICAgICAgdGhpcy5lbGVtZW50ID0gJChlbGVtZW50KTtcclxuICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IG1vbWVudCgpLnN0YXJ0T2YoJ2RheScpO1xyXG4gICAgICAgIHRoaXMuZW5kRGF0ZSA9IG1vbWVudCgpLmVuZE9mKCdkYXknKTtcclxuICAgICAgICB0aGlzLm1pbkRhdGUgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLm1heERhdGUgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLm1heFNwYW4gPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmF1dG9BcHBseSA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuc2luZ2xlRGF0ZVBpY2tlciA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuc2hvd0Ryb3Bkb3ducyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMubWluWWVhciA9IG1vbWVudCgpLnN1YnRyYWN0KDEwMCwgJ3llYXInKS5mb3JtYXQoJ1lZWVknKTtcclxuICAgICAgICB0aGlzLm1heFllYXIgPSBtb21lbnQoKS5hZGQoMTAwLCAneWVhcicpLmZvcm1hdCgnWVlZWScpO1xyXG4gICAgICAgIHRoaXMuc2hvd1dlZWtOdW1iZXJzID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5zaG93SVNPV2Vla051bWJlcnMgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnNob3dDdXN0b21SYW5nZUxhYmVsID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLnRpbWVQaWNrZXIgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnRpbWVQaWNrZXIyNEhvdXIgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnRpbWVQaWNrZXJJbmNyZW1lbnQgPSAxO1xyXG4gICAgICAgIHRoaXMudGltZVBpY2tlclNlY29uZHMgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmxpbmtlZENhbGVuZGFycyA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5hdXRvVXBkYXRlSW5wdXQgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuYWx3YXlzU2hvd0NhbGVuZGFycyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMucmFuZ2VzID0ge307XHJcblxyXG4gICAgICAgIHRoaXMub3BlbnMgPSAncmlnaHQnO1xyXG4gICAgICAgIGlmICh0aGlzLmVsZW1lbnQuaGFzQ2xhc3MoJ3B1bGwtcmlnaHQnKSlcclxuICAgICAgICAgICAgdGhpcy5vcGVucyA9ICdsZWZ0JztcclxuXHJcbiAgICAgICAgdGhpcy5kcm9wcyA9ICdkb3duJztcclxuICAgICAgICBpZiAodGhpcy5lbGVtZW50Lmhhc0NsYXNzKCdkcm9wdXAnKSlcclxuICAgICAgICAgICAgdGhpcy5kcm9wcyA9ICd1cCc7XHJcblxyXG4gICAgICAgIHRoaXMuYnV0dG9uQ2xhc3NlcyA9ICdidG4gYnRuLXNtJztcclxuICAgICAgICB0aGlzLmFwcGx5QnV0dG9uQ2xhc3NlcyA9ICdidG4tcHJpbWFyeSc7XHJcbiAgICAgICAgdGhpcy5jYW5jZWxCdXR0b25DbGFzc2VzID0gJ2J0bi1kZWZhdWx0JztcclxuXHJcbiAgICAgICAgdGhpcy5sb2NhbGUgPSB7XHJcbiAgICAgICAgICAgIGRpcmVjdGlvbjogJ2x0cicsXHJcbiAgICAgICAgICAgIGZvcm1hdDogbW9tZW50LmxvY2FsZURhdGEoKS5sb25nRGF0ZUZvcm1hdCgnTCcpLFxyXG4gICAgICAgICAgICBzZXBhcmF0b3I6ICcgLSAnLFxyXG4gICAgICAgICAgICBhcHBseUxhYmVsOiAnQXBwbHknLFxyXG4gICAgICAgICAgICBjYW5jZWxMYWJlbDogJ0NhbmNlbCcsXHJcbiAgICAgICAgICAgIHdlZWtMYWJlbDogJ1cnLFxyXG4gICAgICAgICAgICBjdXN0b21SYW5nZUxhYmVsOiAnQ3VzdG9tIFJhbmdlJyxcclxuICAgICAgICAgICAgZGF5c09mV2VlazogbW9tZW50LndlZWtkYXlzTWluKCksXHJcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IG1vbWVudC5tb250aHNTaG9ydCgpLFxyXG4gICAgICAgICAgICBmaXJzdERheTogbW9tZW50LmxvY2FsZURhdGEoKS5maXJzdERheU9mV2VlaygpXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYWxsYmFjayA9IGZ1bmN0aW9uKCkgeyB9O1xyXG5cclxuICAgICAgICAvL3NvbWUgc3RhdGUgaW5mb3JtYXRpb25cclxuICAgICAgICB0aGlzLmlzU2hvd2luZyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMubGVmdENhbGVuZGFyID0ge307XHJcbiAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyID0ge307XHJcblxyXG4gICAgICAgIC8vY3VzdG9tIG9wdGlvbnMgZnJvbSB1c2VyXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zICE9PSAnb2JqZWN0JyB8fCBvcHRpb25zID09PSBudWxsKVxyXG4gICAgICAgICAgICBvcHRpb25zID0ge307XHJcblxyXG4gICAgICAgIC8vYWxsb3cgc2V0dGluZyBvcHRpb25zIHdpdGggZGF0YSBhdHRyaWJ1dGVzXHJcbiAgICAgICAgLy9kYXRhLWFwaSBvcHRpb25zIHdpbGwgYmUgb3ZlcndyaXR0ZW4gd2l0aCBjdXN0b20gamF2YXNjcmlwdCBvcHRpb25zXHJcbiAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKHRoaXMuZWxlbWVudC5kYXRhKCksIG9wdGlvbnMpO1xyXG5cclxuICAgICAgICAvL2h0bWwgdGVtcGxhdGUgZm9yIHRoZSBwaWNrZXIgVUlcclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMudGVtcGxhdGUgIT09ICdzdHJpbmcnICYmICEob3B0aW9ucy50ZW1wbGF0ZSBpbnN0YW5jZW9mICQpKVxyXG4gICAgICAgICAgICBvcHRpb25zLnRlbXBsYXRlID1cclxuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJkYXRlcmFuZ2VwaWNrZXJcIj4nICtcclxuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwicmFuZ2VzXCI+PC9kaXY+JyArXHJcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImRycC1jYWxlbmRhciBsZWZ0XCI+JyArXHJcbiAgICAgICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJjYWxlbmRhci10YWJsZVwiPjwvZGl2PicgK1xyXG4gICAgICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiY2FsZW5kYXItdGltZVwiPjwvZGl2PicgK1xyXG4gICAgICAgICAgICAgICAgJzwvZGl2PicgK1xyXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJkcnAtY2FsZW5kYXIgcmlnaHRcIj4nICtcclxuICAgICAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImNhbGVuZGFyLXRhYmxlXCI+PC9kaXY+JyArXHJcbiAgICAgICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJjYWxlbmRhci10aW1lXCI+PC9kaXY+JyArXHJcbiAgICAgICAgICAgICAgICAnPC9kaXY+JyArXHJcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImRycC1idXR0b25zXCI+JyArXHJcbiAgICAgICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiZHJwLXNlbGVjdGVkXCI+PC9zcGFuPicgK1xyXG4gICAgICAgICAgICAgICAgICAgICc8YnV0dG9uIGNsYXNzPVwiY2FuY2VsQnRuXCIgdHlwZT1cImJ1dHRvblwiPjwvYnV0dG9uPicgK1xyXG4gICAgICAgICAgICAgICAgICAgICc8YnV0dG9uIGNsYXNzPVwiYXBwbHlCdG5cIiBkaXNhYmxlZD1cImRpc2FibGVkXCIgdHlwZT1cImJ1dHRvblwiPjwvYnV0dG9uPiAnICtcclxuICAgICAgICAgICAgICAgICc8L2Rpdj4nICtcclxuICAgICAgICAgICAgJzwvZGl2Pic7XHJcblxyXG4gICAgICAgIHRoaXMucGFyZW50RWwgPSAob3B0aW9ucy5wYXJlbnRFbCAmJiAkKG9wdGlvbnMucGFyZW50RWwpLmxlbmd0aCkgPyAkKG9wdGlvbnMucGFyZW50RWwpIDogJCh0aGlzLnBhcmVudEVsKTtcclxuICAgICAgICB0aGlzLmNvbnRhaW5lciA9ICQob3B0aW9ucy50ZW1wbGF0ZSkuYXBwZW5kVG8odGhpcy5wYXJlbnRFbCk7XHJcblxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gaGFuZGxlIGFsbCB0aGUgcG9zc2libGUgb3B0aW9ucyBvdmVycmlkaW5nIGRlZmF1bHRzXHJcbiAgICAgICAgLy9cclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmxvY2FsZSA9PT0gJ29iamVjdCcpIHtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2NhbGUuZGlyZWN0aW9uID09PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxlLmRpcmVjdGlvbiA9IG9wdGlvbnMubG9jYWxlLmRpcmVjdGlvbjtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2NhbGUuZm9ybWF0ID09PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxlLmZvcm1hdCA9IG9wdGlvbnMubG9jYWxlLmZvcm1hdDtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2NhbGUuc2VwYXJhdG9yID09PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxlLnNlcGFyYXRvciA9IG9wdGlvbnMubG9jYWxlLnNlcGFyYXRvcjtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2NhbGUuZGF5c09mV2VlayA9PT0gJ29iamVjdCcpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZS5kYXlzT2ZXZWVrID0gb3B0aW9ucy5sb2NhbGUuZGF5c09mV2Vlay5zbGljZSgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmxvY2FsZS5tb250aE5hbWVzID09PSAnb2JqZWN0JylcclxuICAgICAgICAgICAgICB0aGlzLmxvY2FsZS5tb250aE5hbWVzID0gb3B0aW9ucy5sb2NhbGUubW9udGhOYW1lcy5zbGljZSgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmxvY2FsZS5maXJzdERheSA9PT0gJ251bWJlcicpXHJcbiAgICAgICAgICAgICAgdGhpcy5sb2NhbGUuZmlyc3REYXkgPSBvcHRpb25zLmxvY2FsZS5maXJzdERheTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2NhbGUuYXBwbHlMYWJlbCA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgICAgdGhpcy5sb2NhbGUuYXBwbHlMYWJlbCA9IG9wdGlvbnMubG9jYWxlLmFwcGx5TGFiZWw7XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMubG9jYWxlLmNhbmNlbExhYmVsID09PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgICB0aGlzLmxvY2FsZS5jYW5jZWxMYWJlbCA9IG9wdGlvbnMubG9jYWxlLmNhbmNlbExhYmVsO1xyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmxvY2FsZS53ZWVrTGFiZWwgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICAgIHRoaXMubG9jYWxlLndlZWtMYWJlbCA9IG9wdGlvbnMubG9jYWxlLndlZWtMYWJlbDtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2NhbGUuY3VzdG9tUmFuZ2VMYWJlbCA9PT0gJ3N0cmluZycpe1xyXG4gICAgICAgICAgICAgICAgLy9TdXBwb3J0IHVuaWNvZGUgY2hhcnMgaW4gdGhlIGN1c3RvbSByYW5nZSBuYW1lLlxyXG4gICAgICAgICAgICAgICAgdmFyIGVsZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZXh0YXJlYScpO1xyXG4gICAgICAgICAgICAgICAgZWxlbS5pbm5lckhUTUwgPSBvcHRpb25zLmxvY2FsZS5jdXN0b21SYW5nZUxhYmVsO1xyXG4gICAgICAgICAgICAgICAgdmFyIHJhbmdlSHRtbCA9IGVsZW0udmFsdWU7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZS5jdXN0b21SYW5nZUxhYmVsID0gcmFuZ2VIdG1sO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuY29udGFpbmVyLmFkZENsYXNzKHRoaXMubG9jYWxlLmRpcmVjdGlvbik7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zdGFydERhdGUgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IG1vbWVudChvcHRpb25zLnN0YXJ0RGF0ZSwgdGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmVuZERhdGUgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICB0aGlzLmVuZERhdGUgPSBtb21lbnQob3B0aW9ucy5lbmREYXRlLCB0aGlzLmxvY2FsZS5mb3JtYXQpO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMubWluRGF0ZSA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgIHRoaXMubWluRGF0ZSA9IG1vbWVudChvcHRpb25zLm1pbkRhdGUsIHRoaXMubG9jYWxlLmZvcm1hdCk7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5tYXhEYXRlID09PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgdGhpcy5tYXhEYXRlID0gbW9tZW50KG9wdGlvbnMubWF4RGF0ZSwgdGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnN0YXJ0RGF0ZSA9PT0gJ29iamVjdCcpXHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnREYXRlID0gbW9tZW50KG9wdGlvbnMuc3RhcnREYXRlKTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmVuZERhdGUgPT09ICdvYmplY3QnKVxyXG4gICAgICAgICAgICB0aGlzLmVuZERhdGUgPSBtb21lbnQob3B0aW9ucy5lbmREYXRlKTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm1pbkRhdGUgPT09ICdvYmplY3QnKVxyXG4gICAgICAgICAgICB0aGlzLm1pbkRhdGUgPSBtb21lbnQob3B0aW9ucy5taW5EYXRlKTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm1heERhdGUgPT09ICdvYmplY3QnKVxyXG4gICAgICAgICAgICB0aGlzLm1heERhdGUgPSBtb21lbnQob3B0aW9ucy5tYXhEYXRlKTtcclxuXHJcbiAgICAgICAgLy8gc2FuaXR5IGNoZWNrIGZvciBiYWQgb3B0aW9uc1xyXG4gICAgICAgIGlmICh0aGlzLm1pbkRhdGUgJiYgdGhpcy5zdGFydERhdGUuaXNCZWZvcmUodGhpcy5taW5EYXRlKSlcclxuICAgICAgICAgICAgdGhpcy5zdGFydERhdGUgPSB0aGlzLm1pbkRhdGUuY2xvbmUoKTtcclxuXHJcbiAgICAgICAgLy8gc2FuaXR5IGNoZWNrIGZvciBiYWQgb3B0aW9uc1xyXG4gICAgICAgIGlmICh0aGlzLm1heERhdGUgJiYgdGhpcy5lbmREYXRlLmlzQWZ0ZXIodGhpcy5tYXhEYXRlKSlcclxuICAgICAgICAgICAgdGhpcy5lbmREYXRlID0gdGhpcy5tYXhEYXRlLmNsb25lKCk7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5hcHBseUJ1dHRvbkNsYXNzZXMgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICB0aGlzLmFwcGx5QnV0dG9uQ2xhc3NlcyA9IG9wdGlvbnMuYXBwbHlCdXR0b25DbGFzc2VzO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuYXBwbHlDbGFzcyA9PT0gJ3N0cmluZycpIC8vYmFja3dhcmRzIGNvbXBhdFxyXG4gICAgICAgICAgICB0aGlzLmFwcGx5QnV0dG9uQ2xhc3NlcyA9IG9wdGlvbnMuYXBwbHlDbGFzcztcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmNhbmNlbEJ1dHRvbkNsYXNzZXMgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICB0aGlzLmNhbmNlbEJ1dHRvbkNsYXNzZXMgPSBvcHRpb25zLmNhbmNlbEJ1dHRvbkNsYXNzZXM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jYW5jZWxDbGFzcyA9PT0gJ3N0cmluZycpIC8vYmFja3dhcmRzIGNvbXBhdFxyXG4gICAgICAgICAgICB0aGlzLmNhbmNlbEJ1dHRvbkNsYXNzZXMgPSBvcHRpb25zLmNhbmNlbENsYXNzO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMubWF4U3BhbiA9PT0gJ29iamVjdCcpXHJcbiAgICAgICAgICAgIHRoaXMubWF4U3BhbiA9IG9wdGlvbnMubWF4U3BhbjtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmRhdGVMaW1pdCA9PT0gJ29iamVjdCcpIC8vYmFja3dhcmRzIGNvbXBhdFxyXG4gICAgICAgICAgICB0aGlzLm1heFNwYW4gPSBvcHRpb25zLmRhdGVMaW1pdDtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm9wZW5zID09PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgdGhpcy5vcGVucyA9IG9wdGlvbnMub3BlbnM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kcm9wcyA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgIHRoaXMuZHJvcHMgPSBvcHRpb25zLmRyb3BzO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuc2hvd1dlZWtOdW1iZXJzID09PSAnYm9vbGVhbicpXHJcbiAgICAgICAgICAgIHRoaXMuc2hvd1dlZWtOdW1iZXJzID0gb3B0aW9ucy5zaG93V2Vla051bWJlcnM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zaG93SVNPV2Vla051bWJlcnMgPT09ICdib29sZWFuJylcclxuICAgICAgICAgICAgdGhpcy5zaG93SVNPV2Vla051bWJlcnMgPSBvcHRpb25zLnNob3dJU09XZWVrTnVtYmVycztcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmJ1dHRvbkNsYXNzZXMgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICB0aGlzLmJ1dHRvbkNsYXNzZXMgPSBvcHRpb25zLmJ1dHRvbkNsYXNzZXM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5idXR0b25DbGFzc2VzID09PSAnb2JqZWN0JylcclxuICAgICAgICAgICAgdGhpcy5idXR0b25DbGFzc2VzID0gb3B0aW9ucy5idXR0b25DbGFzc2VzLmpvaW4oJyAnKTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnNob3dEcm9wZG93bnMgPT09ICdib29sZWFuJylcclxuICAgICAgICAgICAgdGhpcy5zaG93RHJvcGRvd25zID0gb3B0aW9ucy5zaG93RHJvcGRvd25zO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMubWluWWVhciA9PT0gJ251bWJlcicpXHJcbiAgICAgICAgICAgIHRoaXMubWluWWVhciA9IG9wdGlvbnMubWluWWVhcjtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm1heFllYXIgPT09ICdudW1iZXInKVxyXG4gICAgICAgICAgICB0aGlzLm1heFllYXIgPSBvcHRpb25zLm1heFllYXI7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zaG93Q3VzdG9tUmFuZ2VMYWJlbCA9PT0gJ2Jvb2xlYW4nKVxyXG4gICAgICAgICAgICB0aGlzLnNob3dDdXN0b21SYW5nZUxhYmVsID0gb3B0aW9ucy5zaG93Q3VzdG9tUmFuZ2VMYWJlbDtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnNpbmdsZURhdGVQaWNrZXIgPT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICB0aGlzLnNpbmdsZURhdGVQaWNrZXIgPSBvcHRpb25zLnNpbmdsZURhdGVQaWNrZXI7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNpbmdsZURhdGVQaWNrZXIpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVuZERhdGUgPSB0aGlzLnN0YXJ0RGF0ZS5jbG9uZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnRpbWVQaWNrZXIgPT09ICdib29sZWFuJylcclxuICAgICAgICAgICAgdGhpcy50aW1lUGlja2VyID0gb3B0aW9ucy50aW1lUGlja2VyO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMudGltZVBpY2tlclNlY29uZHMgPT09ICdib29sZWFuJylcclxuICAgICAgICAgICAgdGhpcy50aW1lUGlja2VyU2Vjb25kcyA9IG9wdGlvbnMudGltZVBpY2tlclNlY29uZHM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy50aW1lUGlja2VySW5jcmVtZW50ID09PSAnbnVtYmVyJylcclxuICAgICAgICAgICAgdGhpcy50aW1lUGlja2VySW5jcmVtZW50ID0gb3B0aW9ucy50aW1lUGlja2VySW5jcmVtZW50O1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMudGltZVBpY2tlcjI0SG91ciA9PT0gJ2Jvb2xlYW4nKVxyXG4gICAgICAgICAgICB0aGlzLnRpbWVQaWNrZXIyNEhvdXIgPSBvcHRpb25zLnRpbWVQaWNrZXIyNEhvdXI7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5hdXRvQXBwbHkgPT09ICdib29sZWFuJylcclxuICAgICAgICAgICAgdGhpcy5hdXRvQXBwbHkgPSBvcHRpb25zLmF1dG9BcHBseTtcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmF1dG9VcGRhdGVJbnB1dCA9PT0gJ2Jvb2xlYW4nKVxyXG4gICAgICAgICAgICB0aGlzLmF1dG9VcGRhdGVJbnB1dCA9IG9wdGlvbnMuYXV0b1VwZGF0ZUlucHV0O1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMubGlua2VkQ2FsZW5kYXJzID09PSAnYm9vbGVhbicpXHJcbiAgICAgICAgICAgIHRoaXMubGlua2VkQ2FsZW5kYXJzID0gb3B0aW9ucy5saW5rZWRDYWxlbmRhcnM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5pc0ludmFsaWREYXRlID09PSAnZnVuY3Rpb24nKVxyXG4gICAgICAgICAgICB0aGlzLmlzSW52YWxpZERhdGUgPSBvcHRpb25zLmlzSW52YWxpZERhdGU7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5pc0N1c3RvbURhdGUgPT09ICdmdW5jdGlvbicpXHJcbiAgICAgICAgICAgIHRoaXMuaXNDdXN0b21EYXRlID0gb3B0aW9ucy5pc0N1c3RvbURhdGU7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5hbHdheXNTaG93Q2FsZW5kYXJzID09PSAnYm9vbGVhbicpXHJcbiAgICAgICAgICAgIHRoaXMuYWx3YXlzU2hvd0NhbGVuZGFycyA9IG9wdGlvbnMuYWx3YXlzU2hvd0NhbGVuZGFycztcclxuXHJcbiAgICAgICAgLy8gdXBkYXRlIGRheSBuYW1lcyBvcmRlciB0byBmaXJzdERheVxyXG4gICAgICAgIGlmICh0aGlzLmxvY2FsZS5maXJzdERheSAhPSAwKSB7XHJcbiAgICAgICAgICAgIHZhciBpdGVyYXRvciA9IHRoaXMubG9jYWxlLmZpcnN0RGF5O1xyXG4gICAgICAgICAgICB3aGlsZSAoaXRlcmF0b3IgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZS5kYXlzT2ZXZWVrLnB1c2godGhpcy5sb2NhbGUuZGF5c09mV2Vlay5zaGlmdCgpKTtcclxuICAgICAgICAgICAgICAgIGl0ZXJhdG9yLS07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhciBzdGFydCwgZW5kLCByYW5nZTtcclxuXHJcbiAgICAgICAgLy9pZiBubyBzdGFydC9lbmQgZGF0ZXMgc2V0LCBjaGVjayBpZiBhbiBpbnB1dCBlbGVtZW50IGNvbnRhaW5zIGluaXRpYWwgdmFsdWVzXHJcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnN0YXJ0RGF0ZSA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIG9wdGlvbnMuZW5kRGF0ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgaWYgKCQodGhpcy5lbGVtZW50KS5pcygnOnRleHQnKSkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHZhbCA9ICQodGhpcy5lbGVtZW50KS52YWwoKSxcclxuICAgICAgICAgICAgICAgICAgICBzcGxpdCA9IHZhbC5zcGxpdCh0aGlzLmxvY2FsZS5zZXBhcmF0b3IpO1xyXG5cclxuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZW5kID0gbnVsbDtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoc3BsaXQubGVuZ3RoID09IDIpIHtcclxuICAgICAgICAgICAgICAgICAgICBzdGFydCA9IG1vbWVudChzcGxpdFswXSwgdGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuICAgICAgICAgICAgICAgICAgICBlbmQgPSBtb21lbnQoc3BsaXRbMV0sIHRoaXMubG9jYWxlLmZvcm1hdCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2luZ2xlRGF0ZVBpY2tlciAmJiB2YWwgIT09IFwiXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICBzdGFydCA9IG1vbWVudCh2YWwsIHRoaXMubG9jYWxlLmZvcm1hdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gbW9tZW50KHZhbCwgdGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChzdGFydCAhPT0gbnVsbCAmJiBlbmQgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXJ0RGF0ZShzdGFydCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRFbmREYXRlKGVuZCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yYW5nZXMgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgIGZvciAocmFuZ2UgaW4gb3B0aW9ucy5yYW5nZXMpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMucmFuZ2VzW3JhbmdlXVswXSA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSBtb21lbnQob3B0aW9ucy5yYW5nZXNbcmFuZ2VdWzBdLCB0aGlzLmxvY2FsZS5mb3JtYXQpO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gbW9tZW50KG9wdGlvbnMucmFuZ2VzW3JhbmdlXVswXSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnJhbmdlc1tyYW5nZV1bMV0gPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IG1vbWVudChvcHRpb25zLnJhbmdlc1tyYW5nZV1bMV0sIHRoaXMubG9jYWxlLmZvcm1hdCk7XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gbW9tZW50KG9wdGlvbnMucmFuZ2VzW3JhbmdlXVsxXSk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHN0YXJ0IG9yIGVuZCBkYXRlIGV4Y2VlZCB0aG9zZSBhbGxvd2VkIGJ5IHRoZSBtaW5EYXRlIG9yIG1heFNwYW5cclxuICAgICAgICAgICAgICAgIC8vIG9wdGlvbnMsIHNob3J0ZW4gdGhlIHJhbmdlIHRvIHRoZSBhbGxvd2FibGUgcGVyaW9kLlxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWluRGF0ZSAmJiBzdGFydC5pc0JlZm9yZSh0aGlzLm1pbkRhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5taW5EYXRlLmNsb25lKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdmFyIG1heERhdGUgPSB0aGlzLm1heERhdGU7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5tYXhTcGFuICYmIG1heERhdGUgJiYgc3RhcnQuY2xvbmUoKS5hZGQodGhpcy5tYXhTcGFuKS5pc0FmdGVyKG1heERhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIG1heERhdGUgPSBzdGFydC5jbG9uZSgpLmFkZCh0aGlzLm1heFNwYW4pO1xyXG4gICAgICAgICAgICAgICAgaWYgKG1heERhdGUgJiYgZW5kLmlzQWZ0ZXIobWF4RGF0ZSkpXHJcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gbWF4RGF0ZS5jbG9uZSgpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBlbmQgb2YgdGhlIHJhbmdlIGlzIGJlZm9yZSB0aGUgbWluaW11bSBvciB0aGUgc3RhcnQgb2YgdGhlIHJhbmdlIGlzXHJcbiAgICAgICAgICAgICAgICAvLyBhZnRlciB0aGUgbWF4aW11bSwgZG9uJ3QgZGlzcGxheSB0aGlzIHJhbmdlIG9wdGlvbiBhdCBhbGwuXHJcbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMubWluRGF0ZSAmJiBlbmQuaXNCZWZvcmUodGhpcy5taW5EYXRlLCB0aGlzLnRpbWVwaWNrZXIgPyAnbWludXRlJyA6ICdkYXknKSlcclxuICAgICAgICAgICAgICAgICAgfHwgKG1heERhdGUgJiYgc3RhcnQuaXNBZnRlcihtYXhEYXRlLCB0aGlzLnRpbWVwaWNrZXIgPyAnbWludXRlJyA6ICdkYXknKSkpXHJcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9TdXBwb3J0IHVuaWNvZGUgY2hhcnMgaW4gdGhlIHJhbmdlIG5hbWVzLlxyXG4gICAgICAgICAgICAgICAgdmFyIGVsZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZXh0YXJlYScpO1xyXG4gICAgICAgICAgICAgICAgZWxlbS5pbm5lckhUTUwgPSByYW5nZTtcclxuICAgICAgICAgICAgICAgIHZhciByYW5nZUh0bWwgPSBlbGVtLnZhbHVlO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMucmFuZ2VzW3JhbmdlSHRtbF0gPSBbc3RhcnQsIGVuZF07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHZhciBsaXN0ID0gJzx1bD4nO1xyXG4gICAgICAgICAgICBmb3IgKHJhbmdlIGluIHRoaXMucmFuZ2VzKSB7XHJcbiAgICAgICAgICAgICAgICBsaXN0ICs9ICc8bGkgZGF0YS1yYW5nZS1rZXk9XCInICsgcmFuZ2UgKyAnXCI+JyArIHJhbmdlICsgJzwvbGk+JztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodGhpcy5zaG93Q3VzdG9tUmFuZ2VMYWJlbCkge1xyXG4gICAgICAgICAgICAgICAgbGlzdCArPSAnPGxpIGRhdGEtcmFuZ2Uta2V5PVwiJyArIHRoaXMubG9jYWxlLmN1c3RvbVJhbmdlTGFiZWwgKyAnXCI+JyArIHRoaXMubG9jYWxlLmN1c3RvbVJhbmdlTGFiZWwgKyAnPC9saT4nO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGxpc3QgKz0gJzwvdWw+JztcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuZmluZCgnLnJhbmdlcycpLnByZXBlbmQobGlzdCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodHlwZW9mIGNiID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2sgPSBjYjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghdGhpcy50aW1lUGlja2VyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnREYXRlID0gdGhpcy5zdGFydERhdGUuc3RhcnRPZignZGF5Jyk7XHJcbiAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IHRoaXMuZW5kRGF0ZS5lbmRPZignZGF5Jyk7XHJcbiAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5jYWxlbmRhci10aW1lJykuaGlkZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9jYW4ndCBiZSB1c2VkIHRvZ2V0aGVyIGZvciBub3dcclxuICAgICAgICBpZiAodGhpcy50aW1lUGlja2VyICYmIHRoaXMuYXV0b0FwcGx5KVxyXG4gICAgICAgICAgICB0aGlzLmF1dG9BcHBseSA9IGZhbHNlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5hdXRvQXBwbHkpIHtcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuYWRkQ2xhc3MoJ2F1dG8tYXBwbHknKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yYW5nZXMgPT09ICdvYmplY3QnKVxyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hZGRDbGFzcygnc2hvdy1yYW5nZXMnKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuc2luZ2xlRGF0ZVBpY2tlcikge1xyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hZGRDbGFzcygnc2luZ2xlJyk7XHJcbiAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5kcnAtY2FsZW5kYXIubGVmdCcpLmFkZENsYXNzKCdzaW5nbGUnKTtcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuZmluZCgnLmRycC1jYWxlbmRhci5sZWZ0Jykuc2hvdygpO1xyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuZHJwLWNhbGVuZGFyLnJpZ2h0JykuaGlkZSgpO1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMudGltZVBpY2tlciAmJiB0aGlzLmF1dG9BcHBseSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuYWRkQ2xhc3MoJ2F1dG8tYXBwbHknKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCh0eXBlb2Ygb3B0aW9ucy5yYW5nZXMgPT09ICd1bmRlZmluZWQnICYmICF0aGlzLnNpbmdsZURhdGVQaWNrZXIpIHx8IHRoaXMuYWx3YXlzU2hvd0NhbGVuZGFycykge1xyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hZGRDbGFzcygnc2hvdy1jYWxlbmRhcicpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5jb250YWluZXIuYWRkQ2xhc3MoJ29wZW5zJyArIHRoaXMub3BlbnMpO1xyXG5cclxuICAgICAgICAvL2FwcGx5IENTUyBjbGFzc2VzIGFuZCBsYWJlbHMgdG8gYnV0dG9uc1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5hcHBseUJ0biwgLmNhbmNlbEJ0bicpLmFkZENsYXNzKHRoaXMuYnV0dG9uQ2xhc3Nlcyk7XHJcbiAgICAgICAgaWYgKHRoaXMuYXBwbHlCdXR0b25DbGFzc2VzLmxlbmd0aClcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuZmluZCgnLmFwcGx5QnRuJykuYWRkQ2xhc3ModGhpcy5hcHBseUJ1dHRvbkNsYXNzZXMpO1xyXG4gICAgICAgIGlmICh0aGlzLmNhbmNlbEJ1dHRvbkNsYXNzZXMubGVuZ3RoKVxyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuY2FuY2VsQnRuJykuYWRkQ2xhc3ModGhpcy5jYW5jZWxCdXR0b25DbGFzc2VzKTtcclxuICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuYXBwbHlCdG4nKS5odG1sKHRoaXMubG9jYWxlLmFwcGx5TGFiZWwpO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5jYW5jZWxCdG4nKS5odG1sKHRoaXMubG9jYWxlLmNhbmNlbExhYmVsKTtcclxuXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBldmVudCBsaXN0ZW5lcnNcclxuICAgICAgICAvL1xyXG5cclxuICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuZHJwLWNhbGVuZGFyJylcclxuICAgICAgICAgICAgLm9uKCdjbGljay5kYXRlcmFuZ2VwaWNrZXInLCAnLnByZXYnLCAkLnByb3h5KHRoaXMuY2xpY2tQcmV2LCB0aGlzKSlcclxuICAgICAgICAgICAgLm9uKCdjbGljay5kYXRlcmFuZ2VwaWNrZXInLCAnLm5leHQnLCAkLnByb3h5KHRoaXMuY2xpY2tOZXh0LCB0aGlzKSlcclxuICAgICAgICAgICAgLm9uKCdtb3VzZWRvd24uZGF0ZXJhbmdlcGlja2VyJywgJ3RkLmF2YWlsYWJsZScsICQucHJveHkodGhpcy5jbGlja0RhdGUsIHRoaXMpKVxyXG4gICAgICAgICAgICAub24oJ21vdXNlZW50ZXIuZGF0ZXJhbmdlcGlja2VyJywgJ3RkLmF2YWlsYWJsZScsICQucHJveHkodGhpcy5ob3ZlckRhdGUsIHRoaXMpKVxyXG4gICAgICAgICAgICAub24oJ2NoYW5nZS5kYXRlcmFuZ2VwaWNrZXInLCAnc2VsZWN0LnllYXJzZWxlY3QnLCAkLnByb3h5KHRoaXMubW9udGhPclllYXJDaGFuZ2VkLCB0aGlzKSlcclxuICAgICAgICAgICAgLm9uKCdjaGFuZ2UuZGF0ZXJhbmdlcGlja2VyJywgJ3NlbGVjdC5tb250aHNlbGVjdCcsICQucHJveHkodGhpcy5tb250aE9yWWVhckNoYW5nZWQsIHRoaXMpKVxyXG4gICAgICAgICAgICAub24oJ2NoYW5nZS5kYXRlcmFuZ2VwaWNrZXInLCAnc2VsZWN0LmhvdXJzZWxlY3Qsc2VsZWN0Lm1pbnV0ZXNlbGVjdCxzZWxlY3Quc2Vjb25kc2VsZWN0LHNlbGVjdC5hbXBtc2VsZWN0JywgJC5wcm94eSh0aGlzLnRpbWVDaGFuZ2VkLCB0aGlzKSk7XHJcblxyXG4gICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5yYW5nZXMnKVxyXG4gICAgICAgICAgICAub24oJ2NsaWNrLmRhdGVyYW5nZXBpY2tlcicsICdsaScsICQucHJveHkodGhpcy5jbGlja1JhbmdlLCB0aGlzKSk7XHJcblxyXG4gICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5kcnAtYnV0dG9ucycpXHJcbiAgICAgICAgICAgIC5vbignY2xpY2suZGF0ZXJhbmdlcGlja2VyJywgJ2J1dHRvbi5hcHBseUJ0bicsICQucHJveHkodGhpcy5jbGlja0FwcGx5LCB0aGlzKSlcclxuICAgICAgICAgICAgLm9uKCdjbGljay5kYXRlcmFuZ2VwaWNrZXInLCAnYnV0dG9uLmNhbmNlbEJ0bicsICQucHJveHkodGhpcy5jbGlja0NhbmNlbCwgdGhpcykpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5lbGVtZW50LmlzKCdpbnB1dCcpIHx8IHRoaXMuZWxlbWVudC5pcygnYnV0dG9uJykpIHtcclxuICAgICAgICAgICAgdGhpcy5lbGVtZW50Lm9uKHtcclxuICAgICAgICAgICAgICAgICdjbGljay5kYXRlcmFuZ2VwaWNrZXInOiAkLnByb3h5KHRoaXMuc2hvdywgdGhpcyksXHJcbiAgICAgICAgICAgICAgICAnZm9jdXMuZGF0ZXJhbmdlcGlja2VyJzogJC5wcm94eSh0aGlzLnNob3csIHRoaXMpLFxyXG4gICAgICAgICAgICAgICAgJ2tleXVwLmRhdGVyYW5nZXBpY2tlcic6ICQucHJveHkodGhpcy5lbGVtZW50Q2hhbmdlZCwgdGhpcyksXHJcbiAgICAgICAgICAgICAgICAna2V5ZG93bi5kYXRlcmFuZ2VwaWNrZXInOiAkLnByb3h5KHRoaXMua2V5ZG93biwgdGhpcykgLy9JRSAxMSBjb21wYXRpYmlsaXR5XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC5vbignY2xpY2suZGF0ZXJhbmdlcGlja2VyJywgJC5wcm94eSh0aGlzLnRvZ2dsZSwgdGhpcykpO1xyXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQub24oJ2tleWRvd24uZGF0ZXJhbmdlcGlja2VyJywgJC5wcm94eSh0aGlzLnRvZ2dsZSwgdGhpcykpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBpZiBhdHRhY2hlZCB0byBhIHRleHQgaW5wdXQsIHNldCB0aGUgaW5pdGlhbCB2YWx1ZVxyXG4gICAgICAgIC8vXHJcblxyXG4gICAgICAgIHRoaXMudXBkYXRlRWxlbWVudCgpO1xyXG5cclxuICAgIH07XHJcblxyXG4gICAgRGF0ZVJhbmdlUGlja2VyLnByb3RvdHlwZSA9IHtcclxuXHJcbiAgICAgICAgY29uc3RydWN0b3I6IERhdGVSYW5nZVBpY2tlcixcclxuXHJcbiAgICAgICAgc2V0U3RhcnREYXRlOiBmdW5jdGlvbihzdGFydERhdGUpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzdGFydERhdGUgPT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUgPSBtb21lbnQoc3RhcnREYXRlLCB0aGlzLmxvY2FsZS5mb3JtYXQpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzdGFydERhdGUgPT09ICdvYmplY3QnKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUgPSBtb21lbnQoc3RhcnREYXRlKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy50aW1lUGlja2VyKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUgPSB0aGlzLnN0YXJ0RGF0ZS5zdGFydE9mKCdkYXknKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnRpbWVQaWNrZXIgJiYgdGhpcy50aW1lUGlja2VySW5jcmVtZW50KVxyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUubWludXRlKE1hdGgucm91bmQodGhpcy5zdGFydERhdGUubWludXRlKCkgLyB0aGlzLnRpbWVQaWNrZXJJbmNyZW1lbnQpICogdGhpcy50aW1lUGlja2VySW5jcmVtZW50KTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLm1pbkRhdGUgJiYgdGhpcy5zdGFydERhdGUuaXNCZWZvcmUodGhpcy5taW5EYXRlKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUgPSB0aGlzLm1pbkRhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRpbWVQaWNrZXIgJiYgdGhpcy50aW1lUGlja2VySW5jcmVtZW50KVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhcnREYXRlLm1pbnV0ZShNYXRoLnJvdW5kKHRoaXMuc3RhcnREYXRlLm1pbnV0ZSgpIC8gdGhpcy50aW1lUGlja2VySW5jcmVtZW50KSAqIHRoaXMudGltZVBpY2tlckluY3JlbWVudCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLm1heERhdGUgJiYgdGhpcy5zdGFydERhdGUuaXNBZnRlcih0aGlzLm1heERhdGUpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IHRoaXMubWF4RGF0ZS5jbG9uZSgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudGltZVBpY2tlciAmJiB0aGlzLnRpbWVQaWNrZXJJbmNyZW1lbnQpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUubWludXRlKE1hdGguZmxvb3IodGhpcy5zdGFydERhdGUubWludXRlKCkgLyB0aGlzLnRpbWVQaWNrZXJJbmNyZW1lbnQpICogdGhpcy50aW1lUGlja2VySW5jcmVtZW50KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzU2hvd2luZylcclxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudCgpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy51cGRhdGVNb250aHNJblZpZXcoKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBzZXRFbmREYXRlOiBmdW5jdGlvbihlbmREYXRlKSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZW5kRGF0ZSA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVuZERhdGUgPSBtb21lbnQoZW5kRGF0ZSwgdGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZW5kRGF0ZSA9PT0gJ29iamVjdCcpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVuZERhdGUgPSBtb21lbnQoZW5kRGF0ZSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIXRoaXMudGltZVBpY2tlcilcclxuICAgICAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IHRoaXMuZW5kRGF0ZS5lbmRPZignZGF5Jyk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy50aW1lUGlja2VyICYmIHRoaXMudGltZVBpY2tlckluY3JlbWVudClcclxuICAgICAgICAgICAgICAgIHRoaXMuZW5kRGF0ZS5taW51dGUoTWF0aC5yb3VuZCh0aGlzLmVuZERhdGUubWludXRlKCkgLyB0aGlzLnRpbWVQaWNrZXJJbmNyZW1lbnQpICogdGhpcy50aW1lUGlja2VySW5jcmVtZW50KTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmVuZERhdGUuaXNCZWZvcmUodGhpcy5zdGFydERhdGUpKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lbmREYXRlID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLm1heERhdGUgJiYgdGhpcy5lbmREYXRlLmlzQWZ0ZXIodGhpcy5tYXhEYXRlKSlcclxuICAgICAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IHRoaXMubWF4RGF0ZS5jbG9uZSgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMubWF4U3BhbiAmJiB0aGlzLnN0YXJ0RGF0ZS5jbG9uZSgpLmFkZCh0aGlzLm1heFNwYW4pLmlzQmVmb3JlKHRoaXMuZW5kRGF0ZSkpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVuZERhdGUgPSB0aGlzLnN0YXJ0RGF0ZS5jbG9uZSgpLmFkZCh0aGlzLm1heFNwYW4pO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5wcmV2aW91c1JpZ2h0VGltZSA9IHRoaXMuZW5kRGF0ZS5jbG9uZSgpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuZmluZCgnLmRycC1zZWxlY3RlZCcpLmh0bWwodGhpcy5zdGFydERhdGUuZm9ybWF0KHRoaXMubG9jYWxlLmZvcm1hdCkgKyB0aGlzLmxvY2FsZS5zZXBhcmF0b3IgKyB0aGlzLmVuZERhdGUuZm9ybWF0KHRoaXMubG9jYWxlLmZvcm1hdCkpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzU2hvd2luZylcclxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudCgpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy51cGRhdGVNb250aHNJblZpZXcoKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBpc0ludmFsaWREYXRlOiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGlzQ3VzdG9tRGF0ZTogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB1cGRhdGVWaWV3OiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMudGltZVBpY2tlcikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJUaW1lUGlja2VyKCdsZWZ0Jyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclRpbWVQaWNrZXIoJ3JpZ2h0Jyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZW5kRGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5yaWdodCAuY2FsZW5kYXItdGltZSBzZWxlY3QnKS5wcm9wKCdkaXNhYmxlZCcsIHRydWUpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcucmlnaHQgLmNhbGVuZGFyLXRpbWUgc2VsZWN0JykucHJvcCgnZGlzYWJsZWQnLCBmYWxzZSkucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSlcclxuICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJy5kcnAtc2VsZWN0ZWQnKS5odG1sKHRoaXMuc3RhcnREYXRlLmZvcm1hdCh0aGlzLmxvY2FsZS5mb3JtYXQpICsgdGhpcy5sb2NhbGUuc2VwYXJhdG9yICsgdGhpcy5lbmREYXRlLmZvcm1hdCh0aGlzLmxvY2FsZS5mb3JtYXQpKTtcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVNb250aHNJblZpZXcoKTtcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVDYWxlbmRhcnMoKTtcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVGb3JtSW5wdXRzKCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgdXBkYXRlTW9udGhzSW5WaWV3OiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIC8vaWYgYm90aCBkYXRlcyBhcmUgdmlzaWJsZSBhbHJlYWR5LCBkbyBub3RoaW5nXHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2luZ2xlRGF0ZVBpY2tlciAmJiB0aGlzLmxlZnRDYWxlbmRhci5tb250aCAmJiB0aGlzLnJpZ2h0Q2FsZW5kYXIubW9udGggJiZcclxuICAgICAgICAgICAgICAgICAgICAodGhpcy5zdGFydERhdGUuZm9ybWF0KCdZWVlZLU1NJykgPT0gdGhpcy5sZWZ0Q2FsZW5kYXIubW9udGguZm9ybWF0KCdZWVlZLU1NJykgfHwgdGhpcy5zdGFydERhdGUuZm9ybWF0KCdZWVlZLU1NJykgPT0gdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLmZvcm1hdCgnWVlZWS1NTScpKVxyXG4gICAgICAgICAgICAgICAgICAgICYmXHJcbiAgICAgICAgICAgICAgICAgICAgKHRoaXMuZW5kRGF0ZS5mb3JtYXQoJ1lZWVktTU0nKSA9PSB0aGlzLmxlZnRDYWxlbmRhci5tb250aC5mb3JtYXQoJ1lZWVktTU0nKSB8fCB0aGlzLmVuZERhdGUuZm9ybWF0KCdZWVlZLU1NJykgPT0gdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLmZvcm1hdCgnWVlZWS1NTScpKVxyXG4gICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRDYWxlbmRhci5tb250aCA9IHRoaXMuc3RhcnREYXRlLmNsb25lKCkuZGF0ZSgyKTtcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5saW5rZWRDYWxlbmRhcnMgJiYgKHRoaXMuZW5kRGF0ZS5tb250aCgpICE9IHRoaXMuc3RhcnREYXRlLm1vbnRoKCkgfHwgdGhpcy5lbmREYXRlLnllYXIoKSAhPSB0aGlzLnN0YXJ0RGF0ZS55ZWFyKCkpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoID0gdGhpcy5lbmREYXRlLmNsb25lKCkuZGF0ZSgyKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKS5kYXRlKDIpLmFkZCgxLCAnbW9udGgnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5sZWZ0Q2FsZW5kYXIubW9udGguZm9ybWF0KCdZWVlZLU1NJykgIT0gdGhpcy5zdGFydERhdGUuZm9ybWF0KCdZWVlZLU1NJykgJiYgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLmZvcm1hdCgnWVlZWS1NTScpICE9IHRoaXMuc3RhcnREYXRlLmZvcm1hdCgnWVlZWS1NTScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sZWZ0Q2FsZW5kYXIubW9udGggPSB0aGlzLnN0YXJ0RGF0ZS5jbG9uZSgpLmRhdGUoMik7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKS5kYXRlKDIpLmFkZCgxLCAnbW9udGgnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhEYXRlICYmIHRoaXMubGlua2VkQ2FsZW5kYXJzICYmICF0aGlzLnNpbmdsZURhdGVQaWNrZXIgJiYgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoID4gdGhpcy5tYXhEYXRlKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoID0gdGhpcy5tYXhEYXRlLmNsb25lKCkuZGF0ZSgyKTtcclxuICAgICAgICAgICAgICB0aGlzLmxlZnRDYWxlbmRhci5tb250aCA9IHRoaXMubWF4RGF0ZS5jbG9uZSgpLmRhdGUoMikuc3VidHJhY3QoMSwgJ21vbnRoJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB1cGRhdGVDYWxlbmRhcnM6IGZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMudGltZVBpY2tlcikge1xyXG4gICAgICAgICAgICAgICAgdmFyIGhvdXIsIG1pbnV0ZSwgc2Vjb25kO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGhvdXIgPSBwYXJzZUludCh0aGlzLmNvbnRhaW5lci5maW5kKCcubGVmdCAuaG91cnNlbGVjdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbWludXRlID0gcGFyc2VJbnQodGhpcy5jb250YWluZXIuZmluZCgnLmxlZnQgLm1pbnV0ZXNlbGVjdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKG1pbnV0ZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWludXRlID0gcGFyc2VJbnQodGhpcy5jb250YWluZXIuZmluZCgnLmxlZnQgLm1pbnV0ZXNlbGVjdCBvcHRpb246bGFzdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHNlY29uZCA9IHRoaXMudGltZVBpY2tlclNlY29uZHMgPyBwYXJzZUludCh0aGlzLmNvbnRhaW5lci5maW5kKCcubGVmdCAuc2Vjb25kc2VsZWN0JykudmFsKCksIDEwKSA6IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnRpbWVQaWNrZXIyNEhvdXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFtcG0gPSB0aGlzLmNvbnRhaW5lci5maW5kKCcubGVmdCAuYW1wbXNlbGVjdCcpLnZhbCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYW1wbSA9PT0gJ1BNJyAmJiBob3VyIDwgMTIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyICs9IDEyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYW1wbSA9PT0gJ0FNJyAmJiBob3VyID09PSAxMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaG91ciA9IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLmZpbmQoJy5yaWdodCAuaG91cnNlbGVjdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbWludXRlID0gcGFyc2VJbnQodGhpcy5jb250YWluZXIuZmluZCgnLnJpZ2h0IC5taW51dGVzZWxlY3QnKS52YWwoKSwgMTApO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc05hTihtaW51dGUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbnV0ZSA9IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLmZpbmQoJy5yaWdodCAubWludXRlc2VsZWN0IG9wdGlvbjpsYXN0JykudmFsKCksIDEwKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgc2Vjb25kID0gdGhpcy50aW1lUGlja2VyU2Vjb25kcyA/IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLmZpbmQoJy5yaWdodCAuc2Vjb25kc2VsZWN0JykudmFsKCksIDEwKSA6IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnRpbWVQaWNrZXIyNEhvdXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFtcG0gPSB0aGlzLmNvbnRhaW5lci5maW5kKCcucmlnaHQgLmFtcG1zZWxlY3QnKS52YWwoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdQTScgJiYgaG91ciA8IDEyKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ciArPSAxMjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdBTScgJiYgaG91ciA9PT0gMTIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyID0gMDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRDYWxlbmRhci5tb250aC5ob3VyKGhvdXIpLm1pbnV0ZShtaW51dGUpLnNlY29uZChzZWNvbmQpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLmhvdXIoaG91cikubWludXRlKG1pbnV0ZSkuc2Vjb25kKHNlY29uZCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyQ2FsZW5kYXIoJ2xlZnQnKTtcclxuICAgICAgICAgICAgdGhpcy5yZW5kZXJDYWxlbmRhcigncmlnaHQnKTtcclxuXHJcbiAgICAgICAgICAgIC8vaGlnaGxpZ2h0IGFueSBwcmVkZWZpbmVkIHJhbmdlIG1hdGNoaW5nIHRoZSBjdXJyZW50IHN0YXJ0IGFuZCBlbmQgZGF0ZXNcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuZmluZCgnLnJhbmdlcyBsaScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSA9PSBudWxsKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUNob3NlbkxhYmVsKCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgcmVuZGVyQ2FsZW5kYXI6IGZ1bmN0aW9uKHNpZGUpIHtcclxuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIEJ1aWxkIHRoZSBtYXRyaXggb2YgZGF0ZXMgdGhhdCB3aWxsIHBvcHVsYXRlIHRoZSBjYWxlbmRhclxyXG4gICAgICAgICAgICAvL1xyXG5cclxuICAgICAgICAgICAgdmFyIGNhbGVuZGFyID0gc2lkZSA9PSAnbGVmdCcgPyB0aGlzLmxlZnRDYWxlbmRhciA6IHRoaXMucmlnaHRDYWxlbmRhcjtcclxuICAgICAgICAgICAgdmFyIG1vbnRoID0gY2FsZW5kYXIubW9udGgubW9udGgoKTtcclxuICAgICAgICAgICAgdmFyIHllYXIgPSBjYWxlbmRhci5tb250aC55ZWFyKCk7XHJcbiAgICAgICAgICAgIHZhciBob3VyID0gY2FsZW5kYXIubW9udGguaG91cigpO1xyXG4gICAgICAgICAgICB2YXIgbWludXRlID0gY2FsZW5kYXIubW9udGgubWludXRlKCk7XHJcbiAgICAgICAgICAgIHZhciBzZWNvbmQgPSBjYWxlbmRhci5tb250aC5zZWNvbmQoKTtcclxuICAgICAgICAgICAgdmFyIGRheXNJbk1vbnRoID0gbW9tZW50KFt5ZWFyLCBtb250aF0pLmRheXNJbk1vbnRoKCk7XHJcbiAgICAgICAgICAgIHZhciBmaXJzdERheSA9IG1vbWVudChbeWVhciwgbW9udGgsIDFdKTtcclxuICAgICAgICAgICAgdmFyIGxhc3REYXkgPSBtb21lbnQoW3llYXIsIG1vbnRoLCBkYXlzSW5Nb250aF0pO1xyXG4gICAgICAgICAgICB2YXIgbGFzdE1vbnRoID0gbW9tZW50KGZpcnN0RGF5KS5zdWJ0cmFjdCgxLCAnbW9udGgnKS5tb250aCgpO1xyXG4gICAgICAgICAgICB2YXIgbGFzdFllYXIgPSBtb21lbnQoZmlyc3REYXkpLnN1YnRyYWN0KDEsICdtb250aCcpLnllYXIoKTtcclxuICAgICAgICAgICAgdmFyIGRheXNJbkxhc3RNb250aCA9IG1vbWVudChbbGFzdFllYXIsIGxhc3RNb250aF0pLmRheXNJbk1vbnRoKCk7XHJcbiAgICAgICAgICAgIHZhciBkYXlPZldlZWsgPSBmaXJzdERheS5kYXkoKTtcclxuXHJcbiAgICAgICAgICAgIC8vaW5pdGlhbGl6ZSBhIDYgcm93cyB4IDcgY29sdW1ucyBhcnJheSBmb3IgdGhlIGNhbGVuZGFyXHJcbiAgICAgICAgICAgIHZhciBjYWxlbmRhciA9IFtdO1xyXG4gICAgICAgICAgICBjYWxlbmRhci5maXJzdERheSA9IGZpcnN0RGF5O1xyXG4gICAgICAgICAgICBjYWxlbmRhci5sYXN0RGF5ID0gbGFzdERheTtcclxuXHJcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBjYWxlbmRhcltpXSA9IFtdO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvL3BvcHVsYXRlIHRoZSBjYWxlbmRhciB3aXRoIGRhdGUgb2JqZWN0c1xyXG4gICAgICAgICAgICB2YXIgc3RhcnREYXkgPSBkYXlzSW5MYXN0TW9udGggLSBkYXlPZldlZWsgKyB0aGlzLmxvY2FsZS5maXJzdERheSArIDE7XHJcbiAgICAgICAgICAgIGlmIChzdGFydERheSA+IGRheXNJbkxhc3RNb250aClcclxuICAgICAgICAgICAgICAgIHN0YXJ0RGF5IC09IDc7XHJcblxyXG4gICAgICAgICAgICBpZiAoZGF5T2ZXZWVrID09IHRoaXMubG9jYWxlLmZpcnN0RGF5KVxyXG4gICAgICAgICAgICAgICAgc3RhcnREYXkgPSBkYXlzSW5MYXN0TW9udGggLSA2O1xyXG5cclxuICAgICAgICAgICAgdmFyIGN1ckRhdGUgPSBtb21lbnQoW2xhc3RZZWFyLCBsYXN0TW9udGgsIHN0YXJ0RGF5LCAxMiwgbWludXRlLCBzZWNvbmRdKTtcclxuXHJcbiAgICAgICAgICAgIHZhciBjb2wsIHJvdztcclxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGNvbCA9IDAsIHJvdyA9IDA7IGkgPCA0MjsgaSsrLCBjb2wrKywgY3VyRGF0ZSA9IG1vbWVudChjdXJEYXRlKS5hZGQoMjQsICdob3VyJykpIHtcclxuICAgICAgICAgICAgICAgIGlmIChpID4gMCAmJiBjb2wgJSA3ID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29sID0gMDtcclxuICAgICAgICAgICAgICAgICAgICByb3crKztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNhbGVuZGFyW3Jvd11bY29sXSA9IGN1ckRhdGUuY2xvbmUoKS5ob3VyKGhvdXIpLm1pbnV0ZShtaW51dGUpLnNlY29uZChzZWNvbmQpO1xyXG4gICAgICAgICAgICAgICAgY3VyRGF0ZS5ob3VyKDEyKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5taW5EYXRlICYmIGNhbGVuZGFyW3Jvd11bY29sXS5mb3JtYXQoJ1lZWVktTU0tREQnKSA9PSB0aGlzLm1pbkRhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgJiYgY2FsZW5kYXJbcm93XVtjb2xdLmlzQmVmb3JlKHRoaXMubWluRGF0ZSkgJiYgc2lkZSA9PSAnbGVmdCcpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYWxlbmRhcltyb3ddW2NvbF0gPSB0aGlzLm1pbkRhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5tYXhEYXRlICYmIGNhbGVuZGFyW3Jvd11bY29sXS5mb3JtYXQoJ1lZWVktTU0tREQnKSA9PSB0aGlzLm1heERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgJiYgY2FsZW5kYXJbcm93XVtjb2xdLmlzQWZ0ZXIodGhpcy5tYXhEYXRlKSAmJiBzaWRlID09ICdyaWdodCcpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYWxlbmRhcltyb3ddW2NvbF0gPSB0aGlzLm1heERhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vbWFrZSB0aGUgY2FsZW5kYXIgb2JqZWN0IGF2YWlsYWJsZSB0byBob3ZlckRhdGUvY2xpY2tEYXRlXHJcbiAgICAgICAgICAgIGlmIChzaWRlID09ICdsZWZ0Jykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sZWZ0Q2FsZW5kYXIuY2FsZW5kYXIgPSBjYWxlbmRhcjtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmlnaHRDYWxlbmRhci5jYWxlbmRhciA9IGNhbGVuZGFyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBEaXNwbGF5IHRoZSBjYWxlbmRhclxyXG4gICAgICAgICAgICAvL1xyXG5cclxuICAgICAgICAgICAgdmFyIG1pbkRhdGUgPSBzaWRlID09ICdsZWZ0JyA/IHRoaXMubWluRGF0ZSA6IHRoaXMuc3RhcnREYXRlO1xyXG4gICAgICAgICAgICB2YXIgbWF4RGF0ZSA9IHRoaXMubWF4RGF0ZTtcclxuICAgICAgICAgICAgdmFyIHNlbGVjdGVkID0gc2lkZSA9PSAnbGVmdCcgPyB0aGlzLnN0YXJ0RGF0ZSA6IHRoaXMuZW5kRGF0ZTtcclxuICAgICAgICAgICAgdmFyIGFycm93ID0gdGhpcy5sb2NhbGUuZGlyZWN0aW9uID09ICdsdHInID8ge2xlZnQ6ICdjaGV2cm9uLWxlZnQnLCByaWdodDogJ2NoZXZyb24tcmlnaHQnfSA6IHtsZWZ0OiAnY2hldnJvbi1yaWdodCcsIHJpZ2h0OiAnY2hldnJvbi1sZWZ0J307XHJcblxyXG4gICAgICAgICAgICB2YXIgaHRtbCA9ICc8dGFibGUgY2xhc3M9XCJ0YWJsZS1jb25kZW5zZWRcIj4nO1xyXG4gICAgICAgICAgICBodG1sICs9ICc8dGhlYWQ+JztcclxuICAgICAgICAgICAgaHRtbCArPSAnPHRyPic7XHJcblxyXG4gICAgICAgICAgICAvLyBhZGQgZW1wdHkgY2VsbCBmb3Igd2VlayBudW1iZXJcclxuICAgICAgICAgICAgaWYgKHRoaXMuc2hvd1dlZWtOdW1iZXJzIHx8IHRoaXMuc2hvd0lTT1dlZWtOdW1iZXJzKVxyXG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHRoPjwvdGg+JztcclxuXHJcbiAgICAgICAgICAgIGlmICgoIW1pbkRhdGUgfHwgbWluRGF0ZS5pc0JlZm9yZShjYWxlbmRhci5maXJzdERheSkpICYmICghdGhpcy5saW5rZWRDYWxlbmRhcnMgfHwgc2lkZSA9PSAnbGVmdCcpKSB7XHJcbiAgICAgICAgICAgICAgICBodG1sICs9ICc8dGggY2xhc3M9XCJwcmV2IGF2YWlsYWJsZVwiPjxzcGFuPjwvc3Bhbj48L3RoPic7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBodG1sICs9ICc8dGg+PC90aD4nO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB2YXIgZGF0ZUh0bWwgPSB0aGlzLmxvY2FsZS5tb250aE5hbWVzW2NhbGVuZGFyWzFdWzFdLm1vbnRoKCldICsgY2FsZW5kYXJbMV1bMV0uZm9ybWF0KFwiIFlZWVlcIik7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5zaG93RHJvcGRvd25zKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudE1vbnRoID0gY2FsZW5kYXJbMV1bMV0ubW9udGgoKTtcclxuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50WWVhciA9IGNhbGVuZGFyWzFdWzFdLnllYXIoKTtcclxuICAgICAgICAgICAgICAgIHZhciBtYXhZZWFyID0gKG1heERhdGUgJiYgbWF4RGF0ZS55ZWFyKCkpIHx8ICh0aGlzLm1heFllYXIpO1xyXG4gICAgICAgICAgICAgICAgdmFyIG1pblllYXIgPSAobWluRGF0ZSAmJiBtaW5EYXRlLnllYXIoKSkgfHwgKHRoaXMubWluWWVhcik7XHJcbiAgICAgICAgICAgICAgICB2YXIgaW5NaW5ZZWFyID0gY3VycmVudFllYXIgPT0gbWluWWVhcjtcclxuICAgICAgICAgICAgICAgIHZhciBpbk1heFllYXIgPSBjdXJyZW50WWVhciA9PSBtYXhZZWFyO1xyXG5cclxuICAgICAgICAgICAgICAgIHZhciBtb250aEh0bWwgPSAnPHNlbGVjdCBjbGFzcz1cIm1vbnRoc2VsZWN0XCI+JztcclxuICAgICAgICAgICAgICAgIGZvciAodmFyIG0gPSAwOyBtIDwgMTI7IG0rKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICgoIWluTWluWWVhciB8fCAobWluRGF0ZSAmJiBtID49IG1pbkRhdGUubW9udGgoKSkpICYmICghaW5NYXhZZWFyIHx8IChtYXhEYXRlICYmIG0gPD0gbWF4RGF0ZS5tb250aCgpKSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbW9udGhIdG1sICs9IFwiPG9wdGlvbiB2YWx1ZT0nXCIgKyBtICsgXCInXCIgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG0gPT09IGN1cnJlbnRNb250aCA/IFwiIHNlbGVjdGVkPSdzZWxlY3RlZCdcIiA6IFwiXCIpICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPlwiICsgdGhpcy5sb2NhbGUubW9udGhOYW1lc1ttXSArIFwiPC9vcHRpb24+XCI7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbW9udGhIdG1sICs9IFwiPG9wdGlvbiB2YWx1ZT0nXCIgKyBtICsgXCInXCIgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG0gPT09IGN1cnJlbnRNb250aCA/IFwiIHNlbGVjdGVkPSdzZWxlY3RlZCdcIiA6IFwiXCIpICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiIGRpc2FibGVkPSdkaXNhYmxlZCc+XCIgKyB0aGlzLmxvY2FsZS5tb250aE5hbWVzW21dICsgXCI8L29wdGlvbj5cIjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBtb250aEh0bWwgKz0gXCI8L3NlbGVjdD5cIjtcclxuXHJcbiAgICAgICAgICAgICAgICB2YXIgeWVhckh0bWwgPSAnPHNlbGVjdCBjbGFzcz1cInllYXJzZWxlY3RcIj4nO1xyXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgeSA9IG1pblllYXI7IHkgPD0gbWF4WWVhcjsgeSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgeWVhckh0bWwgKz0gJzxvcHRpb24gdmFsdWU9XCInICsgeSArICdcIicgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAoeSA9PT0gY3VycmVudFllYXIgPyAnIHNlbGVjdGVkPVwic2VsZWN0ZWRcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAnPicgKyB5ICsgJzwvb3B0aW9uPic7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB5ZWFySHRtbCArPSAnPC9zZWxlY3Q+JztcclxuXHJcbiAgICAgICAgICAgICAgICBkYXRlSHRtbCA9IG1vbnRoSHRtbCArIHllYXJIdG1sO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBodG1sICs9ICc8dGggY29sc3Bhbj1cIjVcIiBjbGFzcz1cIm1vbnRoXCI+JyArIGRhdGVIdG1sICsgJzwvdGg+JztcclxuICAgICAgICAgICAgaWYgKCghbWF4RGF0ZSB8fCBtYXhEYXRlLmlzQWZ0ZXIoY2FsZW5kYXIubGFzdERheSkpICYmICghdGhpcy5saW5rZWRDYWxlbmRhcnMgfHwgc2lkZSA9PSAncmlnaHQnIHx8IHRoaXMuc2luZ2xlRGF0ZVBpY2tlcikpIHtcclxuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzx0aCBjbGFzcz1cIm5leHQgYXZhaWxhYmxlXCI+PHNwYW4+PC9zcGFuPjwvdGg+JztcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzx0aD48L3RoPic7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGh0bWwgKz0gJzwvdHI+JztcclxuICAgICAgICAgICAgaHRtbCArPSAnPHRyPic7XHJcblxyXG4gICAgICAgICAgICAvLyBhZGQgd2VlayBudW1iZXIgbGFiZWxcclxuICAgICAgICAgICAgaWYgKHRoaXMuc2hvd1dlZWtOdW1iZXJzIHx8IHRoaXMuc2hvd0lTT1dlZWtOdW1iZXJzKVxyXG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHRoIGNsYXNzPVwid2Vla1wiPicgKyB0aGlzLmxvY2FsZS53ZWVrTGFiZWwgKyAnPC90aD4nO1xyXG5cclxuICAgICAgICAgICAgJC5lYWNoKHRoaXMubG9jYWxlLmRheXNPZldlZWssIGZ1bmN0aW9uKGluZGV4LCBkYXlPZldlZWspIHtcclxuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzx0aD4nICsgZGF5T2ZXZWVrICsgJzwvdGg+JztcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBodG1sICs9ICc8L3RyPic7XHJcbiAgICAgICAgICAgIGh0bWwgKz0gJzwvdGhlYWQ+JztcclxuICAgICAgICAgICAgaHRtbCArPSAnPHRib2R5Pic7XHJcblxyXG4gICAgICAgICAgICAvL2FkanVzdCBtYXhEYXRlIHRvIHJlZmxlY3QgdGhlIG1heFNwYW4gc2V0dGluZyBpbiBvcmRlciB0b1xyXG4gICAgICAgICAgICAvL2dyZXkgb3V0IGVuZCBkYXRlcyBiZXlvbmQgdGhlIG1heFNwYW5cclxuICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSA9PSBudWxsICYmIHRoaXMubWF4U3Bhbikge1xyXG4gICAgICAgICAgICAgICAgdmFyIG1heExpbWl0ID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKS5hZGQodGhpcy5tYXhTcGFuKS5lbmRPZignZGF5Jyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIW1heERhdGUgfHwgbWF4TGltaXQuaXNCZWZvcmUobWF4RGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXhEYXRlID0gbWF4TGltaXQ7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IDY7IHJvdysrKSB7XHJcbiAgICAgICAgICAgICAgICBodG1sICs9ICc8dHI+JztcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBhZGQgd2VlayBudW1iZXJcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNob3dXZWVrTnVtYmVycylcclxuICAgICAgICAgICAgICAgICAgICBodG1sICs9ICc8dGQgY2xhc3M9XCJ3ZWVrXCI+JyArIGNhbGVuZGFyW3Jvd11bMF0ud2VlaygpICsgJzwvdGQ+JztcclxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuc2hvd0lTT1dlZWtOdW1iZXJzKVxyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gJzx0ZCBjbGFzcz1cIndlZWtcIj4nICsgY2FsZW5kYXJbcm93XVswXS5pc29XZWVrKCkgKyAnPC90ZD4nO1xyXG5cclxuICAgICAgICAgICAgICAgIGZvciAodmFyIGNvbCA9IDA7IGNvbCA8IDc7IGNvbCsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzID0gW107XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vaGlnaGxpZ2h0IHRvZGF5J3MgZGF0ZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjYWxlbmRhcltyb3ddW2NvbF0uaXNTYW1lKG5ldyBEYXRlKCksIFwiZGF5XCIpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goJ3RvZGF5Jyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vaGlnaGxpZ2h0IHdlZWtlbmRzXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGVuZGFyW3Jvd11bY29sXS5pc29XZWVrZGF5KCkgPiA1KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goJ3dlZWtlbmQnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy9ncmV5IG91dCB0aGUgZGF0ZXMgaW4gb3RoZXIgbW9udGhzIGRpc3BsYXllZCBhdCBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGlzIGNhbGVuZGFyXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGVuZGFyW3Jvd11bY29sXS5tb250aCgpICE9IGNhbGVuZGFyWzFdWzFdLm1vbnRoKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnb2ZmJywgJ2VuZHMnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy9kb24ndCBhbGxvdyBzZWxlY3Rpb24gb2YgZGF0ZXMgYmVmb3JlIHRoZSBtaW5pbXVtIGRhdGVcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5taW5EYXRlICYmIGNhbGVuZGFyW3Jvd11bY29sXS5pc0JlZm9yZSh0aGlzLm1pbkRhdGUsICdkYXknKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdvZmYnLCAnZGlzYWJsZWQnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy9kb24ndCBhbGxvdyBzZWxlY3Rpb24gb2YgZGF0ZXMgYWZ0ZXIgdGhlIG1heGltdW0gZGF0ZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXhEYXRlICYmIGNhbGVuZGFyW3Jvd11bY29sXS5pc0FmdGVyKG1heERhdGUsICdkYXknKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdvZmYnLCAnZGlzYWJsZWQnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy9kb24ndCBhbGxvdyBzZWxlY3Rpb24gb2YgZGF0ZSBpZiBhIGN1c3RvbSBmdW5jdGlvbiBkZWNpZGVzIGl0J3MgaW52YWxpZFxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzSW52YWxpZERhdGUoY2FsZW5kYXJbcm93XVtjb2xdKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdvZmYnLCAnZGlzYWJsZWQnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy9oaWdobGlnaHQgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzdGFydCBkYXRlXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGVuZGFyW3Jvd11bY29sXS5mb3JtYXQoJ1lZWVktTU0tREQnKSA9PSB0aGlzLnN0YXJ0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhY3RpdmUnLCAnc3RhcnQtZGF0ZScpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvL2hpZ2hsaWdodCB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGVuZCBkYXRlXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSAhPSBudWxsICYmIGNhbGVuZGFyW3Jvd11bY29sXS5mb3JtYXQoJ1lZWVktTU0tREQnKSA9PSB0aGlzLmVuZERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnYWN0aXZlJywgJ2VuZC1kYXRlJyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vaGlnaGxpZ2h0IGRhdGVzIGluLWJldHdlZW4gdGhlIHNlbGVjdGVkIGRhdGVzXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZW5kRGF0ZSAhPSBudWxsICYmIGNhbGVuZGFyW3Jvd11bY29sXSA+IHRoaXMuc3RhcnREYXRlICYmIGNhbGVuZGFyW3Jvd11bY29sXSA8IHRoaXMuZW5kRGF0ZSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdpbi1yYW5nZScpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvL2FwcGx5IGN1c3RvbSBjbGFzc2VzIGZvciB0aGlzIGRhdGVcclxuICAgICAgICAgICAgICAgICAgICB2YXIgaXNDdXN0b20gPSB0aGlzLmlzQ3VzdG9tRGF0ZShjYWxlbmRhcltyb3ddW2NvbF0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0N1c3RvbSAhPT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpc0N1c3RvbSA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goaXNDdXN0b20pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShjbGFzc2VzLCBpc0N1c3RvbSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB2YXIgY25hbWUgPSAnJywgZGlzYWJsZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNsYXNzZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY25hbWUgKz0gY2xhc3Nlc1tpXSArICcgJztcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsYXNzZXNbaV0gPT0gJ2Rpc2FibGVkJylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkaXNhYmxlZClcclxuICAgICAgICAgICAgICAgICAgICAgICAgY25hbWUgKz0gJ2F2YWlsYWJsZSc7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gJzx0ZCBjbGFzcz1cIicgKyBjbmFtZS5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJykgKyAnXCIgZGF0YS10aXRsZT1cIicgKyAncicgKyByb3cgKyAnYycgKyBjb2wgKyAnXCI+JyArIGNhbGVuZGFyW3Jvd11bY29sXS5kYXRlKCkgKyAnPC90ZD4nO1xyXG5cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzwvdHI+JztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaHRtbCArPSAnPC90Ym9keT4nO1xyXG4gICAgICAgICAgICBodG1sICs9ICc8L3RhYmxlPic7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuZHJwLWNhbGVuZGFyLicgKyBzaWRlICsgJyAuY2FsZW5kYXItdGFibGUnKS5odG1sKGh0bWwpO1xyXG5cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICByZW5kZXJUaW1lUGlja2VyOiBmdW5jdGlvbihzaWRlKSB7XHJcblxyXG4gICAgICAgICAgICAvLyBEb24ndCBib3RoZXIgdXBkYXRpbmcgdGhlIHRpbWUgcGlja2VyIGlmIGl0J3MgY3VycmVudGx5IGRpc2FibGVkXHJcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgYW4gZW5kIGRhdGUgaGFzbid0IGJlZW4gY2xpY2tlZCB5ZXRcclxuICAgICAgICAgICAgaWYgKHNpZGUgPT0gJ3JpZ2h0JyAmJiAhdGhpcy5lbmREYXRlKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB2YXIgaHRtbCwgc2VsZWN0ZWQsIG1pbkRhdGUsIG1heERhdGUgPSB0aGlzLm1heERhdGU7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhTcGFuICYmICghdGhpcy5tYXhEYXRlIHx8IHRoaXMuc3RhcnREYXRlLmNsb25lKCkuYWRkKHRoaXMubWF4U3BhbikuaXNCZWZvcmUodGhpcy5tYXhEYXRlKSkpXHJcbiAgICAgICAgICAgICAgICBtYXhEYXRlID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKS5hZGQodGhpcy5tYXhTcGFuKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChzaWRlID09ICdsZWZ0Jykge1xyXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWQgPSB0aGlzLnN0YXJ0RGF0ZS5jbG9uZSgpO1xyXG4gICAgICAgICAgICAgICAgbWluRGF0ZSA9IHRoaXMubWluRGF0ZTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChzaWRlID09ICdyaWdodCcpIHtcclxuICAgICAgICAgICAgICAgIHNlbGVjdGVkID0gdGhpcy5lbmREYXRlLmNsb25lKCk7XHJcbiAgICAgICAgICAgICAgICBtaW5EYXRlID0gdGhpcy5zdGFydERhdGU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9QcmVzZXJ2ZSB0aGUgdGltZSBhbHJlYWR5IHNlbGVjdGVkXHJcbiAgICAgICAgICAgICAgICB2YXIgdGltZVNlbGVjdG9yID0gdGhpcy5jb250YWluZXIuZmluZCgnLmRycC1jYWxlbmRhci5yaWdodCAuY2FsZW5kYXItdGltZScpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRpbWVTZWxlY3Rvci5odG1sKCkgIT0gJycpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQuaG91cighaXNOYU4oc2VsZWN0ZWQuaG91cigpKSA/IHNlbGVjdGVkLmhvdXIoKSA6IHRpbWVTZWxlY3Rvci5maW5kKCcuaG91cnNlbGVjdCBvcHRpb246c2VsZWN0ZWQnKS52YWwoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQubWludXRlKCFpc05hTihzZWxlY3RlZC5taW51dGUoKSkgPyBzZWxlY3RlZC5taW51dGUoKSA6IHRpbWVTZWxlY3Rvci5maW5kKCcubWludXRlc2VsZWN0IG9wdGlvbjpzZWxlY3RlZCcpLnZhbCgpKTtcclxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5zZWNvbmQoIWlzTmFOKHNlbGVjdGVkLnNlY29uZCgpKSA/IHNlbGVjdGVkLnNlY29uZCgpIDogdGltZVNlbGVjdG9yLmZpbmQoJy5zZWNvbmRzZWxlY3Qgb3B0aW9uOnNlbGVjdGVkJykudmFsKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMudGltZVBpY2tlcjI0SG91cikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYW1wbSA9IHRpbWVTZWxlY3Rvci5maW5kKCcuYW1wbXNlbGVjdCBvcHRpb246c2VsZWN0ZWQnKS52YWwoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdQTScgJiYgc2VsZWN0ZWQuaG91cigpIDwgMTIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5ob3VyKHNlbGVjdGVkLmhvdXIoKSArIDEyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdBTScgJiYgc2VsZWN0ZWQuaG91cigpID09PSAxMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLmhvdXIoMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQuaXNCZWZvcmUodGhpcy5zdGFydERhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAobWF4RGF0ZSAmJiBzZWxlY3RlZC5pc0FmdGVyKG1heERhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkID0gbWF4RGF0ZS5jbG9uZSgpO1xyXG5cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gaG91cnNcclxuICAgICAgICAgICAgLy9cclxuXHJcbiAgICAgICAgICAgIGh0bWwgPSAnPHNlbGVjdCBjbGFzcz1cImhvdXJzZWxlY3RcIj4nO1xyXG5cclxuICAgICAgICAgICAgdmFyIHN0YXJ0ID0gdGhpcy50aW1lUGlja2VyMjRIb3VyID8gMCA6IDE7XHJcbiAgICAgICAgICAgIHZhciBlbmQgPSB0aGlzLnRpbWVQaWNrZXIyNEhvdXIgPyAyMyA6IDEyO1xyXG5cclxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDw9IGVuZDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgaV9pbl8yNCA9IGk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMudGltZVBpY2tlcjI0SG91cilcclxuICAgICAgICAgICAgICAgICAgICBpX2luXzI0ID0gc2VsZWN0ZWQuaG91cigpID49IDEyID8gKGkgPT0gMTIgPyAxMiA6IGkgKyAxMikgOiAoaSA9PSAxMiA/IDAgOiBpKTtcclxuXHJcbiAgICAgICAgICAgICAgICB2YXIgdGltZSA9IHNlbGVjdGVkLmNsb25lKCkuaG91cihpX2luXzI0KTtcclxuICAgICAgICAgICAgICAgIHZhciBkaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKG1pbkRhdGUgJiYgdGltZS5taW51dGUoNTkpLmlzQmVmb3JlKG1pbkRhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGlmIChtYXhEYXRlICYmIHRpbWUubWludXRlKDApLmlzQWZ0ZXIobWF4RGF0ZSkpXHJcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChpX2luXzI0ID09IHNlbGVjdGVkLmhvdXIoKSAmJiAhZGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBodG1sICs9ICc8b3B0aW9uIHZhbHVlPVwiJyArIGkgKyAnXCIgc2VsZWN0ZWQ9XCJzZWxlY3RlZFwiPicgKyBpICsgJzwvb3B0aW9uPic7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaHRtbCArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpICsgJ1wiIGRpc2FibGVkPVwiZGlzYWJsZWRcIiBjbGFzcz1cImRpc2FibGVkXCI+JyArIGkgKyAnPC9vcHRpb24+JztcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaHRtbCArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpICsgJ1wiPicgKyBpICsgJzwvb3B0aW9uPic7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGh0bWwgKz0gJzwvc2VsZWN0PiAnO1xyXG5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gbWludXRlc1xyXG4gICAgICAgICAgICAvL1xyXG5cclxuICAgICAgICAgICAgaHRtbCArPSAnOiA8c2VsZWN0IGNsYXNzPVwibWludXRlc2VsZWN0XCI+JztcclxuXHJcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNjA7IGkgKz0gdGhpcy50aW1lUGlja2VySW5jcmVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgcGFkZGVkID0gaSA8IDEwID8gJzAnICsgaSA6IGk7XHJcbiAgICAgICAgICAgICAgICB2YXIgdGltZSA9IHNlbGVjdGVkLmNsb25lKCkubWludXRlKGkpO1xyXG5cclxuICAgICAgICAgICAgICAgIHZhciBkaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKG1pbkRhdGUgJiYgdGltZS5zZWNvbmQoNTkpLmlzQmVmb3JlKG1pbkRhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGlmIChtYXhEYXRlICYmIHRpbWUuc2Vjb25kKDApLmlzQWZ0ZXIobWF4RGF0ZSkpXHJcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZC5taW51dGUoKSA9PSBpICYmICFkaXNhYmxlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxvcHRpb24gdmFsdWU9XCInICsgaSArICdcIiBzZWxlY3RlZD1cInNlbGVjdGVkXCI+JyArIHBhZGRlZCArICc8L29wdGlvbj4nO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkaXNhYmxlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxvcHRpb24gdmFsdWU9XCInICsgaSArICdcIiBkaXNhYmxlZD1cImRpc2FibGVkXCIgY2xhc3M9XCJkaXNhYmxlZFwiPicgKyBwYWRkZWQgKyAnPC9vcHRpb24+JztcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaHRtbCArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpICsgJ1wiPicgKyBwYWRkZWQgKyAnPC9vcHRpb24+JztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaHRtbCArPSAnPC9zZWxlY3Q+ICc7XHJcblxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBzZWNvbmRzXHJcbiAgICAgICAgICAgIC8vXHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy50aW1lUGlja2VyU2Vjb25kcykge1xyXG4gICAgICAgICAgICAgICAgaHRtbCArPSAnOiA8c2VsZWN0IGNsYXNzPVwic2Vjb25kc2VsZWN0XCI+JztcclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDYwOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgcGFkZGVkID0gaSA8IDEwID8gJzAnICsgaSA6IGk7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRpbWUgPSBzZWxlY3RlZC5jbG9uZSgpLnNlY29uZChpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc2FibGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkRhdGUgJiYgdGltZS5pc0JlZm9yZShtaW5EYXRlKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXhEYXRlICYmIHRpbWUuaXNBZnRlcihtYXhEYXRlKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQuc2Vjb25kKCkgPT0gaSAmJiAhZGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaHRtbCArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpICsgJ1wiIHNlbGVjdGVkPVwic2VsZWN0ZWRcIj4nICsgcGFkZGVkICsgJzwvb3B0aW9uPic7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkaXNhYmxlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBodG1sICs9ICc8b3B0aW9uIHZhbHVlPVwiJyArIGkgKyAnXCIgZGlzYWJsZWQ9XCJkaXNhYmxlZFwiIGNsYXNzPVwiZGlzYWJsZWRcIj4nICsgcGFkZGVkICsgJzwvb3B0aW9uPic7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaHRtbCArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpICsgJ1wiPicgKyBwYWRkZWQgKyAnPC9vcHRpb24+JztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPC9zZWxlY3Q+ICc7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIEFNL1BNXHJcbiAgICAgICAgICAgIC8vXHJcblxyXG4gICAgICAgICAgICBpZiAoIXRoaXMudGltZVBpY2tlcjI0SG91cikge1xyXG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNlbGVjdCBjbGFzcz1cImFtcG1zZWxlY3RcIj4nO1xyXG5cclxuICAgICAgICAgICAgICAgIHZhciBhbV9odG1sID0gJyc7XHJcbiAgICAgICAgICAgICAgICB2YXIgcG1faHRtbCA9ICcnO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChtaW5EYXRlICYmIHNlbGVjdGVkLmNsb25lKCkuaG91cigxMikubWludXRlKDApLnNlY29uZCgwKS5pc0JlZm9yZShtaW5EYXRlKSlcclxuICAgICAgICAgICAgICAgICAgICBhbV9odG1sID0gJyBkaXNhYmxlZD1cImRpc2FibGVkXCIgY2xhc3M9XCJkaXNhYmxlZFwiJztcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAobWF4RGF0ZSAmJiBzZWxlY3RlZC5jbG9uZSgpLmhvdXIoMCkubWludXRlKDApLnNlY29uZCgwKS5pc0FmdGVyKG1heERhdGUpKVxyXG4gICAgICAgICAgICAgICAgICAgIHBtX2h0bWwgPSAnIGRpc2FibGVkPVwiZGlzYWJsZWRcIiBjbGFzcz1cImRpc2FibGVkXCInO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZC5ob3VyKCkgPj0gMTIpIHtcclxuICAgICAgICAgICAgICAgICAgICBodG1sICs9ICc8b3B0aW9uIHZhbHVlPVwiQU1cIicgKyBhbV9odG1sICsgJz5BTTwvb3B0aW9uPjxvcHRpb24gdmFsdWU9XCJQTVwiIHNlbGVjdGVkPVwic2VsZWN0ZWRcIicgKyBwbV9odG1sICsgJz5QTTwvb3B0aW9uPic7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxvcHRpb24gdmFsdWU9XCJBTVwiIHNlbGVjdGVkPVwic2VsZWN0ZWRcIicgKyBhbV9odG1sICsgJz5BTTwvb3B0aW9uPjxvcHRpb24gdmFsdWU9XCJQTVwiJyArIHBtX2h0bWwgKyAnPlBNPC9vcHRpb24+JztcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBodG1sICs9ICc8L3NlbGVjdD4nO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuZHJwLWNhbGVuZGFyLicgKyBzaWRlICsgJyAuY2FsZW5kYXItdGltZScpLmh0bWwoaHRtbCk7XHJcblxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHVwZGF0ZUZvcm1JbnB1dHM6IGZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuc2luZ2xlRGF0ZVBpY2tlciB8fCAodGhpcy5lbmREYXRlICYmICh0aGlzLnN0YXJ0RGF0ZS5pc0JlZm9yZSh0aGlzLmVuZERhdGUpIHx8IHRoaXMuc3RhcnREYXRlLmlzU2FtZSh0aGlzLmVuZERhdGUpKSkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmZpbmQoJ2J1dHRvbi5hcHBseUJ0bicpLnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuZmluZCgnYnV0dG9uLmFwcGx5QnRuJykucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBtb3ZlOiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgdmFyIHBhcmVudE9mZnNldCA9IHsgdG9wOiAwLCBsZWZ0OiAwIH0sXHJcbiAgICAgICAgICAgICAgICBjb250YWluZXJUb3AsXHJcbiAgICAgICAgICAgICAgICBkcm9wcyA9IHRoaXMuZHJvcHM7XHJcblxyXG4gICAgICAgICAgICB2YXIgcGFyZW50UmlnaHRFZGdlID0gJCh3aW5kb3cpLndpZHRoKCk7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5wYXJlbnRFbC5pcygnYm9keScpKSB7XHJcbiAgICAgICAgICAgICAgICBwYXJlbnRPZmZzZXQgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdG9wOiB0aGlzLnBhcmVudEVsLm9mZnNldCgpLnRvcCAtIHRoaXMucGFyZW50RWwuc2Nyb2xsVG9wKCksXHJcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogdGhpcy5wYXJlbnRFbC5vZmZzZXQoKS5sZWZ0IC0gdGhpcy5wYXJlbnRFbC5zY3JvbGxMZWZ0KClcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICBwYXJlbnRSaWdodEVkZ2UgPSB0aGlzLnBhcmVudEVsWzBdLmNsaWVudFdpZHRoICsgdGhpcy5wYXJlbnRFbC5vZmZzZXQoKS5sZWZ0O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBzd2l0Y2ggKGRyb3BzKSB7XHJcbiAgICAgICAgICAgIGNhc2UgJ2F1dG8nOlxyXG4gICAgICAgICAgICAgICAgY29udGFpbmVyVG9wID0gdGhpcy5lbGVtZW50Lm9mZnNldCgpLnRvcCArIHRoaXMuZWxlbWVudC5vdXRlckhlaWdodCgpIC0gcGFyZW50T2Zmc2V0LnRvcDtcclxuICAgICAgICAgICAgICAgIGlmIChjb250YWluZXJUb3AgKyB0aGlzLmNvbnRhaW5lci5vdXRlckhlaWdodCgpID49IHRoaXMucGFyZW50RWxbMF0uc2Nyb2xsSGVpZ2h0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyVG9wID0gdGhpcy5lbGVtZW50Lm9mZnNldCgpLnRvcCAtIHRoaXMuY29udGFpbmVyLm91dGVySGVpZ2h0KCkgLSBwYXJlbnRPZmZzZXQudG9wO1xyXG4gICAgICAgICAgICAgICAgICAgIGRyb3BzID0gJ3VwJztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICd1cCc6XHJcbiAgICAgICAgICAgICAgICBjb250YWluZXJUb3AgPSB0aGlzLmVsZW1lbnQub2Zmc2V0KCkudG9wIC0gdGhpcy5jb250YWluZXIub3V0ZXJIZWlnaHQoKSAtIHBhcmVudE9mZnNldC50b3A7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIGNvbnRhaW5lclRvcCA9IHRoaXMuZWxlbWVudC5vZmZzZXQoKS50b3AgKyB0aGlzLmVsZW1lbnQub3V0ZXJIZWlnaHQoKSAtIHBhcmVudE9mZnNldC50b3A7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gRm9yY2UgdGhlIGNvbnRhaW5lciB0byBpdCdzIGFjdHVhbCB3aWR0aFxyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgIHRvcDogMCxcclxuICAgICAgICAgICAgICBsZWZ0OiAwLFxyXG4gICAgICAgICAgICAgIHJpZ2h0OiAnYXV0bydcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHZhciBjb250YWluZXJXaWR0aCA9IHRoaXMuY29udGFpbmVyLm91dGVyV2lkdGgoKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLnRvZ2dsZUNsYXNzKCdkcm9wLXVwJywgZHJvcHMgPT0gJ3VwJyk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVucyA9PSAnbGVmdCcpIHtcclxuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJSaWdodCA9IHBhcmVudFJpZ2h0RWRnZSAtIHRoaXMuZWxlbWVudC5vZmZzZXQoKS5sZWZ0IC0gdGhpcy5lbGVtZW50Lm91dGVyV2lkdGgoKTtcclxuICAgICAgICAgICAgICAgIGlmIChjb250YWluZXJXaWR0aCArIGNvbnRhaW5lclJpZ2h0ID4gJCh3aW5kb3cpLndpZHRoKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNvbnRhaW5lclRvcCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6ICdhdXRvJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogOVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNvbnRhaW5lclRvcCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGNvbnRhaW5lclJpZ2h0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiAnYXV0bydcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLm9wZW5zID09ICdjZW50ZXInKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgY29udGFpbmVyTGVmdCA9IHRoaXMuZWxlbWVudC5vZmZzZXQoKS5sZWZ0IC0gcGFyZW50T2Zmc2V0LmxlZnQgKyB0aGlzLmVsZW1lbnQub3V0ZXJXaWR0aCgpIC8gMlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLSBjb250YWluZXJXaWR0aCAvIDI7XHJcbiAgICAgICAgICAgICAgICBpZiAoY29udGFpbmVyTGVmdCA8IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNvbnRhaW5lclRvcCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6ICdhdXRvJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogOVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjb250YWluZXJMZWZ0ICsgY29udGFpbmVyV2lkdGggPiAkKHdpbmRvdykud2lkdGgoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNzcyh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogY29udGFpbmVyVG9wLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiAnYXV0bycsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0OiAwXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNzcyh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogY29udGFpbmVyVG9wLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBjb250YWluZXJMZWZ0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICByaWdodDogJ2F1dG8nXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgY29udGFpbmVyTGVmdCA9IHRoaXMuZWxlbWVudC5vZmZzZXQoKS5sZWZ0IC0gcGFyZW50T2Zmc2V0LmxlZnQ7XHJcbiAgICAgICAgICAgICAgICBpZiAoY29udGFpbmVyTGVmdCArIGNvbnRhaW5lcldpZHRoID4gJCh3aW5kb3cpLndpZHRoKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNvbnRhaW5lclRvcCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogJ2F1dG8nLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICByaWdodDogMFxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNvbnRhaW5lclRvcCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogY29udGFpbmVyTGVmdCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6ICdhdXRvJ1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgc2hvdzogZnVuY3Rpb24oZSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmcpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIGNsaWNrIHByb3h5IHRoYXQgaXMgcHJpdmF0ZSB0byB0aGlzIGluc3RhbmNlIG9mIGRhdGVwaWNrZXIsIGZvciB1bmJpbmRpbmdcclxuICAgICAgICAgICAgdGhpcy5fb3V0c2lkZUNsaWNrUHJveHkgPSAkLnByb3h5KGZ1bmN0aW9uKGUpIHsgdGhpcy5vdXRzaWRlQ2xpY2soZSk7IH0sIHRoaXMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQmluZCBnbG9iYWwgZGF0ZXBpY2tlciBtb3VzZWRvd24gZm9yIGhpZGluZyBhbmRcclxuICAgICAgICAgICAgJChkb2N1bWVudClcclxuICAgICAgICAgICAgICAub24oJ21vdXNlZG93bi5kYXRlcmFuZ2VwaWNrZXInLCB0aGlzLl9vdXRzaWRlQ2xpY2tQcm94eSlcclxuICAgICAgICAgICAgICAvLyBhbHNvIHN1cHBvcnQgbW9iaWxlIGRldmljZXNcclxuICAgICAgICAgICAgICAub24oJ3RvdWNoZW5kLmRhdGVyYW5nZXBpY2tlcicsIHRoaXMuX291dHNpZGVDbGlja1Byb3h5KVxyXG4gICAgICAgICAgICAgIC8vIGFsc28gZXhwbGljaXRseSBwbGF5IG5pY2Ugd2l0aCBCb290c3RyYXAgZHJvcGRvd25zLCB3aGljaCBzdG9wUHJvcGFnYXRpb24gd2hlbiBjbGlja2luZyB0aGVtXHJcbiAgICAgICAgICAgICAgLm9uKCdjbGljay5kYXRlcmFuZ2VwaWNrZXInLCAnW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXScsIHRoaXMuX291dHNpZGVDbGlja1Byb3h5KVxyXG4gICAgICAgICAgICAgIC8vIGFuZCBhbHNvIGNsb3NlIHdoZW4gZm9jdXMgY2hhbmdlcyB0byBvdXRzaWRlIHRoZSBwaWNrZXIgKGVnLiB0YWJiaW5nIGJldHdlZW4gY29udHJvbHMpXHJcbiAgICAgICAgICAgICAgLm9uKCdmb2N1c2luLmRhdGVyYW5nZXBpY2tlcicsIHRoaXMuX291dHNpZGVDbGlja1Byb3h5KTtcclxuXHJcbiAgICAgICAgICAgIC8vIFJlcG9zaXRpb24gdGhlIHBpY2tlciBpZiB0aGUgd2luZG93IGlzIHJlc2l6ZWQgd2hpbGUgaXQncyBvcGVuXHJcbiAgICAgICAgICAgICQod2luZG93KS5vbigncmVzaXplLmRhdGVyYW5nZXBpY2tlcicsICQucHJveHkoZnVuY3Rpb24oZSkgeyB0aGlzLm1vdmUoZSk7IH0sIHRoaXMpKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMub2xkU3RhcnREYXRlID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgdGhpcy5vbGRFbmREYXRlID0gdGhpcy5lbmREYXRlLmNsb25lKCk7XHJcbiAgICAgICAgICAgIHRoaXMucHJldmlvdXNSaWdodFRpbWUgPSB0aGlzLmVuZERhdGUuY2xvbmUoKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVmlldygpO1xyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5zaG93KCk7XHJcbiAgICAgICAgICAgIHRoaXMubW92ZSgpO1xyXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQudHJpZ2dlcignc2hvdy5kYXRlcmFuZ2VwaWNrZXInLCB0aGlzKTtcclxuICAgICAgICAgICAgdGhpcy5pc1Nob3dpbmcgPSB0cnVlO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGhpZGU6IGZ1bmN0aW9uKGUpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzU2hvd2luZykgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgLy9pbmNvbXBsZXRlIGRhdGUgc2VsZWN0aW9uLCByZXZlcnQgdG8gbGFzdCB2YWx1ZXNcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVuZERhdGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc3RhcnREYXRlID0gdGhpcy5vbGRTdGFydERhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IHRoaXMub2xkRW5kRGF0ZS5jbG9uZSgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvL2lmIGEgbmV3IGRhdGUgcmFuZ2Ugd2FzIHNlbGVjdGVkLCBpbnZva2UgdGhlIHVzZXIgY2FsbGJhY2sgZnVuY3Rpb25cclxuICAgICAgICAgICAgaWYgKCF0aGlzLnN0YXJ0RGF0ZS5pc1NhbWUodGhpcy5vbGRTdGFydERhdGUpIHx8ICF0aGlzLmVuZERhdGUuaXNTYW1lKHRoaXMub2xkRW5kRGF0ZSkpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrKHRoaXMuc3RhcnREYXRlLmNsb25lKCksIHRoaXMuZW5kRGF0ZS5jbG9uZSgpLCB0aGlzLmNob3NlbkxhYmVsKTtcclxuXHJcbiAgICAgICAgICAgIC8vaWYgcGlja2VyIGlzIGF0dGFjaGVkIHRvIGEgdGV4dCBpbnB1dCwgdXBkYXRlIGl0XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRWxlbWVudCgpO1xyXG5cclxuICAgICAgICAgICAgJChkb2N1bWVudCkub2ZmKCcuZGF0ZXJhbmdlcGlja2VyJyk7XHJcbiAgICAgICAgICAgICQod2luZG93KS5vZmYoJy5kYXRlcmFuZ2VwaWNrZXInKTtcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuaGlkZSgpO1xyXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQudHJpZ2dlcignaGlkZS5kYXRlcmFuZ2VwaWNrZXInLCB0aGlzKTtcclxuICAgICAgICAgICAgdGhpcy5pc1Nob3dpbmcgPSBmYWxzZTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB0b2dnbGU6IGZ1bmN0aW9uKGUpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNTaG93aW5nKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgb3V0c2lkZUNsaWNrOiBmdW5jdGlvbihlKSB7XHJcbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSAkKGUudGFyZ2V0KTtcclxuICAgICAgICAgICAgLy8gaWYgdGhlIHBhZ2UgaXMgY2xpY2tlZCBhbnl3aGVyZSBleGNlcHQgd2l0aGluIHRoZSBkYXRlcmFuZ2VycGlja2VyL2J1dHRvblxyXG4gICAgICAgICAgICAvLyBpdHNlbGYgdGhlbiBjYWxsIHRoaXMuaGlkZSgpXHJcbiAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgIC8vIGllIG1vZGFsIGRpYWxvZyBmaXhcclxuICAgICAgICAgICAgICAgIGUudHlwZSA9PSBcImZvY3VzaW5cIiB8fFxyXG4gICAgICAgICAgICAgICAgdGFyZ2V0LmNsb3Nlc3QodGhpcy5lbGVtZW50KS5sZW5ndGggfHxcclxuICAgICAgICAgICAgICAgIHRhcmdldC5jbG9zZXN0KHRoaXMuY29udGFpbmVyKS5sZW5ndGggfHxcclxuICAgICAgICAgICAgICAgIHRhcmdldC5jbG9zZXN0KCcuY2FsZW5kYXItdGFibGUnKS5sZW5ndGhcclxuICAgICAgICAgICAgICAgICkgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLmhpZGUoKTtcclxuICAgICAgICAgICAgdGhpcy5lbGVtZW50LnRyaWdnZXIoJ291dHNpZGVDbGljay5kYXRlcmFuZ2VwaWNrZXInLCB0aGlzKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBzaG93Q2FsZW5kYXJzOiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIuYWRkQ2xhc3MoJ3Nob3ctY2FsZW5kYXInKTtcclxuICAgICAgICAgICAgdGhpcy5tb3ZlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC50cmlnZ2VyKCdzaG93Q2FsZW5kYXIuZGF0ZXJhbmdlcGlja2VyJywgdGhpcyk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaGlkZUNhbGVuZGFyczogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLnJlbW92ZUNsYXNzKCdzaG93LWNhbGVuZGFyJyk7XHJcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC50cmlnZ2VyKCdoaWRlQ2FsZW5kYXIuZGF0ZXJhbmdlcGlja2VyJywgdGhpcyk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgY2xpY2tSYW5nZTogZnVuY3Rpb24oZSkge1xyXG4gICAgICAgICAgICB2YXIgbGFiZWwgPSBlLnRhcmdldC5nZXRBdHRyaWJ1dGUoJ2RhdGEtcmFuZ2Uta2V5Jyk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuTGFiZWwgPSBsYWJlbDtcclxuICAgICAgICAgICAgaWYgKGxhYmVsID09IHRoaXMubG9jYWxlLmN1c3RvbVJhbmdlTGFiZWwpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2hvd0NhbGVuZGFycygpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdmFyIGRhdGVzID0gdGhpcy5yYW5nZXNbbGFiZWxdO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUgPSBkYXRlc1swXTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IGRhdGVzWzFdO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy50aW1lUGlja2VyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGFydERhdGUuc3RhcnRPZignZGF5Jyk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmREYXRlLmVuZE9mKCdkYXknKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYWx3YXlzU2hvd0NhbGVuZGFycylcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGVDYWxlbmRhcnMoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2xpY2tBcHBseSgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgY2xpY2tQcmV2OiBmdW5jdGlvbihlKSB7XHJcbiAgICAgICAgICAgIHZhciBjYWwgPSAkKGUudGFyZ2V0KS5wYXJlbnRzKCcuZHJwLWNhbGVuZGFyJyk7XHJcbiAgICAgICAgICAgIGlmIChjYWwuaGFzQ2xhc3MoJ2xlZnQnKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sZWZ0Q2FsZW5kYXIubW9udGguc3VidHJhY3QoMSwgJ21vbnRoJyk7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5saW5rZWRDYWxlbmRhcnMpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLnN1YnRyYWN0KDEsICdtb250aCcpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLnN1YnRyYWN0KDEsICdtb250aCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQ2FsZW5kYXJzKCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgY2xpY2tOZXh0OiBmdW5jdGlvbihlKSB7XHJcbiAgICAgICAgICAgIHZhciBjYWwgPSAkKGUudGFyZ2V0KS5wYXJlbnRzKCcuZHJwLWNhbGVuZGFyJyk7XHJcbiAgICAgICAgICAgIGlmIChjYWwuaGFzQ2xhc3MoJ2xlZnQnKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sZWZ0Q2FsZW5kYXIubW9udGguYWRkKDEsICdtb250aCcpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLmFkZCgxLCAnbW9udGgnKTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxpbmtlZENhbGVuZGFycylcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxlZnRDYWxlbmRhci5tb250aC5hZGQoMSwgJ21vbnRoJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy51cGRhdGVDYWxlbmRhcnMoKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBob3ZlckRhdGU6IGZ1bmN0aW9uKGUpIHtcclxuXHJcbiAgICAgICAgICAgIC8vaWdub3JlIGRhdGVzIHRoYXQgY2FuJ3QgYmUgc2VsZWN0ZWRcclxuICAgICAgICAgICAgaWYgKCEkKGUudGFyZ2V0KS5oYXNDbGFzcygnYXZhaWxhYmxlJykpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciB0aXRsZSA9ICQoZS50YXJnZXQpLmF0dHIoJ2RhdGEtdGl0bGUnKTtcclxuICAgICAgICAgICAgdmFyIHJvdyA9IHRpdGxlLnN1YnN0cigxLCAxKTtcclxuICAgICAgICAgICAgdmFyIGNvbCA9IHRpdGxlLnN1YnN0cigzLCAxKTtcclxuICAgICAgICAgICAgdmFyIGNhbCA9ICQoZS50YXJnZXQpLnBhcmVudHMoJy5kcnAtY2FsZW5kYXInKTtcclxuICAgICAgICAgICAgdmFyIGRhdGUgPSBjYWwuaGFzQ2xhc3MoJ2xlZnQnKSA/IHRoaXMubGVmdENhbGVuZGFyLmNhbGVuZGFyW3Jvd11bY29sXSA6IHRoaXMucmlnaHRDYWxlbmRhci5jYWxlbmRhcltyb3ddW2NvbF07XHJcblxyXG4gICAgICAgICAgICAvL2hpZ2hsaWdodCB0aGUgZGF0ZXMgYmV0d2VlbiB0aGUgc3RhcnQgZGF0ZSBhbmQgdGhlIGRhdGUgYmVpbmcgaG92ZXJlZCBhcyBhIHBvdGVudGlhbCBlbmQgZGF0ZVxyXG4gICAgICAgICAgICB2YXIgbGVmdENhbGVuZGFyID0gdGhpcy5sZWZ0Q2FsZW5kYXI7XHJcbiAgICAgICAgICAgIHZhciByaWdodENhbGVuZGFyID0gdGhpcy5yaWdodENhbGVuZGFyO1xyXG4gICAgICAgICAgICB2YXIgc3RhcnREYXRlID0gdGhpcy5zdGFydERhdGU7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5lbmREYXRlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5maW5kKCcuZHJwLWNhbGVuZGFyIHRib2R5IHRkJykuZWFjaChmdW5jdGlvbihpbmRleCwgZWwpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy9za2lwIHdlZWsgbnVtYmVycywgb25seSBsb29rIGF0IGRhdGVzXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQoZWwpLmhhc0NsYXNzKCd3ZWVrJykpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRpdGxlID0gJChlbCkuYXR0cignZGF0YS10aXRsZScpO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciByb3cgPSB0aXRsZS5zdWJzdHIoMSwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbCA9IHRpdGxlLnN1YnN0cigzLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgY2FsID0gJChlbCkucGFyZW50cygnLmRycC1jYWxlbmRhcicpO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBkdCA9IGNhbC5oYXNDbGFzcygnbGVmdCcpID8gbGVmdENhbGVuZGFyLmNhbGVuZGFyW3Jvd11bY29sXSA6IHJpZ2h0Q2FsZW5kYXIuY2FsZW5kYXJbcm93XVtjb2xdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoKGR0LmlzQWZ0ZXIoc3RhcnREYXRlKSAmJiBkdC5pc0JlZm9yZShkYXRlKSkgfHwgZHQuaXNTYW1lKGRhdGUsICdkYXknKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkKGVsKS5hZGRDbGFzcygnaW4tcmFuZ2UnKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkKGVsKS5yZW1vdmVDbGFzcygnaW4tcmFuZ2UnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgY2xpY2tEYXRlOiBmdW5jdGlvbihlKSB7XHJcblxyXG4gICAgICAgICAgICBpZiAoISQoZS50YXJnZXQpLmhhc0NsYXNzKCdhdmFpbGFibGUnKSkgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgdmFyIHRpdGxlID0gJChlLnRhcmdldCkuYXR0cignZGF0YS10aXRsZScpO1xyXG4gICAgICAgICAgICB2YXIgcm93ID0gdGl0bGUuc3Vic3RyKDEsIDEpO1xyXG4gICAgICAgICAgICB2YXIgY29sID0gdGl0bGUuc3Vic3RyKDMsIDEpO1xyXG4gICAgICAgICAgICB2YXIgY2FsID0gJChlLnRhcmdldCkucGFyZW50cygnLmRycC1jYWxlbmRhcicpO1xyXG4gICAgICAgICAgICB2YXIgZGF0ZSA9IGNhbC5oYXNDbGFzcygnbGVmdCcpID8gdGhpcy5sZWZ0Q2FsZW5kYXIuY2FsZW5kYXJbcm93XVtjb2xdIDogdGhpcy5yaWdodENhbGVuZGFyLmNhbGVuZGFyW3Jvd11bY29sXTtcclxuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIHRoaXMgZnVuY3Rpb24gbmVlZHMgdG8gZG8gYSBmZXcgdGhpbmdzOlxyXG4gICAgICAgICAgICAvLyAqIGFsdGVybmF0ZSBiZXR3ZWVuIHNlbGVjdGluZyBhIHN0YXJ0IGFuZCBlbmQgZGF0ZSBmb3IgdGhlIHJhbmdlLFxyXG4gICAgICAgICAgICAvLyAqIGlmIHRoZSB0aW1lIHBpY2tlciBpcyBlbmFibGVkLCBhcHBseSB0aGUgaG91ci9taW51dGUvc2Vjb25kIGZyb20gdGhlIHNlbGVjdCBib3hlcyB0byB0aGUgY2xpY2tlZCBkYXRlXHJcbiAgICAgICAgICAgIC8vICogaWYgYXV0b2FwcGx5IGlzIGVuYWJsZWQsIGFuZCBhbiBlbmQgZGF0ZSB3YXMgY2hvc2VuLCBhcHBseSB0aGUgc2VsZWN0aW9uXHJcbiAgICAgICAgICAgIC8vICogaWYgc2luZ2xlIGRhdGUgcGlja2VyIG1vZGUsIGFuZCB0aW1lIHBpY2tlciBpc24ndCBlbmFibGVkLCBhcHBseSB0aGUgc2VsZWN0aW9uIGltbWVkaWF0ZWx5XHJcbiAgICAgICAgICAgIC8vICogaWYgb25lIG9mIHRoZSBpbnB1dHMgYWJvdmUgdGhlIGNhbGVuZGFycyB3YXMgZm9jdXNlZCwgY2FuY2VsIHRoYXQgbWFudWFsIGlucHV0XHJcbiAgICAgICAgICAgIC8vXHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5lbmREYXRlIHx8IGRhdGUuaXNCZWZvcmUodGhpcy5zdGFydERhdGUsICdkYXknKSkgeyAvL3BpY2tpbmcgc3RhcnRcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRpbWVQaWNrZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgaG91ciA9IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLmZpbmQoJy5sZWZ0IC5ob3Vyc2VsZWN0JykudmFsKCksIDEwKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMudGltZVBpY2tlcjI0SG91cikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYW1wbSA9IHRoaXMuY29udGFpbmVyLmZpbmQoJy5sZWZ0IC5hbXBtc2VsZWN0JykudmFsKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbXBtID09PSAnUE0nICYmIGhvdXIgPCAxMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIgKz0gMTI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbXBtID09PSAnQU0nICYmIGhvdXIgPT09IDEyKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ciA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHZhciBtaW51dGUgPSBwYXJzZUludCh0aGlzLmNvbnRhaW5lci5maW5kKCcubGVmdCAubWludXRlc2VsZWN0JykudmFsKCksIDEwKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4obWludXRlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW51dGUgPSBwYXJzZUludCh0aGlzLmNvbnRhaW5lci5maW5kKCcubGVmdCAubWludXRlc2VsZWN0IG9wdGlvbjpsYXN0JykudmFsKCksIDEwKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlY29uZCA9IHRoaXMudGltZVBpY2tlclNlY29uZHMgPyBwYXJzZUludCh0aGlzLmNvbnRhaW5lci5maW5kKCcubGVmdCAuc2Vjb25kc2VsZWN0JykudmFsKCksIDEwKSA6IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF0ZSA9IGRhdGUuY2xvbmUoKS5ob3VyKGhvdXIpLm1pbnV0ZShtaW51dGUpLnNlY29uZChzZWNvbmQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lbmREYXRlID0gbnVsbDtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhcnREYXRlKGRhdGUuY2xvbmUoKSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuZW5kRGF0ZSAmJiBkYXRlLmlzQmVmb3JlKHRoaXMuc3RhcnREYXRlKSkge1xyXG4gICAgICAgICAgICAgICAgLy9zcGVjaWFsIGNhc2U6IGNsaWNraW5nIHRoZSBzYW1lIGRhdGUgZm9yIHN0YXJ0L2VuZCxcclxuICAgICAgICAgICAgICAgIC8vYnV0IHRoZSB0aW1lIG9mIHRoZSBlbmQgZGF0ZSBpcyBiZWZvcmUgdGhlIHN0YXJ0IGRhdGVcclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0RW5kRGF0ZSh0aGlzLnN0YXJ0RGF0ZS5jbG9uZSgpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHsgLy8gcGlja2luZyBlbmRcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRpbWVQaWNrZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgaG91ciA9IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLmZpbmQoJy5yaWdodCAuaG91cnNlbGVjdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnRpbWVQaWNrZXIyNEhvdXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFtcG0gPSB0aGlzLmNvbnRhaW5lci5maW5kKCcucmlnaHQgLmFtcG1zZWxlY3QnKS52YWwoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdQTScgJiYgaG91ciA8IDEyKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ciArPSAxMjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdBTScgJiYgaG91ciA9PT0gMTIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyID0gMDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pbnV0ZSA9IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLmZpbmQoJy5yaWdodCAubWludXRlc2VsZWN0JykudmFsKCksIDEwKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4obWludXRlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW51dGUgPSBwYXJzZUludCh0aGlzLmNvbnRhaW5lci5maW5kKCcucmlnaHQgLm1pbnV0ZXNlbGVjdCBvcHRpb246bGFzdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHZhciBzZWNvbmQgPSB0aGlzLnRpbWVQaWNrZXJTZWNvbmRzID8gcGFyc2VJbnQodGhpcy5jb250YWluZXIuZmluZCgnLnJpZ2h0IC5zZWNvbmRzZWxlY3QnKS52YWwoKSwgMTApIDogMDtcclxuICAgICAgICAgICAgICAgICAgICBkYXRlID0gZGF0ZS5jbG9uZSgpLmhvdXIoaG91cikubWludXRlKG1pbnV0ZSkuc2Vjb25kKHNlY29uZCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldEVuZERhdGUoZGF0ZS5jbG9uZSgpKTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmF1dG9BcHBseSkge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUNob3NlbkxhYmVsKCk7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuY2xpY2tBcHBseSgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5zaW5nbGVEYXRlUGlja2VyKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldEVuZERhdGUodGhpcy5zdGFydERhdGUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnRpbWVQaWNrZXIgJiYgdGhpcy5hdXRvQXBwbHkpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGlja0FwcGx5KCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVmlldygpO1xyXG5cclxuICAgICAgICAgICAgLy9UaGlzIGlzIHRvIGNhbmNlbCB0aGUgYmx1ciBldmVudCBoYW5kbGVyIGlmIHRoZSBtb3VzZSB3YXMgaW4gb25lIG9mIHRoZSBpbnB1dHNcclxuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgY2FsY3VsYXRlQ2hvc2VuTGFiZWw6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIGN1c3RvbVJhbmdlID0gdHJ1ZTtcclxuICAgICAgICAgICAgdmFyIGkgPSAwO1xyXG4gICAgICAgICAgICBmb3IgKHZhciByYW5nZSBpbiB0aGlzLnJhbmdlcykge1xyXG4gICAgICAgICAgICAgIGlmICh0aGlzLnRpbWVQaWNrZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgZm9ybWF0ID0gdGhpcy50aW1lUGlja2VyU2Vjb25kcyA/IFwiWVlZWS1NTS1ERCBISDptbTpzc1wiIDogXCJZWVlZLU1NLUREIEhIOm1tXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9pZ25vcmUgdGltZXMgd2hlbiBjb21wYXJpbmcgZGF0ZXMgaWYgdGltZSBwaWNrZXIgc2Vjb25kcyBpcyBub3QgZW5hYmxlZFxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXJ0RGF0ZS5mb3JtYXQoZm9ybWF0KSA9PSB0aGlzLnJhbmdlc1tyYW5nZV1bMF0uZm9ybWF0KGZvcm1hdCkgJiYgdGhpcy5lbmREYXRlLmZvcm1hdChmb3JtYXQpID09IHRoaXMucmFuZ2VzW3JhbmdlXVsxXS5mb3JtYXQoZm9ybWF0KSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21SYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNob3NlbkxhYmVsID0gdGhpcy5jb250YWluZXIuZmluZCgnLnJhbmdlcyBsaTplcSgnICsgaSArICcpJykuYWRkQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2RhdGEtcmFuZ2Uta2V5Jyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9pZ25vcmUgdGltZXMgd2hlbiBjb21wYXJpbmcgZGF0ZXMgaWYgdGltZSBwaWNrZXIgaXMgbm90IGVuYWJsZWRcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGFydERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgPT0gdGhpcy5yYW5nZXNbcmFuZ2VdWzBdLmZvcm1hdCgnWVlZWS1NTS1ERCcpICYmIHRoaXMuZW5kRGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKSA9PSB0aGlzLnJhbmdlc1tyYW5nZV1bMV0uZm9ybWF0KCdZWVlZLU1NLUREJykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tUmFuZ2UgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jaG9zZW5MYWJlbCA9IHRoaXMuY29udGFpbmVyLmZpbmQoJy5yYW5nZXMgbGk6ZXEoJyArIGkgKyAnKScpLmFkZENsYXNzKCdhY3RpdmUnKS5hdHRyKCdkYXRhLXJhbmdlLWtleScpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpKys7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGN1c3RvbVJhbmdlKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zaG93Q3VzdG9tUmFuZ2VMYWJlbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2hvc2VuTGFiZWwgPSB0aGlzLmNvbnRhaW5lci5maW5kKCcucmFuZ2VzIGxpOmxhc3QnKS5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignZGF0YS1yYW5nZS1rZXknKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jaG9zZW5MYWJlbCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dDYWxlbmRhcnMoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGNsaWNrQXBwbHk6IGZ1bmN0aW9uKGUpIHtcclxuICAgICAgICAgICAgdGhpcy5oaWRlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC50cmlnZ2VyKCdhcHBseS5kYXRlcmFuZ2VwaWNrZXInLCB0aGlzKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBjbGlja0NhbmNlbDogZnVuY3Rpb24oZSkge1xyXG4gICAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IHRoaXMub2xkU3RhcnREYXRlO1xyXG4gICAgICAgICAgICB0aGlzLmVuZERhdGUgPSB0aGlzLm9sZEVuZERhdGU7XHJcbiAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xyXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQudHJpZ2dlcignY2FuY2VsLmRhdGVyYW5nZXBpY2tlcicsIHRoaXMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIG1vbnRoT3JZZWFyQ2hhbmdlZDogZnVuY3Rpb24oZSkge1xyXG4gICAgICAgICAgICB2YXIgaXNMZWZ0ID0gJChlLnRhcmdldCkuY2xvc2VzdCgnLmRycC1jYWxlbmRhcicpLmhhc0NsYXNzKCdsZWZ0JyksXHJcbiAgICAgICAgICAgICAgICBsZWZ0T3JSaWdodCA9IGlzTGVmdCA/ICdsZWZ0JyA6ICdyaWdodCcsXHJcbiAgICAgICAgICAgICAgICBjYWwgPSB0aGlzLmNvbnRhaW5lci5maW5kKCcuZHJwLWNhbGVuZGFyLicrbGVmdE9yUmlnaHQpO1xyXG5cclxuICAgICAgICAgICAgLy8gTW9udGggbXVzdCBiZSBOdW1iZXIgZm9yIG5ldyBtb21lbnQgdmVyc2lvbnNcclxuICAgICAgICAgICAgdmFyIG1vbnRoID0gcGFyc2VJbnQoY2FsLmZpbmQoJy5tb250aHNlbGVjdCcpLnZhbCgpLCAxMCk7XHJcbiAgICAgICAgICAgIHZhciB5ZWFyID0gY2FsLmZpbmQoJy55ZWFyc2VsZWN0JykudmFsKCk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWlzTGVmdCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHllYXIgPCB0aGlzLnN0YXJ0RGF0ZS55ZWFyKCkgfHwgKHllYXIgPT0gdGhpcy5zdGFydERhdGUueWVhcigpICYmIG1vbnRoIDwgdGhpcy5zdGFydERhdGUubW9udGgoKSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBtb250aCA9IHRoaXMuc3RhcnREYXRlLm1vbnRoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgeWVhciA9IHRoaXMuc3RhcnREYXRlLnllYXIoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMubWluRGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHllYXIgPCB0aGlzLm1pbkRhdGUueWVhcigpIHx8ICh5ZWFyID09IHRoaXMubWluRGF0ZS55ZWFyKCkgJiYgbW9udGggPCB0aGlzLm1pbkRhdGUubW9udGgoKSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBtb250aCA9IHRoaXMubWluRGF0ZS5tb250aCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHllYXIgPSB0aGlzLm1pbkRhdGUueWVhcigpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhEYXRlKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoeWVhciA+IHRoaXMubWF4RGF0ZS55ZWFyKCkgfHwgKHllYXIgPT0gdGhpcy5tYXhEYXRlLnllYXIoKSAmJiBtb250aCA+IHRoaXMubWF4RGF0ZS5tb250aCgpKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG1vbnRoID0gdGhpcy5tYXhEYXRlLm1vbnRoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgeWVhciA9IHRoaXMubWF4RGF0ZS55ZWFyKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChpc0xlZnQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubGVmdENhbGVuZGFyLm1vbnRoLm1vbnRoKG1vbnRoKS55ZWFyKHllYXIpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGlua2VkQ2FsZW5kYXJzKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmlnaHRDYWxlbmRhci5tb250aCA9IHRoaXMubGVmdENhbGVuZGFyLm1vbnRoLmNsb25lKCkuYWRkKDEsICdtb250aCcpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLm1vbnRoKG1vbnRoKS55ZWFyKHllYXIpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGlua2VkQ2FsZW5kYXJzKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGVmdENhbGVuZGFyLm1vbnRoID0gdGhpcy5yaWdodENhbGVuZGFyLm1vbnRoLmNsb25lKCkuc3VidHJhY3QoMSwgJ21vbnRoJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy51cGRhdGVDYWxlbmRhcnMoKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB0aW1lQ2hhbmdlZDogZnVuY3Rpb24oZSkge1xyXG5cclxuICAgICAgICAgICAgdmFyIGNhbCA9ICQoZS50YXJnZXQpLmNsb3Nlc3QoJy5kcnAtY2FsZW5kYXInKSxcclxuICAgICAgICAgICAgICAgIGlzTGVmdCA9IGNhbC5oYXNDbGFzcygnbGVmdCcpO1xyXG5cclxuICAgICAgICAgICAgdmFyIGhvdXIgPSBwYXJzZUludChjYWwuZmluZCgnLmhvdXJzZWxlY3QnKS52YWwoKSwgMTApO1xyXG4gICAgICAgICAgICB2YXIgbWludXRlID0gcGFyc2VJbnQoY2FsLmZpbmQoJy5taW51dGVzZWxlY3QnKS52YWwoKSwgMTApO1xyXG4gICAgICAgICAgICBpZiAoaXNOYU4obWludXRlKSkge1xyXG4gICAgICAgICAgICAgICAgbWludXRlID0gcGFyc2VJbnQoY2FsLmZpbmQoJy5taW51dGVzZWxlY3Qgb3B0aW9uOmxhc3QnKS52YWwoKSwgMTApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZhciBzZWNvbmQgPSB0aGlzLnRpbWVQaWNrZXJTZWNvbmRzID8gcGFyc2VJbnQoY2FsLmZpbmQoJy5zZWNvbmRzZWxlY3QnKS52YWwoKSwgMTApIDogMDtcclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy50aW1lUGlja2VyMjRIb3VyKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgYW1wbSA9IGNhbC5maW5kKCcuYW1wbXNlbGVjdCcpLnZhbCgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFtcG0gPT09ICdQTScgJiYgaG91ciA8IDEyKVxyXG4gICAgICAgICAgICAgICAgICAgIGhvdXIgKz0gMTI7XHJcbiAgICAgICAgICAgICAgICBpZiAoYW1wbSA9PT0gJ0FNJyAmJiBob3VyID09PSAxMilcclxuICAgICAgICAgICAgICAgICAgICBob3VyID0gMDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGlzTGVmdCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5zdGFydERhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIHN0YXJ0LmhvdXIoaG91cik7XHJcbiAgICAgICAgICAgICAgICBzdGFydC5taW51dGUobWludXRlKTtcclxuICAgICAgICAgICAgICAgIHN0YXJ0LnNlY29uZChzZWNvbmQpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGFydERhdGUoc3RhcnQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2luZ2xlRGF0ZVBpY2tlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IHRoaXMuc3RhcnREYXRlLmNsb25lKCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZW5kRGF0ZSAmJiB0aGlzLmVuZERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgPT0gc3RhcnQuZm9ybWF0KCdZWVlZLU1NLUREJykgJiYgdGhpcy5lbmREYXRlLmlzQmVmb3JlKHN0YXJ0KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RW5kRGF0ZShzdGFydC5jbG9uZSgpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmVuZERhdGUpIHtcclxuICAgICAgICAgICAgICAgIHZhciBlbmQgPSB0aGlzLmVuZERhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgICAgIGVuZC5ob3VyKGhvdXIpO1xyXG4gICAgICAgICAgICAgICAgZW5kLm1pbnV0ZShtaW51dGUpO1xyXG4gICAgICAgICAgICAgICAgZW5kLnNlY29uZChzZWNvbmQpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZXRFbmREYXRlKGVuZCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vdXBkYXRlIHRoZSBjYWxlbmRhcnMgc28gYWxsIGNsaWNrYWJsZSBkYXRlcyByZWZsZWN0IHRoZSBuZXcgdGltZSBjb21wb25lbnRcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVDYWxlbmRhcnMoKTtcclxuXHJcbiAgICAgICAgICAgIC8vdXBkYXRlIHRoZSBmb3JtIGlucHV0cyBhYm92ZSB0aGUgY2FsZW5kYXJzIHdpdGggdGhlIG5ldyB0aW1lXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRm9ybUlucHV0cygpO1xyXG5cclxuICAgICAgICAgICAgLy9yZS1yZW5kZXIgdGhlIHRpbWUgcGlja2VycyBiZWNhdXNlIGNoYW5naW5nIG9uZSBzZWxlY3Rpb24gY2FuIGFmZmVjdCB3aGF0J3MgZW5hYmxlZCBpbiBhbm90aGVyXHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyVGltZVBpY2tlcignbGVmdCcpO1xyXG4gICAgICAgICAgICB0aGlzLnJlbmRlclRpbWVQaWNrZXIoJ3JpZ2h0Jyk7XHJcblxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGVsZW1lbnRDaGFuZ2VkOiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVsZW1lbnQuaXMoJ2lucHV0JykpIHJldHVybjtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVsZW1lbnQudmFsKCkubGVuZ3RoKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB2YXIgZGF0ZVN0cmluZyA9IHRoaXMuZWxlbWVudC52YWwoKS5zcGxpdCh0aGlzLmxvY2FsZS5zZXBhcmF0b3IpLFxyXG4gICAgICAgICAgICAgICAgc3RhcnQgPSBudWxsLFxyXG4gICAgICAgICAgICAgICAgZW5kID0gbnVsbDtcclxuXHJcbiAgICAgICAgICAgIGlmIChkYXRlU3RyaW5nLmxlbmd0aCA9PT0gMikge1xyXG4gICAgICAgICAgICAgICAgc3RhcnQgPSBtb21lbnQoZGF0ZVN0cmluZ1swXSwgdGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuICAgICAgICAgICAgICAgIGVuZCA9IG1vbWVudChkYXRlU3RyaW5nWzFdLCB0aGlzLmxvY2FsZS5mb3JtYXQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5zaW5nbGVEYXRlUGlja2VyIHx8IHN0YXJ0ID09PSBudWxsIHx8IGVuZCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgc3RhcnQgPSBtb21lbnQodGhpcy5lbGVtZW50LnZhbCgpLCB0aGlzLmxvY2FsZS5mb3JtYXQpO1xyXG4gICAgICAgICAgICAgICAgZW5kID0gc3RhcnQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghc3RhcnQuaXNWYWxpZCgpIHx8ICFlbmQuaXNWYWxpZCgpKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFN0YXJ0RGF0ZShzdGFydCk7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0RW5kRGF0ZShlbmQpO1xyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZpZXcoKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBrZXlkb3duOiBmdW5jdGlvbihlKSB7XHJcbiAgICAgICAgICAgIC8vaGlkZSBvbiB0YWIgb3IgZW50ZXJcclxuICAgICAgICAgICAgaWYgKChlLmtleUNvZGUgPT09IDkpIHx8IChlLmtleUNvZGUgPT09IDEzKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vaGlkZSBvbiBlc2MgYW5kIHByZXZlbnQgcHJvcGFnYXRpb25cclxuICAgICAgICAgICAgaWYgKGUua2V5Q29kZSA9PT0gMjcpIHtcclxuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB1cGRhdGVFbGVtZW50OiBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZWxlbWVudC5pcygnaW5wdXQnKSAmJiB0aGlzLmF1dG9VcGRhdGVJbnB1dCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIG5ld1ZhbHVlID0gdGhpcy5zdGFydERhdGUuZm9ybWF0KHRoaXMubG9jYWxlLmZvcm1hdCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2luZ2xlRGF0ZVBpY2tlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlICs9IHRoaXMubG9jYWxlLnNlcGFyYXRvciArIHRoaXMuZW5kRGF0ZS5mb3JtYXQodGhpcy5sb2NhbGUuZm9ybWF0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChuZXdWYWx1ZSAhPT0gdGhpcy5lbGVtZW50LnZhbCgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50LnZhbChuZXdWYWx1ZSkudHJpZ2dlcignY2hhbmdlJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5yZW1vdmUoKTtcclxuICAgICAgICAgICAgdGhpcy5lbGVtZW50Lm9mZignLmRhdGVyYW5nZXBpY2tlcicpO1xyXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQucmVtb3ZlRGF0YSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICB9O1xyXG5cclxuICAgICQuZm4uZGF0ZXJhbmdlcGlja2VyID0gZnVuY3Rpb24ob3B0aW9ucywgY2FsbGJhY2spIHtcclxuICAgICAgICB2YXIgaW1wbGVtZW50T3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCAkLmZuLmRhdGVyYW5nZXBpY2tlci5kZWZhdWx0T3B0aW9ucywgb3B0aW9ucyk7XHJcbiAgICAgICAgdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB2YXIgZWwgPSAkKHRoaXMpO1xyXG4gICAgICAgICAgICBpZiAoZWwuZGF0YSgnZGF0ZXJhbmdlcGlja2VyJykpXHJcbiAgICAgICAgICAgICAgICBlbC5kYXRhKCdkYXRlcmFuZ2VwaWNrZXInKS5yZW1vdmUoKTtcclxuICAgICAgICAgICAgZWwuZGF0YSgnZGF0ZXJhbmdlcGlja2VyJywgbmV3IERhdGVSYW5nZVBpY2tlcihlbCwgaW1wbGVtZW50T3B0aW9ucywgY2FsbGJhY2spKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgcmV0dXJuIERhdGVSYW5nZVBpY2tlcjtcclxuXHJcbn0pKTtcclxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/bootstrap-daterangepicker/daterangepicker.js\n");
/***/ }),
/***/ "jquery":
/*!*************************!*\
!*** external "jQuery" ***!
\*************************/
/***/ (function(module) {
"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE_jquery__;
/***/ }),
/***/ "moment":
/*!*************************!*\
!*** external "moment" ***!
\*************************/
/***/ (function(module) {
"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE_moment__;
/***/ })
/******/ });
/************************************************************************/
/******/ // 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].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(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 */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval-source-map devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./libs/bootstrap-daterangepicker/bootstrap-daterangepicker.js");
/******/
/******/ return __webpack_exports__;
/******/ })()
;
});