1209 lines
1.7 MiB
1209 lines
1.7 MiB
/*
|
|
* 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/).
|
|
*/
|
|
/******/ (() => { // webpackBootstrap
|
|
/******/ "use strict";
|
|
/******/ var __webpack_modules__ = ({
|
|
|
|
/***/ 111:
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(112);\n/* harmony import */ var _fullcalendar_interaction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(117);\n/* harmony import */ var _fullcalendar_daygrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(118);\n/* harmony import */ var _fullcalendar_timegrid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(120);\n/* harmony import */ var _fullcalendar_list__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(122);\n/**\n * @description Fullcalendar Plugin Init\n * @see https://fullcalendar.io/docs\n */\n\n\n\n\n\n\ndocument.addEventListener('DOMContentLoaded', function () {\n var calendarEl = document.getElementById('calendar');\n if (calendarEl != undefined) {\n var calendar = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__.Calendar(calendarEl, {\n plugins: [_fullcalendar_interaction__WEBPACK_IMPORTED_MODULE_1__[\"default\"], _fullcalendar_daygrid__WEBPACK_IMPORTED_MODULE_2__[\"default\"], _fullcalendar_timegrid__WEBPACK_IMPORTED_MODULE_3__[\"default\"], _fullcalendar_list__WEBPACK_IMPORTED_MODULE_4__[\"default\"]],\n headerToolbar: {\n left: 'prev,next today',\n center: 'title',\n right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'\n },\n initialDate: '2023-01-12',\n navLinks: true,\n // can click day/week names to navigate views\n editable: true,\n dayMaxEvents: true,\n // allow \"more\" link when too many events\n events: [{\n title: 'All Day Event',\n start: '2023-01-01'\n }, {\n title: 'Long Event',\n start: '2023-01-07',\n end: '2023-01-10'\n }, {\n groupId: 999,\n title: 'Repeating Event',\n start: '2023-01-09T16:00:00'\n }, {\n groupId: 999,\n title: 'Repeating Event',\n start: '2023-01-16T16:00:00'\n }, {\n title: 'Conference',\n start: '2023-01-11',\n end: '2023-01-13'\n }, {\n title: 'Meeting',\n start: '2023-01-12T10:30:00',\n end: '2023-01-12T12:30:00'\n }, {\n title: 'Lunch',\n start: '2023-01-12T12:00:00'\n }, {\n title: 'Meeting',\n start: '2023-01-12T14:30:00'\n }, {\n title: 'Happy Hour',\n start: '2023-01-12T17:30:00'\n }, {\n title: 'Dinner',\n start: '2023-01-12T20:00:00'\n }, {\n title: 'Birthday Party',\n start: '2023-01-13T07:00:00'\n }, {\n title: 'Click for Google',\n url: 'http://google.com/',\n start: '2023-01-28'\n }]\n });\n calendar.render();\n }\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTExLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUU4QztBQUNZO0FBQ1I7QUFDRTtBQUNSO0FBRTVDSyxRQUFRLENBQUNDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLFlBQVc7RUFDdkQsSUFBTUMsVUFBVSxHQUFHRixRQUFRLENBQUNHLGNBQWMsQ0FBQyxVQUFVLENBQUM7RUFFdkQsSUFBSUQsVUFBVSxJQUFJRSxTQUFTLEVBQUU7SUFDM0IsSUFBTUMsUUFBUSxHQUFHLElBQUlWLHdEQUFRLENBQUNPLFVBQVUsRUFBRTtNQUN4Q0ksT0FBTyxFQUFFLENBQUVWLGlFQUFpQixFQUFFQyw2REFBYSxFQUFFQyw4REFBYyxFQUFFQywwREFBVSxDQUFFO01BQ3pFUSxhQUFhLEVBQUU7UUFDYkMsSUFBSSxFQUFFLGlCQUFpQjtRQUN2QkMsTUFBTSxFQUFFLE9BQU87UUFDZkMsS0FBSyxFQUFFO01BQ1QsQ0FBQztNQUNEQyxXQUFXLEVBQUUsWUFBWTtNQUN6QkMsUUFBUSxFQUFFLElBQUk7TUFBRTtNQUNoQkMsUUFBUSxFQUFFLElBQUk7TUFDZEMsWUFBWSxFQUFFLElBQUk7TUFBRTtNQUNwQkMsTUFBTSxFQUFFLENBQ047UUFDRUMsS0FBSyxFQUFFLGVBQWU7UUFDdEJDLEtBQUssRUFBRTtNQUNULENBQUMsRUFDRDtRQUNFRCxLQUFLLEVBQUUsWUFBWTtRQUNuQkMsS0FBSyxFQUFFLFlBQVk7UUFDbkJDLEdBQUcsRUFBRTtNQUNQLENBQUMsRUFDRDtRQUNFQyxPQUFPLEVBQUUsR0FBRztRQUNaSCxLQUFLLEVBQUUsaUJBQWlCO1FBQ3hCQyxLQUFLLEVBQUU7TUFDVCxDQUFDLEVBQ0Q7UUFDRUUsT0FBTyxFQUFFLEdBQUc7UUFDWkgsS0FBSyxFQUFFLGlCQUFpQjtRQUN4QkMsS0FBSyxFQUFFO01BQ1QsQ0FBQyxFQUNEO1FBQ0VELEtBQUssRUFBRSxZQUFZO1FBQ25CQyxLQUFLLEVBQUUsWUFBWTtRQUNuQkMsR0FBRyxFQUFFO01BQ1AsQ0FBQyxFQUNEO1FBQ0VGLEtBQUssRUFBRSxTQUFTO1FBQ2hCQyxLQUFLLEVBQUUscUJBQXFCO1FBQzVCQyxHQUFHLEVBQUU7TUFDUCxDQUFDLEVBQ0Q7UUFDRUYsS0FBSyxFQUFFLE9BQU87UUFDZEMsS0FBSyxFQUFFO01BQ1QsQ0FBQyxFQUNEO1FBQ0VELEtBQUssRUFBRSxTQUFTO1FBQ2hCQyxLQUFLLEVBQUU7TUFDVCxDQUFDLEVBQ0Q7UUFDRUQsS0FBSyxFQUFFLFlBQVk7UUFDbkJDLEtBQUssRUFBRTtNQUNULENBQUMsRUFDRDtRQUNFRCxLQUFLLEVBQUUsUUFBUTtRQUNmQyxLQUFLLEVBQUU7TUFDVCxDQUFDLEVBQ0Q7UUFDRUQsS0FBSyxFQUFFLGdCQUFnQjtRQUN2QkMsS0FBSyxFQUFFO01BQ1QsQ0FBQyxFQUNEO1FBQ0VELEtBQUssRUFBRSxrQkFBa0I7UUFDekJJLEdBQUcsRUFBRSxvQkFBb0I7UUFDekJILEtBQUssRUFBRTtNQUNULENBQUM7SUFFTCxDQUFDLENBQUM7SUFFRlosUUFBUSxDQUFDZ0IsTUFBTSxDQUFDLENBQUM7RUFDbkI7QUFDRCxDQUFDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcmNoaXRlY3R1aS1odG1sLWZyZWUvLi9zcmMvc2NyaXB0cy1pbml0L2NhbGVuZGFyLmpzP2M2YTAiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAZGVzY3JpcHRpb24gRnVsbGNhbGVuZGFyIFBsdWdpbiBJbml0XG4gKiBAc2VlIGh0dHBzOi8vZnVsbGNhbGVuZGFyLmlvL2RvY3NcbiAqL1xuXG5pbXBvcnQgeyBDYWxlbmRhciB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZSc7XG5pbXBvcnQgaW50ZXJhY3Rpb25QbHVnaW4gZnJvbSAnQGZ1bGxjYWxlbmRhci9pbnRlcmFjdGlvbic7XG5pbXBvcnQgZGF5R3JpZFBsdWdpbiBmcm9tICdAZnVsbGNhbGVuZGFyL2RheWdyaWQnO1xuaW1wb3J0IHRpbWVHcmlkUGx1Z2luIGZyb20gJ0BmdWxsY2FsZW5kYXIvdGltZWdyaWQnO1xuaW1wb3J0IGxpc3RQbHVnaW4gZnJvbSAnQGZ1bGxjYWxlbmRhci9saXN0JztcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xuICBjb25zdCBjYWxlbmRhckVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NhbGVuZGFyJyk7XG5cbiBpZiAoY2FsZW5kYXJFbCAhPSB1bmRlZmluZWQpIHtcbiAgIGNvbnN0IGNhbGVuZGFyID0gbmV3IENhbGVuZGFyKGNhbGVuZGFyRWwsIHtcbiAgICAgcGx1Z2luczogWyBpbnRlcmFjdGlvblBsdWdpbiwgZGF5R3JpZFBsdWdpbiwgdGltZUdyaWRQbHVnaW4sIGxpc3RQbHVnaW4gXSxcbiAgICAgaGVhZGVyVG9vbGJhcjoge1xuICAgICAgIGxlZnQ6ICdwcmV2LG5leHQgdG9kYXknLFxuICAgICAgIGNlbnRlcjogJ3RpdGxlJyxcbiAgICAgICByaWdodDogJ2RheUdyaWRNb250aCx0aW1lR3JpZFdlZWssdGltZUdyaWREYXksbGlzdFdlZWsnXG4gICAgIH0sXG4gICAgIGluaXRpYWxEYXRlOiAnMjAyMy0wMS0xMicsXG4gICAgIG5hdkxpbmtzOiB0cnVlLCAvLyBjYW4gY2xpY2sgZGF5L3dlZWsgbmFtZXMgdG8gbmF2aWdhdGUgdmlld3NcbiAgICAgZWRpdGFibGU6IHRydWUsXG4gICAgIGRheU1heEV2ZW50czogdHJ1ZSwgLy8gYWxsb3cgXCJtb3JlXCIgbGluayB3aGVuIHRvbyBtYW55IGV2ZW50c1xuICAgICBldmVudHM6IFtcbiAgICAgICB7XG4gICAgICAgICB0aXRsZTogJ0FsbCBEYXkgRXZlbnQnLFxuICAgICAgICAgc3RhcnQ6ICcyMDIzLTAxLTAxJyxcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIHRpdGxlOiAnTG9uZyBFdmVudCcsXG4gICAgICAgICBzdGFydDogJzIwMjMtMDEtMDcnLFxuICAgICAgICAgZW5kOiAnMjAyMy0wMS0xMCdcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIGdyb3VwSWQ6IDk5OSxcbiAgICAgICAgIHRpdGxlOiAnUmVwZWF0aW5nIEV2ZW50JyxcbiAgICAgICAgIHN0YXJ0OiAnMjAyMy0wMS0wOVQxNjowMDowMCdcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIGdyb3VwSWQ6IDk5OSxcbiAgICAgICAgIHRpdGxlOiAnUmVwZWF0aW5nIEV2ZW50JyxcbiAgICAgICAgIHN0YXJ0OiAnMjAyMy0wMS0xNlQxNjowMDowMCdcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIHRpdGxlOiAnQ29uZmVyZW5jZScsXG4gICAgICAgICBzdGFydDogJzIwMjMtMDEtMTEnLFxuICAgICAgICAgZW5kOiAnMjAyMy0wMS0xMydcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIHRpdGxlOiAnTWVldGluZycsXG4gICAgICAgICBzdGFydDogJzIwMjMtMDEtMTJUMTA6MzA6MDAnLFxuICAgICAgICAgZW5kOiAnMjAyMy0wMS0xMlQxMjozMDowMCdcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIHRpdGxlOiAnTHVuY2gnLFxuICAgICAgICAgc3RhcnQ6ICcyMDIzLTAxLTEyVDEyOjAwOjAwJ1xuICAgICAgIH0sXG4gICAgICAge1xuICAgICAgICAgdGl0bGU6ICdNZWV0aW5nJyxcbiAgICAgICAgIHN0YXJ0OiAnMjAyMy0wMS0xMlQxNDozMDowMCdcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIHRpdGxlOiAnSGFwcHkgSG91cicsXG4gICAgICAgICBzdGFydDogJzIwMjMtMDEtMTJUMTc6MzA6MDAnXG4gICAgICAgfSxcbiAgICAgICB7XG4gICAgICAgICB0aXRsZTogJ0Rpbm5lcicsXG4gICAgICAgICBzdGFydDogJzIwMjMtMDEtMTJUMjA6MDA6MDAnXG4gICAgICAgfSxcbiAgICAgICB7XG4gICAgICAgICB0aXRsZTogJ0JpcnRoZGF5IFBhcnR5JyxcbiAgICAgICAgIHN0YXJ0OiAnMjAyMy0wMS0xM1QwNzowMDowMCdcbiAgICAgICB9LFxuICAgICAgIHtcbiAgICAgICAgIHRpdGxlOiAnQ2xpY2sgZm9yIEdvb2dsZScsXG4gICAgICAgICB1cmw6ICdodHRwOi8vZ29vZ2xlLmNvbS8nLFxuICAgICAgICAgc3RhcnQ6ICcyMDIzLTAxLTI4J1xuICAgICAgIH1cbiAgICAgXVxuICAgfSk7XG5cbiAgIGNhbGVuZGFyLnJlbmRlcigpO1xuIH1cbn0pOyJdLCJuYW1lcyI6WyJDYWxlbmRhciIsImludGVyYWN0aW9uUGx1Z2luIiwiZGF5R3JpZFBsdWdpbiIsInRpbWVHcmlkUGx1Z2luIiwibGlzdFBsdWdpbiIsImRvY3VtZW50IiwiYWRkRXZlbnRMaXN0ZW5lciIsImNhbGVuZGFyRWwiLCJnZXRFbGVtZW50QnlJZCIsInVuZGVmaW5lZCIsImNhbGVuZGFyIiwicGx1Z2lucyIsImhlYWRlclRvb2xiYXIiLCJsZWZ0IiwiY2VudGVyIiwicmlnaHQiLCJpbml0aWFsRGF0ZSIsIm5hdkxpbmtzIiwiZWRpdGFibGUiLCJkYXlNYXhFdmVudHMiLCJldmVudHMiLCJ0aXRsZSIsInN0YXJ0IiwiZW5kIiwiZ3JvdXBJZCIsInVybCIsInJlbmRlciJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///111\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 112:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Calendar: () => (/* binding */ Calendar),\n/* harmony export */ JsonRequestError: () => (/* reexport safe */ _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.ae),\n/* harmony export */ createPlugin: () => (/* binding */ createPlugin),\n/* harmony export */ formatDate: () => (/* binding */ formatDate),\n/* harmony export */ formatRange: () => (/* binding */ formatRange),\n/* harmony export */ globalLocales: () => (/* binding */ globalLocales),\n/* harmony export */ globalPlugins: () => (/* binding */ globalPlugins),\n/* harmony export */ sliceEvents: () => (/* binding */ sliceEvents),\n/* harmony export */ version: () => (/* binding */ version)\n/* harmony export */ });\n/* harmony import */ var _internal_common_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113);\n/* harmony import */ var preact__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(114);\n/* harmony import */ var preact_compat__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(115);\n\n\n\n\n\nconst globalLocales = [];\n\nconst MINIMAL_RAW_EN_LOCALE = {\n code: 'en',\n week: {\n dow: 0,\n doy: 4, // 4 days need to be within the year to be considered the first week\n },\n direction: 'ltr',\n buttonText: {\n prev: 'prev',\n next: 'next',\n prevYear: 'prev year',\n nextYear: 'next year',\n year: 'year',\n today: 'today',\n month: 'month',\n week: 'week',\n day: 'day',\n list: 'list',\n },\n weekText: 'W',\n weekTextLong: 'Week',\n closeHint: 'Close',\n timeHint: 'Time',\n eventHint: 'Event',\n allDayText: 'all-day',\n moreLinkText: 'more',\n noEventsText: 'No events to display',\n};\nconst RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), { \n // Includes things we don't want other locales to inherit,\n // things that derive from other translatable strings.\n buttonHints: {\n prev: 'Previous $0',\n next: 'Next $0',\n today(buttonText, unit) {\n return (unit === 'day')\n ? 'Today'\n : `This ${buttonText}`;\n },\n }, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {\n return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;\n } });\nfunction organizeRawLocales(explicitRawLocales) {\n let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';\n let allRawLocales = globalLocales.concat(explicitRawLocales);\n let rawLocaleMap = {\n en: RAW_EN_LOCALE,\n };\n for (let rawLocale of allRawLocales) {\n rawLocaleMap[rawLocale.code] = rawLocale;\n }\n return {\n map: rawLocaleMap,\n defaultCode,\n };\n}\nfunction buildLocale(inputSingular, available) {\n if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {\n return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);\n }\n return queryLocale(inputSingular, available);\n}\nfunction queryLocale(codeArg, available) {\n let codes = [].concat(codeArg || []); // will convert to array\n let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;\n return parseLocale(codeArg, codes, raw);\n}\nfunction queryRawLocale(codes, available) {\n for (let i = 0; i < codes.length; i += 1) {\n let parts = codes[i].toLocaleLowerCase().split('-');\n for (let j = parts.length; j > 0; j -= 1) {\n let simpleId = parts.slice(0, j).join('-');\n if (available[simpleId]) {\n return available[simpleId];\n }\n }\n }\n return null;\n}\nfunction parseLocale(codeArg, codes, raw) {\n let merged = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.m)([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);\n delete merged.code; // don't want this part of the options\n let { week } = merged;\n delete merged.week;\n return {\n codeArg,\n codes,\n week,\n simpleNumberFormat: new Intl.NumberFormat(codeArg),\n options: merged,\n };\n}\n\n// TODO: easier way to add new hooks? need to update a million things\nfunction createPlugin(input) {\n return {\n id: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.g)(),\n name: input.name,\n premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,\n deps: input.deps || [],\n reducers: input.reducers || [],\n isLoadingFuncs: input.isLoadingFuncs || [],\n contextInit: [].concat(input.contextInit || []),\n eventRefiners: input.eventRefiners || {},\n eventDefMemberAdders: input.eventDefMemberAdders || [],\n eventSourceRefiners: input.eventSourceRefiners || {},\n isDraggableTransformers: input.isDraggableTransformers || [],\n eventDragMutationMassagers: input.eventDragMutationMassagers || [],\n eventDefMutationAppliers: input.eventDefMutationAppliers || [],\n dateSelectionTransformers: input.dateSelectionTransformers || [],\n datePointTransforms: input.datePointTransforms || [],\n dateSpanTransforms: input.dateSpanTransforms || [],\n views: input.views || {},\n viewPropsTransformers: input.viewPropsTransformers || [],\n isPropsValid: input.isPropsValid || null,\n externalDefTransforms: input.externalDefTransforms || [],\n viewContainerAppends: input.viewContainerAppends || [],\n eventDropTransformers: input.eventDropTransformers || [],\n componentInteractions: input.componentInteractions || [],\n calendarInteractions: input.calendarInteractions || [],\n themeClasses: input.themeClasses || {},\n eventSourceDefs: input.eventSourceDefs || [],\n cmdFormatter: input.cmdFormatter,\n recurringTypes: input.recurringTypes || [],\n namedTimeZonedImpl: input.namedTimeZonedImpl,\n initialView: input.initialView || '',\n elementDraggingImpl: input.elementDraggingImpl,\n optionChangeHandlers: input.optionChangeHandlers || {},\n scrollGridImpl: input.scrollGridImpl || null,\n listenerRefiners: input.listenerRefiners || {},\n optionRefiners: input.optionRefiners || {},\n propSetHandlers: input.propSetHandlers || {},\n };\n}\nfunction buildPluginHooks(pluginDefs, globalDefs) {\n let currentPluginIds = {};\n let hooks = {\n premiumReleaseDate: undefined,\n reducers: [],\n isLoadingFuncs: [],\n contextInit: [],\n eventRefiners: {},\n eventDefMemberAdders: [],\n eventSourceRefiners: {},\n isDraggableTransformers: [],\n eventDragMutationMassagers: [],\n eventDefMutationAppliers: [],\n dateSelectionTransformers: [],\n datePointTransforms: [],\n dateSpanTransforms: [],\n views: {},\n viewPropsTransformers: [],\n isPropsValid: null,\n externalDefTransforms: [],\n viewContainerAppends: [],\n eventDropTransformers: [],\n componentInteractions: [],\n calendarInteractions: [],\n themeClasses: {},\n eventSourceDefs: [],\n cmdFormatter: null,\n recurringTypes: [],\n namedTimeZonedImpl: null,\n initialView: '',\n elementDraggingImpl: null,\n optionChangeHandlers: {},\n scrollGridImpl: null,\n listenerRefiners: {},\n optionRefiners: {},\n propSetHandlers: {},\n };\n function addDefs(defs) {\n for (let def of defs) {\n const pluginName = def.name;\n const currentId = currentPluginIds[pluginName];\n if (currentId === undefined) {\n currentPluginIds[pluginName] = def.id;\n addDefs(def.deps);\n hooks = combineHooks(hooks, def);\n }\n else if (currentId !== def.id) {\n // different ID than the one already added\n console.warn(`Duplicate plugin '${pluginName}'`);\n }\n }\n }\n if (pluginDefs) {\n addDefs(pluginDefs);\n }\n addDefs(globalDefs);\n return hooks;\n}\nfunction buildBuildPluginHooks() {\n let currentOverrideDefs = [];\n let currentGlobalDefs = [];\n let currentHooks;\n return (overrideDefs, globalDefs) => {\n if (!currentHooks || !(0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.i)(overrideDefs, currentOverrideDefs) || !(0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.i)(globalDefs, currentGlobalDefs)) {\n currentHooks = buildPluginHooks(overrideDefs, globalDefs);\n }\n currentOverrideDefs = overrideDefs;\n currentGlobalDefs = globalDefs;\n return currentHooks;\n };\n}\nfunction combineHooks(hooks0, hooks1) {\n return {\n premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),\n reducers: hooks0.reducers.concat(hooks1.reducers),\n isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),\n contextInit: hooks0.contextInit.concat(hooks1.contextInit),\n eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),\n eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),\n eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),\n isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),\n eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),\n eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),\n dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),\n datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),\n dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),\n views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),\n viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),\n isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,\n externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),\n viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),\n eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),\n calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),\n componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),\n themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),\n eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),\n cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,\n recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),\n namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,\n initialView: hooks0.initialView || hooks1.initialView,\n elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,\n optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),\n scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,\n listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),\n optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),\n propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),\n };\n}\nfunction compareOptionalDates(date0, date1) {\n if (date0 === undefined) {\n return date1;\n }\n if (date1 === undefined) {\n return date0;\n }\n return new Date(Math.max(date0.valueOf(), date1.valueOf()));\n}\n\nclass StandardTheme extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.T {\n}\nStandardTheme.prototype.classes = {\n root: 'fc-theme-standard',\n tableCellShaded: 'fc-cell-shaded',\n buttonGroup: 'fc-button-group',\n button: 'fc-button fc-button-primary',\n buttonActive: 'fc-button-active',\n};\nStandardTheme.prototype.baseIconClass = 'fc-icon';\nStandardTheme.prototype.iconClasses = {\n close: 'fc-icon-x',\n prev: 'fc-icon-chevron-left',\n next: 'fc-icon-chevron-right',\n prevYear: 'fc-icon-chevrons-left',\n nextYear: 'fc-icon-chevrons-right',\n};\nStandardTheme.prototype.rtlIconClasses = {\n prev: 'fc-icon-chevron-right',\n next: 'fc-icon-chevron-left',\n prevYear: 'fc-icon-chevrons-right',\n nextYear: 'fc-icon-chevrons-left',\n};\nStandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly\nStandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';\nStandardTheme.prototype.iconOverridePrefix = 'fc-icon-';\n\nfunction compileViewDefs(defaultConfigs, overrideConfigs) {\n let hash = {};\n let viewType;\n for (viewType in defaultConfigs) {\n ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);\n }\n for (viewType in overrideConfigs) {\n ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);\n }\n return hash;\n}\nfunction ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {\n if (hash[viewType]) {\n return hash[viewType];\n }\n let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);\n if (viewDef) {\n hash[viewType] = viewDef;\n }\n return viewDef;\n}\nfunction buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {\n let defaultConfig = defaultConfigs[viewType];\n let overrideConfig = overrideConfigs[viewType];\n let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :\n ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));\n let theComponent = queryProp('component');\n let superType = queryProp('superType');\n let superDef = null;\n if (superType) {\n if (superType === viewType) {\n throw new Error('Can\\'t have a custom view type that references itself');\n }\n superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);\n }\n if (!theComponent && superDef) {\n theComponent = superDef.component;\n }\n if (!theComponent) {\n return null; // don't throw a warning, might be settings for a single-unit view\n }\n return {\n type: viewType,\n component: theComponent,\n defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),\n overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),\n };\n}\n\nfunction parseViewConfigs(inputs) {\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a)(inputs, parseViewConfig);\n}\nfunction parseViewConfig(input) {\n let rawOptions = typeof input === 'function' ?\n { component: input } :\n input;\n let { component } = rawOptions;\n if (rawOptions.content) {\n // TODO: remove content/classNames/didMount/etc from options?\n component = createViewHookComponent(rawOptions);\n }\n else if (component && !(component.prototype instanceof _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.B)) {\n // WHY?: people were using `component` property for `content`\n // TODO: converge on one setting name\n component = createViewHookComponent(Object.assign(Object.assign({}, rawOptions), { content: component }));\n }\n return {\n superType: rawOptions.type,\n component: component,\n rawOptions, // includes type and component too :(\n };\n}\nfunction createViewHookComponent(options) {\n return (viewProps) => ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.V.Consumer, null, (context) => ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"div\", elClasses: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.b)(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, customGenerator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));\n}\n\nfunction buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {\n let defaultConfigs = parseViewConfigs(defaultInputs);\n let overrideConfigs = parseViewConfigs(optionOverrides.views);\n let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a)(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));\n}\nfunction buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {\n let durationInput = viewDef.overrides.duration ||\n viewDef.defaults.duration ||\n dynamicOptionOverrides.duration ||\n optionOverrides.duration;\n let duration = null;\n let durationUnit = '';\n let singleUnit = '';\n let singleUnitOverrides = {};\n if (durationInput) {\n duration = createDurationCached(durationInput);\n if (duration) { // valid?\n let denom = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.c)(duration);\n durationUnit = denom.unit;\n if (denom.value === 1) {\n singleUnit = durationUnit;\n singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};\n }\n }\n }\n let queryButtonText = (optionsSubset) => {\n let buttonTextMap = optionsSubset.buttonText || {};\n let buttonTextKey = viewDef.defaults.buttonTextKey;\n if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {\n return buttonTextMap[buttonTextKey];\n }\n if (buttonTextMap[viewDef.type] != null) {\n return buttonTextMap[viewDef.type];\n }\n if (buttonTextMap[singleUnit] != null) {\n return buttonTextMap[singleUnit];\n }\n return null;\n };\n let queryButtonTitle = (optionsSubset) => {\n let buttonHints = optionsSubset.buttonHints || {};\n let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text\n if (buttonKey != null && buttonHints[buttonKey] != null) {\n return buttonHints[buttonKey];\n }\n if (buttonHints[viewDef.type] != null) {\n return buttonHints[viewDef.type];\n }\n if (buttonHints[singleUnit] != null) {\n return buttonHints[singleUnit];\n }\n return null;\n };\n return {\n type: viewDef.type,\n component: viewDef.component,\n duration,\n durationUnit,\n singleUnit,\n optionDefaults: viewDef.defaults,\n optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),\n buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||\n queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence\n viewDef.overrides.buttonText,\n buttonTextDefault: queryButtonText(localeDefaults) ||\n viewDef.defaults.buttonText ||\n queryButtonText(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e) ||\n viewDef.type,\n // not DRY\n buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||\n queryButtonTitle(optionOverrides) ||\n viewDef.overrides.buttonHint,\n buttonTitleDefault: queryButtonTitle(localeDefaults) ||\n viewDef.defaults.buttonHint ||\n queryButtonTitle(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e),\n // will eventually fall back to buttonText\n };\n}\n// hack to get memoization working\nlet durationInputMap = {};\nfunction createDurationCached(durationInput) {\n let json = JSON.stringify(durationInput);\n let res = durationInputMap[json];\n if (res === undefined) {\n res = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.d)(durationInput);\n durationInputMap[json] = res;\n }\n return res;\n}\n\nfunction reduceViewType(viewType, action) {\n switch (action.type) {\n case 'CHANGE_VIEW_TYPE':\n viewType = action.viewType;\n }\n return viewType;\n}\n\nfunction reduceCurrentDate(currentDate, action) {\n switch (action.type) {\n case 'CHANGE_DATE':\n return action.dateMarker;\n default:\n return currentDate;\n }\n}\n// should be initialized once and stay constant\n// this will change too\nfunction getInitialDate(options, dateEnv, nowManager) {\n let initialDateInput = options.initialDate;\n // compute the initial ambig-timezone date\n if (initialDateInput != null) {\n return dateEnv.createMarker(initialDateInput);\n }\n return nowManager.getDateMarker();\n}\n\nfunction reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {\n switch (action.type) {\n case 'SET_OPTION':\n return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });\n default:\n return dynamicOptionOverrides;\n }\n}\n\nfunction reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {\n let dp;\n switch (action.type) {\n case 'CHANGE_VIEW_TYPE':\n return dateProfileGenerator.build(action.dateMarker || currentDate);\n case 'CHANGE_DATE':\n return dateProfileGenerator.build(action.dateMarker);\n case 'PREV':\n dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);\n if (dp.isValid) {\n return dp;\n }\n break;\n case 'NEXT':\n dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);\n if (dp.isValid) {\n return dp;\n }\n break;\n }\n return currentDateProfile;\n}\n\nfunction initEventSources(calendarOptions, dateProfile, context) {\n let activeRange = dateProfile ? dateProfile.activeRange : null;\n return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);\n}\nfunction reduceEventSources(eventSources, action, dateProfile, context) {\n let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?\n switch (action.type) {\n case 'ADD_EVENT_SOURCES': // already parsed\n return addSources(eventSources, action.sources, activeRange, context);\n case 'REMOVE_EVENT_SOURCE':\n return removeSource(eventSources, action.sourceId);\n case 'PREV': // TODO: how do we track all actions that affect dateProfile :(\n case 'NEXT':\n case 'CHANGE_DATE':\n case 'CHANGE_VIEW_TYPE':\n if (dateProfile) {\n return fetchDirtySources(eventSources, activeRange, context);\n }\n return eventSources;\n case 'FETCH_EVENT_SOURCES':\n return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.f)(action.sourceIds) :\n excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);\n case 'RECEIVE_EVENTS':\n case 'RECEIVE_EVENT_ERROR':\n return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);\n case 'REMOVE_ALL_EVENT_SOURCES':\n return {};\n default:\n return eventSources;\n }\n}\nfunction reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {\n let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?\n return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);\n}\nfunction computeEventSourcesLoading(eventSources) {\n for (let sourceId in eventSources) {\n if (eventSources[sourceId].isFetching) {\n return true;\n }\n }\n return false;\n}\nfunction addSources(eventSourceHash, sources, fetchRange, context) {\n let hash = {};\n for (let source of sources) {\n hash[source.sourceId] = source;\n }\n if (fetchRange) {\n hash = fetchDirtySources(hash, fetchRange, context);\n }\n return Object.assign(Object.assign({}, eventSourceHash), hash);\n}\nfunction removeSource(eventSourceHash, sourceId) {\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.h)(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);\n}\nfunction fetchDirtySources(sourceHash, fetchRange, context) {\n return fetchSourcesByIds(sourceHash, (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.h)(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);\n}\nfunction isSourceDirty(eventSource, fetchRange, context) {\n if (!doesSourceNeedRange(eventSource, context)) {\n return !eventSource.latestFetchId;\n }\n return !context.options.lazyFetching ||\n !eventSource.fetchRange ||\n eventSource.isFetching || // always cancel outdated in-progress fetches\n fetchRange.start < eventSource.fetchRange.start ||\n fetchRange.end > eventSource.fetchRange.end;\n}\nfunction fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {\n let nextSources = {};\n for (let sourceId in prevSources) {\n let source = prevSources[sourceId];\n if (sourceIdHash[sourceId]) {\n nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);\n }\n else {\n nextSources[sourceId] = source;\n }\n }\n return nextSources;\n}\nfunction fetchSource(eventSource, fetchRange, isRefetch, context) {\n let { options, calendarApi } = context;\n let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];\n let fetchId = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.g)();\n sourceDef.fetch({\n eventSource,\n range: fetchRange,\n isRefetch,\n context,\n }, (res) => {\n let { rawEvents } = res;\n if (options.eventSourceSuccess) {\n rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;\n }\n if (eventSource.success) {\n rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;\n }\n context.dispatch({\n type: 'RECEIVE_EVENTS',\n sourceId: eventSource.sourceId,\n fetchId,\n fetchRange,\n rawEvents,\n });\n }, (error) => {\n let errorHandled = false;\n if (options.eventSourceFailure) {\n options.eventSourceFailure.call(calendarApi, error);\n errorHandled = true;\n }\n if (eventSource.failure) {\n eventSource.failure(error);\n errorHandled = true;\n }\n if (!errorHandled) {\n console.warn(error.message, error);\n }\n context.dispatch({\n type: 'RECEIVE_EVENT_ERROR',\n sourceId: eventSource.sourceId,\n fetchId,\n fetchRange,\n error,\n });\n });\n return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });\n}\nfunction receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {\n let eventSource = sourceHash[sourceId];\n if (eventSource && // not already removed\n fetchId === eventSource.latestFetchId) {\n return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });\n }\n return sourceHash;\n}\nfunction excludeStaticSources(eventSources, context) {\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.h)(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));\n}\nfunction parseInitialSources(rawOptions, context) {\n let refiners = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.j)(context);\n let rawSources = [].concat(rawOptions.eventSources || []);\n let sources = []; // parsed\n if (rawOptions.initialEvents) {\n rawSources.unshift(rawOptions.initialEvents);\n }\n if (rawOptions.events) {\n rawSources.unshift(rawOptions.events);\n }\n for (let rawSource of rawSources) {\n let source = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.p)(rawSource, context, refiners);\n if (source) {\n sources.push(source);\n }\n }\n return sources;\n}\nfunction doesSourceNeedRange(eventSource, context) {\n let defs = context.pluginHooks.eventSourceDefs;\n return !defs[eventSource.sourceDefId].ignoreRange;\n}\n\nfunction reduceDateSelection(currentSelection, action) {\n switch (action.type) {\n case 'UNSELECT_DATES':\n return null;\n case 'SELECT_DATES':\n return action.selection;\n default:\n return currentSelection;\n }\n}\n\nfunction reduceSelectedEvent(currentInstanceId, action) {\n switch (action.type) {\n case 'UNSELECT_EVENT':\n return '';\n case 'SELECT_EVENT':\n return action.eventInstanceId;\n default:\n return currentInstanceId;\n }\n}\n\nfunction reduceEventDrag(currentDrag, action) {\n let newDrag;\n switch (action.type) {\n case 'UNSET_EVENT_DRAG':\n return null;\n case 'SET_EVENT_DRAG':\n newDrag = action.state;\n return {\n affectedEvents: newDrag.affectedEvents,\n mutatedEvents: newDrag.mutatedEvents,\n isEvent: newDrag.isEvent,\n };\n default:\n return currentDrag;\n }\n}\n\nfunction reduceEventResize(currentResize, action) {\n let newResize;\n switch (action.type) {\n case 'UNSET_EVENT_RESIZE':\n return null;\n case 'SET_EVENT_RESIZE':\n newResize = action.state;\n return {\n affectedEvents: newResize.affectedEvents,\n mutatedEvents: newResize.mutatedEvents,\n isEvent: newResize.isEvent,\n };\n default:\n return currentResize;\n }\n}\n\nfunction parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {\n let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;\n let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;\n return { header, footer };\n}\nfunction parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {\n let sectionWidgets = {};\n let viewsWithButtons = [];\n let hasTitle = false;\n for (let sectionName in sectionStrHash) {\n let sectionStr = sectionStrHash[sectionName];\n let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);\n sectionWidgets[sectionName] = sectionRes.widgets;\n viewsWithButtons.push(...sectionRes.viewsWithButtons);\n hasTitle = hasTitle || sectionRes.hasTitle;\n }\n return { sectionWidgets, viewsWithButtons, hasTitle };\n}\n/*\nBAD: querying icons and text here. should be done at render time\n*/\nfunction parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined\ncalendarOptionOverrides, // overrides only!, unrefined :(\ntheme, viewSpecs, calendarApi) {\n let isRtl = calendarOptions.direction === 'rtl';\n let calendarCustomButtons = calendarOptions.customButtons || {};\n let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};\n let calendarButtonText = calendarOptions.buttonText || {};\n let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};\n let calendarButtonHints = calendarOptions.buttonHints || {};\n let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];\n let viewsWithButtons = [];\n let hasTitle = false;\n let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {\n if (buttonName === 'title') {\n hasTitle = true;\n return { buttonName };\n }\n let customButtonProps;\n let viewSpec;\n let buttonClick;\n let buttonIcon; // only one of these will be set\n let buttonText; // \"\n let buttonHint;\n // ^ for the title=\"\" attribute, for accessibility\n if ((customButtonProps = calendarCustomButtons[buttonName])) {\n buttonClick = (ev) => {\n if (customButtonProps.click) {\n customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?\n }\n };\n (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||\n (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||\n (buttonText = customButtonProps.text);\n buttonHint = customButtonProps.hint || customButtonProps.text;\n }\n else if ((viewSpec = viewSpecs[buttonName])) {\n viewsWithButtons.push(buttonName);\n buttonClick = () => {\n calendarApi.changeView(buttonName);\n };\n (buttonText = viewSpec.buttonTextOverride) ||\n (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||\n (buttonText = viewSpec.buttonTextDefault);\n let textFallback = viewSpec.buttonTextOverride ||\n viewSpec.buttonTextDefault;\n buttonHint = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.k)(viewSpec.buttonTitleOverride ||\n viewSpec.buttonTitleDefault ||\n calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName\n textFallback);\n }\n else if (calendarApi[buttonName]) { // a calendarApi method\n buttonClick = () => {\n calendarApi[buttonName]();\n };\n (buttonText = calendarButtonTextOverrides[buttonName]) ||\n (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||\n (buttonText = calendarButtonText[buttonName]); // everything else is considered default\n if (buttonName === 'prevYear' || buttonName === 'nextYear') {\n let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';\n buttonHint = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.k)(calendarButtonHintOverrides[prevOrNext] ||\n calendarButtonHints[prevOrNext], [\n calendarButtonText.year || 'year',\n 'year',\n ], calendarButtonText[buttonName]);\n }\n else {\n buttonHint = (navUnit) => (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.k)(calendarButtonHintOverrides[buttonName] ||\n calendarButtonHints[buttonName], [\n calendarButtonText[navUnit] || navUnit,\n navUnit,\n ], calendarButtonText[buttonName]);\n }\n }\n return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };\n })));\n return { widgets, viewsWithButtons, hasTitle };\n}\n\n// always represents the current view. otherwise, it'd need to change value every time date changes\nclass ViewImpl {\n constructor(type, getCurrentData, dateEnv) {\n this.type = type;\n this.getCurrentData = getCurrentData;\n this.dateEnv = dateEnv;\n }\n get calendar() {\n return this.getCurrentData().calendarApi;\n }\n get title() {\n return this.getCurrentData().viewTitle;\n }\n get activeStart() {\n return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);\n }\n get activeEnd() {\n return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);\n }\n get currentStart() {\n return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);\n }\n get currentEnd() {\n return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);\n }\n getOption(name) {\n return this.getCurrentData().options[name]; // are the view-specific options\n }\n}\n\nlet eventSourceDef$2 = {\n ignoreRange: true,\n parseMeta(refined) {\n if (Array.isArray(refined.events)) {\n return refined.events;\n }\n return null;\n },\n fetch(arg, successCallback) {\n successCallback({\n rawEvents: arg.eventSource.meta,\n });\n },\n};\nconst arrayEventSourcePlugin = createPlugin({\n name: 'array-event-source',\n eventSourceDefs: [eventSourceDef$2],\n});\n\nlet eventSourceDef$1 = {\n parseMeta(refined) {\n if (typeof refined.events === 'function') {\n return refined.events;\n }\n return null;\n },\n fetch(arg, successCallback, errorCallback) {\n const { dateEnv } = arg.context;\n const func = arg.eventSource.meta;\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.u)(func.bind(null, (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.l)(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);\n },\n};\nconst funcEventSourcePlugin = createPlugin({\n name: 'func-event-source',\n eventSourceDefs: [eventSourceDef$1],\n});\n\nconst JSON_FEED_EVENT_SOURCE_REFINERS = {\n method: String,\n extraParams: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.n,\n startParam: String,\n endParam: String,\n timeZoneParam: String,\n};\n\nlet eventSourceDef = {\n parseMeta(refined) {\n if (refined.url && (refined.format === 'json' || !refined.format)) {\n return {\n url: refined.url,\n format: 'json',\n method: (refined.method || 'GET').toUpperCase(),\n extraParams: refined.extraParams,\n startParam: refined.startParam,\n endParam: refined.endParam,\n timeZoneParam: refined.timeZoneParam,\n };\n }\n return null;\n },\n fetch(arg, successCallback, errorCallback) {\n const { meta } = arg.eventSource;\n const requestParams = buildRequestParams(meta, arg.range, arg.context);\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.r)(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {\n successCallback({ rawEvents, response });\n }, errorCallback);\n },\n};\nconst jsonFeedEventSourcePlugin = createPlugin({\n name: 'json-event-source',\n eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,\n eventSourceDefs: [eventSourceDef],\n});\nfunction buildRequestParams(meta, range, context) {\n let { dateEnv, options } = context;\n let startParam;\n let endParam;\n let timeZoneParam;\n let customRequestParams;\n let params = {};\n startParam = meta.startParam;\n if (startParam == null) {\n startParam = options.startParam;\n }\n endParam = meta.endParam;\n if (endParam == null) {\n endParam = options.endParam;\n }\n timeZoneParam = meta.timeZoneParam;\n if (timeZoneParam == null) {\n timeZoneParam = options.timeZoneParam;\n }\n // retrieve any outbound GET/POST data from the options\n if (typeof meta.extraParams === 'function') {\n // supplied as a function that returns a key/value object\n customRequestParams = meta.extraParams();\n }\n else {\n // probably supplied as a straight key/value object\n customRequestParams = meta.extraParams || {};\n }\n Object.assign(params, customRequestParams);\n params[startParam] = dateEnv.formatIso(range.start);\n params[endParam] = dateEnv.formatIso(range.end);\n if (dateEnv.timeZone !== 'local') {\n params[timeZoneParam] = dateEnv.timeZone;\n }\n return params;\n}\n\nconst SIMPLE_RECURRING_REFINERS = {\n daysOfWeek: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.n,\n startTime: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.d,\n endTime: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.d,\n duration: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.d,\n startRecur: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.n,\n endRecur: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.n,\n};\n\nlet recurring = {\n parse(refined, dateEnv) {\n if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {\n let recurringData = {\n daysOfWeek: refined.daysOfWeek || null,\n startTime: refined.startTime || null,\n endTime: refined.endTime || null,\n startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,\n endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,\n dateEnv,\n };\n let duration;\n if (refined.duration) {\n duration = refined.duration;\n }\n if (!duration && refined.startTime && refined.endTime) {\n duration = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.s)(refined.endTime, refined.startTime);\n }\n return {\n allDayGuess: Boolean(!refined.startTime && !refined.endTime),\n duration,\n typeData: recurringData, // doesn't need endTime anymore but oh well\n };\n }\n return null;\n },\n expand(typeData, framingRange, dateEnv) {\n let clippedFramingRange = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.o)(framingRange, { start: typeData.startRecur, end: typeData.endRecur });\n if (clippedFramingRange) {\n return expandRanges(typeData.daysOfWeek, typeData.startTime, typeData.dateEnv, dateEnv, clippedFramingRange);\n }\n return [];\n },\n};\nconst simpleRecurringEventsPlugin = createPlugin({\n name: 'simple-recurring-event',\n recurringTypes: [recurring],\n eventRefiners: SIMPLE_RECURRING_REFINERS,\n});\nfunction expandRanges(daysOfWeek, startTime, eventDateEnv, calendarDateEnv, framingRange) {\n let dowHash = daysOfWeek ? (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.f)(daysOfWeek) : null;\n let dayMarker = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.q)(framingRange.start);\n let endMarker = framingRange.end;\n let instanceStarts = [];\n // https://github.com/fullcalendar/fullcalendar/issues/7934\n if (startTime) {\n if (startTime.milliseconds < 0) {\n // possible for next-day to have negative business hours that go into current day\n endMarker = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.t)(endMarker, 1);\n }\n else if (startTime.milliseconds >= 1000 * 60 * 60 * 24) {\n // possible for prev-day to have >24hr business hours that go into current day\n dayMarker = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.t)(dayMarker, -1);\n }\n }\n while (dayMarker < endMarker) {\n let instanceStart;\n // if everyday, or this particular day-of-week\n if (!dowHash || dowHash[dayMarker.getUTCDay()]) {\n if (startTime) {\n instanceStart = calendarDateEnv.add(dayMarker, startTime);\n }\n else {\n instanceStart = dayMarker;\n }\n instanceStarts.push(calendarDateEnv.createMarker(eventDateEnv.toDate(instanceStart)));\n }\n dayMarker = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.t)(dayMarker, 1);\n }\n return instanceStarts;\n}\n\nconst changeHandlerPlugin = createPlugin({\n name: 'change-handler',\n optionChangeHandlers: {\n events(events, context) {\n handleEventSources([events], context);\n },\n eventSources: handleEventSources,\n },\n});\n/*\nBUG: if `event` was supplied, all previously-given `eventSources` will be wiped out\n*/\nfunction handleEventSources(inputs, context) {\n let unfoundSources = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.v)(context.getCurrentData().eventSources);\n if (unfoundSources.length === 1 &&\n inputs.length === 1 &&\n Array.isArray(unfoundSources[0]._raw) &&\n Array.isArray(inputs[0])) {\n context.dispatch({\n type: 'RESET_RAW_EVENTS',\n sourceId: unfoundSources[0].sourceId,\n rawEvents: inputs[0],\n });\n return;\n }\n let newInputs = [];\n for (let input of inputs) {\n let inputFound = false;\n for (let i = 0; i < unfoundSources.length; i += 1) {\n if (unfoundSources[i]._raw === input) {\n unfoundSources.splice(i, 1); // delete\n inputFound = true;\n break;\n }\n }\n if (!inputFound) {\n newInputs.push(input);\n }\n }\n for (let unfoundSource of unfoundSources) {\n context.dispatch({\n type: 'REMOVE_EVENT_SOURCE',\n sourceId: unfoundSource.sourceId,\n });\n }\n for (let newInput of newInputs) {\n context.calendarApi.addEventSource(newInput);\n }\n}\n\nfunction handleDateProfile(dateProfile, context) {\n context.emitter.trigger('datesSet', Object.assign(Object.assign({}, (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.l)(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));\n}\n\nfunction handleEventStore(eventStore, context) {\n let { emitter } = context;\n if (emitter.hasHandlers('eventsSet')) {\n emitter.trigger('eventsSet', (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.w)(eventStore, context));\n }\n}\n\n/*\nthis array is exposed on the root namespace so that UMD plugins can add to it.\nsee the rollup-bundles script.\n*/\nconst globalPlugins = [\n arrayEventSourcePlugin,\n funcEventSourcePlugin,\n jsonFeedEventSourcePlugin,\n simpleRecurringEventsPlugin,\n changeHandlerPlugin,\n createPlugin({\n name: 'misc',\n isLoadingFuncs: [\n (state) => computeEventSourcesLoading(state.eventSources),\n ],\n propSetHandlers: {\n dateProfile: handleDateProfile,\n eventStore: handleEventStore,\n },\n }),\n];\n\nclass TaskRunner {\n constructor(runTaskOption, drainedOption) {\n this.runTaskOption = runTaskOption;\n this.drainedOption = drainedOption;\n this.queue = [];\n this.delayedRunner = new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.D(this.drain.bind(this));\n }\n request(task, delay) {\n this.queue.push(task);\n this.delayedRunner.request(delay);\n }\n pause(scope) {\n this.delayedRunner.pause(scope);\n }\n resume(scope, force) {\n this.delayedRunner.resume(scope, force);\n }\n drain() {\n let { queue } = this;\n while (queue.length) {\n let completedTasks = [];\n let task;\n while ((task = queue.shift())) {\n this.runTask(task);\n completedTasks.push(task);\n }\n this.drained(completedTasks);\n } // keep going, in case new tasks were added in the drained handler\n }\n runTask(task) {\n if (this.runTaskOption) {\n this.runTaskOption(task);\n }\n }\n drained(completedTasks) {\n if (this.drainedOption) {\n this.drainedOption(completedTasks);\n }\n }\n}\n\n// Computes what the title at the top of the calendarApi should be for this view\nfunction buildTitle(dateProfile, viewOptions, dateEnv) {\n let range;\n // for views that span a large unit of time, show the proper interval, ignoring stray days before and after\n if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {\n range = dateProfile.currentRange;\n }\n else { // for day units or smaller, use the actual day range\n range = dateProfile.activeRange;\n }\n return dateEnv.formatRange(range.start, range.end, (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.x)(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {\n isEndExclusive: dateProfile.isRangeAllDay,\n defaultSeparator: viewOptions.titleRangeSeparator,\n });\n}\n// Generates the format string that should be used to generate the title for the current date range.\n// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.\nfunction buildTitleFormat(dateProfile) {\n let { currentRangeUnit } = dateProfile;\n if (currentRangeUnit === 'year') {\n return { year: 'numeric' };\n }\n if (currentRangeUnit === 'month') {\n return { year: 'numeric', month: 'long' }; // like \"September 2014\"\n }\n let days = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.y)(dateProfile.currentRange.start, dateProfile.currentRange.end);\n if (days !== null && days > 1) {\n // multi-day range. shorter, like \"Sep 9 - 10 2014\"\n return { year: 'numeric', month: 'short', day: 'numeric' };\n }\n // one day. longer, like \"September 9 2014\"\n return { year: 'numeric', month: 'long', day: 'numeric' };\n}\n\n/*\nTODO: test switching timezones when NO timezone plugin\n*/\nclass CalendarNowManager {\n constructor() {\n this.resetListeners = new Set();\n }\n handleInput(dateEnv, // will change if timezone setup changed\n nowInput) {\n const oldDateEnv = this.dateEnv;\n if (dateEnv !== oldDateEnv) {\n if (typeof nowInput === 'function') {\n this.nowFn = nowInput;\n }\n else if (!oldDateEnv) { // first time?\n this.nowAnchorDate = dateEnv.toDate(nowInput\n ? dateEnv.createMarker(nowInput)\n : dateEnv.createNowMarker());\n this.nowAnchorQueried = Date.now();\n }\n this.dateEnv = dateEnv;\n // not first time? fire reset handlers\n if (oldDateEnv) {\n for (const resetListener of this.resetListeners.values()) {\n resetListener();\n }\n }\n }\n }\n getDateMarker() {\n return this.nowAnchorDate\n ? this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf() +\n (Date.now() - this.nowAnchorQueried))\n : this.dateEnv.createMarker(this.nowFn());\n }\n addResetListener(handler) {\n this.resetListeners.add(handler);\n }\n removeResetListener(handler) {\n this.resetListeners.delete(handler);\n }\n}\n\n// in future refactor, do the redux-style function(state=initial) for initial-state\n// also, whatever is happening in constructor, have it happen in action queue too\nclass CalendarDataManager {\n constructor(props) {\n this.computeCurrentViewData = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(this._computeCurrentViewData);\n this.organizeRawLocales = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(organizeRawLocales);\n this.buildLocale = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildLocale);\n this.buildPluginHooks = buildBuildPluginHooks();\n this.buildDateEnv = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildDateEnv$1);\n this.buildTheme = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildTheme);\n this.parseToolbars = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(parseToolbars);\n this.buildViewSpecs = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildViewSpecs);\n this.buildDateProfileGenerator = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.A)(buildDateProfileGenerator);\n this.buildViewApi = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildViewApi);\n this.buildViewUiProps = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.A)(buildViewUiProps);\n this.buildEventUiBySource = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildEventUiBySource, _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.E);\n this.buildEventUiBases = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildEventUiBases);\n this.parseContextBusinessHours = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.A)(parseContextBusinessHours);\n this.buildTitle = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildTitle);\n this.nowManager = new CalendarNowManager();\n this.emitter = new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.F();\n this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));\n this.currentCalendarOptionsInput = {};\n this.currentCalendarOptionsRefined = {};\n this.currentViewOptionsInput = {};\n this.currentViewOptionsRefined = {};\n this.currentCalendarOptionsRefiners = {};\n this.optionsForRefining = [];\n this.optionsForHandling = [];\n this.getCurrentData = () => this.data;\n this.dispatch = (action) => {\n this.actionRunner.request(action); // protects against recursive calls to _handleAction\n };\n this.props = props;\n this.actionRunner.pause();\n this.nowManager = new CalendarNowManager();\n let dynamicOptionOverrides = {};\n let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);\n let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;\n let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);\n // wire things up\n // TODO: not DRY\n props.calendarApi.currentDataManager = this;\n this.emitter.setThisContext(props.calendarApi);\n this.emitter.setOptions(currentViewData.options);\n let calendarContext = {\n nowManager: this.nowManager,\n dateEnv: optionsData.dateEnv,\n options: optionsData.calendarOptions,\n pluginHooks: optionsData.pluginHooks,\n calendarApi: props.calendarApi,\n dispatch: this.dispatch,\n emitter: this.emitter,\n getCurrentData: this.getCurrentData,\n };\n let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv, this.nowManager);\n let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);\n if (!(0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.G)(dateProfile.activeRange, currentDate)) {\n currentDate = dateProfile.currentRange.start;\n }\n // needs to be after setThisContext\n for (let callback of optionsData.pluginHooks.contextInit) {\n callback(calendarContext);\n }\n // NOT DRY\n let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);\n let initialState = {\n dynamicOptionOverrides,\n currentViewType,\n currentDate,\n dateProfile,\n businessHours: this.parseContextBusinessHours(calendarContext),\n eventSources,\n eventUiBases: {},\n eventStore: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.H)(),\n renderableEventStore: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.H)(),\n dateSelection: null,\n eventSelection: '',\n eventDrag: null,\n eventResize: null,\n selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,\n };\n let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);\n for (let reducer of optionsData.pluginHooks.reducers) {\n Object.assign(initialState, reducer(null, null, contextAndState));\n }\n if (computeIsLoading(initialState, calendarContext)) {\n this.emitter.trigger('loading', true); // NOT DRY\n }\n this.state = initialState;\n this.updateData();\n this.actionRunner.resume();\n }\n resetOptions(optionOverrides, changedOptionNames) {\n let { props } = this;\n if (changedOptionNames === undefined) {\n props.optionOverrides = optionOverrides;\n }\n else {\n props.optionOverrides = Object.assign(Object.assign({}, (props.optionOverrides || {})), optionOverrides);\n this.optionsForRefining.push(...changedOptionNames);\n }\n if (changedOptionNames === undefined || changedOptionNames.length) {\n this.actionRunner.request({\n type: 'NOTHING',\n });\n }\n }\n _handleAction(action) {\n let { props, state, emitter } = this;\n let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);\n let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);\n let currentViewType = reduceViewType(state.currentViewType, action);\n let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);\n // wire things up\n // TODO: not DRY\n props.calendarApi.currentDataManager = this;\n emitter.setThisContext(props.calendarApi);\n emitter.setOptions(currentViewData.options);\n let calendarContext = {\n nowManager: this.nowManager,\n dateEnv: optionsData.dateEnv,\n options: optionsData.calendarOptions,\n pluginHooks: optionsData.pluginHooks,\n calendarApi: props.calendarApi,\n dispatch: this.dispatch,\n emitter,\n getCurrentData: this.getCurrentData,\n };\n let { currentDate, dateProfile } = state;\n if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack\n dateProfile = currentViewData.dateProfileGenerator.build(currentDate);\n }\n currentDate = reduceCurrentDate(currentDate, action);\n dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);\n if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator\n action.type === 'NEXT' || // \"\n !(0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.G)(dateProfile.currentRange, currentDate)) {\n currentDate = dateProfile.currentRange.start;\n }\n let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);\n let eventStore = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.I)(state.eventStore, action, eventSources, dateProfile, calendarContext);\n let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading\n let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?\n (state.renderableEventStore || eventStore) : // try from previous state\n eventStore;\n let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj\n let eventUiBySource = this.buildEventUiBySource(eventSources);\n let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);\n let newState = {\n dynamicOptionOverrides,\n currentViewType,\n currentDate,\n dateProfile,\n eventSources,\n eventStore,\n renderableEventStore,\n selectionConfig,\n eventUiBases,\n businessHours: this.parseContextBusinessHours(calendarContext),\n dateSelection: reduceDateSelection(state.dateSelection, action),\n eventSelection: reduceSelectedEvent(state.eventSelection, action),\n eventDrag: reduceEventDrag(state.eventDrag, action),\n eventResize: reduceEventResize(state.eventResize, action),\n };\n let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);\n for (let reducer of optionsData.pluginHooks.reducers) {\n Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value\n }\n let wasLoading = computeIsLoading(state, calendarContext);\n let isLoading = computeIsLoading(newState, calendarContext);\n // TODO: use propSetHandlers in plugin system\n if (!wasLoading && isLoading) {\n emitter.trigger('loading', true);\n }\n else if (wasLoading && !isLoading) {\n emitter.trigger('loading', false);\n }\n this.state = newState;\n if (props.onAction) {\n props.onAction(action);\n }\n }\n updateData() {\n let { props, state } = this;\n let oldData = this.data;\n let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);\n let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);\n let data = this.data = Object.assign(Object.assign(Object.assign({ nowManager: this.nowManager, viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);\n let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;\n let oldCalendarOptions = oldData && oldData.calendarOptions;\n let newCalendarOptions = optionsData.calendarOptions;\n if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {\n if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {\n // hack\n state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);\n state.eventStore = data.eventStore = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.J)(data.eventStore, oldData.dateEnv, data.dateEnv);\n state.renderableEventStore = data.renderableEventStore = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.J)(data.renderableEventStore, oldData.dateEnv, data.dateEnv);\n }\n for (let optionName in changeHandlers) {\n if (this.optionsForHandling.indexOf(optionName) !== -1 ||\n oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {\n changeHandlers[optionName](newCalendarOptions[optionName], data);\n }\n }\n }\n this.optionsForHandling = [];\n if (props.onData) {\n props.onData(data);\n }\n }\n computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {\n // TODO: blacklist options that are handled by optionChangeHandlers\n if (!this.optionsForRefining.length &&\n optionOverrides === this.stableOptionOverrides &&\n dynamicOptionOverrides === this.stableDynamicOptionOverrides) {\n return this.stableCalendarOptionsData;\n }\n let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);\n warnUnknownOptions(extra);\n let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);\n let viewSpecs = this.buildViewSpecs(pluginHooks.views, this.stableOptionOverrides, this.stableDynamicOptionOverrides, localeDefaults);\n let theme = this.buildTheme(refinedOptions, pluginHooks);\n let toolbarConfig = this.parseToolbars(refinedOptions, this.stableOptionOverrides, theme, viewSpecs, calendarApi);\n return this.stableCalendarOptionsData = {\n calendarOptions: refinedOptions,\n pluginHooks,\n dateEnv,\n viewSpecs,\n theme,\n toolbarConfig,\n localeDefaults,\n availableRawLocales: availableLocaleData.map,\n };\n }\n // always called from behind a memoizer\n processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {\n let { locales, locale } = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.K)([\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e,\n optionOverrides,\n dynamicOptionOverrides,\n ]);\n let availableLocaleData = this.organizeRawLocales(locales);\n let availableRawLocales = availableLocaleData.map;\n let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;\n let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);\n let refiners = this.currentCalendarOptionsRefiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.L), _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.M), _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.N), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);\n let extra = {};\n let raw = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.K)([\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e,\n localeDefaults,\n optionOverrides,\n dynamicOptionOverrides,\n ]);\n let refined = {};\n let currentRaw = this.currentCalendarOptionsInput;\n let currentRefined = this.currentCalendarOptionsRefined;\n let anyChanges = false;\n for (let optionName in raw) {\n if (this.optionsForRefining.indexOf(optionName) === -1 && (raw[optionName] === currentRaw[optionName] || (_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.O[optionName] &&\n (optionName in currentRaw) &&\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.O[optionName](currentRaw[optionName], raw[optionName])))) {\n refined[optionName] = currentRefined[optionName];\n }\n else if (refiners[optionName]) {\n refined[optionName] = refiners[optionName](raw[optionName]);\n anyChanges = true;\n }\n else {\n extra[optionName] = currentRaw[optionName];\n }\n }\n if (anyChanges) {\n this.currentCalendarOptionsInput = raw;\n this.currentCalendarOptionsRefined = refined;\n this.stableOptionOverrides = optionOverrides;\n this.stableDynamicOptionOverrides = dynamicOptionOverrides;\n }\n this.optionsForHandling.push(...this.optionsForRefining);\n this.optionsForRefining = [];\n return {\n rawOptions: this.currentCalendarOptionsInput,\n refinedOptions: this.currentCalendarOptionsRefined,\n pluginHooks,\n availableLocaleData,\n localeDefaults,\n extra,\n };\n }\n _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {\n let viewSpec = optionsData.viewSpecs[viewType];\n if (!viewSpec) {\n throw new Error(`viewType \"${viewType}\" is not available. Please make sure you've loaded all neccessary plugins`);\n }\n let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);\n warnUnknownOptions(extra);\n this.nowManager.handleInput(optionsData.dateEnv, refinedOptions.now);\n let dateProfileGenerator = this.buildDateProfileGenerator({\n dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,\n nowManager: this.nowManager,\n duration: viewSpec.duration,\n durationUnit: viewSpec.durationUnit,\n usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,\n dateEnv: optionsData.dateEnv,\n calendarApi: this.props.calendarApi,\n slotMinTime: refinedOptions.slotMinTime,\n slotMaxTime: refinedOptions.slotMaxTime,\n showNonCurrentDates: refinedOptions.showNonCurrentDates,\n dayCount: refinedOptions.dayCount,\n dateAlignment: refinedOptions.dateAlignment,\n dateIncrement: refinedOptions.dateIncrement,\n hiddenDays: refinedOptions.hiddenDays,\n weekends: refinedOptions.weekends,\n validRangeInput: refinedOptions.validRange,\n visibleRangeInput: refinedOptions.visibleRange,\n fixedWeekCount: refinedOptions.fixedWeekCount,\n });\n let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);\n return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };\n }\n processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {\n let raw = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.K)([\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e,\n viewSpec.optionDefaults,\n localeDefaults,\n optionOverrides,\n viewSpec.optionOverrides,\n dynamicOptionOverrides,\n ]);\n let refiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.L), _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.M), _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.N), _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.P), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);\n let refined = {};\n let currentRaw = this.currentViewOptionsInput;\n let currentRefined = this.currentViewOptionsRefined;\n let anyChanges = false;\n let extra = {};\n for (let optionName in raw) {\n if (raw[optionName] === currentRaw[optionName] ||\n (_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.O[optionName] &&\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.O[optionName](raw[optionName], currentRaw[optionName]))) {\n refined[optionName] = currentRefined[optionName];\n }\n else {\n if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||\n (_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.O[optionName] &&\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.O[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {\n if (optionName in this.currentCalendarOptionsRefined) { // might be an \"extra\" prop\n refined[optionName] = this.currentCalendarOptionsRefined[optionName];\n }\n }\n else if (refiners[optionName]) {\n refined[optionName] = refiners[optionName](raw[optionName]);\n }\n else {\n extra[optionName] = raw[optionName];\n }\n anyChanges = true;\n }\n }\n if (anyChanges) {\n this.currentViewOptionsInput = raw;\n this.currentViewOptionsRefined = refined;\n }\n return {\n rawOptions: this.currentViewOptionsInput,\n refinedOptions: this.currentViewOptionsRefined,\n extra,\n };\n }\n}\nfunction buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {\n let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);\n return new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.Q({\n calendarSystem: 'gregory',\n timeZone,\n namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,\n locale,\n weekNumberCalculation,\n firstDay,\n weekText,\n cmdFormatter: pluginHooks.cmdFormatter,\n defaultSeparator,\n });\n}\nfunction buildTheme(options, pluginHooks) {\n let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;\n return new ThemeClass(options);\n}\nfunction buildDateProfileGenerator(props) {\n let DateProfileGeneratorClass = props.dateProfileGeneratorClass || _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.R;\n return new DateProfileGeneratorClass(props);\n}\nfunction buildViewApi(type, getCurrentData, dateEnv) {\n return new ViewImpl(type, getCurrentData, dateEnv);\n}\nfunction buildEventUiBySource(eventSources) {\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a)(eventSources, (eventSource) => eventSource.ui);\n}\nfunction buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {\n let eventUiBases = { '': eventUiSingleBase };\n for (let defId in eventDefs) {\n let def = eventDefs[defId];\n if (def.sourceId && eventUiBySource[def.sourceId]) {\n eventUiBases[defId] = eventUiBySource[def.sourceId];\n }\n }\n return eventUiBases;\n}\nfunction buildViewUiProps(calendarContext) {\n let { options } = calendarContext;\n return {\n eventUiSingleBase: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.S)({\n display: options.eventDisplay,\n editable: options.editable,\n startEditable: options.eventStartEditable,\n durationEditable: options.eventDurationEditable,\n constraint: options.eventConstraint,\n overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,\n allow: options.eventAllow,\n backgroundColor: options.eventBackgroundColor,\n borderColor: options.eventBorderColor,\n textColor: options.eventTextColor,\n color: options.eventColor,\n // classNames: options.eventClassNames // render hook will handle this\n }, calendarContext),\n selectionConfig: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.S)({\n constraint: options.selectConstraint,\n overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,\n allow: options.selectAllow,\n }, calendarContext),\n };\n}\nfunction computeIsLoading(state, context) {\n for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {\n if (isLoadingFunc(state)) {\n return true;\n }\n }\n return false;\n}\nfunction parseContextBusinessHours(calendarContext) {\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.U)(calendarContext.options.businessHours, calendarContext);\n}\nfunction warnUnknownOptions(options, viewName) {\n for (let optionName in options) {\n console.warn(`Unknown option '${optionName}'` +\n (viewName ? ` for view '${viewName}'` : ''));\n }\n}\n\nclass ToolbarSection extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));\n return (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)('div', { className: 'fc-toolbar-chunk' }, ...children);\n }\n renderWidgetGroup(widgetGroup) {\n let { props } = this;\n let { theme } = this.context;\n let children = [];\n let isOnlyButtons = true;\n for (let widget of widgetGroup) {\n let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;\n if (buttonName === 'title') {\n isOnlyButtons = false;\n children.push((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"h2\", { className: \"fc-toolbar-title\", id: props.titleId }, props.title));\n }\n else {\n let isPressed = buttonName === props.activeButton;\n let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||\n (!props.isPrevEnabled && buttonName === 'prev') ||\n (!props.isNextEnabled && buttonName === 'next');\n let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];\n if (isPressed) {\n buttonClasses.push(theme.getClass('buttonActive'));\n }\n children.push((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"button\", { type: \"button\", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, \"aria-pressed\": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"span\", { className: buttonIcon, role: \"img\" }) : '')));\n }\n }\n if (children.length > 1) {\n let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';\n return (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)('div', { className: groupClassName }, ...children);\n }\n return children[0];\n }\n}\n\nclass Toolbar extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let { model, extraClassName } = this.props;\n let forceLtr = false;\n let startContent;\n let endContent;\n let sectionWidgets = model.sectionWidgets;\n let centerContent = sectionWidgets.center;\n if (sectionWidgets.left) {\n forceLtr = true;\n startContent = sectionWidgets.left;\n }\n else {\n startContent = sectionWidgets.start;\n }\n if (sectionWidgets.right) {\n forceLtr = true;\n endContent = sectionWidgets.right;\n }\n else {\n endContent = sectionWidgets.end;\n }\n let classNames = [\n extraClassName || '',\n 'fc-toolbar',\n forceLtr ? 'fc-toolbar-ltr' : '',\n ];\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: classNames.join(' ') },\n this.renderSection('start', startContent || []),\n this.renderSection('center', centerContent || []),\n this.renderSection('end', endContent || [])));\n }\n renderSection(key, widgetGroups) {\n let { props } = this;\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled, titleId: props.titleId }));\n }\n}\n\nclass ViewHarness extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.B {\n constructor() {\n super(...arguments);\n this.state = {\n availableWidth: null,\n };\n this.handleEl = (el) => {\n this.el = el;\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.W)(this.props.elRef, el);\n this.updateAvailableWidth();\n };\n this.handleResize = () => {\n this.updateAvailableWidth();\n };\n }\n render() {\n let { props, state } = this;\n let { aspectRatio } = props;\n let classNames = [\n 'fc-view-harness',\n (aspectRatio || props.liquid || props.height)\n ? 'fc-view-harness-active' // harness controls the height\n : 'fc-view-harness-passive', // let the view do the height\n ];\n let height = '';\n let paddingBottom = '';\n if (aspectRatio) {\n if (state.availableWidth !== null) {\n height = state.availableWidth / aspectRatio;\n }\n else {\n // while waiting to know availableWidth, we can't set height to *zero*\n // because will cause lots of unnecessary scrollbars within scrollgrid.\n // BETTER: don't start rendering ANYTHING yet until we know container width\n // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)\n paddingBottom = `${(1 / aspectRatio) * 100}%`;\n }\n }\n else {\n height = props.height || '';\n }\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { \"aria-labelledby\": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));\n }\n componentDidMount() {\n this.context.addResizeHandler(this.handleResize);\n }\n componentWillUnmount() {\n this.context.removeResizeHandler(this.handleResize);\n }\n updateAvailableWidth() {\n if (this.el && // needed. but why?\n this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth\n ) {\n this.setState({ availableWidth: this.el.offsetWidth });\n }\n }\n}\n\n/*\nDetects when the user clicks on an event within a DateComponent\n*/\nclass EventClicking extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.X {\n constructor(settings) {\n super(settings);\n this.handleSegClick = (ev, segEl) => {\n let { component } = this;\n let { context } = component;\n let seg = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.Y)(segEl);\n if (seg && // might be the <div> surrounding the more link\n component.isValidSegDownEl(ev.target)) {\n // our way to simulate a link click for elements that can't be <a> tags\n // grab before trigger fired in case trigger trashes DOM thru rerendering\n let hasUrlContainer = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.Z)(ev.target, '.fc-event-forced-url');\n let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';\n context.emitter.trigger('eventClick', {\n el: segEl,\n event: new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__._(component.context, seg.eventRange.def, seg.eventRange.instance),\n jsEvent: ev,\n view: context.viewApi,\n });\n if (url && !ev.defaultPrevented) {\n window.location.href = url;\n }\n }\n };\n this.destroy = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.$)(settings.el, 'click', '.fc-event', // on both fg and bg events\n this.handleSegClick);\n }\n}\n\n/*\nTriggers events and adds/removes core classNames when the user's pointer\nenters/leaves event-elements of a component.\n*/\nclass EventHovering extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.X {\n constructor(settings) {\n super(settings);\n // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it\n this.handleEventElRemove = (el) => {\n if (el === this.currentSegEl) {\n this.handleSegLeave(null, this.currentSegEl);\n }\n };\n this.handleSegEnter = (ev, segEl) => {\n if ((0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.Y)(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper\n this.currentSegEl = segEl;\n this.triggerEvent('eventMouseEnter', ev, segEl);\n }\n };\n this.handleSegLeave = (ev, segEl) => {\n if (this.currentSegEl) {\n this.currentSegEl = null;\n this.triggerEvent('eventMouseLeave', ev, segEl);\n }\n };\n this.removeHoverListeners = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a0)(settings.el, '.fc-event', // on both fg and bg events\n this.handleSegEnter, this.handleSegLeave);\n }\n destroy() {\n this.removeHoverListeners();\n }\n triggerEvent(publicEvName, ev, segEl) {\n let { component } = this;\n let { context } = component;\n let seg = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.Y)(segEl);\n if (!ev || component.isValidSegDownEl(ev.target)) {\n context.emitter.trigger(publicEvName, {\n el: segEl,\n event: new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__._(context, seg.eventRange.def, seg.eventRange.instance),\n jsEvent: ev,\n view: context.viewApi,\n });\n }\n }\n}\n\nclass CalendarContent extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a1 {\n constructor() {\n super(...arguments);\n this.buildViewContext = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a2);\n this.buildViewPropTransformers = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildViewPropTransformers);\n this.buildToolbarProps = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildToolbarProps);\n this.headerRef = (0,preact__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.footerRef = (0,preact__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.interactionsStore = {};\n // eslint-disable-next-line\n this.state = {\n viewLabelId: (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a3)(),\n };\n // Component Registration\n // -----------------------------------------------------------------------------------------------------------------\n this.registerInteractiveComponent = (component, settingsInput) => {\n let settings = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a4)(component, settingsInput);\n let DEFAULT_INTERACTIONS = [\n EventClicking,\n EventHovering,\n ];\n let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);\n let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));\n this.interactionsStore[component.uid] = interactions;\n _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a5[component.uid] = settings;\n };\n this.unregisterInteractiveComponent = (component) => {\n let listeners = this.interactionsStore[component.uid];\n if (listeners) {\n for (let listener of listeners) {\n listener.destroy();\n }\n delete this.interactionsStore[component.uid];\n }\n delete _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a5[component.uid];\n };\n // Resizing\n // -----------------------------------------------------------------------------------------------------------------\n this.resizeRunner = new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.D(() => {\n this.props.emitter.trigger('_resize', true); // should window resizes be considered \"forced\" ?\n this.props.emitter.trigger('windowResize', { view: this.props.viewApi });\n });\n this.handleWindowResize = (ev) => {\n let { options } = this.props;\n if (options.handleWindowResize &&\n ev.target === window // avoid jqui events\n ) {\n this.resizeRunner.request(options.windowResizeDelay);\n }\n };\n }\n /*\n renders INSIDE of an outer div\n */\n render() {\n let { props } = this;\n let { toolbarConfig, options } = props;\n let viewVGrow = false;\n let viewHeight = '';\n let viewAspectRatio;\n if (props.isHeightAuto || props.forPrint) {\n viewHeight = '';\n }\n else if (options.height != null) {\n viewVGrow = true;\n }\n else if (options.contentHeight != null) {\n viewHeight = options.contentHeight;\n }\n else {\n viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall\n }\n let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.nowManager, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);\n let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)\n ? this.state.viewLabelId\n : undefined;\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.V.Provider, { value: viewContext },\n (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a6, { unit: \"day\" }, (nowDate) => {\n let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, nowDate, props.viewTitle);\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(preact__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n toolbarConfig.header && ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: \"fc-header-toolbar\", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),\n (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(ViewHarness, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },\n this.renderView(props),\n this.buildAppendContent()),\n toolbarConfig.footer && ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: \"fc-footer-toolbar\", model: toolbarConfig.footer, titleId: \"\" }, toolbarProps)))));\n })));\n }\n componentDidMount() {\n let { props } = this;\n this.calendarInteractions = props.pluginHooks.calendarInteractions\n .map((CalendarInteractionClass) => new CalendarInteractionClass(props));\n window.addEventListener('resize', this.handleWindowResize);\n let { propSetHandlers } = props.pluginHooks;\n for (let propName in propSetHandlers) {\n propSetHandlers[propName](props[propName], props);\n }\n }\n componentDidUpdate(prevProps) {\n let { props } = this;\n let { propSetHandlers } = props.pluginHooks;\n for (let propName in propSetHandlers) {\n if (props[propName] !== prevProps[propName]) {\n propSetHandlers[propName](props[propName], props);\n }\n }\n }\n componentWillUnmount() {\n window.removeEventListener('resize', this.handleWindowResize);\n this.resizeRunner.clear();\n for (let interaction of this.calendarInteractions) {\n interaction.destroy();\n }\n this.props.emitter.trigger('_unmount');\n }\n buildAppendContent() {\n let { props } = this;\n let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));\n return (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(preact__WEBPACK_IMPORTED_MODULE_1__.Fragment, {}, ...children);\n }\n renderView(props) {\n let { pluginHooks } = props;\n let { viewSpec } = props;\n let viewProps = {\n dateProfile: props.dateProfile,\n businessHours: props.businessHours,\n eventStore: props.renderableEventStore,\n eventUiBases: props.eventUiBases,\n dateSelection: props.dateSelection,\n eventSelection: props.eventSelection,\n eventDrag: props.eventDrag,\n eventResize: props.eventResize,\n isHeightAuto: props.isHeightAuto,\n forPrint: props.forPrint,\n };\n let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);\n for (let transformer of transformers) {\n Object.assign(viewProps, transformer.transform(viewProps, props));\n }\n let ViewComponent = viewSpec.component;\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(ViewComponent, Object.assign({}, viewProps)));\n }\n}\nfunction buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {\n // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid\n let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason\n let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);\n let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);\n return {\n title,\n activeButton: viewSpec.type,\n navUnit: viewSpec.singleUnit,\n isTodayEnabled: todayInfo.isValid && !(0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.G)(dateProfile.currentRange, now),\n isPrevEnabled: prevInfo.isValid,\n isNextEnabled: nextInfo.isValid,\n };\n}\n// Plugin\n// -----------------------------------------------------------------------------------------------------------------\nfunction buildViewPropTransformers(theClasses) {\n return theClasses.map((TheClass) => new TheClass());\n}\n\nclass Calendar extends _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a7 {\n constructor(el, optionOverrides = {}) {\n super();\n this.isRendering = false;\n this.isRendered = false;\n this.currentClassNames = [];\n this.customContentRenderId = 0;\n this.handleAction = (action) => {\n // actions we know we want to render immediately\n switch (action.type) {\n case 'SET_EVENT_DRAG':\n case 'SET_EVENT_RESIZE':\n this.renderRunner.tryDrain();\n }\n };\n this.handleData = (data) => {\n this.currentData = data;\n this.renderRunner.request(data.calendarOptions.rerenderDelay);\n };\n this.handleRenderRequest = () => {\n if (this.isRendering) {\n this.isRendered = true;\n let { currentData } = this;\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a8)(() => {\n (0,preact__WEBPACK_IMPORTED_MODULE_1__.render)((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a9, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {\n this.setClassNames(classNames);\n this.setHeight(height);\n return ((0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.aa.Provider, { value: this.customContentRenderId },\n (0,preact__WEBPACK_IMPORTED_MODULE_1__.createElement)(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));\n }), this.el);\n });\n }\n else if (this.isRendered) {\n this.isRendered = false;\n (0,preact__WEBPACK_IMPORTED_MODULE_1__.render)(null, this.el);\n this.setClassNames([]);\n this.setHeight('');\n }\n };\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.ab)(el);\n this.el = el;\n this.renderRunner = new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.D(this.handleRenderRequest);\n new CalendarDataManager({\n optionOverrides,\n calendarApi: this,\n onAction: this.handleAction,\n onData: this.handleData,\n });\n }\n render() {\n let wasRendering = this.isRendering;\n if (!wasRendering) {\n this.isRendering = true;\n }\n else {\n this.customContentRenderId += 1;\n }\n this.renderRunner.request();\n if (wasRendering) {\n this.updateSize();\n }\n }\n destroy() {\n if (this.isRendering) {\n this.isRendering = false;\n this.renderRunner.request();\n }\n }\n updateSize() {\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.a8)(() => {\n super.updateSize();\n });\n }\n batchRendering(func) {\n this.renderRunner.pause('batchRendering');\n func();\n this.renderRunner.resume('batchRendering');\n }\n pauseRendering() {\n this.renderRunner.pause('pauseRendering');\n }\n resumeRendering() {\n this.renderRunner.resume('pauseRendering', true);\n }\n resetOptions(optionOverrides, changedOptionNames) {\n this.currentDataManager.resetOptions(optionOverrides, changedOptionNames);\n }\n setClassNames(classNames) {\n if (!(0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.i)(classNames, this.currentClassNames)) {\n let { classList } = this.el;\n for (let className of this.currentClassNames) {\n classList.remove(className);\n }\n for (let className of classNames) {\n classList.add(className);\n }\n this.currentClassNames = classNames;\n }\n }\n setHeight(height) {\n (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.ac)(this.el, 'height', height);\n }\n}\n\nfunction formatDate(dateInput, options = {}) {\n let dateEnv = buildDateEnv(options);\n let formatter = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.x)(options);\n let dateMeta = dateEnv.createMarkerMeta(dateInput);\n if (!dateMeta) { // TODO: warning?\n return '';\n }\n return dateEnv.format(dateMeta.marker, formatter, {\n forcedTzo: dateMeta.forcedTzo,\n });\n}\nfunction formatRange(startInput, endInput, options) {\n let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object\n let formatter = (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.x)(options);\n let startMeta = dateEnv.createMarkerMeta(startInput);\n let endMeta = dateEnv.createMarkerMeta(endInput);\n if (!startMeta || !endMeta) { // TODO: warning?\n return '';\n }\n return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {\n forcedStartTzo: startMeta.forcedTzo,\n forcedEndTzo: endMeta.forcedTzo,\n isEndExclusive: options.isEndExclusive,\n defaultSeparator: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e.defaultRangeSeparator,\n });\n}\n// TODO: more DRY and optimized\nfunction buildDateEnv(settings) {\n let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere\n return new _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.Q(Object.assign(Object.assign({ timeZone: _internal_common_js__WEBPACK_IMPORTED_MODULE_0__.e.timeZone, calendarSystem: 'gregory' }, settings), { locale }));\n}\n\n// HELPERS\n/*\nif nextDayThreshold is specified, slicing is done in an all-day fashion.\nyou can get nextDayThreshold from context.nextDayThreshold\n*/\nfunction sliceEvents(props, allDay) {\n return (0,_internal_common_js__WEBPACK_IMPORTED_MODULE_0__.ad)(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;\n}\n\nconst version = '6.1.19';\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTEyLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUFvL0M7QUFDdDdDO0FBQ007QUFDN0M7O0FBRXZCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFvRDtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLFdBQVc7QUFDckMsU0FBUztBQUNULEtBQUs7QUFDTCx1QkFBdUIsVUFBVSxZQUFZLDBCQUEwQjtBQUN2RSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLGtCQUFrQjtBQUN0QztBQUNBLG1DQUFtQyxPQUFPO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixzREFBVTtBQUMzQix3QkFBd0I7QUFDeEIsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLHNEQUFJO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRDtBQUNoRDtBQUNBLDREQUE0RDtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0Esc0RBQXNEO0FBQ3RELGtEQUFrRDtBQUNsRCxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQSw0QkFBNEI7QUFDNUIsMEJBQTBCO0FBQzFCLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0QsV0FBVztBQUM3RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLHNEQUFhLHdDQUF3QyxzREFBYTtBQUNoRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRDtBQUNBLDJEQUEyRDtBQUMzRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNERBQTREO0FBQzVEO0FBQ0Esd0RBQXdEO0FBQ3hELHNEQUFzRDtBQUN0RCx1REFBdUQ7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEIsa0RBQUs7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQ7QUFDNUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Qsb0NBQW9DLGtEQUFrRDtBQUN0SSxpREFBaUQscUNBQXFDLG9EQUFvRDtBQUMxSTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxzREFBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQSxVQUFVLG1CQUFtQjtBQUM3QjtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxrREFBYTtBQUN4RTtBQUNBO0FBQ0EsMEVBQTBFLGlCQUFpQixvQkFBb0I7QUFDL0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixxREFBYSxDQUFDLGtEQUFlLCtCQUErQixxREFBYSxDQUFDLGtEQUFnQixJQUFJLHlCQUF5QixzREFBbUIsK0RBQStELGdCQUFnQixvREFBb0QscUtBQXFLO0FBQzdjOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxzREFBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEIsd0JBQXdCLHNEQUEyQjtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RDtBQUN2RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGtEQUFvQjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QixrREFBb0I7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxzREFBYztBQUM1QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaURBQWlELDZCQUE2Qiw0Q0FBNEM7QUFDMUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0Esb0VBQW9FO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixzREFBVztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0VBQW9FO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QztBQUN6QztBQUNBO0FBQ0EsV0FBVyxzREFBVTtBQUNyQjtBQUNBO0FBQ0EseUNBQXlDLHNEQUFVO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSx1QkFBdUI7QUFDakM7QUFDQSxrQkFBa0Isc0RBQUk7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxjQUFjLFlBQVk7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMLHlDQUF5QyxrQkFBa0IsMENBQTBDO0FBQ3JHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkMsaUJBQWlCLDBDQUEwQyxrQkFBa0IsK0JBQStCLEdBQUc7QUFDNUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLHNEQUFVO0FBQ3JCO0FBQ0E7QUFDQSxtQkFBbUIsc0RBQXdCO0FBQzNDO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLHNEQUFnQjtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEVBQTRFO0FBQzVFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsc0RBQWtCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrREFBK0Q7QUFDL0Q7QUFDQTtBQUNBLDZCQUE2QixzREFBa0I7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLHNEQUFrQjtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsS0FBSztBQUNMLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsZ0JBQWdCLFVBQVU7QUFDMUI7QUFDQSxRQUFRLHNEQUFXLGlCQUFpQixzREFBeUIsd0RBQXdELFdBQVc7QUFDaEksS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsaUJBQWlCLGtEQUFRO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxnQkFBZ0IsT0FBTztBQUN2QjtBQUNBLFFBQVEsc0RBQVc7QUFDbkIsOEJBQThCLHFCQUFxQjtBQUNuRCxTQUFTO0FBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQSxVQUFVLG1CQUFtQjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixrREFBUTtBQUN4QixlQUFlLGtEQUFjO0FBQzdCLGFBQWEsa0RBQWM7QUFDM0IsY0FBYyxrREFBYztBQUM1QixnQkFBZ0Isa0RBQVE7QUFDeEIsY0FBYyxrREFBUTtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixzREFBaUI7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLGtDQUFrQyxzREFBZSxpQkFBaUIsb0RBQW9EO0FBQ3RIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQSwrQkFBK0Isc0RBQVc7QUFDMUMsb0JBQW9CLHNEQUFVO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixzREFBTztBQUMvQjtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isc0RBQU87QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixzREFBTztBQUMzQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTCxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsc0RBQWlCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QiwyQkFBMkI7QUFDbkQ7QUFDQSw2Q0FBNkM7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzRUFBc0UsRUFBRSxzREFBeUIsK0NBQStDLHVCQUF1QjtBQUN2Szs7QUFFQTtBQUNBLFVBQVUsVUFBVTtBQUNwQjtBQUNBLHFDQUFxQyxzREFBYztBQUNuRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxrREFBYTtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLHVEQUF1RCxzREFBZTtBQUN0RTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxtQkFBbUI7QUFDN0I7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGlCQUFpQixrQ0FBa0M7QUFDbkQ7QUFDQSxlQUFlLHNEQUFhO0FBQzVCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxzREFBTztBQUM3QyxrQ0FBa0Msc0RBQU87QUFDekMsMkJBQTJCLHNEQUFPO0FBQ2xDO0FBQ0EsNEJBQTRCLHNEQUFPO0FBQ25DLDBCQUEwQixzREFBTztBQUNqQyw2QkFBNkIsc0RBQU87QUFDcEMsOEJBQThCLHNEQUFPO0FBQ3JDLHlDQUF5QyxzREFBYTtBQUN0RCw0QkFBNEIsc0RBQU87QUFDbkMsZ0NBQWdDLHNEQUFhO0FBQzdDLG9DQUFvQyxzREFBTyx1QkFBdUIsa0RBQVk7QUFDOUUsaUNBQWlDLHNEQUFPO0FBQ3hDLHlDQUF5QyxzREFBYTtBQUN0RCwwQkFBMEIsc0RBQU87QUFDakM7QUFDQSwyQkFBMkIsa0RBQU87QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLHNEQUFtQjtBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUIsd0JBQXdCLHNEQUFxQjtBQUM3QyxrQ0FBa0Msc0RBQXFCO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDREQUE0RDtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRDtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrRUFBa0UsOEJBQThCO0FBQ2hHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsY0FBYyx3QkFBd0I7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLDJCQUEyQjtBQUN6QyxvR0FBb0c7QUFDcEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxzREFBbUI7QUFDaEM7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHNEQUFnQjtBQUN6Qyx3RUFBd0U7QUFDeEU7QUFDQTtBQUNBO0FBQ0EsY0FBYyxxQ0FBcUMsMENBQTBDO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDREQUE0RDtBQUM1RDtBQUNBLDhFQUE4RTtBQUM5RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQSwyRUFBMkUsK09BQStPO0FBQzFUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscURBQXFELHNEQUFxQjtBQUMxRSx5RUFBeUUsc0RBQXFCO0FBQzlGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLDJFQUEyRTtBQUN6RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGtCQUFrQixFQUFFLHNEQUFlO0FBQ2pELFlBQVksa0RBQW9CO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUlBQXFJLEVBQUUsa0RBQW9CLEdBQUcsa0RBQTBCLEdBQUcsa0RBQXdCO0FBQ25OO0FBQ0Esa0JBQWtCLHNEQUFlO0FBQ2pDLFlBQVksa0RBQW9CO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNIQUFzSCxrREFBMEI7QUFDaEo7QUFDQSxnQkFBZ0Isa0RBQTBCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxTQUFTO0FBQ2xEO0FBQ0EsY0FBYyx3QkFBd0I7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxrQkFBa0Isc0RBQWU7QUFDakMsWUFBWSxrREFBb0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkdBQTZHLEVBQUUsa0RBQW9CLEdBQUcsa0RBQTBCLEdBQUcsa0RBQXdCLEdBQUcsa0RBQW9CO0FBQ2xOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLGtEQUEwQjtBQUMzQyxvQkFBb0Isa0RBQTBCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGtEQUEwQjtBQUMvQyx3QkFBd0Isa0RBQTBCO0FBQ2xELDRFQUE0RTtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsa0RBQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVFQUF1RSxrREFBb0I7QUFDM0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxzREFBTztBQUNsQjtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsVUFBVTtBQUNwQjtBQUNBLDJCQUEyQixzREFBYTtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QseUJBQXlCLHNEQUFhO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxzREFBa0I7QUFDN0I7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLFdBQVc7QUFDbkQsc0NBQXNDLFNBQVM7QUFDL0M7QUFDQTs7QUFFQSw2QkFBNkIsa0RBQWE7QUFDMUM7QUFDQTtBQUNBLGVBQWUscURBQWEsVUFBVSwrQkFBK0I7QUFDckU7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDhEQUE4RDtBQUNoRjtBQUNBO0FBQ0EsOEJBQThCLHFEQUFhLFNBQVMsa0RBQWtEO0FBQ3RHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyxXQUFXO0FBQ3REO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixxREFBYSxhQUFhLDZNQUE2TSw4QkFBOEIscURBQWEsV0FBVyxvQ0FBb0M7QUFDL1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIscURBQWEsVUFBVSwyQkFBMkI7QUFDckU7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLGtEQUFhO0FBQ25DO0FBQ0EsY0FBYyx3QkFBd0I7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLHFEQUFhLFVBQVUsaUNBQWlDO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsZ0JBQWdCLHFEQUFhLG1CQUFtQiwwUEFBMFA7QUFDMVM7QUFDQTs7QUFFQSwwQkFBMEIsa0RBQWE7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLHNEQUFNO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxlQUFlO0FBQzdCLGNBQWMsY0FBYztBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHdCQUF3QjtBQUMzRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLHFEQUFhLFVBQVUsb0dBQW9HLHlCQUF5QjtBQUNwSztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLHFDQUFxQztBQUNqRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGtEQUFXO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixZQUFZO0FBQzlCLGtCQUFrQixVQUFVO0FBQzVCLHNCQUFzQixzREFBUTtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxzREFBYztBQUNwRDtBQUNBO0FBQ0E7QUFDQSwrQkFBK0Isa0RBQVM7QUFDeEM7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHNEQUFnQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEIsa0RBQVc7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLHNEQUFRLFdBQVc7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsdURBQXVCO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQixjQUFjLFVBQVU7QUFDeEIsa0JBQWtCLHNEQUFRO0FBQzFCO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixrREFBUztBQUNwQztBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQSw4QkFBOEIsbURBQWE7QUFDM0M7QUFDQTtBQUNBLGdDQUFnQyxzREFBTyxDQUFDLG1EQUFnQjtBQUN4RCx5Q0FBeUMsc0RBQU87QUFDaEQsaUNBQWlDLHNEQUFPO0FBQ3hDLHlCQUF5QixpREFBUztBQUNsQyx5QkFBeUIsaURBQVM7QUFDbEM7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHVEQUFjO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLHVEQUF3QjtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksbURBQXdCO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixtREFBd0I7QUFDM0M7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLGtEQUFhO0FBQzdDLHlEQUF5RDtBQUN6RCx5REFBeUQsMEJBQTBCO0FBQ25GLFNBQVM7QUFDVDtBQUNBLGtCQUFrQixVQUFVO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsY0FBYyx5QkFBeUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixxREFBYSxDQUFDLGtEQUFlLGFBQWEsb0JBQW9CO0FBQzlFLFlBQVkscURBQWEsQ0FBQyxtREFBUSxJQUFJLGFBQWE7QUFDbkQ7QUFDQSx3QkFBd0IscURBQWEsQ0FBQyw0Q0FBUTtBQUM5Qyw2Q0FBNkMscURBQWEsMEJBQTBCLDZHQUE2RztBQUNqTSxvQkFBb0IscURBQWEsZ0JBQWdCLCtGQUErRjtBQUNoSjtBQUNBO0FBQ0EsNkNBQTZDLHFEQUFhLDBCQUEwQixvR0FBb0c7QUFDeEwsYUFBYTtBQUNiO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLGtCQUFrQjtBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQSxlQUFlLHFEQUFhLENBQUMsNENBQVEsSUFBSTtBQUN6QztBQUNBO0FBQ0EsY0FBYyxjQUFjO0FBQzVCLGNBQWMsV0FBVztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLHFEQUFhLGdDQUFnQztBQUM3RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVFQUF1RTtBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsc0RBQW1CO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUIsbURBQVk7QUFDbkMsd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsY0FBYztBQUNwQyxnQkFBZ0IsdURBQVM7QUFDekIsb0JBQW9CLDhDQUFNLENBQUMscURBQWEsQ0FBQyxtREFBWSxJQUFJLDhGQUE4RjtBQUN2SjtBQUNBO0FBQ0EsZ0NBQWdDLHFEQUFhLENBQUMsbURBQVEsYUFBYSxtQ0FBbUM7QUFDdEcsNEJBQTRCLHFEQUFhLGtDQUFrQyxnREFBZ0Q7QUFDM0gscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsOENBQU07QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLHVEQUFpQjtBQUN6QjtBQUNBLGdDQUFnQyxrREFBYTtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsdURBQVM7QUFDakI7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLHNEQUFhO0FBQzFCLGtCQUFrQixZQUFZO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSx1REFBYztBQUN0QjtBQUNBOztBQUVBLDJDQUEyQztBQUMzQztBQUNBLG9CQUFvQixzREFBZTtBQUNuQztBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0Esb0ZBQW9GLEdBQUc7QUFDdkYsb0JBQW9CLHNEQUFlO0FBQ25DO0FBQ0E7QUFDQSxrQ0FBa0M7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLGtEQUFvQjtBQUM5QyxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsbUZBQW1GO0FBQ25GLGVBQWUsa0RBQU8sK0JBQStCLFVBQVUsa0RBQW9CLHNDQUFzQyxlQUFlLFFBQVE7QUFDaEo7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyx1REFBZTtBQUMxQjs7QUFFQTs7QUFFK0ciLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcmNoaXRlY3R1aS1odG1sLWZyZWUvLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL2luZGV4LmpzPzk0ZDUiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbSBhcyBtZXJnZVByb3BzLCBnIGFzIGd1aWQsIGkgYXMgaXNBcnJheXNFcXVhbCwgVCBhcyBUaGVtZSwgYSBhcyBtYXBIYXNoLCBCIGFzIEJhc2VDb21wb25lbnQsIFYgYXMgVmlld0NvbnRleHRUeXBlLCBDIGFzIENvbnRlbnRDb250YWluZXIsIGIgYXMgYnVpbGRWaWV3Q2xhc3NOYW1lcywgYyBhcyBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IsIGQgYXMgY3JlYXRlRHVyYXRpb24sIGUgYXMgQkFTRV9PUFRJT05fREVGQVVMVFMsIGYgYXMgYXJyYXlUb0hhc2gsIGggYXMgZmlsdGVySGFzaCwgaiBhcyBidWlsZEV2ZW50U291cmNlUmVmaW5lcnMsIHAgYXMgcGFyc2VFdmVudFNvdXJjZSwgayBhcyBmb3JtYXRXaXRoT3JkaW5hbHMsIHUgYXMgdW5wcm9taXNpZnksIGwgYXMgYnVpbGRSYW5nZUFwaVdpdGhUaW1lWm9uZSwgbiBhcyBpZGVudGl0eSwgciBhcyByZXF1ZXN0SnNvbiwgcyBhcyBzdWJ0cmFjdER1cmF0aW9ucywgbyBhcyBpbnRlcnNlY3RSYW5nZXMsIHEgYXMgc3RhcnRPZkRheSwgdCBhcyBhZGREYXlzLCB2IGFzIGhhc2hWYWx1ZXNUb0FycmF5LCB3IGFzIGJ1aWxkRXZlbnRBcGlzLCBEIGFzIERlbGF5ZWRSdW5uZXIsIHggYXMgY3JlYXRlRm9ybWF0dGVyLCB5IGFzIGRpZmZXaG9sZURheXMsIHogYXMgbWVtb2l6ZSwgQSBhcyBtZW1vaXplT2JqQXJnLCBFIGFzIGlzUHJvcHNFcXVhbCwgRiBhcyBFbWl0dGVyLCBHIGFzIHJhbmdlQ29udGFpbnNNYXJrZXIsIEggYXMgY3JlYXRlRW1wdHlFdmVudFN0b3JlLCBJIGFzIHJlZHVjZUV2ZW50U3RvcmUsIEogYXMgcmV6b25lRXZlbnRTdG9yZURhdGVzLCBLIGFzIG1lcmdlUmF3T3B0aW9ucywgTCBhcyBCQVNFX09QVElPTl9SRUZJTkVSUywgTSBhcyBDQUxFTkRBUl9MSVNURU5FUl9SRUZJTkVSUywgTiBhcyBDQUxFTkRBUl9PUFRJT05fUkVGSU5FUlMsIE8gYXMgQ09NUExFWF9PUFRJT05fQ09NUEFSQVRPUlMsIFAgYXMgVklFV19PUFRJT05fUkVGSU5FUlMsIFEgYXMgRGF0ZUVudiwgUiBhcyBEYXRlUHJvZmlsZUdlbmVyYXRvciwgUyBhcyBjcmVhdGVFdmVudFVpLCBVIGFzIHBhcnNlQnVzaW5lc3NIb3VycywgVyBhcyBzZXRSZWYsIFggYXMgSW50ZXJhY3Rpb24sIFkgYXMgZ2V0RWxTZWcsIFogYXMgZWxlbWVudENsb3Nlc3QsIF8gYXMgRXZlbnRJbXBsLCAkIGFzIGxpc3RlbkJ5U2VsZWN0b3IsIGEwIGFzIGxpc3RlblRvSG92ZXJCeVNlbGVjdG9yLCBhMSBhcyBQdXJlQ29tcG9uZW50LCBhMiBhcyBidWlsZFZpZXdDb250ZXh0LCBhMyBhcyBnZXRVbmlxdWVEb21JZCwgYTQgYXMgcGFyc2VJbnRlcmFjdGlvblNldHRpbmdzLCBhNSBhcyBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUsIGE2IGFzIE5vd1RpbWVyLCBhNyBhcyBDYWxlbmRhckltcGwsIGE4IGFzIGZsdXNoU3luYywgYTkgYXMgQ2FsZW5kYXJSb290LCBhYSBhcyBSZW5kZXJJZCwgYWIgYXMgZW5zdXJlRWxIYXNTdHlsZXMsIGFjIGFzIGFwcGx5U3R5bGVQcm9wLCBhZCBhcyBzbGljZUV2ZW50U3RvcmUgfSBmcm9tICcuL2ludGVybmFsLWNvbW1vbi5qcyc7XG5leHBvcnQgeyBhZSBhcyBKc29uUmVxdWVzdEVycm9yIH0gZnJvbSAnLi9pbnRlcm5hbC1jb21tb24uanMnO1xuaW1wb3J0IHsgY3JlYXRlRWxlbWVudCwgY3JlYXRlUmVmLCBGcmFnbWVudCwgcmVuZGVyIH0gZnJvbSAncHJlYWN0JztcbmltcG9ydCAncHJlYWN0L2NvbXBhdCc7XG5cbmNvbnN0IGdsb2JhbExvY2FsZXMgPSBbXTtcblxuY29uc3QgTUlOSU1BTF9SQVdfRU5fTE9DQUxFID0ge1xuICAgIGNvZGU6ICdlbicsXG4gICAgd2Vlazoge1xuICAgICAgICBkb3c6IDAsXG4gICAgICAgIGRveTogNCwgLy8gNCBkYXlzIG5lZWQgdG8gYmUgd2l0aGluIHRoZSB5ZWFyIHRvIGJlIGNvbnNpZGVyZWQgdGhlIGZpcnN0IHdlZWtcbiAgICB9LFxuICAgIGRpcmVjdGlvbjogJ2x0cicsXG4gICAgYnV0dG9uVGV4dDoge1xuICAgICAgICBwcmV2OiAncHJldicsXG4gICAgICAgIG5leHQ6ICduZXh0JyxcbiAgICAgICAgcHJldlllYXI6ICdwcmV2IHllYXInLFxuICAgICAgICBuZXh0WWVhcjogJ25leHQgeWVhcicsXG4gICAgICAgIHllYXI6ICd5ZWFyJyxcbiAgICAgICAgdG9kYXk6ICd0b2RheScsXG4gICAgICAgIG1vbnRoOiAnbW9udGgnLFxuICAgICAgICB3ZWVrOiAnd2VlaycsXG4gICAgICAgIGRheTogJ2RheScsXG4gICAgICAgIGxpc3Q6ICdsaXN0JyxcbiAgICB9LFxuICAgIHdlZWtUZXh0OiAnVycsXG4gICAgd2Vla1RleHRMb25nOiAnV2VlaycsXG4gICAgY2xvc2VIaW50OiAnQ2xvc2UnLFxuICAgIHRpbWVIaW50OiAnVGltZScsXG4gICAgZXZlbnRIaW50OiAnRXZlbnQnLFxuICAgIGFsbERheVRleHQ6ICdhbGwtZGF5JyxcbiAgICBtb3JlTGlua1RleHQ6ICdtb3JlJyxcbiAgICBub0V2ZW50c1RleHQ6ICdObyBldmVudHMgdG8gZGlzcGxheScsXG59O1xuY29uc3QgUkFXX0VOX0xPQ0FMRSA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgTUlOSU1BTF9SQVdfRU5fTE9DQUxFKSwgeyBcbiAgICAvLyBJbmNsdWRlcyB0aGluZ3Mgd2UgZG9uJ3Qgd2FudCBvdGhlciBsb2NhbGVzIHRvIGluaGVyaXQsXG4gICAgLy8gdGhpbmdzIHRoYXQgZGVyaXZlIGZyb20gb3RoZXIgdHJhbnNsYXRhYmxlIHN0cmluZ3MuXG4gICAgYnV0dG9uSGludHM6IHtcbiAgICAgICAgcHJldjogJ1ByZXZpb3VzICQwJyxcbiAgICAgICAgbmV4dDogJ05leHQgJDAnLFxuICAgICAgICB0b2RheShidXR0b25UZXh0LCB1bml0KSB7XG4gICAgICAgICAgICByZXR1cm4gKHVuaXQgPT09ICdkYXknKVxuICAgICAgICAgICAgICAgID8gJ1RvZGF5J1xuICAgICAgICAgICAgICAgIDogYFRoaXMgJHtidXR0b25UZXh0fWA7XG4gICAgICAgIH0sXG4gICAgfSwgdmlld0hpbnQ6ICckMCB2aWV3JywgbmF2TGlua0hpbnQ6ICdHbyB0byAkMCcsIG1vcmVMaW5rSGludChldmVudENudCkge1xuICAgICAgICByZXR1cm4gYFNob3cgJHtldmVudENudH0gbW9yZSBldmVudCR7ZXZlbnRDbnQgPT09IDEgPyAnJyA6ICdzJ31gO1xuICAgIH0gfSk7XG5mdW5jdGlvbiBvcmdhbml6ZVJhd0xvY2FsZXMoZXhwbGljaXRSYXdMb2NhbGVzKSB7XG4gICAgbGV0IGRlZmF1bHRDb2RlID0gZXhwbGljaXRSYXdMb2NhbGVzLmxlbmd0aCA+IDAgPyBleHBsaWNpdFJhd0xvY2FsZXNbMF0uY29kZSA6ICdlbic7XG4gICAgbGV0IGFsbFJhd0xvY2FsZXMgPSBnbG9iYWxMb2NhbGVzLmNvbmNhdChleHBsaWNpdFJhd0xvY2FsZXMpO1xuICAgIGxldCByYXdMb2NhbGVNYXAgPSB7XG4gICAgICAgIGVuOiBSQVdfRU5fTE9DQUxFLFxuICAgIH07XG4gICAgZm9yIChsZXQgcmF3TG9jYWxlIG9mIGFsbFJhd0xvY2FsZXMpIHtcbiAgICAgICAgcmF3TG9jYWxlTWFwW3Jhd0xvY2FsZS5jb2RlXSA9IHJhd0xvY2FsZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbWFwOiByYXdMb2NhbGVNYXAsXG4gICAgICAgIGRlZmF1bHRDb2RlLFxuICAgIH07XG59XG5mdW5jdGlvbiBidWlsZExvY2FsZShpbnB1dFNpbmd1bGFyLCBhdmFpbGFibGUpIHtcbiAgICBpZiAodHlwZW9mIGlucHV0U2luZ3VsYXIgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGlucHV0U2luZ3VsYXIpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUxvY2FsZShpbnB1dFNpbmd1bGFyLmNvZGUsIFtpbnB1dFNpbmd1bGFyLmNvZGVdLCBpbnB1dFNpbmd1bGFyKTtcbiAgICB9XG4gICAgcmV0dXJuIHF1ZXJ5TG9jYWxlKGlucHV0U2luZ3VsYXIsIGF2YWlsYWJsZSk7XG59XG5mdW5jdGlvbiBxdWVyeUxvY2FsZShjb2RlQXJnLCBhdmFpbGFibGUpIHtcbiAgICBsZXQgY29kZXMgPSBbXS5jb25jYXQoY29kZUFyZyB8fCBbXSk7IC8vIHdpbGwgY29udmVydCB0byBhcnJheVxuICAgIGxldCByYXcgPSBxdWVyeVJhd0xvY2FsZShjb2RlcywgYXZhaWxhYmxlKSB8fCBSQVdfRU5fTE9DQUxFO1xuICAgIHJldHVybiBwYXJzZUxvY2FsZShjb2RlQXJnLCBjb2RlcywgcmF3KTtcbn1cbmZ1bmN0aW9uIHF1ZXJ5UmF3TG9jYWxlKGNvZGVzLCBhdmFpbGFibGUpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGxldCBwYXJ0cyA9IGNvZGVzW2ldLnRvTG9jYWxlTG93ZXJDYXNlKCkuc3BsaXQoJy0nKTtcbiAgICAgICAgZm9yIChsZXQgaiA9IHBhcnRzLmxlbmd0aDsgaiA+IDA7IGogLT0gMSkge1xuICAgICAgICAgICAgbGV0IHNpbXBsZUlkID0gcGFydHMuc2xpY2UoMCwgaikuam9pbignLScpO1xuICAgICAgICAgICAgaWYgKGF2YWlsYWJsZVtzaW1wbGVJZF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXZhaWxhYmxlW3NpbXBsZUlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIHBhcnNlTG9jYWxlKGNvZGVBcmcsIGNvZGVzLCByYXcpIHtcbiAgICBsZXQgbWVyZ2VkID0gbWVyZ2VQcm9wcyhbTUlOSU1BTF9SQVdfRU5fTE9DQUxFLCByYXddLCBbJ2J1dHRvblRleHQnXSk7XG4gICAgZGVsZXRlIG1lcmdlZC5jb2RlOyAvLyBkb24ndCB3YW50IHRoaXMgcGFydCBvZiB0aGUgb3B0aW9uc1xuICAgIGxldCB7IHdlZWsgfSA9IG1lcmdlZDtcbiAgICBkZWxldGUgbWVyZ2VkLndlZWs7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29kZUFyZyxcbiAgICAgICAgY29kZXMsXG4gICAgICAgIHdlZWssXG4gICAgICAgIHNpbXBsZU51bWJlckZvcm1hdDogbmV3IEludGwuTnVtYmVyRm9ybWF0KGNvZGVBcmcpLFxuICAgICAgICBvcHRpb25zOiBtZXJnZWQsXG4gICAgfTtcbn1cblxuLy8gVE9ETzogZWFzaWVyIHdheSB0byBhZGQgbmV3IGhvb2tzPyBuZWVkIHRvIHVwZGF0ZSBhIG1pbGxpb24gdGhpbmdzXG5mdW5jdGlvbiBjcmVhdGVQbHVnaW4oaW5wdXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBpZDogZ3VpZCgpLFxuICAgICAgICBuYW1lOiBpbnB1dC5uYW1lLFxuICAgICAgICBwcmVtaXVtUmVsZWFzZURhdGU6IGlucHV0LnByZW1pdW1SZWxlYXNlRGF0ZSA/IG5ldyBEYXRlKGlucHV0LnByZW1pdW1SZWxlYXNlRGF0ZSkgOiB1bmRlZmluZWQsXG4gICAgICAgIGRlcHM6IGlucHV0LmRlcHMgfHwgW10sXG4gICAgICAgIHJlZHVjZXJzOiBpbnB1dC5yZWR1Y2VycyB8fCBbXSxcbiAgICAgICAgaXNMb2FkaW5nRnVuY3M6IGlucHV0LmlzTG9hZGluZ0Z1bmNzIHx8IFtdLFxuICAgICAgICBjb250ZXh0SW5pdDogW10uY29uY2F0KGlucHV0LmNvbnRleHRJbml0IHx8IFtdKSxcbiAgICAgICAgZXZlbnRSZWZpbmVyczogaW5wdXQuZXZlbnRSZWZpbmVycyB8fCB7fSxcbiAgICAgICAgZXZlbnREZWZNZW1iZXJBZGRlcnM6IGlucHV0LmV2ZW50RGVmTWVtYmVyQWRkZXJzIHx8IFtdLFxuICAgICAgICBldmVudFNvdXJjZVJlZmluZXJzOiBpbnB1dC5ldmVudFNvdXJjZVJlZmluZXJzIHx8IHt9LFxuICAgICAgICBpc0RyYWdnYWJsZVRyYW5zZm9ybWVyczogaW5wdXQuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBpbnB1dC5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2VycyB8fCBbXSxcbiAgICAgICAgZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzOiBpbnB1dC5ldmVudERlZk11dGF0aW9uQXBwbGllcnMgfHwgW10sXG4gICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IGlucHV0LmRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IGlucHV0LmRhdGVQb2ludFRyYW5zZm9ybXMgfHwgW10sXG4gICAgICAgIGRhdGVTcGFuVHJhbnNmb3JtczogaW5wdXQuZGF0ZVNwYW5UcmFuc2Zvcm1zIHx8IFtdLFxuICAgICAgICB2aWV3czogaW5wdXQudmlld3MgfHwge30sXG4gICAgICAgIHZpZXdQcm9wc1RyYW5zZm9ybWVyczogaW5wdXQudmlld1Byb3BzVHJhbnNmb3JtZXJzIHx8IFtdLFxuICAgICAgICBpc1Byb3BzVmFsaWQ6IGlucHV0LmlzUHJvcHNWYWxpZCB8fCBudWxsLFxuICAgICAgICBleHRlcm5hbERlZlRyYW5zZm9ybXM6IGlucHV0LmV4dGVybmFsRGVmVHJhbnNmb3JtcyB8fCBbXSxcbiAgICAgICAgdmlld0NvbnRhaW5lckFwcGVuZHM6IGlucHV0LnZpZXdDb250YWluZXJBcHBlbmRzIHx8IFtdLFxuICAgICAgICBldmVudERyb3BUcmFuc2Zvcm1lcnM6IGlucHV0LmV2ZW50RHJvcFRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgY29tcG9uZW50SW50ZXJhY3Rpb25zOiBpbnB1dC5jb21wb25lbnRJbnRlcmFjdGlvbnMgfHwgW10sXG4gICAgICAgIGNhbGVuZGFySW50ZXJhY3Rpb25zOiBpbnB1dC5jYWxlbmRhckludGVyYWN0aW9ucyB8fCBbXSxcbiAgICAgICAgdGhlbWVDbGFzc2VzOiBpbnB1dC50aGVtZUNsYXNzZXMgfHwge30sXG4gICAgICAgIGV2ZW50U291cmNlRGVmczogaW5wdXQuZXZlbnRTb3VyY2VEZWZzIHx8IFtdLFxuICAgICAgICBjbWRGb3JtYXR0ZXI6IGlucHV0LmNtZEZvcm1hdHRlcixcbiAgICAgICAgcmVjdXJyaW5nVHlwZXM6IGlucHV0LnJlY3VycmluZ1R5cGVzIHx8IFtdLFxuICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IGlucHV0Lm5hbWVkVGltZVpvbmVkSW1wbCxcbiAgICAgICAgaW5pdGlhbFZpZXc6IGlucHV0LmluaXRpYWxWaWV3IHx8ICcnLFxuICAgICAgICBlbGVtZW50RHJhZ2dpbmdJbXBsOiBpbnB1dC5lbGVtZW50RHJhZ2dpbmdJbXBsLFxuICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczogaW5wdXQub3B0aW9uQ2hhbmdlSGFuZGxlcnMgfHwge30sXG4gICAgICAgIHNjcm9sbEdyaWRJbXBsOiBpbnB1dC5zY3JvbGxHcmlkSW1wbCB8fCBudWxsLFxuICAgICAgICBsaXN0ZW5lclJlZmluZXJzOiBpbnB1dC5saXN0ZW5lclJlZmluZXJzIHx8IHt9LFxuICAgICAgICBvcHRpb25SZWZpbmVyczogaW5wdXQub3B0aW9uUmVmaW5lcnMgfHwge30sXG4gICAgICAgIHByb3BTZXRIYW5kbGVyczogaW5wdXQucHJvcFNldEhhbmRsZXJzIHx8IHt9LFxuICAgIH07XG59XG5mdW5jdGlvbiBidWlsZFBsdWdpbkhvb2tzKHBsdWdpbkRlZnMsIGdsb2JhbERlZnMpIHtcbiAgICBsZXQgY3VycmVudFBsdWdpbklkcyA9IHt9O1xuICAgIGxldCBob29rcyA9IHtcbiAgICAgICAgcHJlbWl1bVJlbGVhc2VEYXRlOiB1bmRlZmluZWQsXG4gICAgICAgIHJlZHVjZXJzOiBbXSxcbiAgICAgICAgaXNMb2FkaW5nRnVuY3M6IFtdLFxuICAgICAgICBjb250ZXh0SW5pdDogW10sXG4gICAgICAgIGV2ZW50UmVmaW5lcnM6IHt9LFxuICAgICAgICBldmVudERlZk1lbWJlckFkZGVyczogW10sXG4gICAgICAgIGV2ZW50U291cmNlUmVmaW5lcnM6IHt9LFxuICAgICAgICBpc0RyYWdnYWJsZVRyYW5zZm9ybWVyczogW10sXG4gICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBbXSxcbiAgICAgICAgZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzOiBbXSxcbiAgICAgICAgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyczogW10sXG4gICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IFtdLFxuICAgICAgICBkYXRlU3BhblRyYW5zZm9ybXM6IFtdLFxuICAgICAgICB2aWV3czoge30sXG4gICAgICAgIHZpZXdQcm9wc1RyYW5zZm9ybWVyczogW10sXG4gICAgICAgIGlzUHJvcHNWYWxpZDogbnVsbCxcbiAgICAgICAgZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zOiBbXSxcbiAgICAgICAgdmlld0NvbnRhaW5lckFwcGVuZHM6IFtdLFxuICAgICAgICBldmVudERyb3BUcmFuc2Zvcm1lcnM6IFtdLFxuICAgICAgICBjb21wb25lbnRJbnRlcmFjdGlvbnM6IFtdLFxuICAgICAgICBjYWxlbmRhckludGVyYWN0aW9uczogW10sXG4gICAgICAgIHRoZW1lQ2xhc3Nlczoge30sXG4gICAgICAgIGV2ZW50U291cmNlRGVmczogW10sXG4gICAgICAgIGNtZEZvcm1hdHRlcjogbnVsbCxcbiAgICAgICAgcmVjdXJyaW5nVHlwZXM6IFtdLFxuICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IG51bGwsXG4gICAgICAgIGluaXRpYWxWaWV3OiAnJyxcbiAgICAgICAgZWxlbWVudERyYWdnaW5nSW1wbDogbnVsbCxcbiAgICAgICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IHt9LFxuICAgICAgICBzY3JvbGxHcmlkSW1wbDogbnVsbCxcbiAgICAgICAgbGlzdGVuZXJSZWZpbmVyczoge30sXG4gICAgICAgIG9wdGlvblJlZmluZXJzOiB7fSxcbiAgICAgICAgcHJvcFNldEhhbmRsZXJzOiB7fSxcbiAgICB9O1xuICAgIGZ1bmN0aW9uIGFkZERlZnMoZGVmcykge1xuICAgICAgICBmb3IgKGxldCBkZWYgb2YgZGVmcykge1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luTmFtZSA9IGRlZi5uYW1lO1xuICAgICAgICAgICAgY29uc3QgY3VycmVudElkID0gY3VycmVudFBsdWdpbklkc1twbHVnaW5OYW1lXTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50SWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQbHVnaW5JZHNbcGx1Z2luTmFtZV0gPSBkZWYuaWQ7XG4gICAgICAgICAgICAgICAgYWRkRGVmcyhkZWYuZGVwcyk7XG4gICAgICAgICAgICAgICAgaG9va3MgPSBjb21iaW5lSG9va3MoaG9va3MsIGRlZik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjdXJyZW50SWQgIT09IGRlZi5pZCkge1xuICAgICAgICAgICAgICAgIC8vIGRpZmZlcmVudCBJRCB0aGFuIHRoZSBvbmUgYWxyZWFkeSBhZGRlZFxuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgRHVwbGljYXRlIHBsdWdpbiAnJHtwbHVnaW5OYW1lfSdgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAocGx1Z2luRGVmcykge1xuICAgICAgICBhZGREZWZzKHBsdWdpbkRlZnMpO1xuICAgIH1cbiAgICBhZGREZWZzKGdsb2JhbERlZnMpO1xuICAgIHJldHVybiBob29rcztcbn1cbmZ1bmN0aW9uIGJ1aWxkQnVpbGRQbHVnaW5Ib29rcygpIHtcbiAgICBsZXQgY3VycmVudE92ZXJyaWRlRGVmcyA9IFtdO1xuICAgIGxldCBjdXJyZW50R2xvYmFsRGVmcyA9IFtdO1xuICAgIGxldCBjdXJyZW50SG9va3M7XG4gICAgcmV0dXJuIChvdmVycmlkZURlZnMsIGdsb2JhbERlZnMpID0+IHtcbiAgICAgICAgaWYgKCFjdXJyZW50SG9va3MgfHwgIWlzQXJyYXlzRXF1YWwob3ZlcnJpZGVEZWZzLCBjdXJyZW50T3ZlcnJpZGVEZWZzKSB8fCAhaXNBcnJheXNFcXVhbChnbG9iYWxEZWZzLCBjdXJyZW50R2xvYmFsRGVmcykpIHtcbiAgICAgICAgICAgIGN1cnJlbnRIb29rcyA9IGJ1aWxkUGx1Z2luSG9va3Mob3ZlcnJpZGVEZWZzLCBnbG9iYWxEZWZzKTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50T3ZlcnJpZGVEZWZzID0gb3ZlcnJpZGVEZWZzO1xuICAgICAgICBjdXJyZW50R2xvYmFsRGVmcyA9IGdsb2JhbERlZnM7XG4gICAgICAgIHJldHVybiBjdXJyZW50SG9va3M7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGNvbWJpbmVIb29rcyhob29rczAsIGhvb2tzMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHByZW1pdW1SZWxlYXNlRGF0ZTogY29tcGFyZU9wdGlvbmFsRGF0ZXMoaG9va3MwLnByZW1pdW1SZWxlYXNlRGF0ZSwgaG9va3MxLnByZW1pdW1SZWxlYXNlRGF0ZSksXG4gICAgICAgIHJlZHVjZXJzOiBob29rczAucmVkdWNlcnMuY29uY2F0KGhvb2tzMS5yZWR1Y2VycyksXG4gICAgICAgIGlzTG9hZGluZ0Z1bmNzOiBob29rczAuaXNMb2FkaW5nRnVuY3MuY29uY2F0KGhvb2tzMS5pc0xvYWRpbmdGdW5jcyksXG4gICAgICAgIGNvbnRleHRJbml0OiBob29rczAuY29udGV4dEluaXQuY29uY2F0KGhvb2tzMS5jb250ZXh0SW5pdCksXG4gICAgICAgIGV2ZW50UmVmaW5lcnM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgaG9va3MwLmV2ZW50UmVmaW5lcnMpLCBob29rczEuZXZlbnRSZWZpbmVycyksXG4gICAgICAgIGV2ZW50RGVmTWVtYmVyQWRkZXJzOiBob29rczAuZXZlbnREZWZNZW1iZXJBZGRlcnMuY29uY2F0KGhvb2tzMS5ldmVudERlZk1lbWJlckFkZGVycyksXG4gICAgICAgIGV2ZW50U291cmNlUmVmaW5lcnM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgaG9va3MwLmV2ZW50U291cmNlUmVmaW5lcnMpLCBob29rczEuZXZlbnRTb3VyY2VSZWZpbmVycyksXG4gICAgICAgIGlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzOiBob29rczAuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnMuY29uY2F0KGhvb2tzMS5pc0RyYWdnYWJsZVRyYW5zZm9ybWVycyksXG4gICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBob29rczAuZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnMuY29uY2F0KGhvb2tzMS5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2VycyksXG4gICAgICAgIGV2ZW50RGVmTXV0YXRpb25BcHBsaWVyczogaG9va3MwLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycy5jb25jYXQoaG9va3MxLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycyksXG4gICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IGhvb2tzMC5kYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyksXG4gICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IGhvb2tzMC5kYXRlUG9pbnRUcmFuc2Zvcm1zLmNvbmNhdChob29rczEuZGF0ZVBvaW50VHJhbnNmb3JtcyksXG4gICAgICAgIGRhdGVTcGFuVHJhbnNmb3JtczogaG9va3MwLmRhdGVTcGFuVHJhbnNmb3Jtcy5jb25jYXQoaG9va3MxLmRhdGVTcGFuVHJhbnNmb3JtcyksXG4gICAgICAgIHZpZXdzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGhvb2tzMC52aWV3cyksIGhvb2tzMS52aWV3cyksXG4gICAgICAgIHZpZXdQcm9wc1RyYW5zZm9ybWVyczogaG9va3MwLnZpZXdQcm9wc1RyYW5zZm9ybWVycy5jb25jYXQoaG9va3MxLnZpZXdQcm9wc1RyYW5zZm9ybWVycyksXG4gICAgICAgIGlzUHJvcHNWYWxpZDogaG9va3MxLmlzUHJvcHNWYWxpZCB8fCBob29rczAuaXNQcm9wc1ZhbGlkLFxuICAgICAgICBleHRlcm5hbERlZlRyYW5zZm9ybXM6IGhvb2tzMC5leHRlcm5hbERlZlRyYW5zZm9ybXMuY29uY2F0KGhvb2tzMS5leHRlcm5hbERlZlRyYW5zZm9ybXMpLFxuICAgICAgICB2aWV3Q29udGFpbmVyQXBwZW5kczogaG9va3MwLnZpZXdDb250YWluZXJBcHBlbmRzLmNvbmNhdChob29rczEudmlld0NvbnRhaW5lckFwcGVuZHMpLFxuICAgICAgICBldmVudERyb3BUcmFuc2Zvcm1lcnM6IGhvb2tzMC5ldmVudERyb3BUcmFuc2Zvcm1lcnMuY29uY2F0KGhvb2tzMS5ldmVudERyb3BUcmFuc2Zvcm1lcnMpLFxuICAgICAgICBjYWxlbmRhckludGVyYWN0aW9uczogaG9va3MwLmNhbGVuZGFySW50ZXJhY3Rpb25zLmNvbmNhdChob29rczEuY2FsZW5kYXJJbnRlcmFjdGlvbnMpLFxuICAgICAgICBjb21wb25lbnRJbnRlcmFjdGlvbnM6IGhvb2tzMC5jb21wb25lbnRJbnRlcmFjdGlvbnMuY29uY2F0KGhvb2tzMS5jb21wb25lbnRJbnRlcmFjdGlvbnMpLFxuICAgICAgICB0aGVtZUNsYXNzZXM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgaG9va3MwLnRoZW1lQ2xhc3NlcyksIGhvb2tzMS50aGVtZUNsYXNzZXMpLFxuICAgICAgICBldmVudFNvdXJjZURlZnM6IGhvb2tzMC5ldmVudFNvdXJjZURlZnMuY29uY2F0KGhvb2tzMS5ldmVudFNvdXJjZURlZnMpLFxuICAgICAgICBjbWRGb3JtYXR0ZXI6IGhvb2tzMS5jbWRGb3JtYXR0ZXIgfHwgaG9va3MwLmNtZEZvcm1hdHRlcixcbiAgICAgICAgcmVjdXJyaW5nVHlwZXM6IGhvb2tzMC5yZWN1cnJpbmdUeXBlcy5jb25jYXQoaG9va3MxLnJlY3VycmluZ1R5cGVzKSxcbiAgICAgICAgbmFtZWRUaW1lWm9uZWRJbXBsOiBob29rczEubmFtZWRUaW1lWm9uZWRJbXBsIHx8IGhvb2tzMC5uYW1lZFRpbWVab25lZEltcGwsXG4gICAgICAgIGluaXRpYWxWaWV3OiBob29rczAuaW5pdGlhbFZpZXcgfHwgaG9va3MxLmluaXRpYWxWaWV3LFxuICAgICAgICBlbGVtZW50RHJhZ2dpbmdJbXBsOiBob29rczAuZWxlbWVudERyYWdnaW5nSW1wbCB8fCBob29rczEuZWxlbWVudERyYWdnaW5nSW1wbCxcbiAgICAgICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgaG9va3MwLm9wdGlvbkNoYW5nZUhhbmRsZXJzKSwgaG9va3MxLm9wdGlvbkNoYW5nZUhhbmRsZXJzKSxcbiAgICAgICAgc2Nyb2xsR3JpZEltcGw6IGhvb2tzMS5zY3JvbGxHcmlkSW1wbCB8fCBob29rczAuc2Nyb2xsR3JpZEltcGwsXG4gICAgICAgIGxpc3RlbmVyUmVmaW5lcnM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgaG9va3MwLmxpc3RlbmVyUmVmaW5lcnMpLCBob29rczEubGlzdGVuZXJSZWZpbmVycyksXG4gICAgICAgIG9wdGlvblJlZmluZXJzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGhvb2tzMC5vcHRpb25SZWZpbmVycyksIGhvb2tzMS5vcHRpb25SZWZpbmVycyksXG4gICAgICAgIHByb3BTZXRIYW5kbGVyczogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBob29rczAucHJvcFNldEhhbmRsZXJzKSwgaG9va3MxLnByb3BTZXRIYW5kbGVycyksXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGNvbXBhcmVPcHRpb25hbERhdGVzKGRhdGUwLCBkYXRlMSkge1xuICAgIGlmIChkYXRlMCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBkYXRlMTtcbiAgICB9XG4gICAgaWYgKGRhdGUxID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGRhdGUwO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IERhdGUoTWF0aC5tYXgoZGF0ZTAudmFsdWVPZigpLCBkYXRlMS52YWx1ZU9mKCkpKTtcbn1cblxuY2xhc3MgU3RhbmRhcmRUaGVtZSBleHRlbmRzIFRoZW1lIHtcbn1cblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmNsYXNzZXMgPSB7XG4gICAgcm9vdDogJ2ZjLXRoZW1lLXN0YW5kYXJkJyxcbiAgICB0YWJsZUNlbGxTaGFkZWQ6ICdmYy1jZWxsLXNoYWRlZCcsXG4gICAgYnV0dG9uR3JvdXA6ICdmYy1idXR0b24tZ3JvdXAnLFxuICAgIGJ1dHRvbjogJ2ZjLWJ1dHRvbiBmYy1idXR0b24tcHJpbWFyeScsXG4gICAgYnV0dG9uQWN0aXZlOiAnZmMtYnV0dG9uLWFjdGl2ZScsXG59O1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuYmFzZUljb25DbGFzcyA9ICdmYy1pY29uJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25DbGFzc2VzID0ge1xuICAgIGNsb3NlOiAnZmMtaWNvbi14JyxcbiAgICBwcmV2OiAnZmMtaWNvbi1jaGV2cm9uLWxlZnQnLFxuICAgIG5leHQ6ICdmYy1pY29uLWNoZXZyb24tcmlnaHQnLFxuICAgIHByZXZZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1sZWZ0JyxcbiAgICBuZXh0WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtcmlnaHQnLFxufTtcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLnJ0bEljb25DbGFzc2VzID0ge1xuICAgIHByZXY6ICdmYy1pY29uLWNoZXZyb24tcmlnaHQnLFxuICAgIG5leHQ6ICdmYy1pY29uLWNoZXZyb24tbGVmdCcsXG4gICAgcHJldlllYXI6ICdmYy1pY29uLWNoZXZyb25zLXJpZ2h0JyxcbiAgICBuZXh0WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtbGVmdCcsXG59O1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlT3B0aW9uID0gJ2J1dHRvbkljb25zJzsgLy8gVE9ETzogbWFrZSBUUy1mcmllbmRseVxuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlQ3VzdG9tQnV0dG9uT3B0aW9uID0gJ2ljb24nO1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlUHJlZml4ID0gJ2ZjLWljb24tJztcblxuZnVuY3Rpb24gY29tcGlsZVZpZXdEZWZzKGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpIHtcbiAgICBsZXQgaGFzaCA9IHt9O1xuICAgIGxldCB2aWV3VHlwZTtcbiAgICBmb3IgKHZpZXdUeXBlIGluIGRlZmF1bHRDb25maWdzKSB7XG4gICAgICAgIGVuc3VyZVZpZXdEZWYodmlld1R5cGUsIGhhc2gsIGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpO1xuICAgIH1cbiAgICBmb3IgKHZpZXdUeXBlIGluIG92ZXJyaWRlQ29uZmlncykge1xuICAgICAgICBlbnN1cmVWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICB9XG4gICAgcmV0dXJuIGhhc2g7XG59XG5mdW5jdGlvbiBlbnN1cmVWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKSB7XG4gICAgaWYgKGhhc2hbdmlld1R5cGVdKSB7XG4gICAgICAgIHJldHVybiBoYXNoW3ZpZXdUeXBlXTtcbiAgICB9XG4gICAgbGV0IHZpZXdEZWYgPSBidWlsZFZpZXdEZWYodmlld1R5cGUsIGhhc2gsIGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpO1xuICAgIGlmICh2aWV3RGVmKSB7XG4gICAgICAgIGhhc2hbdmlld1R5cGVdID0gdmlld0RlZjtcbiAgICB9XG4gICAgcmV0dXJuIHZpZXdEZWY7XG59XG5mdW5jdGlvbiBidWlsZFZpZXdEZWYodmlld1R5cGUsIGhhc2gsIGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpIHtcbiAgICBsZXQgZGVmYXVsdENvbmZpZyA9IGRlZmF1bHRDb25maWdzW3ZpZXdUeXBlXTtcbiAgICBsZXQgb3ZlcnJpZGVDb25maWcgPSBvdmVycmlkZUNvbmZpZ3Nbdmlld1R5cGVdO1xuICAgIGxldCBxdWVyeVByb3AgPSAobmFtZSkgPT4gKChkZWZhdWx0Q29uZmlnICYmIGRlZmF1bHRDb25maWdbbmFtZV0gIT09IG51bGwpID8gZGVmYXVsdENvbmZpZ1tuYW1lXSA6XG4gICAgICAgICgob3ZlcnJpZGVDb25maWcgJiYgb3ZlcnJpZGVDb25maWdbbmFtZV0gIT09IG51bGwpID8gb3ZlcnJpZGVDb25maWdbbmFtZV0gOiBudWxsKSk7XG4gICAgbGV0IHRoZUNvbXBvbmVudCA9IHF1ZXJ5UHJvcCgnY29tcG9uZW50Jyk7XG4gICAgbGV0IHN1cGVyVHlwZSA9IHF1ZXJ5UHJvcCgnc3VwZXJUeXBlJyk7XG4gICAgbGV0IHN1cGVyRGVmID0gbnVsbDtcbiAgICBpZiAoc3VwZXJUeXBlKSB7XG4gICAgICAgIGlmIChzdXBlclR5cGUgPT09IHZpZXdUeXBlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgaGF2ZSBhIGN1c3RvbSB2aWV3IHR5cGUgdGhhdCByZWZlcmVuY2VzIGl0c2VsZicpO1xuICAgICAgICB9XG4gICAgICAgIHN1cGVyRGVmID0gZW5zdXJlVmlld0RlZihzdXBlclR5cGUsIGhhc2gsIGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpO1xuICAgIH1cbiAgICBpZiAoIXRoZUNvbXBvbmVudCAmJiBzdXBlckRlZikge1xuICAgICAgICB0aGVDb21wb25lbnQgPSBzdXBlckRlZi5jb21wb25lbnQ7XG4gICAgfVxuICAgIGlmICghdGhlQ29tcG9uZW50KSB7XG4gICAgICAgIHJldHVybiBudWxsOyAvLyBkb24ndCB0aHJvdyBhIHdhcm5pbmcsIG1pZ2h0IGJlIHNldHRpbmdzIGZvciBhIHNpbmdsZS11bml0IHZpZXdcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogdmlld1R5cGUsXG4gICAgICAgIGNvbXBvbmVudDogdGhlQ29tcG9uZW50LFxuICAgICAgICBkZWZhdWx0czogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCAoc3VwZXJEZWYgPyBzdXBlckRlZi5kZWZhdWx0cyA6IHt9KSksIChkZWZhdWx0Q29uZmlnID8gZGVmYXVsdENvbmZpZy5yYXdPcHRpb25zIDoge30pKSxcbiAgICAgICAgb3ZlcnJpZGVzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIChzdXBlckRlZiA/IHN1cGVyRGVmLm92ZXJyaWRlcyA6IHt9KSksIChvdmVycmlkZUNvbmZpZyA/IG92ZXJyaWRlQ29uZmlnLnJhd09wdGlvbnMgOiB7fSkpLFxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHBhcnNlVmlld0NvbmZpZ3MoaW5wdXRzKSB7XG4gICAgcmV0dXJuIG1hcEhhc2goaW5wdXRzLCBwYXJzZVZpZXdDb25maWcpO1xufVxuZnVuY3Rpb24gcGFyc2VWaWV3Q29uZmlnKGlucHV0KSB7XG4gICAgbGV0IHJhd09wdGlvbnMgPSB0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbicgP1xuICAgICAgICB7IGNvbXBvbmVudDogaW5wdXQgfSA6XG4gICAgICAgIGlucHV0O1xuICAgIGxldCB7IGNvbXBvbmVudCB9ID0gcmF3T3B0aW9ucztcbiAgICBpZiAocmF3T3B0aW9ucy5jb250ZW50KSB7XG4gICAgICAgIC8vIFRPRE86IHJlbW92ZSBjb250ZW50L2NsYXNzTmFtZXMvZGlkTW91bnQvZXRjIGZyb20gb3B0aW9ucz9cbiAgICAgICAgY29tcG9uZW50ID0gY3JlYXRlVmlld0hvb2tDb21wb25lbnQocmF3T3B0aW9ucyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGNvbXBvbmVudCAmJiAhKGNvbXBvbmVudC5wcm90b3R5cGUgaW5zdGFuY2VvZiBCYXNlQ29tcG9uZW50KSkge1xuICAgICAgICAvLyBXSFk/OiBwZW9wbGUgd2VyZSB1c2luZyBgY29tcG9uZW50YCBwcm9wZXJ0eSBmb3IgYGNvbnRlbnRgXG4gICAgICAgIC8vIFRPRE86IGNvbnZlcmdlIG9uIG9uZSBzZXR0aW5nIG5hbWVcbiAgICAgICAgY29tcG9uZW50ID0gY3JlYXRlVmlld0hvb2tDb21wb25lbnQoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCByYXdPcHRpb25zKSwgeyBjb250ZW50OiBjb21wb25lbnQgfSkpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzdXBlclR5cGU6IHJhd09wdGlvbnMudHlwZSxcbiAgICAgICAgY29tcG9uZW50OiBjb21wb25lbnQsXG4gICAgICAgIHJhd09wdGlvbnMsIC8vIGluY2x1ZGVzIHR5cGUgYW5kIGNvbXBvbmVudCB0b28gOihcbiAgICB9O1xufVxuZnVuY3Rpb24gY3JlYXRlVmlld0hvb2tDb21wb25lbnQob3B0aW9ucykge1xuICAgIHJldHVybiAodmlld1Byb3BzKSA9PiAoY3JlYXRlRWxlbWVudChWaWV3Q29udGV4dFR5cGUuQ29uc3VtZXIsIG51bGwsIChjb250ZXh0KSA9PiAoY3JlYXRlRWxlbWVudChDb250ZW50Q29udGFpbmVyLCB7IGVsVGFnOiBcImRpdlwiLCBlbENsYXNzZXM6IGJ1aWxkVmlld0NsYXNzTmFtZXMoY29udGV4dC52aWV3U3BlYyksIHJlbmRlclByb3BzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHZpZXdQcm9wcyksIHsgbmV4dERheVRocmVzaG9sZDogY29udGV4dC5vcHRpb25zLm5leHREYXlUaHJlc2hvbGQgfSksIGdlbmVyYXRvck5hbWU6IHVuZGVmaW5lZCwgY3VzdG9tR2VuZXJhdG9yOiBvcHRpb25zLmNvbnRlbnQsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5jbGFzc05hbWVzLCBkaWRNb3VudDogb3B0aW9ucy5kaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMud2lsbFVubW91bnQgfSkpKSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVmlld1NwZWNzKGRlZmF1bHRJbnB1dHMsIG9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcywgbG9jYWxlRGVmYXVsdHMpIHtcbiAgICBsZXQgZGVmYXVsdENvbmZpZ3MgPSBwYXJzZVZpZXdDb25maWdzKGRlZmF1bHRJbnB1dHMpO1xuICAgIGxldCBvdmVycmlkZUNvbmZpZ3MgPSBwYXJzZVZpZXdDb25maWdzKG9wdGlvbk92ZXJyaWRlcy52aWV3cyk7XG4gICAgbGV0IHZpZXdEZWZzID0gY29tcGlsZVZpZXdEZWZzKGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpO1xuICAgIHJldHVybiBtYXBIYXNoKHZpZXdEZWZzLCAodmlld0RlZikgPT4gYnVpbGRWaWV3U3BlYyh2aWV3RGVmLCBvdmVycmlkZUNvbmZpZ3MsIG9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcywgbG9jYWxlRGVmYXVsdHMpKTtcbn1cbmZ1bmN0aW9uIGJ1aWxkVmlld1NwZWModmlld0RlZiwgb3ZlcnJpZGVDb25maWdzLCBvcHRpb25PdmVycmlkZXMsIGR5bmFtaWNPcHRpb25PdmVycmlkZXMsIGxvY2FsZURlZmF1bHRzKSB7XG4gICAgbGV0IGR1cmF0aW9uSW5wdXQgPSB2aWV3RGVmLm92ZXJyaWRlcy5kdXJhdGlvbiB8fFxuICAgICAgICB2aWV3RGVmLmRlZmF1bHRzLmR1cmF0aW9uIHx8XG4gICAgICAgIGR5bmFtaWNPcHRpb25PdmVycmlkZXMuZHVyYXRpb24gfHxcbiAgICAgICAgb3B0aW9uT3ZlcnJpZGVzLmR1cmF0aW9uO1xuICAgIGxldCBkdXJhdGlvbiA9IG51bGw7XG4gICAgbGV0IGR1cmF0aW9uVW5pdCA9ICcnO1xuICAgIGxldCBzaW5nbGVVbml0ID0gJyc7XG4gICAgbGV0IHNpbmdsZVVuaXRPdmVycmlkZXMgPSB7fTtcbiAgICBpZiAoZHVyYXRpb25JbnB1dCkge1xuICAgICAgICBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uQ2FjaGVkKGR1cmF0aW9uSW5wdXQpO1xuICAgICAgICBpZiAoZHVyYXRpb24pIHsgLy8gdmFsaWQ/XG4gICAgICAgICAgICBsZXQgZGVub20gPSBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZHVyYXRpb24pO1xuICAgICAgICAgICAgZHVyYXRpb25Vbml0ID0gZGVub20udW5pdDtcbiAgICAgICAgICAgIGlmIChkZW5vbS52YWx1ZSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZVVuaXQgPSBkdXJhdGlvblVuaXQ7XG4gICAgICAgICAgICAgICAgc2luZ2xlVW5pdE92ZXJyaWRlcyA9IG92ZXJyaWRlQ29uZmlnc1tkdXJhdGlvblVuaXRdID8gb3ZlcnJpZGVDb25maWdzW2R1cmF0aW9uVW5pdF0ucmF3T3B0aW9ucyA6IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGxldCBxdWVyeUJ1dHRvblRleHQgPSAob3B0aW9uc1N1YnNldCkgPT4ge1xuICAgICAgICBsZXQgYnV0dG9uVGV4dE1hcCA9IG9wdGlvbnNTdWJzZXQuYnV0dG9uVGV4dCB8fCB7fTtcbiAgICAgICAgbGV0IGJ1dHRvblRleHRLZXkgPSB2aWV3RGVmLmRlZmF1bHRzLmJ1dHRvblRleHRLZXk7XG4gICAgICAgIGlmIChidXR0b25UZXh0S2V5ICE9IG51bGwgJiYgYnV0dG9uVGV4dE1hcFtidXR0b25UZXh0S2V5XSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYnV0dG9uVGV4dE1hcFtidXR0b25UZXh0S2V5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9uVGV4dE1hcFt2aWV3RGVmLnR5cGVdICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBidXR0b25UZXh0TWFwW3ZpZXdEZWYudHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1dHRvblRleHRNYXBbc2luZ2xlVW5pdF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGJ1dHRvblRleHRNYXBbc2luZ2xlVW5pdF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBsZXQgcXVlcnlCdXR0b25UaXRsZSA9IChvcHRpb25zU3Vic2V0KSA9PiB7XG4gICAgICAgIGxldCBidXR0b25IaW50cyA9IG9wdGlvbnNTdWJzZXQuYnV0dG9uSGludHMgfHwge307XG4gICAgICAgIGxldCBidXR0b25LZXkgPSB2aWV3RGVmLmRlZmF1bHRzLmJ1dHRvblRleHRLZXk7IC8vIHVzZSBzYW1lIGtleSBhcyB0ZXh0XG4gICAgICAgIGlmIChidXR0b25LZXkgIT0gbnVsbCAmJiBidXR0b25IaW50c1tidXR0b25LZXldICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBidXR0b25IaW50c1tidXR0b25LZXldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChidXR0b25IaW50c1t2aWV3RGVmLnR5cGVdICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBidXR0b25IaW50c1t2aWV3RGVmLnR5cGVdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChidXR0b25IaW50c1tzaW5nbGVVbml0XSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYnV0dG9uSGludHNbc2luZ2xlVW5pdF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiB2aWV3RGVmLnR5cGUsXG4gICAgICAgIGNvbXBvbmVudDogdmlld0RlZi5jb21wb25lbnQsXG4gICAgICAgIGR1cmF0aW9uLFxuICAgICAgICBkdXJhdGlvblVuaXQsXG4gICAgICAgIHNpbmdsZVVuaXQsXG4gICAgICAgIG9wdGlvbkRlZmF1bHRzOiB2aWV3RGVmLmRlZmF1bHRzLFxuICAgICAgICBvcHRpb25PdmVycmlkZXM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2luZ2xlVW5pdE92ZXJyaWRlcyksIHZpZXdEZWYub3ZlcnJpZGVzKSxcbiAgICAgICAgYnV0dG9uVGV4dE92ZXJyaWRlOiBxdWVyeUJ1dHRvblRleHQoZHluYW1pY09wdGlvbk92ZXJyaWRlcykgfHxcbiAgICAgICAgICAgIHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25PdmVycmlkZXMpIHx8IC8vIGNvbnN0cnVjdG9yLXNwZWNpZmllZCBidXR0b25UZXh0IGxvb2t1cCBoYXNoIHRha2VzIHByZWNlZGVuY2VcbiAgICAgICAgICAgIHZpZXdEZWYub3ZlcnJpZGVzLmJ1dHRvblRleHQsXG4gICAgICAgIGJ1dHRvblRleHREZWZhdWx0OiBxdWVyeUJ1dHRvblRleHQobG9jYWxlRGVmYXVsdHMpIHx8XG4gICAgICAgICAgICB2aWV3RGVmLmRlZmF1bHRzLmJ1dHRvblRleHQgfHxcbiAgICAgICAgICAgIHF1ZXJ5QnV0dG9uVGV4dChCQVNFX09QVElPTl9ERUZBVUxUUykgfHxcbiAgICAgICAgICAgIHZpZXdEZWYudHlwZSxcbiAgICAgICAgLy8gbm90IERSWVxuICAgICAgICBidXR0b25UaXRsZU92ZXJyaWRlOiBxdWVyeUJ1dHRvblRpdGxlKGR5bmFtaWNPcHRpb25PdmVycmlkZXMpIHx8XG4gICAgICAgICAgICBxdWVyeUJ1dHRvblRpdGxlKG9wdGlvbk92ZXJyaWRlcykgfHxcbiAgICAgICAgICAgIHZpZXdEZWYub3ZlcnJpZGVzLmJ1dHRvbkhpbnQsXG4gICAgICAgIGJ1dHRvblRpdGxlRGVmYXVsdDogcXVlcnlCdXR0b25UaXRsZShsb2NhbGVEZWZhdWx0cykgfHxcbiAgICAgICAgICAgIHZpZXdEZWYuZGVmYXVsdHMuYnV0dG9uSGludCB8fFxuICAgICAgICAgICAgcXVlcnlCdXR0b25UaXRsZShCQVNFX09QVElPTl9ERUZBVUxUUyksXG4gICAgICAgIC8vIHdpbGwgZXZlbnR1YWxseSBmYWxsIGJhY2sgdG8gYnV0dG9uVGV4dFxuICAgIH07XG59XG4vLyBoYWNrIHRvIGdldCBtZW1vaXphdGlvbiB3b3JraW5nXG5sZXQgZHVyYXRpb25JbnB1dE1hcCA9IHt9O1xuZnVuY3Rpb24gY3JlYXRlRHVyYXRpb25DYWNoZWQoZHVyYXRpb25JbnB1dCkge1xuICAgIGxldCBqc29uID0gSlNPTi5zdHJpbmdpZnkoZHVyYXRpb25JbnB1dCk7XG4gICAgbGV0IHJlcyA9IGR1cmF0aW9uSW5wdXRNYXBbanNvbl07XG4gICAgaWYgKHJlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlcyA9IGNyZWF0ZUR1cmF0aW9uKGR1cmF0aW9uSW5wdXQpO1xuICAgICAgICBkdXJhdGlvbklucHV0TWFwW2pzb25dID0gcmVzO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiByZWR1Y2VWaWV3VHlwZSh2aWV3VHlwZSwgYWN0aW9uKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdDSEFOR0VfVklFV19UWVBFJzpcbiAgICAgICAgICAgIHZpZXdUeXBlID0gYWN0aW9uLnZpZXdUeXBlO1xuICAgIH1cbiAgICByZXR1cm4gdmlld1R5cGU7XG59XG5cbmZ1bmN0aW9uIHJlZHVjZUN1cnJlbnREYXRlKGN1cnJlbnREYXRlLCBhY3Rpb24pIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9EQVRFJzpcbiAgICAgICAgICAgIHJldHVybiBhY3Rpb24uZGF0ZU1hcmtlcjtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50RGF0ZTtcbiAgICB9XG59XG4vLyBzaG91bGQgYmUgaW5pdGlhbGl6ZWQgb25jZSBhbmQgc3RheSBjb25zdGFudFxuLy8gdGhpcyB3aWxsIGNoYW5nZSB0b29cbmZ1bmN0aW9uIGdldEluaXRpYWxEYXRlKG9wdGlvbnMsIGRhdGVFbnYsIG5vd01hbmFnZXIpIHtcbiAgICBsZXQgaW5pdGlhbERhdGVJbnB1dCA9IG9wdGlvbnMuaW5pdGlhbERhdGU7XG4gICAgLy8gY29tcHV0ZSB0aGUgaW5pdGlhbCBhbWJpZy10aW1lem9uZSBkYXRlXG4gICAgaWYgKGluaXRpYWxEYXRlSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZGF0ZUVudi5jcmVhdGVNYXJrZXIoaW5pdGlhbERhdGVJbnB1dCk7XG4gICAgfVxuICAgIHJldHVybiBub3dNYW5hZ2VyLmdldERhdGVNYXJrZXIoKTtcbn1cblxuZnVuY3Rpb24gcmVkdWNlRHluYW1pY09wdGlvbk92ZXJyaWRlcyhkeW5hbWljT3B0aW9uT3ZlcnJpZGVzLCBhY3Rpb24pIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ1NFVF9PUFRJT04nOlxuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZHluYW1pY09wdGlvbk92ZXJyaWRlcyksIHsgW2FjdGlvbi5vcHRpb25OYW1lXTogYWN0aW9uLnJhd09wdGlvblZhbHVlIH0pO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGR5bmFtaWNPcHRpb25PdmVycmlkZXM7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWR1Y2VEYXRlUHJvZmlsZShjdXJyZW50RGF0ZVByb2ZpbGUsIGFjdGlvbiwgY3VycmVudERhdGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKSB7XG4gICAgbGV0IGRwO1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnQ0hBTkdFX1ZJRVdfVFlQRSc6XG4gICAgICAgICAgICByZXR1cm4gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGQoYWN0aW9uLmRhdGVNYXJrZXIgfHwgY3VycmVudERhdGUpO1xuICAgICAgICBjYXNlICdDSEFOR0VfREFURSc6XG4gICAgICAgICAgICByZXR1cm4gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGQoYWN0aW9uLmRhdGVNYXJrZXIpO1xuICAgICAgICBjYXNlICdQUkVWJzpcbiAgICAgICAgICAgIGRwID0gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGRQcmV2KGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpO1xuICAgICAgICAgICAgaWYgKGRwLmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZHA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgICAgICBkcCA9IGRhdGVQcm9maWxlR2VuZXJhdG9yLmJ1aWxkTmV4dChjdXJyZW50RGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlKTtcbiAgICAgICAgICAgIGlmIChkcC5pc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50RGF0ZVByb2ZpbGU7XG59XG5cbmZ1bmN0aW9uIGluaXRFdmVudFNvdXJjZXMoY2FsZW5kYXJPcHRpb25zLCBkYXRlUHJvZmlsZSwgY29udGV4dCkge1xuICAgIGxldCBhY3RpdmVSYW5nZSA9IGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsO1xuICAgIHJldHVybiBhZGRTb3VyY2VzKHt9LCBwYXJzZUluaXRpYWxTb3VyY2VzKGNhbGVuZGFyT3B0aW9ucywgY29udGV4dCksIGFjdGl2ZVJhbmdlLCBjb250ZXh0KTtcbn1cbmZ1bmN0aW9uIHJlZHVjZUV2ZW50U291cmNlcyhldmVudFNvdXJjZXMsIGFjdGlvbiwgZGF0ZVByb2ZpbGUsIGNvbnRleHQpIHtcbiAgICBsZXQgYWN0aXZlUmFuZ2UgPSBkYXRlUHJvZmlsZSA/IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIDogbnVsbDsgLy8gbmVlZCB0aGlzIGNoZWNrP1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnQUREX0VWRU5UX1NPVVJDRVMnOiAvLyBhbHJlYWR5IHBhcnNlZFxuICAgICAgICAgICAgcmV0dXJuIGFkZFNvdXJjZXMoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlcywgYWN0aXZlUmFuZ2UsIGNvbnRleHQpO1xuICAgICAgICBjYXNlICdSRU1PVkVfRVZFTlRfU09VUkNFJzpcbiAgICAgICAgICAgIHJldHVybiByZW1vdmVTb3VyY2UoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlSWQpO1xuICAgICAgICBjYXNlICdQUkVWJzogLy8gVE9ETzogaG93IGRvIHdlIHRyYWNrIGFsbCBhY3Rpb25zIHRoYXQgYWZmZWN0IGRhdGVQcm9maWxlIDooXG4gICAgICAgIGNhc2UgJ05FWFQnOlxuICAgICAgICBjYXNlICdDSEFOR0VfREFURSc6XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgaWYgKGRhdGVQcm9maWxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoRGlydHlTb3VyY2VzKGV2ZW50U291cmNlcywgYWN0aXZlUmFuZ2UsIGNvbnRleHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50U291cmNlcztcbiAgICAgICAgY2FzZSAnRkVUQ0hfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgICAgICByZXR1cm4gZmV0Y2hTb3VyY2VzQnlJZHMoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlSWRzID8gLy8gd2h5IG5vIHR5cGU/XG4gICAgICAgICAgICAgICAgYXJyYXlUb0hhc2goYWN0aW9uLnNvdXJjZUlkcykgOlxuICAgICAgICAgICAgICAgIGV4Y2x1ZGVTdGF0aWNTb3VyY2VzKGV2ZW50U291cmNlcywgY29udGV4dCksIGFjdGl2ZVJhbmdlLCBhY3Rpb24uaXNSZWZldGNoIHx8IGZhbHNlLCBjb250ZXh0KTtcbiAgICAgICAgY2FzZSAnUkVDRUlWRV9FVkVOVFMnOlxuICAgICAgICBjYXNlICdSRUNFSVZFX0VWRU5UX0VSUk9SJzpcbiAgICAgICAgICAgIHJldHVybiByZWNlaXZlUmVzcG9uc2UoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlSWQsIGFjdGlvbi5mZXRjaElkLCBhY3Rpb24uZmV0Y2hSYW5nZSk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9BTExfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZXZlbnRTb3VyY2VzO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZHVjZUV2ZW50U291cmNlc05ld1RpbWVab25lKGV2ZW50U291cmNlcywgZGF0ZVByb2ZpbGUsIGNvbnRleHQpIHtcbiAgICBsZXQgYWN0aXZlUmFuZ2UgPSBkYXRlUHJvZmlsZSA/IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIDogbnVsbDsgLy8gbmVlZCB0aGlzIGNoZWNrP1xuICAgIHJldHVybiBmZXRjaFNvdXJjZXNCeUlkcyhldmVudFNvdXJjZXMsIGV4Y2x1ZGVTdGF0aWNTb3VyY2VzKGV2ZW50U291cmNlcywgY29udGV4dCksIGFjdGl2ZVJhbmdlLCB0cnVlLCBjb250ZXh0KTtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVFdmVudFNvdXJjZXNMb2FkaW5nKGV2ZW50U291cmNlcykge1xuICAgIGZvciAobGV0IHNvdXJjZUlkIGluIGV2ZW50U291cmNlcykge1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2VzW3NvdXJjZUlkXS5pc0ZldGNoaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiBhZGRTb3VyY2VzKGV2ZW50U291cmNlSGFzaCwgc291cmNlcywgZmV0Y2hSYW5nZSwgY29udGV4dCkge1xuICAgIGxldCBoYXNoID0ge307XG4gICAgZm9yIChsZXQgc291cmNlIG9mIHNvdXJjZXMpIHtcbiAgICAgICAgaGFzaFtzb3VyY2Uuc291cmNlSWRdID0gc291cmNlO1xuICAgIH1cbiAgICBpZiAoZmV0Y2hSYW5nZSkge1xuICAgICAgICBoYXNoID0gZmV0Y2hEaXJ0eVNvdXJjZXMoaGFzaCwgZmV0Y2hSYW5nZSwgY29udGV4dCk7XG4gICAgfVxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGV2ZW50U291cmNlSGFzaCksIGhhc2gpO1xufVxuZnVuY3Rpb24gcmVtb3ZlU291cmNlKGV2ZW50U291cmNlSGFzaCwgc291cmNlSWQpIHtcbiAgICByZXR1cm4gZmlsdGVySGFzaChldmVudFNvdXJjZUhhc2gsIChldmVudFNvdXJjZSkgPT4gZXZlbnRTb3VyY2Uuc291cmNlSWQgIT09IHNvdXJjZUlkKTtcbn1cbmZ1bmN0aW9uIGZldGNoRGlydHlTb3VyY2VzKHNvdXJjZUhhc2gsIGZldGNoUmFuZ2UsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gZmV0Y2hTb3VyY2VzQnlJZHMoc291cmNlSGFzaCwgZmlsdGVySGFzaChzb3VyY2VIYXNoLCAoZXZlbnRTb3VyY2UpID0+IGlzU291cmNlRGlydHkoZXZlbnRTb3VyY2UsIGZldGNoUmFuZ2UsIGNvbnRleHQpKSwgZmV0Y2hSYW5nZSwgZmFsc2UsIGNvbnRleHQpO1xufVxuZnVuY3Rpb24gaXNTb3VyY2VEaXJ0eShldmVudFNvdXJjZSwgZmV0Y2hSYW5nZSwgY29udGV4dCkge1xuICAgIGlmICghZG9lc1NvdXJjZU5lZWRSYW5nZShldmVudFNvdXJjZSwgY29udGV4dCkpIHtcbiAgICAgICAgcmV0dXJuICFldmVudFNvdXJjZS5sYXRlc3RGZXRjaElkO1xuICAgIH1cbiAgICByZXR1cm4gIWNvbnRleHQub3B0aW9ucy5sYXp5RmV0Y2hpbmcgfHxcbiAgICAgICAgIWV2ZW50U291cmNlLmZldGNoUmFuZ2UgfHxcbiAgICAgICAgZXZlbnRTb3VyY2UuaXNGZXRjaGluZyB8fCAvLyBhbHdheXMgY2FuY2VsIG91dGRhdGVkIGluLXByb2dyZXNzIGZldGNoZXNcbiAgICAgICAgZmV0Y2hSYW5nZS5zdGFydCA8IGV2ZW50U291cmNlLmZldGNoUmFuZ2Uuc3RhcnQgfHxcbiAgICAgICAgZmV0Y2hSYW5nZS5lbmQgPiBldmVudFNvdXJjZS5mZXRjaFJhbmdlLmVuZDtcbn1cbmZ1bmN0aW9uIGZldGNoU291cmNlc0J5SWRzKHByZXZTb3VyY2VzLCBzb3VyY2VJZEhhc2gsIGZldGNoUmFuZ2UsIGlzUmVmZXRjaCwgY29udGV4dCkge1xuICAgIGxldCBuZXh0U291cmNlcyA9IHt9O1xuICAgIGZvciAobGV0IHNvdXJjZUlkIGluIHByZXZTb3VyY2VzKSB7XG4gICAgICAgIGxldCBzb3VyY2UgPSBwcmV2U291cmNlc1tzb3VyY2VJZF07XG4gICAgICAgIGlmIChzb3VyY2VJZEhhc2hbc291cmNlSWRdKSB7XG4gICAgICAgICAgICBuZXh0U291cmNlc1tzb3VyY2VJZF0gPSBmZXRjaFNvdXJjZShzb3VyY2UsIGZldGNoUmFuZ2UsIGlzUmVmZXRjaCwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBuZXh0U291cmNlc1tzb3VyY2VJZF0gPSBzb3VyY2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5leHRTb3VyY2VzO1xufVxuZnVuY3Rpb24gZmV0Y2hTb3VyY2UoZXZlbnRTb3VyY2UsIGZldGNoUmFuZ2UsIGlzUmVmZXRjaCwgY29udGV4dCkge1xuICAgIGxldCB7IG9wdGlvbnMsIGNhbGVuZGFyQXBpIH0gPSBjb250ZXh0O1xuICAgIGxldCBzb3VyY2VEZWYgPSBjb250ZXh0LnBsdWdpbkhvb2tzLmV2ZW50U291cmNlRGVmc1tldmVudFNvdXJjZS5zb3VyY2VEZWZJZF07XG4gICAgbGV0IGZldGNoSWQgPSBndWlkKCk7XG4gICAgc291cmNlRGVmLmZldGNoKHtcbiAgICAgICAgZXZlbnRTb3VyY2UsXG4gICAgICAgIHJhbmdlOiBmZXRjaFJhbmdlLFxuICAgICAgICBpc1JlZmV0Y2gsXG4gICAgICAgIGNvbnRleHQsXG4gICAgfSwgKHJlcykgPT4ge1xuICAgICAgICBsZXQgeyByYXdFdmVudHMgfSA9IHJlcztcbiAgICAgICAgaWYgKG9wdGlvbnMuZXZlbnRTb3VyY2VTdWNjZXNzKSB7XG4gICAgICAgICAgICByYXdFdmVudHMgPSBvcHRpb25zLmV2ZW50U291cmNlU3VjY2Vzcy5jYWxsKGNhbGVuZGFyQXBpLCByYXdFdmVudHMsIHJlcy5yZXNwb25zZSkgfHwgcmF3RXZlbnRzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudFNvdXJjZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICByYXdFdmVudHMgPSBldmVudFNvdXJjZS5zdWNjZXNzLmNhbGwoY2FsZW5kYXJBcGksIHJhd0V2ZW50cywgcmVzLnJlc3BvbnNlKSB8fCByYXdFdmVudHM7XG4gICAgICAgIH1cbiAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVDRUlWRV9FVkVOVFMnLFxuICAgICAgICAgICAgc291cmNlSWQ6IGV2ZW50U291cmNlLnNvdXJjZUlkLFxuICAgICAgICAgICAgZmV0Y2hJZCxcbiAgICAgICAgICAgIGZldGNoUmFuZ2UsXG4gICAgICAgICAgICByYXdFdmVudHMsXG4gICAgICAgIH0pO1xuICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICBsZXQgZXJyb3JIYW5kbGVkID0gZmFsc2U7XG4gICAgICAgIGlmIChvcHRpb25zLmV2ZW50U291cmNlRmFpbHVyZSkge1xuICAgICAgICAgICAgb3B0aW9ucy5ldmVudFNvdXJjZUZhaWx1cmUuY2FsbChjYWxlbmRhckFwaSwgZXJyb3IpO1xuICAgICAgICAgICAgZXJyb3JIYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZlbnRTb3VyY2UuZmFpbHVyZSkge1xuICAgICAgICAgICAgZXZlbnRTb3VyY2UuZmFpbHVyZShlcnJvcik7XG4gICAgICAgICAgICBlcnJvckhhbmRsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZXJyb3JIYW5kbGVkKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oZXJyb3IubWVzc2FnZSwgZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1JFQ0VJVkVfRVZFTlRfRVJST1InLFxuICAgICAgICAgICAgc291cmNlSWQ6IGV2ZW50U291cmNlLnNvdXJjZUlkLFxuICAgICAgICAgICAgZmV0Y2hJZCxcbiAgICAgICAgICAgIGZldGNoUmFuZ2UsXG4gICAgICAgICAgICBlcnJvcixcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnRTb3VyY2UpLCB7IGlzRmV0Y2hpbmc6IHRydWUsIGxhdGVzdEZldGNoSWQ6IGZldGNoSWQgfSk7XG59XG5mdW5jdGlvbiByZWNlaXZlUmVzcG9uc2Uoc291cmNlSGFzaCwgc291cmNlSWQsIGZldGNoSWQsIGZldGNoUmFuZ2UpIHtcbiAgICBsZXQgZXZlbnRTb3VyY2UgPSBzb3VyY2VIYXNoW3NvdXJjZUlkXTtcbiAgICBpZiAoZXZlbnRTb3VyY2UgJiYgLy8gbm90IGFscmVhZHkgcmVtb3ZlZFxuICAgICAgICBmZXRjaElkID09PSBldmVudFNvdXJjZS5sYXRlc3RGZXRjaElkKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNvdXJjZUhhc2gpLCB7IFtzb3VyY2VJZF06IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnRTb3VyY2UpLCB7IGlzRmV0Y2hpbmc6IGZhbHNlLCBmZXRjaFJhbmdlIH0pIH0pO1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlSGFzaDtcbn1cbmZ1bmN0aW9uIGV4Y2x1ZGVTdGF0aWNTb3VyY2VzKGV2ZW50U291cmNlcywgY29udGV4dCkge1xuICAgIHJldHVybiBmaWx0ZXJIYXNoKGV2ZW50U291cmNlcywgKGV2ZW50U291cmNlKSA9PiBkb2VzU291cmNlTmVlZFJhbmdlKGV2ZW50U291cmNlLCBjb250ZXh0KSk7XG59XG5mdW5jdGlvbiBwYXJzZUluaXRpYWxTb3VyY2VzKHJhd09wdGlvbnMsIGNvbnRleHQpIHtcbiAgICBsZXQgcmVmaW5lcnMgPSBidWlsZEV2ZW50U291cmNlUmVmaW5lcnMoY29udGV4dCk7XG4gICAgbGV0IHJhd1NvdXJjZXMgPSBbXS5jb25jYXQocmF3T3B0aW9ucy5ldmVudFNvdXJjZXMgfHwgW10pO1xuICAgIGxldCBzb3VyY2VzID0gW107IC8vIHBhcnNlZFxuICAgIGlmIChyYXdPcHRpb25zLmluaXRpYWxFdmVudHMpIHtcbiAgICAgICAgcmF3U291cmNlcy51bnNoaWZ0KHJhd09wdGlvbnMuaW5pdGlhbEV2ZW50cyk7XG4gICAgfVxuICAgIGlmIChyYXdPcHRpb25zLmV2ZW50cykge1xuICAgICAgICByYXdTb3VyY2VzLnVuc2hpZnQocmF3T3B0aW9ucy5ldmVudHMpO1xuICAgIH1cbiAgICBmb3IgKGxldCByYXdTb3VyY2Ugb2YgcmF3U291cmNlcykge1xuICAgICAgICBsZXQgc291cmNlID0gcGFyc2VFdmVudFNvdXJjZShyYXdTb3VyY2UsIGNvbnRleHQsIHJlZmluZXJzKTtcbiAgICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNvdXJjZXM7XG59XG5mdW5jdGlvbiBkb2VzU291cmNlTmVlZFJhbmdlKGV2ZW50U291cmNlLCBjb250ZXh0KSB7XG4gICAgbGV0IGRlZnMgPSBjb250ZXh0LnBsdWdpbkhvb2tzLmV2ZW50U291cmNlRGVmcztcbiAgICByZXR1cm4gIWRlZnNbZXZlbnRTb3VyY2Uuc291cmNlRGVmSWRdLmlnbm9yZVJhbmdlO1xufVxuXG5mdW5jdGlvbiByZWR1Y2VEYXRlU2VsZWN0aW9uKGN1cnJlbnRTZWxlY3Rpb24sIGFjdGlvbikge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnVU5TRUxFQ1RfREFURVMnOlxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGNhc2UgJ1NFTEVDVF9EQVRFUyc6XG4gICAgICAgICAgICByZXR1cm4gYWN0aW9uLnNlbGVjdGlvbjtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50U2VsZWN0aW9uO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVkdWNlU2VsZWN0ZWRFdmVudChjdXJyZW50SW5zdGFuY2VJZCwgYWN0aW9uKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdVTlNFTEVDVF9FVkVOVCc6XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIGNhc2UgJ1NFTEVDVF9FVkVOVCc6XG4gICAgICAgICAgICByZXR1cm4gYWN0aW9uLmV2ZW50SW5zdGFuY2VJZDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50SW5zdGFuY2VJZDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlZHVjZUV2ZW50RHJhZyhjdXJyZW50RHJhZywgYWN0aW9uKSB7XG4gICAgbGV0IG5ld0RyYWc7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdVTlNFVF9FVkVOVF9EUkFHJzpcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICBjYXNlICdTRVRfRVZFTlRfRFJBRyc6XG4gICAgICAgICAgICBuZXdEcmFnID0gYWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogbmV3RHJhZy5hZmZlY3RlZEV2ZW50cyxcbiAgICAgICAgICAgICAgICBtdXRhdGVkRXZlbnRzOiBuZXdEcmFnLm11dGF0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgaXNFdmVudDogbmV3RHJhZy5pc0V2ZW50LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50RHJhZztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlZHVjZUV2ZW50UmVzaXplKGN1cnJlbnRSZXNpemUsIGFjdGlvbikge1xuICAgIGxldCBuZXdSZXNpemU7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdVTlNFVF9FVkVOVF9SRVNJWkUnOlxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGNhc2UgJ1NFVF9FVkVOVF9SRVNJWkUnOlxuICAgICAgICAgICAgbmV3UmVzaXplID0gYWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogbmV3UmVzaXplLmFmZmVjdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IG5ld1Jlc2l6ZS5tdXRhdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IG5ld1Jlc2l6ZS5pc0V2ZW50LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50UmVzaXplO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcGFyc2VUb29sYmFycyhjYWxlbmRhck9wdGlvbnMsIGNhbGVuZGFyT3B0aW9uT3ZlcnJpZGVzLCB0aGVtZSwgdmlld1NwZWNzLCBjYWxlbmRhckFwaSkge1xuICAgIGxldCBoZWFkZXIgPSBjYWxlbmRhck9wdGlvbnMuaGVhZGVyVG9vbGJhciA/IHBhcnNlVG9vbGJhcihjYWxlbmRhck9wdGlvbnMuaGVhZGVyVG9vbGJhciwgY2FsZW5kYXJPcHRpb25zLCBjYWxlbmRhck9wdGlvbk92ZXJyaWRlcywgdGhlbWUsIHZpZXdTcGVjcywgY2FsZW5kYXJBcGkpIDogbnVsbDtcbiAgICBsZXQgZm9vdGVyID0gY2FsZW5kYXJPcHRpb25zLmZvb3RlclRvb2xiYXIgPyBwYXJzZVRvb2xiYXIoY2FsZW5kYXJPcHRpb25zLmZvb3RlclRvb2xiYXIsIGNhbGVuZGFyT3B0aW9ucywgY2FsZW5kYXJPcHRpb25PdmVycmlkZXMsIHRoZW1lLCB2aWV3U3BlY3MsIGNhbGVuZGFyQXBpKSA6IG51bGw7XG4gICAgcmV0dXJuIHsgaGVhZGVyLCBmb290ZXIgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlVG9vbGJhcihzZWN0aW9uU3RySGFzaCwgY2FsZW5kYXJPcHRpb25zLCBjYWxlbmRhck9wdGlvbk92ZXJyaWRlcywgdGhlbWUsIHZpZXdTcGVjcywgY2FsZW5kYXJBcGkpIHtcbiAgICBsZXQgc2VjdGlvbldpZGdldHMgPSB7fTtcbiAgICBsZXQgdmlld3NXaXRoQnV0dG9ucyA9IFtdO1xuICAgIGxldCBoYXNUaXRsZSA9IGZhbHNlO1xuICAgIGZvciAobGV0IHNlY3Rpb25OYW1lIGluIHNlY3Rpb25TdHJIYXNoKSB7XG4gICAgICAgIGxldCBzZWN0aW9uU3RyID0gc2VjdGlvblN0ckhhc2hbc2VjdGlvbk5hbWVdO1xuICAgICAgICBsZXQgc2VjdGlvblJlcyA9IHBhcnNlU2VjdGlvbihzZWN0aW9uU3RyLCBjYWxlbmRhck9wdGlvbnMsIGNhbGVuZGFyT3B0aW9uT3ZlcnJpZGVzLCB0aGVtZSwgdmlld1NwZWNzLCBjYWxlbmRhckFwaSk7XG4gICAgICAgIHNlY3Rpb25XaWRnZXRzW3NlY3Rpb25OYW1lXSA9IHNlY3Rpb25SZXMud2lkZ2V0cztcbiAgICAgICAgdmlld3NXaXRoQnV0dG9ucy5wdXNoKC4uLnNlY3Rpb25SZXMudmlld3NXaXRoQnV0dG9ucyk7XG4gICAgICAgIGhhc1RpdGxlID0gaGFzVGl0bGUgfHwgc2VjdGlvblJlcy5oYXNUaXRsZTtcbiAgICB9XG4gICAgcmV0dXJuIHsgc2VjdGlvbldpZGdldHMsIHZpZXdzV2l0aEJ1dHRvbnMsIGhhc1RpdGxlIH07XG59XG4vKlxuQkFEOiBxdWVyeWluZyBpY29ucyBhbmQgdGV4dCBoZXJlLiBzaG91bGQgYmUgZG9uZSBhdCByZW5kZXIgdGltZVxuKi9cbmZ1bmN0aW9uIHBhcnNlU2VjdGlvbihzZWN0aW9uU3RyLCBjYWxlbmRhck9wdGlvbnMsIC8vIGRlZmF1bHRzK292ZXJyaWRlcywgdGhlbiByZWZpbmVkXG5jYWxlbmRhck9wdGlvbk92ZXJyaWRlcywgLy8gb3ZlcnJpZGVzIG9ubHkhLCB1bnJlZmluZWQgOihcbnRoZW1lLCB2aWV3U3BlY3MsIGNhbGVuZGFyQXBpKSB7XG4gICAgbGV0IGlzUnRsID0gY2FsZW5kYXJPcHRpb25zLmRpcmVjdGlvbiA9PT0gJ3J0bCc7XG4gICAgbGV0IGNhbGVuZGFyQ3VzdG9tQnV0dG9ucyA9IGNhbGVuZGFyT3B0aW9ucy5jdXN0b21CdXR0b25zIHx8IHt9O1xuICAgIGxldCBjYWxlbmRhckJ1dHRvblRleHRPdmVycmlkZXMgPSBjYWxlbmRhck9wdGlvbk92ZXJyaWRlcy5idXR0b25UZXh0IHx8IHt9O1xuICAgIGxldCBjYWxlbmRhckJ1dHRvblRleHQgPSBjYWxlbmRhck9wdGlvbnMuYnV0dG9uVGV4dCB8fCB7fTtcbiAgICBsZXQgY2FsZW5kYXJCdXR0b25IaW50T3ZlcnJpZGVzID0gY2FsZW5kYXJPcHRpb25PdmVycmlkZXMuYnV0dG9uSGludHMgfHwge307XG4gICAgbGV0IGNhbGVuZGFyQnV0dG9uSGludHMgPSBjYWxlbmRhck9wdGlvbnMuYnV0dG9uSGludHMgfHwge307XG4gICAgbGV0IHNlY3Rpb25TdWJzdHJzID0gc2VjdGlvblN0ciA/IHNlY3Rpb25TdHIuc3BsaXQoJyAnKSA6IFtdO1xuICAgIGxldCB2aWV3c1dpdGhCdXR0b25zID0gW107XG4gICAgbGV0IGhhc1RpdGxlID0gZmFsc2U7XG4gICAgbGV0IHdpZGdldHMgPSBzZWN0aW9uU3Vic3Rycy5tYXAoKGJ1dHRvbkdyb3VwU3RyKSA9PiAoYnV0dG9uR3JvdXBTdHIuc3BsaXQoJywnKS5tYXAoKGJ1dHRvbk5hbWUpID0+IHtcbiAgICAgICAgaWYgKGJ1dHRvbk5hbWUgPT09ICd0aXRsZScpIHtcbiAgICAgICAgICAgIGhhc1RpdGxlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiB7IGJ1dHRvbk5hbWUgfTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgY3VzdG9tQnV0dG9uUHJvcHM7XG4gICAgICAgIGxldCB2aWV3U3BlYztcbiAgICAgICAgbGV0IGJ1dHRvbkNsaWNrO1xuICAgICAgICBsZXQgYnV0dG9uSWNvbjsgLy8gb25seSBvbmUgb2YgdGhlc2Ugd2lsbCBiZSBzZXRcbiAgICAgICAgbGV0IGJ1dHRvblRleHQ7IC8vIFwiXG4gICAgICAgIGxldCBidXR0b25IaW50O1xuICAgICAgICAvLyBeIGZvciB0aGUgdGl0bGU9XCJcIiBhdHRyaWJ1dGUsIGZvciBhY2Nlc3NpYmlsaXR5XG4gICAgICAgIGlmICgoY3VzdG9tQnV0dG9uUHJvcHMgPSBjYWxlbmRhckN1c3RvbUJ1dHRvbnNbYnV0dG9uTmFtZV0pKSB7XG4gICAgICAgICAgICBidXR0b25DbGljayA9IChldikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjdXN0b21CdXR0b25Qcm9wcy5jbGljaykge1xuICAgICAgICAgICAgICAgICAgICBjdXN0b21CdXR0b25Qcm9wcy5jbGljay5jYWxsKGV2LnRhcmdldCwgZXYsIGV2LnRhcmdldCk7IC8vIFRPRE86IHVzZSBDYWxlbmRhciB0aGlzIGNvbnRleHQ/XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIChidXR0b25JY29uID0gdGhlbWUuZ2V0Q3VzdG9tQnV0dG9uSWNvbkNsYXNzKGN1c3RvbUJ1dHRvblByb3BzKSkgfHxcbiAgICAgICAgICAgICAgICAoYnV0dG9uSWNvbiA9IHRoZW1lLmdldEljb25DbGFzcyhidXR0b25OYW1lLCBpc1J0bCkpIHx8XG4gICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSBjdXN0b21CdXR0b25Qcm9wcy50ZXh0KTtcbiAgICAgICAgICAgIGJ1dHRvbkhpbnQgPSBjdXN0b21CdXR0b25Qcm9wcy5oaW50IHx8IGN1c3RvbUJ1dHRvblByb3BzLnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoKHZpZXdTcGVjID0gdmlld1NwZWNzW2J1dHRvbk5hbWVdKSkge1xuICAgICAgICAgICAgdmlld3NXaXRoQnV0dG9ucy5wdXNoKGJ1dHRvbk5hbWUpO1xuICAgICAgICAgICAgYnV0dG9uQ2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXJBcGkuY2hhbmdlVmlldyhidXR0b25OYW1lKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAoYnV0dG9uVGV4dCA9IHZpZXdTcGVjLmJ1dHRvblRleHRPdmVycmlkZSkgfHxcbiAgICAgICAgICAgICAgICAoYnV0dG9uSWNvbiA9IHRoZW1lLmdldEljb25DbGFzcyhidXR0b25OYW1lLCBpc1J0bCkpIHx8XG4gICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSB2aWV3U3BlYy5idXR0b25UZXh0RGVmYXVsdCk7XG4gICAgICAgICAgICBsZXQgdGV4dEZhbGxiYWNrID0gdmlld1NwZWMuYnV0dG9uVGV4dE92ZXJyaWRlIHx8XG4gICAgICAgICAgICAgICAgdmlld1NwZWMuYnV0dG9uVGV4dERlZmF1bHQ7XG4gICAgICAgICAgICBidXR0b25IaW50ID0gZm9ybWF0V2l0aE9yZGluYWxzKHZpZXdTcGVjLmJ1dHRvblRpdGxlT3ZlcnJpZGUgfHxcbiAgICAgICAgICAgICAgICB2aWV3U3BlYy5idXR0b25UaXRsZURlZmF1bHQgfHxcbiAgICAgICAgICAgICAgICBjYWxlbmRhck9wdGlvbnMudmlld0hpbnQsIFt0ZXh0RmFsbGJhY2ssIGJ1dHRvbk5hbWVdLCAvLyB2aWV3LW5hbWUgPSBidXR0b25OYW1lXG4gICAgICAgICAgICB0ZXh0RmFsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNhbGVuZGFyQXBpW2J1dHRvbk5hbWVdKSB7IC8vIGEgY2FsZW5kYXJBcGkgbWV0aG9kXG4gICAgICAgICAgICBidXR0b25DbGljayA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhckFwaVtidXR0b25OYW1lXSgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIChidXR0b25UZXh0ID0gY2FsZW5kYXJCdXR0b25UZXh0T3ZlcnJpZGVzW2J1dHRvbk5hbWVdKSB8fFxuICAgICAgICAgICAgICAgIChidXR0b25JY29uID0gdGhlbWUuZ2V0SWNvbkNsYXNzKGJ1dHRvbk5hbWUsIGlzUnRsKSkgfHxcbiAgICAgICAgICAgICAgICAoYnV0dG9uVGV4dCA9IGNhbGVuZGFyQnV0dG9uVGV4dFtidXR0b25OYW1lXSk7IC8vIGV2ZXJ5dGhpbmcgZWxzZSBpcyBjb25zaWRlcmVkIGRlZmF1bHRcbiAgICAgICAgICAgIGlmIChidXR0b25OYW1lID09PSAncHJldlllYXInIHx8IGJ1dHRvbk5hbWUgPT09ICduZXh0WWVhcicpIHtcbiAgICAgICAgICAgICAgICBsZXQgcHJldk9yTmV4dCA9IGJ1dHRvbk5hbWUgPT09ICdwcmV2WWVhcicgPyAncHJldicgOiAnbmV4dCc7XG4gICAgICAgICAgICAgICAgYnV0dG9uSGludCA9IGZvcm1hdFdpdGhPcmRpbmFscyhjYWxlbmRhckJ1dHRvbkhpbnRPdmVycmlkZXNbcHJldk9yTmV4dF0gfHxcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXJCdXR0b25IaW50c1twcmV2T3JOZXh0XSwgW1xuICAgICAgICAgICAgICAgICAgICBjYWxlbmRhckJ1dHRvblRleHQueWVhciB8fCAneWVhcicsXG4gICAgICAgICAgICAgICAgICAgICd5ZWFyJyxcbiAgICAgICAgICAgICAgICBdLCBjYWxlbmRhckJ1dHRvblRleHRbYnV0dG9uTmFtZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uSGludCA9IChuYXZVbml0KSA9PiBmb3JtYXRXaXRoT3JkaW5hbHMoY2FsZW5kYXJCdXR0b25IaW50T3ZlcnJpZGVzW2J1dHRvbk5hbWVdIHx8XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyQnV0dG9uSGludHNbYnV0dG9uTmFtZV0sIFtcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXJCdXR0b25UZXh0W25hdlVuaXRdIHx8IG5hdlVuaXQsXG4gICAgICAgICAgICAgICAgICAgIG5hdlVuaXQsXG4gICAgICAgICAgICAgICAgXSwgY2FsZW5kYXJCdXR0b25UZXh0W2J1dHRvbk5hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBidXR0b25OYW1lLCBidXR0b25DbGljaywgYnV0dG9uSWNvbiwgYnV0dG9uVGV4dCwgYnV0dG9uSGludCB9O1xuICAgIH0pKSk7XG4gICAgcmV0dXJuIHsgd2lkZ2V0cywgdmlld3NXaXRoQnV0dG9ucywgaGFzVGl0bGUgfTtcbn1cblxuLy8gYWx3YXlzIHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmlldy4gb3RoZXJ3aXNlLCBpdCdkIG5lZWQgdG8gY2hhbmdlIHZhbHVlIGV2ZXJ5IHRpbWUgZGF0ZSBjaGFuZ2VzXG5jbGFzcyBWaWV3SW1wbCB7XG4gICAgY29uc3RydWN0b3IodHlwZSwgZ2V0Q3VycmVudERhdGEsIGRhdGVFbnYpIHtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5nZXRDdXJyZW50RGF0YSA9IGdldEN1cnJlbnREYXRhO1xuICAgICAgICB0aGlzLmRhdGVFbnYgPSBkYXRlRW52O1xuICAgIH1cbiAgICBnZXQgY2FsZW5kYXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEN1cnJlbnREYXRhKCkuY2FsZW5kYXJBcGk7XG4gICAgfVxuICAgIGdldCB0aXRsZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q3VycmVudERhdGEoKS52aWV3VGl0bGU7XG4gICAgfVxuICAgIGdldCBhY3RpdmVTdGFydCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi50b0RhdGUodGhpcy5nZXRDdXJyZW50RGF0YSgpLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLnN0YXJ0KTtcbiAgICB9XG4gICAgZ2V0IGFjdGl2ZUVuZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi50b0RhdGUodGhpcy5nZXRDdXJyZW50RGF0YSgpLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLmVuZCk7XG4gICAgfVxuICAgIGdldCBjdXJyZW50U3RhcnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGVFbnYudG9EYXRlKHRoaXMuZ2V0Q3VycmVudERhdGEoKS5kYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2Uuc3RhcnQpO1xuICAgIH1cbiAgICBnZXQgY3VycmVudEVuZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi50b0RhdGUodGhpcy5nZXRDdXJyZW50RGF0YSgpLmRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5lbmQpO1xuICAgIH1cbiAgICBnZXRPcHRpb24obmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDdXJyZW50RGF0YSgpLm9wdGlvbnNbbmFtZV07IC8vIGFyZSB0aGUgdmlldy1zcGVjaWZpYyBvcHRpb25zXG4gICAgfVxufVxuXG5sZXQgZXZlbnRTb3VyY2VEZWYkMiA9IHtcbiAgICBpZ25vcmVSYW5nZTogdHJ1ZSxcbiAgICBwYXJzZU1ldGEocmVmaW5lZCkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyZWZpbmVkLmV2ZW50cykpIHtcbiAgICAgICAgICAgIHJldHVybiByZWZpbmVkLmV2ZW50cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICAgIGZldGNoKGFyZywgc3VjY2Vzc0NhbGxiYWNrKSB7XG4gICAgICAgIHN1Y2Nlc3NDYWxsYmFjayh7XG4gICAgICAgICAgICByYXdFdmVudHM6IGFyZy5ldmVudFNvdXJjZS5tZXRhLFxuICAgICAgICB9KTtcbiAgICB9LFxufTtcbmNvbnN0IGFycmF5RXZlbnRTb3VyY2VQbHVnaW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIG5hbWU6ICdhcnJheS1ldmVudC1zb3VyY2UnLFxuICAgIGV2ZW50U291cmNlRGVmczogW2V2ZW50U291cmNlRGVmJDJdLFxufSk7XG5cbmxldCBldmVudFNvdXJjZURlZiQxID0ge1xuICAgIHBhcnNlTWV0YShyZWZpbmVkKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmVmaW5lZC5ldmVudHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiByZWZpbmVkLmV2ZW50cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICAgIGZldGNoKGFyZywgc3VjY2Vzc0NhbGxiYWNrLCBlcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIGNvbnN0IHsgZGF0ZUVudiB9ID0gYXJnLmNvbnRleHQ7XG4gICAgICAgIGNvbnN0IGZ1bmMgPSBhcmcuZXZlbnRTb3VyY2UubWV0YTtcbiAgICAgICAgdW5wcm9taXNpZnkoZnVuYy5iaW5kKG51bGwsIGJ1aWxkUmFuZ2VBcGlXaXRoVGltZVpvbmUoYXJnLnJhbmdlLCBkYXRlRW52KSksIChyYXdFdmVudHMpID0+IHN1Y2Nlc3NDYWxsYmFjayh7IHJhd0V2ZW50cyB9KSwgZXJyb3JDYWxsYmFjayk7XG4gICAgfSxcbn07XG5jb25zdCBmdW5jRXZlbnRTb3VyY2VQbHVnaW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIG5hbWU6ICdmdW5jLWV2ZW50LXNvdXJjZScsXG4gICAgZXZlbnRTb3VyY2VEZWZzOiBbZXZlbnRTb3VyY2VEZWYkMV0sXG59KTtcblxuY29uc3QgSlNPTl9GRUVEX0VWRU5UX1NPVVJDRV9SRUZJTkVSUyA9IHtcbiAgICBtZXRob2Q6IFN0cmluZyxcbiAgICBleHRyYVBhcmFtczogaWRlbnRpdHksXG4gICAgc3RhcnRQYXJhbTogU3RyaW5nLFxuICAgIGVuZFBhcmFtOiBTdHJpbmcsXG4gICAgdGltZVpvbmVQYXJhbTogU3RyaW5nLFxufTtcblxubGV0IGV2ZW50U291cmNlRGVmID0ge1xuICAgIHBhcnNlTWV0YShyZWZpbmVkKSB7XG4gICAgICAgIGlmIChyZWZpbmVkLnVybCAmJiAocmVmaW5lZC5mb3JtYXQgPT09ICdqc29uJyB8fCAhcmVmaW5lZC5mb3JtYXQpKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHVybDogcmVmaW5lZC51cmwsXG4gICAgICAgICAgICAgICAgZm9ybWF0OiAnanNvbicsXG4gICAgICAgICAgICAgICAgbWV0aG9kOiAocmVmaW5lZC5tZXRob2QgfHwgJ0dFVCcpLnRvVXBwZXJDYXNlKCksXG4gICAgICAgICAgICAgICAgZXh0cmFQYXJhbXM6IHJlZmluZWQuZXh0cmFQYXJhbXMsXG4gICAgICAgICAgICAgICAgc3RhcnRQYXJhbTogcmVmaW5lZC5zdGFydFBhcmFtLFxuICAgICAgICAgICAgICAgIGVuZFBhcmFtOiByZWZpbmVkLmVuZFBhcmFtLFxuICAgICAgICAgICAgICAgIHRpbWVab25lUGFyYW06IHJlZmluZWQudGltZVpvbmVQYXJhbSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSxcbiAgICBmZXRjaChhcmcsIHN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaykge1xuICAgICAgICBjb25zdCB7IG1ldGEgfSA9IGFyZy5ldmVudFNvdXJjZTtcbiAgICAgICAgY29uc3QgcmVxdWVzdFBhcmFtcyA9IGJ1aWxkUmVxdWVzdFBhcmFtcyhtZXRhLCBhcmcucmFuZ2UsIGFyZy5jb250ZXh0KTtcbiAgICAgICAgcmVxdWVzdEpzb24obWV0YS5tZXRob2QsIG1ldGEudXJsLCByZXF1ZXN0UGFyYW1zKS50aGVuKChbcmF3RXZlbnRzLCByZXNwb25zZV0pID0+IHtcbiAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayh7IHJhd0V2ZW50cywgcmVzcG9uc2UgfSk7XG4gICAgICAgIH0sIGVycm9yQ2FsbGJhY2spO1xuICAgIH0sXG59O1xuY29uc3QganNvbkZlZWRFdmVudFNvdXJjZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgbmFtZTogJ2pzb24tZXZlbnQtc291cmNlJyxcbiAgICBldmVudFNvdXJjZVJlZmluZXJzOiBKU09OX0ZFRURfRVZFTlRfU09VUkNFX1JFRklORVJTLFxuICAgIGV2ZW50U291cmNlRGVmczogW2V2ZW50U291cmNlRGVmXSxcbn0pO1xuZnVuY3Rpb24gYnVpbGRSZXF1ZXN0UGFyYW1zKG1ldGEsIHJhbmdlLCBjb250ZXh0KSB7XG4gICAgbGV0IHsgZGF0ZUVudiwgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICBsZXQgc3RhcnRQYXJhbTtcbiAgICBsZXQgZW5kUGFyYW07XG4gICAgbGV0IHRpbWVab25lUGFyYW07XG4gICAgbGV0IGN1c3RvbVJlcXVlc3RQYXJhbXM7XG4gICAgbGV0IHBhcmFtcyA9IHt9O1xuICAgIHN0YXJ0UGFyYW0gPSBtZXRhLnN0YXJ0UGFyYW07XG4gICAgaWYgKHN0YXJ0UGFyYW0gPT0gbnVsbCkge1xuICAgICAgICBzdGFydFBhcmFtID0gb3B0aW9ucy5zdGFydFBhcmFtO1xuICAgIH1cbiAgICBlbmRQYXJhbSA9IG1ldGEuZW5kUGFyYW07XG4gICAgaWYgKGVuZFBhcmFtID09IG51bGwpIHtcbiAgICAgICAgZW5kUGFyYW0gPSBvcHRpb25zLmVuZFBhcmFtO1xuICAgIH1cbiAgICB0aW1lWm9uZVBhcmFtID0gbWV0YS50aW1lWm9uZVBhcmFtO1xuICAgIGlmICh0aW1lWm9uZVBhcmFtID09IG51bGwpIHtcbiAgICAgICAgdGltZVpvbmVQYXJhbSA9IG9wdGlvbnMudGltZVpvbmVQYXJhbTtcbiAgICB9XG4gICAgLy8gcmV0cmlldmUgYW55IG91dGJvdW5kIEdFVC9QT1NUIGRhdGEgZnJvbSB0aGUgb3B0aW9uc1xuICAgIGlmICh0eXBlb2YgbWV0YS5leHRyYVBhcmFtcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAvLyBzdXBwbGllZCBhcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGtleS92YWx1ZSBvYmplY3RcbiAgICAgICAgY3VzdG9tUmVxdWVzdFBhcmFtcyA9IG1ldGEuZXh0cmFQYXJhbXMoKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIHByb2JhYmx5IHN1cHBsaWVkIGFzIGEgc3RyYWlnaHQga2V5L3ZhbHVlIG9iamVjdFxuICAgICAgICBjdXN0b21SZXF1ZXN0UGFyYW1zID0gbWV0YS5leHRyYVBhcmFtcyB8fCB7fTtcbiAgICB9XG4gICAgT2JqZWN0LmFzc2lnbihwYXJhbXMsIGN1c3RvbVJlcXVlc3RQYXJhbXMpO1xuICAgIHBhcmFtc1tzdGFydFBhcmFtXSA9IGRhdGVFbnYuZm9ybWF0SXNvKHJhbmdlLnN0YXJ0KTtcbiAgICBwYXJhbXNbZW5kUGFyYW1dID0gZGF0ZUVudi5mb3JtYXRJc28ocmFuZ2UuZW5kKTtcbiAgICBpZiAoZGF0ZUVudi50aW1lWm9uZSAhPT0gJ2xvY2FsJykge1xuICAgICAgICBwYXJhbXNbdGltZVpvbmVQYXJhbV0gPSBkYXRlRW52LnRpbWVab25lO1xuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xufVxuXG5jb25zdCBTSU1QTEVfUkVDVVJSSU5HX1JFRklORVJTID0ge1xuICAgIGRheXNPZldlZWs6IGlkZW50aXR5LFxuICAgIHN0YXJ0VGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgZW5kVGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgZHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIHN0YXJ0UmVjdXI6IGlkZW50aXR5LFxuICAgIGVuZFJlY3VyOiBpZGVudGl0eSxcbn07XG5cbmxldCByZWN1cnJpbmcgPSB7XG4gICAgcGFyc2UocmVmaW5lZCwgZGF0ZUVudikge1xuICAgICAgICBpZiAocmVmaW5lZC5kYXlzT2ZXZWVrIHx8IHJlZmluZWQuc3RhcnRUaW1lIHx8IHJlZmluZWQuZW5kVGltZSB8fCByZWZpbmVkLnN0YXJ0UmVjdXIgfHwgcmVmaW5lZC5lbmRSZWN1cikge1xuICAgICAgICAgICAgbGV0IHJlY3VycmluZ0RhdGEgPSB7XG4gICAgICAgICAgICAgICAgZGF5c09mV2VlazogcmVmaW5lZC5kYXlzT2ZXZWVrIHx8IG51bGwsXG4gICAgICAgICAgICAgICAgc3RhcnRUaW1lOiByZWZpbmVkLnN0YXJ0VGltZSB8fCBudWxsLFxuICAgICAgICAgICAgICAgIGVuZFRpbWU6IHJlZmluZWQuZW5kVGltZSB8fCBudWxsLFxuICAgICAgICAgICAgICAgIHN0YXJ0UmVjdXI6IHJlZmluZWQuc3RhcnRSZWN1ciA/IGRhdGVFbnYuY3JlYXRlTWFya2VyKHJlZmluZWQuc3RhcnRSZWN1cikgOiBudWxsLFxuICAgICAgICAgICAgICAgIGVuZFJlY3VyOiByZWZpbmVkLmVuZFJlY3VyID8gZGF0ZUVudi5jcmVhdGVNYXJrZXIocmVmaW5lZC5lbmRSZWN1cikgOiBudWxsLFxuICAgICAgICAgICAgICAgIGRhdGVFbnYsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGV0IGR1cmF0aW9uO1xuICAgICAgICAgICAgaWYgKHJlZmluZWQuZHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IHJlZmluZWQuZHVyYXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWR1cmF0aW9uICYmIHJlZmluZWQuc3RhcnRUaW1lICYmIHJlZmluZWQuZW5kVGltZSkge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gc3VidHJhY3REdXJhdGlvbnMocmVmaW5lZC5lbmRUaW1lLCByZWZpbmVkLnN0YXJ0VGltZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFsbERheUd1ZXNzOiBCb29sZWFuKCFyZWZpbmVkLnN0YXJ0VGltZSAmJiAhcmVmaW5lZC5lbmRUaW1lKSxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICB0eXBlRGF0YTogcmVjdXJyaW5nRGF0YSwgLy8gZG9lc24ndCBuZWVkIGVuZFRpbWUgYW55bW9yZSBidXQgb2ggd2VsbFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICAgIGV4cGFuZCh0eXBlRGF0YSwgZnJhbWluZ1JhbmdlLCBkYXRlRW52KSB7XG4gICAgICAgIGxldCBjbGlwcGVkRnJhbWluZ1JhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKGZyYW1pbmdSYW5nZSwgeyBzdGFydDogdHlwZURhdGEuc3RhcnRSZWN1ciwgZW5kOiB0eXBlRGF0YS5lbmRSZWN1ciB9KTtcbiAgICAgICAgaWYgKGNsaXBwZWRGcmFtaW5nUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBleHBhbmRSYW5nZXModHlwZURhdGEuZGF5c09mV2VlaywgdHlwZURhdGEuc3RhcnRUaW1lLCB0eXBlRGF0YS5kYXRlRW52LCBkYXRlRW52LCBjbGlwcGVkRnJhbWluZ1JhbmdlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgfSxcbn07XG5jb25zdCBzaW1wbGVSZWN1cnJpbmdFdmVudHNQbHVnaW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIG5hbWU6ICdzaW1wbGUtcmVjdXJyaW5nLWV2ZW50JyxcbiAgICByZWN1cnJpbmdUeXBlczogW3JlY3VycmluZ10sXG4gICAgZXZlbnRSZWZpbmVyczogU0lNUExFX1JFQ1VSUklOR19SRUZJTkVSUyxcbn0pO1xuZnVuY3Rpb24gZXhwYW5kUmFuZ2VzKGRheXNPZldlZWssIHN0YXJ0VGltZSwgZXZlbnREYXRlRW52LCBjYWxlbmRhckRhdGVFbnYsIGZyYW1pbmdSYW5nZSkge1xuICAgIGxldCBkb3dIYXNoID0gZGF5c09mV2VlayA/IGFycmF5VG9IYXNoKGRheXNPZldlZWspIDogbnVsbDtcbiAgICBsZXQgZGF5TWFya2VyID0gc3RhcnRPZkRheShmcmFtaW5nUmFuZ2Uuc3RhcnQpO1xuICAgIGxldCBlbmRNYXJrZXIgPSBmcmFtaW5nUmFuZ2UuZW5kO1xuICAgIGxldCBpbnN0YW5jZVN0YXJ0cyA9IFtdO1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mdWxsY2FsZW5kYXIvZnVsbGNhbGVuZGFyL2lzc3Vlcy83OTM0XG4gICAgaWYgKHN0YXJ0VGltZSkge1xuICAgICAgICBpZiAoc3RhcnRUaW1lLm1pbGxpc2Vjb25kcyA8IDApIHtcbiAgICAgICAgICAgIC8vIHBvc3NpYmxlIGZvciBuZXh0LWRheSB0byBoYXZlIG5lZ2F0aXZlIGJ1c2luZXNzIGhvdXJzIHRoYXQgZ28gaW50byBjdXJyZW50IGRheVxuICAgICAgICAgICAgZW5kTWFya2VyID0gYWRkRGF5cyhlbmRNYXJrZXIsIDEpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHN0YXJ0VGltZS5taWxsaXNlY29uZHMgPj0gMTAwMCAqIDYwICogNjAgKiAyNCkge1xuICAgICAgICAgICAgLy8gcG9zc2libGUgZm9yIHByZXYtZGF5IHRvIGhhdmUgPjI0aHIgYnVzaW5lc3MgaG91cnMgdGhhdCBnbyBpbnRvIGN1cnJlbnQgZGF5XG4gICAgICAgICAgICBkYXlNYXJrZXIgPSBhZGREYXlzKGRheU1hcmtlciwgLTEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHdoaWxlIChkYXlNYXJrZXIgPCBlbmRNYXJrZXIpIHtcbiAgICAgICAgbGV0IGluc3RhbmNlU3RhcnQ7XG4gICAgICAgIC8vIGlmIGV2ZXJ5ZGF5LCBvciB0aGlzIHBhcnRpY3VsYXIgZGF5LW9mLXdlZWtcbiAgICAgICAgaWYgKCFkb3dIYXNoIHx8IGRvd0hhc2hbZGF5TWFya2VyLmdldFVUQ0RheSgpXSkge1xuICAgICAgICAgICAgaWYgKHN0YXJ0VGltZSkge1xuICAgICAgICAgICAgICAgIGluc3RhbmNlU3RhcnQgPSBjYWxlbmRhckRhdGVFbnYuYWRkKGRheU1hcmtlciwgc3RhcnRUaW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGluc3RhbmNlU3RhcnQgPSBkYXlNYXJrZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbnN0YW5jZVN0YXJ0cy5wdXNoKGNhbGVuZGFyRGF0ZUVudi5jcmVhdGVNYXJrZXIoZXZlbnREYXRlRW52LnRvRGF0ZShpbnN0YW5jZVN0YXJ0KSkpO1xuICAgICAgICB9XG4gICAgICAgIGRheU1hcmtlciA9IGFkZERheXMoZGF5TWFya2VyLCAxKTtcbiAgICB9XG4gICAgcmV0dXJuIGluc3RhbmNlU3RhcnRzO1xufVxuXG5jb25zdCBjaGFuZ2VIYW5kbGVyUGx1Z2luID0gY3JlYXRlUGx1Z2luKHtcbiAgICBuYW1lOiAnY2hhbmdlLWhhbmRsZXInLFxuICAgIG9wdGlvbkNoYW5nZUhhbmRsZXJzOiB7XG4gICAgICAgIGV2ZW50cyhldmVudHMsIGNvbnRleHQpIHtcbiAgICAgICAgICAgIGhhbmRsZUV2ZW50U291cmNlcyhbZXZlbnRzXSwgY29udGV4dCk7XG4gICAgICAgIH0sXG4gICAgICAgIGV2ZW50U291cmNlczogaGFuZGxlRXZlbnRTb3VyY2VzLFxuICAgIH0sXG59KTtcbi8qXG5CVUc6IGlmIGBldmVudGAgd2FzIHN1cHBsaWVkLCBhbGwgcHJldmlvdXNseS1naXZlbiBgZXZlbnRTb3VyY2VzYCB3aWxsIGJlIHdpcGVkIG91dFxuKi9cbmZ1bmN0aW9uIGhhbmRsZUV2ZW50U291cmNlcyhpbnB1dHMsIGNvbnRleHQpIHtcbiAgICBsZXQgdW5mb3VuZFNvdXJjZXMgPSBoYXNoVmFsdWVzVG9BcnJheShjb250ZXh0LmdldEN1cnJlbnREYXRhKCkuZXZlbnRTb3VyY2VzKTtcbiAgICBpZiAodW5mb3VuZFNvdXJjZXMubGVuZ3RoID09PSAxICYmXG4gICAgICAgIGlucHV0cy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheSh1bmZvdW5kU291cmNlc1swXS5fcmF3KSAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGlucHV0c1swXSkpIHtcbiAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVTRVRfUkFXX0VWRU5UUycsXG4gICAgICAgICAgICBzb3VyY2VJZDogdW5mb3VuZFNvdXJjZXNbMF0uc291cmNlSWQsXG4gICAgICAgICAgICByYXdFdmVudHM6IGlucHV0c1swXSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IG5ld0lucHV0cyA9IFtdO1xuICAgIGZvciAobGV0IGlucHV0IG9mIGlucHV0cykge1xuICAgICAgICBsZXQgaW5wdXRGb3VuZCA9IGZhbHNlO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHVuZm91bmRTb3VyY2VzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBpZiAodW5mb3VuZFNvdXJjZXNbaV0uX3JhdyA9PT0gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICB1bmZvdW5kU291cmNlcy5zcGxpY2UoaSwgMSk7IC8vIGRlbGV0ZVxuICAgICAgICAgICAgICAgIGlucHV0Rm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghaW5wdXRGb3VuZCkge1xuICAgICAgICAgICAgbmV3SW5wdXRzLnB1c2goaW5wdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAobGV0IHVuZm91bmRTb3VyY2Ugb2YgdW5mb3VuZFNvdXJjZXMpIHtcbiAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVNT1ZFX0VWRU5UX1NPVVJDRScsXG4gICAgICAgICAgICBzb3VyY2VJZDogdW5mb3VuZFNvdXJjZS5zb3VyY2VJZCxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGZvciAobGV0IG5ld0lucHV0IG9mIG5ld0lucHV0cykge1xuICAgICAgICBjb250ZXh0LmNhbGVuZGFyQXBpLmFkZEV2ZW50U291cmNlKG5ld0lucHV0KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZURhdGVQcm9maWxlKGRhdGVQcm9maWxlLCBjb250ZXh0KSB7XG4gICAgY29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2RhdGVzU2V0JywgT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBidWlsZFJhbmdlQXBpV2l0aFRpbWVab25lKGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBjb250ZXh0LmRhdGVFbnYpKSwgeyB2aWV3OiBjb250ZXh0LnZpZXdBcGkgfSkpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVFdmVudFN0b3JlKGV2ZW50U3RvcmUsIGNvbnRleHQpIHtcbiAgICBsZXQgeyBlbWl0dGVyIH0gPSBjb250ZXh0O1xuICAgIGlmIChlbWl0dGVyLmhhc0hhbmRsZXJzKCdldmVudHNTZXQnKSkge1xuICAgICAgICBlbWl0dGVyLnRyaWdnZXIoJ2V2ZW50c1NldCcsIGJ1aWxkRXZlbnRBcGlzKGV2ZW50U3RvcmUsIGNvbnRleHQpKTtcbiAgICB9XG59XG5cbi8qXG50aGlzIGFycmF5IGlzIGV4cG9zZWQgb24gdGhlIHJvb3QgbmFtZXNwYWNlIHNvIHRoYXQgVU1EIHBsdWdpbnMgY2FuIGFkZCB0byBpdC5cbnNlZSB0aGUgcm9sbHVwLWJ1bmRsZXMgc2NyaXB0LlxuKi9cbmNvbnN0IGdsb2JhbFBsdWdpbnMgPSBbXG4gICAgYXJyYXlFdmVudFNvdXJjZVBsdWdpbixcbiAgICBmdW5jRXZlbnRTb3VyY2VQbHVnaW4sXG4gICAganNvbkZlZWRFdmVudFNvdXJjZVBsdWdpbixcbiAgICBzaW1wbGVSZWN1cnJpbmdFdmVudHNQbHVnaW4sXG4gICAgY2hhbmdlSGFuZGxlclBsdWdpbixcbiAgICBjcmVhdGVQbHVnaW4oe1xuICAgICAgICBuYW1lOiAnbWlzYycsXG4gICAgICAgIGlzTG9hZGluZ0Z1bmNzOiBbXG4gICAgICAgICAgICAoc3RhdGUpID0+IGNvbXB1dGVFdmVudFNvdXJjZXNMb2FkaW5nKHN0YXRlLmV2ZW50U291cmNlcyksXG4gICAgICAgIF0sXG4gICAgICAgIHByb3BTZXRIYW5kbGVyczoge1xuICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IGhhbmRsZURhdGVQcm9maWxlLFxuICAgICAgICAgICAgZXZlbnRTdG9yZTogaGFuZGxlRXZlbnRTdG9yZSxcbiAgICAgICAgfSxcbiAgICB9KSxcbl07XG5cbmNsYXNzIFRhc2tSdW5uZXIge1xuICAgIGNvbnN0cnVjdG9yKHJ1blRhc2tPcHRpb24sIGRyYWluZWRPcHRpb24pIHtcbiAgICAgICAgdGhpcy5ydW5UYXNrT3B0aW9uID0gcnVuVGFza09wdGlvbjtcbiAgICAgICAgdGhpcy5kcmFpbmVkT3B0aW9uID0gZHJhaW5lZE9wdGlvbjtcbiAgICAgICAgdGhpcy5xdWV1ZSA9IFtdO1xuICAgICAgICB0aGlzLmRlbGF5ZWRSdW5uZXIgPSBuZXcgRGVsYXllZFJ1bm5lcih0aGlzLmRyYWluLmJpbmQodGhpcykpO1xuICAgIH1cbiAgICByZXF1ZXN0KHRhc2ssIGRlbGF5KSB7XG4gICAgICAgIHRoaXMucXVldWUucHVzaCh0YXNrKTtcbiAgICAgICAgdGhpcy5kZWxheWVkUnVubmVyLnJlcXVlc3QoZGVsYXkpO1xuICAgIH1cbiAgICBwYXVzZShzY29wZSkge1xuICAgICAgICB0aGlzLmRlbGF5ZWRSdW5uZXIucGF1c2Uoc2NvcGUpO1xuICAgIH1cbiAgICByZXN1bWUoc2NvcGUsIGZvcmNlKSB7XG4gICAgICAgIHRoaXMuZGVsYXllZFJ1bm5lci5yZXN1bWUoc2NvcGUsIGZvcmNlKTtcbiAgICB9XG4gICAgZHJhaW4oKSB7XG4gICAgICAgIGxldCB7IHF1ZXVlIH0gPSB0aGlzO1xuICAgICAgICB3aGlsZSAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgICAgICBsZXQgY29tcGxldGVkVGFza3MgPSBbXTtcbiAgICAgICAgICAgIGxldCB0YXNrO1xuICAgICAgICAgICAgd2hpbGUgKCh0YXNrID0gcXVldWUuc2hpZnQoKSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1blRhc2sodGFzayk7XG4gICAgICAgICAgICAgICAgY29tcGxldGVkVGFza3MucHVzaCh0YXNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZHJhaW5lZChjb21wbGV0ZWRUYXNrcyk7XG4gICAgICAgIH0gLy8ga2VlcCBnb2luZywgaW4gY2FzZSBuZXcgdGFza3Mgd2VyZSBhZGRlZCBpbiB0aGUgZHJhaW5lZCBoYW5kbGVyXG4gICAgfVxuICAgIHJ1blRhc2sodGFzaykge1xuICAgICAgICBpZiAodGhpcy5ydW5UYXNrT3B0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnJ1blRhc2tPcHRpb24odGFzayk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZHJhaW5lZChjb21wbGV0ZWRUYXNrcykge1xuICAgICAgICBpZiAodGhpcy5kcmFpbmVkT3B0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmRyYWluZWRPcHRpb24oY29tcGxldGVkVGFza3MpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBDb21wdXRlcyB3aGF0IHRoZSB0aXRsZSBhdCB0aGUgdG9wIG9mIHRoZSBjYWxlbmRhckFwaSBzaG91bGQgYmUgZm9yIHRoaXMgdmlld1xuZnVuY3Rpb24gYnVpbGRUaXRsZShkYXRlUHJvZmlsZSwgdmlld09wdGlvbnMsIGRhdGVFbnYpIHtcbiAgICBsZXQgcmFuZ2U7XG4gICAgLy8gZm9yIHZpZXdzIHRoYXQgc3BhbiBhIGxhcmdlIHVuaXQgb2YgdGltZSwgc2hvdyB0aGUgcHJvcGVyIGludGVydmFsLCBpZ25vcmluZyBzdHJheSBkYXlzIGJlZm9yZSBhbmQgYWZ0ZXJcbiAgICBpZiAoL14oeWVhcnxtb250aCkkLy50ZXN0KGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpKSB7XG4gICAgICAgIHJhbmdlID0gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gZm9yIGRheSB1bml0cyBvciBzbWFsbGVyLCB1c2UgdGhlIGFjdHVhbCBkYXkgcmFuZ2VcbiAgICAgICAgcmFuZ2UgPSBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2UocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCwgY3JlYXRlRm9ybWF0dGVyKHZpZXdPcHRpb25zLnRpdGxlRm9ybWF0IHx8IGJ1aWxkVGl0bGVGb3JtYXQoZGF0ZVByb2ZpbGUpKSwge1xuICAgICAgICBpc0VuZEV4Y2x1c2l2ZTogZGF0ZVByb2ZpbGUuaXNSYW5nZUFsbERheSxcbiAgICAgICAgZGVmYXVsdFNlcGFyYXRvcjogdmlld09wdGlvbnMudGl0bGVSYW5nZVNlcGFyYXRvcixcbiAgICB9KTtcbn1cbi8vIEdlbmVyYXRlcyB0aGUgZm9ybWF0IHN0cmluZyB0aGF0IHNob3VsZCBiZSB1c2VkIHRvIGdlbmVyYXRlIHRoZSB0aXRsZSBmb3IgdGhlIGN1cnJlbnQgZGF0ZSByYW5nZS5cbi8vIEF0dGVtcHRzIHRvIGNvbXB1dGUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgZm9ybWF0IGlmIG5vdCBleHBsaWNpdGx5IHNwZWNpZmllZCB3aXRoIGB0aXRsZUZvcm1hdGAuXG5mdW5jdGlvbiBidWlsZFRpdGxlRm9ybWF0KGRhdGVQcm9maWxlKSB7XG4gICAgbGV0IHsgY3VycmVudFJhbmdlVW5pdCB9ID0gZGF0ZVByb2ZpbGU7XG4gICAgaWYgKGN1cnJlbnRSYW5nZVVuaXQgPT09ICd5ZWFyJykge1xuICAgICAgICByZXR1cm4geyB5ZWFyOiAnbnVtZXJpYycgfTtcbiAgICB9XG4gICAgaWYgKGN1cnJlbnRSYW5nZVVuaXQgPT09ICdtb250aCcpIHtcbiAgICAgICAgcmV0dXJuIHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnIH07IC8vIGxpa2UgXCJTZXB0ZW1iZXIgMjAxNFwiXG4gICAgfVxuICAgIGxldCBkYXlzID0gZGlmZldob2xlRGF5cyhkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2Uuc3RhcnQsIGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5lbmQpO1xuICAgIGlmIChkYXlzICE9PSBudWxsICYmIGRheXMgPiAxKSB7XG4gICAgICAgIC8vIG11bHRpLWRheSByYW5nZS4gc2hvcnRlciwgbGlrZSBcIlNlcCA5IC0gMTAgMjAxNFwiXG4gICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdzaG9ydCcsIGRheTogJ251bWVyaWMnIH07XG4gICAgfVxuICAgIC8vIG9uZSBkYXkuIGxvbmdlciwgbGlrZSBcIlNlcHRlbWJlciA5IDIwMTRcIlxuICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdsb25nJywgZGF5OiAnbnVtZXJpYycgfTtcbn1cblxuLypcblRPRE86IHRlc3Qgc3dpdGNoaW5nIHRpbWV6b25lcyB3aGVuIE5PIHRpbWV6b25lIHBsdWdpblxuKi9cbmNsYXNzIENhbGVuZGFyTm93TWFuYWdlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMucmVzZXRMaXN0ZW5lcnMgPSBuZXcgU2V0KCk7XG4gICAgfVxuICAgIGhhbmRsZUlucHV0KGRhdGVFbnYsIC8vIHdpbGwgY2hhbmdlIGlmIHRpbWV6b25lIHNldHVwIGNoYW5nZWRcbiAgICBub3dJbnB1dCkge1xuICAgICAgICBjb25zdCBvbGREYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICBpZiAoZGF0ZUVudiAhPT0gb2xkRGF0ZUVudikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBub3dJbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMubm93Rm4gPSBub3dJbnB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFvbGREYXRlRW52KSB7IC8vIGZpcnN0IHRpbWU/XG4gICAgICAgICAgICAgICAgdGhpcy5ub3dBbmNob3JEYXRlID0gZGF0ZUVudi50b0RhdGUobm93SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgPyBkYXRlRW52LmNyZWF0ZU1hcmtlcihub3dJbnB1dClcbiAgICAgICAgICAgICAgICAgICAgOiBkYXRlRW52LmNyZWF0ZU5vd01hcmtlcigpKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vd0FuY2hvclF1ZXJpZWQgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kYXRlRW52ID0gZGF0ZUVudjtcbiAgICAgICAgICAgIC8vIG5vdCBmaXJzdCB0aW1lPyBmaXJlIHJlc2V0IGhhbmRsZXJzXG4gICAgICAgICAgICBpZiAob2xkRGF0ZUVudikge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcmVzZXRMaXN0ZW5lciBvZiB0aGlzLnJlc2V0TGlzdGVuZXJzLnZhbHVlcygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc2V0TGlzdGVuZXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0RGF0ZU1hcmtlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubm93QW5jaG9yRGF0ZVxuICAgICAgICAgICAgPyB0aGlzLmRhdGVFbnYudGltZXN0YW1wVG9NYXJrZXIodGhpcy5ub3dBbmNob3JEYXRlLnZhbHVlT2YoKSArXG4gICAgICAgICAgICAgICAgKERhdGUubm93KCkgLSB0aGlzLm5vd0FuY2hvclF1ZXJpZWQpKVxuICAgICAgICAgICAgOiB0aGlzLmRhdGVFbnYuY3JlYXRlTWFya2VyKHRoaXMubm93Rm4oKSk7XG4gICAgfVxuICAgIGFkZFJlc2V0TGlzdGVuZXIoaGFuZGxlcikge1xuICAgICAgICB0aGlzLnJlc2V0TGlzdGVuZXJzLmFkZChoYW5kbGVyKTtcbiAgICB9XG4gICAgcmVtb3ZlUmVzZXRMaXN0ZW5lcihoYW5kbGVyKSB7XG4gICAgICAgIHRoaXMucmVzZXRMaXN0ZW5lcnMuZGVsZXRlKGhhbmRsZXIpO1xuICAgIH1cbn1cblxuLy8gaW4gZnV0dXJlIHJlZmFjdG9yLCBkbyB0aGUgcmVkdXgtc3R5bGUgZnVuY3Rpb24oc3RhdGU9aW5pdGlhbCkgZm9yIGluaXRpYWwtc3RhdGVcbi8vIGFsc28sIHdoYXRldmVyIGlzIGhhcHBlbmluZyBpbiBjb25zdHJ1Y3RvciwgaGF2ZSBpdCBoYXBwZW4gaW4gYWN0aW9uIHF1ZXVlIHRvb1xuY2xhc3MgQ2FsZW5kYXJEYXRhTWFuYWdlciB7XG4gICAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICAgICAgdGhpcy5jb21wdXRlQ3VycmVudFZpZXdEYXRhID0gbWVtb2l6ZSh0aGlzLl9jb21wdXRlQ3VycmVudFZpZXdEYXRhKTtcbiAgICAgICAgdGhpcy5vcmdhbml6ZVJhd0xvY2FsZXMgPSBtZW1vaXplKG9yZ2FuaXplUmF3TG9jYWxlcyk7XG4gICAgICAgIHRoaXMuYnVpbGRMb2NhbGUgPSBtZW1vaXplKGJ1aWxkTG9jYWxlKTtcbiAgICAgICAgdGhpcy5idWlsZFBsdWdpbkhvb2tzID0gYnVpbGRCdWlsZFBsdWdpbkhvb2tzKCk7XG4gICAgICAgIHRoaXMuYnVpbGREYXRlRW52ID0gbWVtb2l6ZShidWlsZERhdGVFbnYkMSk7XG4gICAgICAgIHRoaXMuYnVpbGRUaGVtZSA9IG1lbW9pemUoYnVpbGRUaGVtZSk7XG4gICAgICAgIHRoaXMucGFyc2VUb29sYmFycyA9IG1lbW9pemUocGFyc2VUb29sYmFycyk7XG4gICAgICAgIHRoaXMuYnVpbGRWaWV3U3BlY3MgPSBtZW1vaXplKGJ1aWxkVmlld1NwZWNzKTtcbiAgICAgICAgdGhpcy5idWlsZERhdGVQcm9maWxlR2VuZXJhdG9yID0gbWVtb2l6ZU9iakFyZyhidWlsZERhdGVQcm9maWxlR2VuZXJhdG9yKTtcbiAgICAgICAgdGhpcy5idWlsZFZpZXdBcGkgPSBtZW1vaXplKGJ1aWxkVmlld0FwaSk7XG4gICAgICAgIHRoaXMuYnVpbGRWaWV3VWlQcm9wcyA9IG1lbW9pemVPYmpBcmcoYnVpbGRWaWV3VWlQcm9wcyk7XG4gICAgICAgIHRoaXMuYnVpbGRFdmVudFVpQnlTb3VyY2UgPSBtZW1vaXplKGJ1aWxkRXZlbnRVaUJ5U291cmNlLCBpc1Byb3BzRXF1YWwpO1xuICAgICAgICB0aGlzLmJ1aWxkRXZlbnRVaUJhc2VzID0gbWVtb2l6ZShidWlsZEV2ZW50VWlCYXNlcyk7XG4gICAgICAgIHRoaXMucGFyc2VDb250ZXh0QnVzaW5lc3NIb3VycyA9IG1lbW9pemVPYmpBcmcocGFyc2VDb250ZXh0QnVzaW5lc3NIb3Vycyk7XG4gICAgICAgIHRoaXMuYnVpbGRUaXRsZSA9IG1lbW9pemUoYnVpbGRUaXRsZSk7XG4gICAgICAgIHRoaXMubm93TWFuYWdlciA9IG5ldyBDYWxlbmRhck5vd01hbmFnZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcbiAgICAgICAgdGhpcy5hY3Rpb25SdW5uZXIgPSBuZXcgVGFza1J1bm5lcih0aGlzLl9oYW5kbGVBY3Rpb24uYmluZCh0aGlzKSwgdGhpcy51cGRhdGVEYXRhLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmN1cnJlbnRDYWxlbmRhck9wdGlvbnNJbnB1dCA9IHt9O1xuICAgICAgICB0aGlzLmN1cnJlbnRDYWxlbmRhck9wdGlvbnNSZWZpbmVkID0ge307XG4gICAgICAgIHRoaXMuY3VycmVudFZpZXdPcHRpb25zSW5wdXQgPSB7fTtcbiAgICAgICAgdGhpcy5jdXJyZW50Vmlld09wdGlvbnNSZWZpbmVkID0ge307XG4gICAgICAgIHRoaXMuY3VycmVudENhbGVuZGFyT3B0aW9uc1JlZmluZXJzID0ge307XG4gICAgICAgIHRoaXMub3B0aW9uc0ZvclJlZmluaW5nID0gW107XG4gICAgICAgIHRoaXMub3B0aW9uc0ZvckhhbmRsaW5nID0gW107XG4gICAgICAgIHRoaXMuZ2V0Q3VycmVudERhdGEgPSAoKSA9PiB0aGlzLmRhdGE7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2ggPSAoYWN0aW9uKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFjdGlvblJ1bm5lci5yZXF1ZXN0KGFjdGlvbik7IC8vIHByb3RlY3RzIGFnYWluc3QgcmVjdXJzaXZlIGNhbGxzIHRvIF9oYW5kbGVBY3Rpb25cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICAgICAgICB0aGlzLmFjdGlvblJ1bm5lci5wYXVzZSgpO1xuICAgICAgICB0aGlzLm5vd01hbmFnZXIgPSBuZXcgQ2FsZW5kYXJOb3dNYW5hZ2VyKCk7XG4gICAgICAgIGxldCBkeW5hbWljT3B0aW9uT3ZlcnJpZGVzID0ge307XG4gICAgICAgIGxldCBvcHRpb25zRGF0YSA9IHRoaXMuY29tcHV0ZU9wdGlvbnNEYXRhKHByb3BzLm9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcywgcHJvcHMuY2FsZW5kYXJBcGkpO1xuICAgICAgICBsZXQgY3VycmVudFZpZXdUeXBlID0gb3B0aW9uc0RhdGEuY2FsZW5kYXJPcHRpb25zLmluaXRpYWxWaWV3IHx8IG9wdGlvbnNEYXRhLnBsdWdpbkhvb2tzLmluaXRpYWxWaWV3O1xuICAgICAgICBsZXQgY3VycmVudFZpZXdEYXRhID0gdGhpcy5jb21wdXRlQ3VycmVudFZpZXdEYXRhKGN1cnJlbnRWaWV3VHlwZSwgb3B0aW9uc0RhdGEsIHByb3BzLm9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcyk7XG4gICAgICAgIC8vIHdpcmUgdGhpbmdzIHVwXG4gICAgICAgIC8vIFRPRE86IG5vdCBEUllcbiAgICAgICAgcHJvcHMuY2FsZW5kYXJBcGkuY3VycmVudERhdGFNYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5lbWl0dGVyLnNldFRoaXNDb250ZXh0KHByb3BzLmNhbGVuZGFyQXBpKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyLnNldE9wdGlvbnMoY3VycmVudFZpZXdEYXRhLm9wdGlvbnMpO1xuICAgICAgICBsZXQgY2FsZW5kYXJDb250ZXh0ID0ge1xuICAgICAgICAgICAgbm93TWFuYWdlcjogdGhpcy5ub3dNYW5hZ2VyLFxuICAgICAgICAgICAgZGF0ZUVudjogb3B0aW9uc0RhdGEuZGF0ZUVudixcbiAgICAgICAgICAgIG9wdGlvbnM6IG9wdGlvbnNEYXRhLmNhbGVuZGFyT3B0aW9ucyxcbiAgICAgICAgICAgIHBsdWdpbkhvb2tzOiBvcHRpb25zRGF0YS5wbHVnaW5Ib29rcyxcbiAgICAgICAgICAgIGNhbGVuZGFyQXBpOiBwcm9wcy5jYWxlbmRhckFwaSxcbiAgICAgICAgICAgIGRpc3BhdGNoOiB0aGlzLmRpc3BhdGNoLFxuICAgICAgICAgICAgZW1pdHRlcjogdGhpcy5lbWl0dGVyLFxuICAgICAgICAgICAgZ2V0Q3VycmVudERhdGE6IHRoaXMuZ2V0Q3VycmVudERhdGEsXG4gICAgICAgIH07XG4gICAgICAgIGxldCBjdXJyZW50RGF0ZSA9IGdldEluaXRpYWxEYXRlKG9wdGlvbnNEYXRhLmNhbGVuZGFyT3B0aW9ucywgb3B0aW9uc0RhdGEuZGF0ZUVudiwgdGhpcy5ub3dNYW5hZ2VyKTtcbiAgICAgICAgbGV0IGRhdGVQcm9maWxlID0gY3VycmVudFZpZXdEYXRhLmRhdGVQcm9maWxlR2VuZXJhdG9yLmJ1aWxkKGN1cnJlbnREYXRlKTtcbiAgICAgICAgaWYgKCFyYW5nZUNvbnRhaW5zTWFya2VyKGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBjdXJyZW50RGF0ZSkpIHtcbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0O1xuICAgICAgICB9XG4gICAgICAgIC8vIG5lZWRzIHRvIGJlIGFmdGVyIHNldFRoaXNDb250ZXh0XG4gICAgICAgIGZvciAobGV0IGNhbGxiYWNrIG9mIG9wdGlvbnNEYXRhLnBsdWdpbkhvb2tzLmNvbnRleHRJbml0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayhjYWxlbmRhckNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5PVCBEUllcbiAgICAgICAgbGV0IGV2ZW50U291cmNlcyA9IGluaXRFdmVudFNvdXJjZXMob3B0aW9uc0RhdGEuY2FsZW5kYXJPcHRpb25zLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXJDb250ZXh0KTtcbiAgICAgICAgbGV0IGluaXRpYWxTdGF0ZSA9IHtcbiAgICAgICAgICAgIGR5bmFtaWNPcHRpb25PdmVycmlkZXMsXG4gICAgICAgICAgICBjdXJyZW50Vmlld1R5cGUsXG4gICAgICAgICAgICBjdXJyZW50RGF0ZSxcbiAgICAgICAgICAgIGRhdGVQcm9maWxlLFxuICAgICAgICAgICAgYnVzaW5lc3NIb3VyczogdGhpcy5wYXJzZUNvbnRleHRCdXNpbmVzc0hvdXJzKGNhbGVuZGFyQ29udGV4dCksXG4gICAgICAgICAgICBldmVudFNvdXJjZXMsXG4gICAgICAgICAgICBldmVudFVpQmFzZXM6IHt9LFxuICAgICAgICAgICAgZXZlbnRTdG9yZTogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICByZW5kZXJhYmxlRXZlbnRTdG9yZTogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICBkYXRlU2VsZWN0aW9uOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246ICcnLFxuICAgICAgICAgICAgZXZlbnREcmFnOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IG51bGwsXG4gICAgICAgICAgICBzZWxlY3Rpb25Db25maWc6IHRoaXMuYnVpbGRWaWV3VWlQcm9wcyhjYWxlbmRhckNvbnRleHQpLnNlbGVjdGlvbkNvbmZpZyxcbiAgICAgICAgfTtcbiAgICAgICAgbGV0IGNvbnRleHRBbmRTdGF0ZSA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgY2FsZW5kYXJDb250ZXh0KSwgaW5pdGlhbFN0YXRlKTtcbiAgICAgICAgZm9yIChsZXQgcmVkdWNlciBvZiBvcHRpb25zRGF0YS5wbHVnaW5Ib29rcy5yZWR1Y2Vycykge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihpbml0aWFsU3RhdGUsIHJlZHVjZXIobnVsbCwgbnVsbCwgY29udGV4dEFuZFN0YXRlKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbXB1dGVJc0xvYWRpbmcoaW5pdGlhbFN0YXRlLCBjYWxlbmRhckNvbnRleHQpKSB7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignbG9hZGluZycsIHRydWUpOyAvLyBOT1QgRFJZXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0ZSA9IGluaXRpYWxTdGF0ZTtcbiAgICAgICAgdGhpcy51cGRhdGVEYXRhKCk7XG4gICAgICAgIHRoaXMuYWN0aW9uUnVubmVyLnJlc3VtZSgpO1xuICAgIH1cbiAgICByZXNldE9wdGlvbnMob3B0aW9uT3ZlcnJpZGVzLCBjaGFuZ2VkT3B0aW9uTmFtZXMpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGlmIChjaGFuZ2VkT3B0aW9uTmFtZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcHJvcHMub3B0aW9uT3ZlcnJpZGVzID0gb3B0aW9uT3ZlcnJpZGVzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcHJvcHMub3B0aW9uT3ZlcnJpZGVzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCAocHJvcHMub3B0aW9uT3ZlcnJpZGVzIHx8IHt9KSksIG9wdGlvbk92ZXJyaWRlcyk7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnNGb3JSZWZpbmluZy5wdXNoKC4uLmNoYW5nZWRPcHRpb25OYW1lcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZWRPcHRpb25OYW1lcyA9PT0gdW5kZWZpbmVkIHx8IGNoYW5nZWRPcHRpb25OYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuYWN0aW9uUnVubmVyLnJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdOT1RISU5HJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIF9oYW5kbGVBY3Rpb24oYWN0aW9uKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBzdGF0ZSwgZW1pdHRlciB9ID0gdGhpcztcbiAgICAgICAgbGV0IGR5bmFtaWNPcHRpb25PdmVycmlkZXMgPSByZWR1Y2VEeW5hbWljT3B0aW9uT3ZlcnJpZGVzKHN0YXRlLmR5bmFtaWNPcHRpb25PdmVycmlkZXMsIGFjdGlvbik7XG4gICAgICAgIGxldCBvcHRpb25zRGF0YSA9IHRoaXMuY29tcHV0ZU9wdGlvbnNEYXRhKHByb3BzLm9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcywgcHJvcHMuY2FsZW5kYXJBcGkpO1xuICAgICAgICBsZXQgY3VycmVudFZpZXdUeXBlID0gcmVkdWNlVmlld1R5cGUoc3RhdGUuY3VycmVudFZpZXdUeXBlLCBhY3Rpb24pO1xuICAgICAgICBsZXQgY3VycmVudFZpZXdEYXRhID0gdGhpcy5jb21wdXRlQ3VycmVudFZpZXdEYXRhKGN1cnJlbnRWaWV3VHlwZSwgb3B0aW9uc0RhdGEsIHByb3BzLm9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcyk7XG4gICAgICAgIC8vIHdpcmUgdGhpbmdzIHVwXG4gICAgICAgIC8vIFRPRE86IG5vdCBEUllcbiAgICAgICAgcHJvcHMuY2FsZW5kYXJBcGkuY3VycmVudERhdGFNYW5hZ2VyID0gdGhpcztcbiAgICAgICAgZW1pdHRlci5zZXRUaGlzQ29udGV4dChwcm9wcy5jYWxlbmRhckFwaSk7XG4gICAgICAgIGVtaXR0ZXIuc2V0T3B0aW9ucyhjdXJyZW50Vmlld0RhdGEub3B0aW9ucyk7XG4gICAgICAgIGxldCBjYWxlbmRhckNvbnRleHQgPSB7XG4gICAgICAgICAgICBub3dNYW5hZ2VyOiB0aGlzLm5vd01hbmFnZXIsXG4gICAgICAgICAgICBkYXRlRW52OiBvcHRpb25zRGF0YS5kYXRlRW52LFxuICAgICAgICAgICAgb3B0aW9uczogb3B0aW9uc0RhdGEuY2FsZW5kYXJPcHRpb25zLFxuICAgICAgICAgICAgcGx1Z2luSG9va3M6IG9wdGlvbnNEYXRhLnBsdWdpbkhvb2tzLFxuICAgICAgICAgICAgY2FsZW5kYXJBcGk6IHByb3BzLmNhbGVuZGFyQXBpLFxuICAgICAgICAgICAgZGlzcGF0Y2g6IHRoaXMuZGlzcGF0Y2gsXG4gICAgICAgICAgICBlbWl0dGVyLFxuICAgICAgICAgICAgZ2V0Q3VycmVudERhdGE6IHRoaXMuZ2V0Q3VycmVudERhdGEsXG4gICAgICAgIH07XG4gICAgICAgIGxldCB7IGN1cnJlbnREYXRlLCBkYXRlUHJvZmlsZSB9ID0gc3RhdGU7XG4gICAgICAgIGlmICh0aGlzLmRhdGEgJiYgdGhpcy5kYXRhLmRhdGVQcm9maWxlR2VuZXJhdG9yICE9PSBjdXJyZW50Vmlld0RhdGEuZGF0ZVByb2ZpbGVHZW5lcmF0b3IpIHsgLy8gaGFja1xuICAgICAgICAgICAgZGF0ZVByb2ZpbGUgPSBjdXJyZW50Vmlld0RhdGEuZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGQoY3VycmVudERhdGUpO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnREYXRlID0gcmVkdWNlQ3VycmVudERhdGUoY3VycmVudERhdGUsIGFjdGlvbik7XG4gICAgICAgIGRhdGVQcm9maWxlID0gcmVkdWNlRGF0ZVByb2ZpbGUoZGF0ZVByb2ZpbGUsIGFjdGlvbiwgY3VycmVudERhdGUsIGN1cnJlbnRWaWV3RGF0YS5kYXRlUHJvZmlsZUdlbmVyYXRvcik7XG4gICAgICAgIGlmIChhY3Rpb24udHlwZSA9PT0gJ1BSRVYnIHx8IC8vIFRPRE86IG1vdmUgdGhpcyBsb2dpYyBpbnRvIERhdGVQcm9maWxlR2VuZXJhdG9yXG4gICAgICAgICAgICBhY3Rpb24udHlwZSA9PT0gJ05FWFQnIHx8IC8vIFwiXG4gICAgICAgICAgICAhcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2UsIGN1cnJlbnREYXRlKSkge1xuICAgICAgICAgICAgY3VycmVudERhdGUgPSBkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2Uuc3RhcnQ7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGV2ZW50U291cmNlcyA9IHJlZHVjZUV2ZW50U291cmNlcyhzdGF0ZS5ldmVudFNvdXJjZXMsIGFjdGlvbiwgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyQ29udGV4dCk7XG4gICAgICAgIGxldCBldmVudFN0b3JlID0gcmVkdWNlRXZlbnRTdG9yZShzdGF0ZS5ldmVudFN0b3JlLCBhY3Rpb24sIGV2ZW50U291cmNlcywgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyQ29udGV4dCk7XG4gICAgICAgIGxldCBpc0V2ZW50c0xvYWRpbmcgPSBjb21wdXRlRXZlbnRTb3VyY2VzTG9hZGluZyhldmVudFNvdXJjZXMpOyAvLyBCQUQuIGFsc28gY2FsbGVkIGluIHRoaXMgZnVuYyBpbiBjb21wdXRlSXNMb2FkaW5nXG4gICAgICAgIGxldCByZW5kZXJhYmxlRXZlbnRTdG9yZSA9IChpc0V2ZW50c0xvYWRpbmcgJiYgIWN1cnJlbnRWaWV3RGF0YS5vcHRpb25zLnByb2dyZXNzaXZlRXZlbnRSZW5kZXJpbmcpID9cbiAgICAgICAgICAgIChzdGF0ZS5yZW5kZXJhYmxlRXZlbnRTdG9yZSB8fCBldmVudFN0b3JlKSA6IC8vIHRyeSBmcm9tIHByZXZpb3VzIHN0YXRlXG4gICAgICAgICAgICBldmVudFN0b3JlO1xuICAgICAgICBsZXQgeyBldmVudFVpU2luZ2xlQmFzZSwgc2VsZWN0aW9uQ29uZmlnIH0gPSB0aGlzLmJ1aWxkVmlld1VpUHJvcHMoY2FsZW5kYXJDb250ZXh0KTsgLy8gd2lsbCBtZW1vaXplIG9ialxuICAgICAgICBsZXQgZXZlbnRVaUJ5U291cmNlID0gdGhpcy5idWlsZEV2ZW50VWlCeVNvdXJjZShldmVudFNvdXJjZXMpO1xuICAgICAgICBsZXQgZXZlbnRVaUJhc2VzID0gdGhpcy5idWlsZEV2ZW50VWlCYXNlcyhyZW5kZXJhYmxlRXZlbnRTdG9yZS5kZWZzLCBldmVudFVpU2luZ2xlQmFzZSwgZXZlbnRVaUJ5U291cmNlKTtcbiAgICAgICAgbGV0IG5ld1N0YXRlID0ge1xuICAgICAgICAgICAgZHluYW1pY09wdGlvbk92ZXJyaWRlcyxcbiAgICAgICAgICAgIGN1cnJlbnRWaWV3VHlwZSxcbiAgICAgICAgICAgIGN1cnJlbnREYXRlLFxuICAgICAgICAgICAgZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICBldmVudFNvdXJjZXMsXG4gICAgICAgICAgICBldmVudFN0b3JlLFxuICAgICAgICAgICAgcmVuZGVyYWJsZUV2ZW50U3RvcmUsXG4gICAgICAgICAgICBzZWxlY3Rpb25Db25maWcsXG4gICAgICAgICAgICBldmVudFVpQmFzZXMsXG4gICAgICAgICAgICBidXNpbmVzc0hvdXJzOiB0aGlzLnBhcnNlQ29udGV4dEJ1c2luZXNzSG91cnMoY2FsZW5kYXJDb250ZXh0KSxcbiAgICAgICAgICAgIGRhdGVTZWxlY3Rpb246IHJlZHVjZURhdGVTZWxlY3Rpb24oc3RhdGUuZGF0ZVNlbGVjdGlvbiwgYWN0aW9uKSxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiByZWR1Y2VTZWxlY3RlZEV2ZW50KHN0YXRlLmV2ZW50U2VsZWN0aW9uLCBhY3Rpb24pLFxuICAgICAgICAgICAgZXZlbnREcmFnOiByZWR1Y2VFdmVudERyYWcoc3RhdGUuZXZlbnREcmFnLCBhY3Rpb24pLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IHJlZHVjZUV2ZW50UmVzaXplKHN0YXRlLmV2ZW50UmVzaXplLCBhY3Rpb24pLFxuICAgICAgICB9O1xuICAgICAgICBsZXQgY29udGV4dEFuZFN0YXRlID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBjYWxlbmRhckNvbnRleHQpLCBuZXdTdGF0ZSk7XG4gICAgICAgIGZvciAobGV0IHJlZHVjZXIgb2Ygb3B0aW9uc0RhdGEucGx1Z2luSG9va3MucmVkdWNlcnMpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24obmV3U3RhdGUsIHJlZHVjZXIoc3RhdGUsIGFjdGlvbiwgY29udGV4dEFuZFN0YXRlKSk7IC8vIGdpdmUgdGhlIE9MRCBzdGF0ZSwgZm9yIG9sZCB2YWx1ZVxuICAgICAgICB9XG4gICAgICAgIGxldCB3YXNMb2FkaW5nID0gY29tcHV0ZUlzTG9hZGluZyhzdGF0ZSwgY2FsZW5kYXJDb250ZXh0KTtcbiAgICAgICAgbGV0IGlzTG9hZGluZyA9IGNvbXB1dGVJc0xvYWRpbmcobmV3U3RhdGUsIGNhbGVuZGFyQ29udGV4dCk7XG4gICAgICAgIC8vIFRPRE86IHVzZSBwcm9wU2V0SGFuZGxlcnMgaW4gcGx1Z2luIHN5c3RlbVxuICAgICAgICBpZiAoIXdhc0xvYWRpbmcgJiYgaXNMb2FkaW5nKSB7XG4gICAgICAgICAgICBlbWl0dGVyLnRyaWdnZXIoJ2xvYWRpbmcnLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh3YXNMb2FkaW5nICYmICFpc0xvYWRpbmcpIHtcbiAgICAgICAgICAgIGVtaXR0ZXIudHJpZ2dlcignbG9hZGluZycsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7XG4gICAgICAgIGlmIChwcm9wcy5vbkFjdGlvbikge1xuICAgICAgICAgICAgcHJvcHMub25BY3Rpb24oYWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB1cGRhdGVEYXRhKCkge1xuICAgICAgICBsZXQgeyBwcm9wcywgc3RhdGUgfSA9IHRoaXM7XG4gICAgICAgIGxldCBvbGREYXRhID0gdGhpcy5kYXRhO1xuICAgICAgICBsZXQgb3B0aW9uc0RhdGEgPSB0aGlzLmNvbXB1dGVPcHRpb25zRGF0YShwcm9wcy5vcHRpb25PdmVycmlkZXMsIHN0YXRlLmR5bmFtaWNPcHRpb25PdmVycmlkZXMsIHByb3BzLmNhbGVuZGFyQXBpKTtcbiAgICAgICAgbGV0IGN1cnJlbnRWaWV3RGF0YSA9IHRoaXMuY29tcHV0ZUN1cnJlbnRWaWV3RGF0YShzdGF0ZS5jdXJyZW50Vmlld1R5cGUsIG9wdGlvbnNEYXRhLCBwcm9wcy5vcHRpb25PdmVycmlkZXMsIHN0YXRlLmR5bmFtaWNPcHRpb25PdmVycmlkZXMpO1xuICAgICAgICBsZXQgZGF0YSA9IHRoaXMuZGF0YSA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHsgbm93TWFuYWdlcjogdGhpcy5ub3dNYW5hZ2VyLCB2aWV3VGl0bGU6IHRoaXMuYnVpbGRUaXRsZShzdGF0ZS5kYXRlUHJvZmlsZSwgY3VycmVudFZpZXdEYXRhLm9wdGlvbnMsIG9wdGlvbnNEYXRhLmRhdGVFbnYpLCBjYWxlbmRhckFwaTogcHJvcHMuY2FsZW5kYXJBcGksIGRpc3BhdGNoOiB0aGlzLmRpc3BhdGNoLCBlbWl0dGVyOiB0aGlzLmVtaXR0ZXIsIGdldEN1cnJlbnREYXRhOiB0aGlzLmdldEN1cnJlbnREYXRhIH0sIG9wdGlvbnNEYXRhKSwgY3VycmVudFZpZXdEYXRhKSwgc3RhdGUpO1xuICAgICAgICBsZXQgY2hhbmdlSGFuZGxlcnMgPSBvcHRpb25zRGF0YS5wbHVnaW5Ib29rcy5vcHRpb25DaGFuZ2VIYW5kbGVycztcbiAgICAgICAgbGV0IG9sZENhbGVuZGFyT3B0aW9ucyA9IG9sZERhdGEgJiYgb2xkRGF0YS5jYWxlbmRhck9wdGlvbnM7XG4gICAgICAgIGxldCBuZXdDYWxlbmRhck9wdGlvbnMgPSBvcHRpb25zRGF0YS5jYWxlbmRhck9wdGlvbnM7XG4gICAgICAgIGlmIChvbGRDYWxlbmRhck9wdGlvbnMgJiYgb2xkQ2FsZW5kYXJPcHRpb25zICE9PSBuZXdDYWxlbmRhck9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvbGRDYWxlbmRhck9wdGlvbnMudGltZVpvbmUgIT09IG5ld0NhbGVuZGFyT3B0aW9ucy50aW1lWm9uZSkge1xuICAgICAgICAgICAgICAgIC8vIGhhY2tcbiAgICAgICAgICAgICAgICBzdGF0ZS5ldmVudFNvdXJjZXMgPSBkYXRhLmV2ZW50U291cmNlcyA9IHJlZHVjZUV2ZW50U291cmNlc05ld1RpbWVab25lKGRhdGEuZXZlbnRTb3VyY2VzLCBzdGF0ZS5kYXRlUHJvZmlsZSwgZGF0YSk7XG4gICAgICAgICAgICAgICAgc3RhdGUuZXZlbnRTdG9yZSA9IGRhdGEuZXZlbnRTdG9yZSA9IHJlem9uZUV2ZW50U3RvcmVEYXRlcyhkYXRhLmV2ZW50U3RvcmUsIG9sZERhdGEuZGF0ZUVudiwgZGF0YS5kYXRlRW52KTtcbiAgICAgICAgICAgICAgICBzdGF0ZS5yZW5kZXJhYmxlRXZlbnRTdG9yZSA9IGRhdGEucmVuZGVyYWJsZUV2ZW50U3RvcmUgPSByZXpvbmVFdmVudFN0b3JlRGF0ZXMoZGF0YS5yZW5kZXJhYmxlRXZlbnRTdG9yZSwgb2xkRGF0YS5kYXRlRW52LCBkYXRhLmRhdGVFbnYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgb3B0aW9uTmFtZSBpbiBjaGFuZ2VIYW5kbGVycykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnNGb3JIYW5kbGluZy5pbmRleE9mKG9wdGlvbk5hbWUpICE9PSAtMSB8fFxuICAgICAgICAgICAgICAgICAgICBvbGRDYWxlbmRhck9wdGlvbnNbb3B0aW9uTmFtZV0gIT09IG5ld0NhbGVuZGFyT3B0aW9uc1tvcHRpb25OYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VIYW5kbGVyc1tvcHRpb25OYW1lXShuZXdDYWxlbmRhck9wdGlvbnNbb3B0aW9uTmFtZV0sIGRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wdGlvbnNGb3JIYW5kbGluZyA9IFtdO1xuICAgICAgICBpZiAocHJvcHMub25EYXRhKSB7XG4gICAgICAgICAgICBwcm9wcy5vbkRhdGEoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29tcHV0ZU9wdGlvbnNEYXRhKG9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcywgY2FsZW5kYXJBcGkpIHtcbiAgICAgICAgLy8gVE9ETzogYmxhY2tsaXN0IG9wdGlvbnMgdGhhdCBhcmUgaGFuZGxlZCBieSBvcHRpb25DaGFuZ2VIYW5kbGVyc1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9uc0ZvclJlZmluaW5nLmxlbmd0aCAmJlxuICAgICAgICAgICAgb3B0aW9uT3ZlcnJpZGVzID09PSB0aGlzLnN0YWJsZU9wdGlvbk92ZXJyaWRlcyAmJlxuICAgICAgICAgICAgZHluYW1pY09wdGlvbk92ZXJyaWRlcyA9PT0gdGhpcy5zdGFibGVEeW5hbWljT3B0aW9uT3ZlcnJpZGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFibGVDYWxlbmRhck9wdGlvbnNEYXRhO1xuICAgICAgICB9XG4gICAgICAgIGxldCB7IHJlZmluZWRPcHRpb25zLCBwbHVnaW5Ib29rcywgbG9jYWxlRGVmYXVsdHMsIGF2YWlsYWJsZUxvY2FsZURhdGEsIGV4dHJhLCB9ID0gdGhpcy5wcm9jZXNzUmF3Q2FsZW5kYXJPcHRpb25zKG9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcyk7XG4gICAgICAgIHdhcm5Vbmtub3duT3B0aW9ucyhleHRyYSk7XG4gICAgICAgIGxldCBkYXRlRW52ID0gdGhpcy5idWlsZERhdGVFbnYocmVmaW5lZE9wdGlvbnMudGltZVpvbmUsIHJlZmluZWRPcHRpb25zLmxvY2FsZSwgcmVmaW5lZE9wdGlvbnMud2Vla051bWJlckNhbGN1bGF0aW9uLCByZWZpbmVkT3B0aW9ucy5maXJzdERheSwgcmVmaW5lZE9wdGlvbnMud2Vla1RleHQsIHBsdWdpbkhvb2tzLCBhdmFpbGFibGVMb2NhbGVEYXRhLCByZWZpbmVkT3B0aW9ucy5kZWZhdWx0UmFuZ2VTZXBhcmF0b3IpO1xuICAgICAgICBsZXQgdmlld1NwZWNzID0gdGhpcy5idWlsZFZpZXdTcGVjcyhwbHVnaW5Ib29rcy52aWV3cywgdGhpcy5zdGFibGVPcHRpb25PdmVycmlkZXMsIHRoaXMuc3RhYmxlRHluYW1pY09wdGlvbk92ZXJyaWRlcywgbG9jYWxlRGVmYXVsdHMpO1xuICAgICAgICBsZXQgdGhlbWUgPSB0aGlzLmJ1aWxkVGhlbWUocmVmaW5lZE9wdGlvbnMsIHBsdWdpbkhvb2tzKTtcbiAgICAgICAgbGV0IHRvb2xiYXJDb25maWcgPSB0aGlzLnBhcnNlVG9vbGJhcnMocmVmaW5lZE9wdGlvbnMsIHRoaXMuc3RhYmxlT3B0aW9uT3ZlcnJpZGVzLCB0aGVtZSwgdmlld1NwZWNzLCBjYWxlbmRhckFwaSk7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YWJsZUNhbGVuZGFyT3B0aW9uc0RhdGEgPSB7XG4gICAgICAgICAgICBjYWxlbmRhck9wdGlvbnM6IHJlZmluZWRPcHRpb25zLFxuICAgICAgICAgICAgcGx1Z2luSG9va3MsXG4gICAgICAgICAgICBkYXRlRW52LFxuICAgICAgICAgICAgdmlld1NwZWNzLFxuICAgICAgICAgICAgdGhlbWUsXG4gICAgICAgICAgICB0b29sYmFyQ29uZmlnLFxuICAgICAgICAgICAgbG9jYWxlRGVmYXVsdHMsXG4gICAgICAgICAgICBhdmFpbGFibGVSYXdMb2NhbGVzOiBhdmFpbGFibGVMb2NhbGVEYXRhLm1hcCxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gYWx3YXlzIGNhbGxlZCBmcm9tIGJlaGluZCBhIG1lbW9pemVyXG4gICAgcHJvY2Vzc1Jhd0NhbGVuZGFyT3B0aW9ucyhvcHRpb25PdmVycmlkZXMsIGR5bmFtaWNPcHRpb25PdmVycmlkZXMpIHtcbiAgICAgICAgbGV0IHsgbG9jYWxlcywgbG9jYWxlIH0gPSBtZXJnZVJhd09wdGlvbnMoW1xuICAgICAgICAgICAgQkFTRV9PUFRJT05fREVGQVVMVFMsXG4gICAgICAgICAgICBvcHRpb25PdmVycmlkZXMsXG4gICAgICAgICAgICBkeW5hbWljT3B0aW9uT3ZlcnJpZGVzLFxuICAgICAgICBdKTtcbiAgICAgICAgbGV0IGF2YWlsYWJsZUxvY2FsZURhdGEgPSB0aGlzLm9yZ2FuaXplUmF3TG9jYWxlcyhsb2NhbGVzKTtcbiAgICAgICAgbGV0IGF2YWlsYWJsZVJhd0xvY2FsZXMgPSBhdmFpbGFibGVMb2NhbGVEYXRhLm1hcDtcbiAgICAgICAgbGV0IGxvY2FsZURlZmF1bHRzID0gdGhpcy5idWlsZExvY2FsZShsb2NhbGUgfHwgYXZhaWxhYmxlTG9jYWxlRGF0YS5kZWZhdWx0Q29kZSwgYXZhaWxhYmxlUmF3TG9jYWxlcykub3B0aW9ucztcbiAgICAgICAgbGV0IHBsdWdpbkhvb2tzID0gdGhpcy5idWlsZFBsdWdpbkhvb2tzKG9wdGlvbk92ZXJyaWRlcy5wbHVnaW5zIHx8IFtdLCBnbG9iYWxQbHVnaW5zKTtcbiAgICAgICAgbGV0IHJlZmluZXJzID0gdGhpcy5jdXJyZW50Q2FsZW5kYXJPcHRpb25zUmVmaW5lcnMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIEJBU0VfT1BUSU9OX1JFRklORVJTKSwgQ0FMRU5EQVJfTElTVEVORVJfUkVGSU5FUlMpLCBDQUxFTkRBUl9PUFRJT05fUkVGSU5FUlMpLCBwbHVnaW5Ib29rcy5saXN0ZW5lclJlZmluZXJzKSwgcGx1Z2luSG9va3Mub3B0aW9uUmVmaW5lcnMpO1xuICAgICAgICBsZXQgZXh0cmEgPSB7fTtcbiAgICAgICAgbGV0IHJhdyA9IG1lcmdlUmF3T3B0aW9ucyhbXG4gICAgICAgICAgICBCQVNFX09QVElPTl9ERUZBVUxUUyxcbiAgICAgICAgICAgIGxvY2FsZURlZmF1bHRzLFxuICAgICAgICAgICAgb3B0aW9uT3ZlcnJpZGVzLFxuICAgICAgICAgICAgZHluYW1pY09wdGlvbk92ZXJyaWRlcyxcbiAgICAgICAgXSk7XG4gICAgICAgIGxldCByZWZpbmVkID0ge307XG4gICAgICAgIGxldCBjdXJyZW50UmF3ID0gdGhpcy5jdXJyZW50Q2FsZW5kYXJPcHRpb25zSW5wdXQ7XG4gICAgICAgIGxldCBjdXJyZW50UmVmaW5lZCA9IHRoaXMuY3VycmVudENhbGVuZGFyT3B0aW9uc1JlZmluZWQ7XG4gICAgICAgIGxldCBhbnlDaGFuZ2VzID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IG9wdGlvbk5hbWUgaW4gcmF3KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zRm9yUmVmaW5pbmcuaW5kZXhPZihvcHRpb25OYW1lKSA9PT0gLTEgJiYgKHJhd1tvcHRpb25OYW1lXSA9PT0gY3VycmVudFJhd1tvcHRpb25OYW1lXSB8fCAoQ09NUExFWF9PUFRJT05fQ09NUEFSQVRPUlNbb3B0aW9uTmFtZV0gJiZcbiAgICAgICAgICAgICAgICAob3B0aW9uTmFtZSBpbiBjdXJyZW50UmF3KSAmJlxuICAgICAgICAgICAgICAgIENPTVBMRVhfT1BUSU9OX0NPTVBBUkFUT1JTW29wdGlvbk5hbWVdKGN1cnJlbnRSYXdbb3B0aW9uTmFtZV0sIHJhd1tvcHRpb25OYW1lXSkpKSkge1xuICAgICAgICAgICAgICAgIHJlZmluZWRbb3B0aW9uTmFtZV0gPSBjdXJyZW50UmVmaW5lZFtvcHRpb25OYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJlZmluZXJzW29wdGlvbk5hbWVdKSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtvcHRpb25OYW1lXSA9IHJlZmluZXJzW29wdGlvbk5hbWVdKHJhd1tvcHRpb25OYW1lXSk7XG4gICAgICAgICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBleHRyYVtvcHRpb25OYW1lXSA9IGN1cnJlbnRSYXdbb3B0aW9uTmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFueUNoYW5nZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudENhbGVuZGFyT3B0aW9uc0lucHV0ID0gcmF3O1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FsZW5kYXJPcHRpb25zUmVmaW5lZCA9IHJlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0YWJsZU9wdGlvbk92ZXJyaWRlcyA9IG9wdGlvbk92ZXJyaWRlcztcbiAgICAgICAgICAgIHRoaXMuc3RhYmxlRHluYW1pY09wdGlvbk92ZXJyaWRlcyA9IGR5bmFtaWNPcHRpb25PdmVycmlkZXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vcHRpb25zRm9ySGFuZGxpbmcucHVzaCguLi50aGlzLm9wdGlvbnNGb3JSZWZpbmluZyk7XG4gICAgICAgIHRoaXMub3B0aW9uc0ZvclJlZmluaW5nID0gW107XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByYXdPcHRpb25zOiB0aGlzLmN1cnJlbnRDYWxlbmRhck9wdGlvbnNJbnB1dCxcbiAgICAgICAgICAgIHJlZmluZWRPcHRpb25zOiB0aGlzLmN1cnJlbnRDYWxlbmRhck9wdGlvbnNSZWZpbmVkLFxuICAgICAgICAgICAgcGx1Z2luSG9va3MsXG4gICAgICAgICAgICBhdmFpbGFibGVMb2NhbGVEYXRhLFxuICAgICAgICAgICAgbG9jYWxlRGVmYXVsdHMsXG4gICAgICAgICAgICBleHRyYSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgX2NvbXB1dGVDdXJyZW50Vmlld0RhdGEodmlld1R5cGUsIG9wdGlvbnNEYXRhLCBvcHRpb25PdmVycmlkZXMsIGR5bmFtaWNPcHRpb25PdmVycmlkZXMpIHtcbiAgICAgICAgbGV0IHZpZXdTcGVjID0gb3B0aW9uc0RhdGEudmlld1NwZWNzW3ZpZXdUeXBlXTtcbiAgICAgICAgaWYgKCF2aWV3U3BlYykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2aWV3VHlwZSBcIiR7dmlld1R5cGV9XCIgaXMgbm90IGF2YWlsYWJsZS4gUGxlYXNlIG1ha2Ugc3VyZSB5b3UndmUgbG9hZGVkIGFsbCBuZWNjZXNzYXJ5IHBsdWdpbnNgKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgeyByZWZpbmVkT3B0aW9ucywgZXh0cmEgfSA9IHRoaXMucHJvY2Vzc1Jhd1ZpZXdPcHRpb25zKHZpZXdTcGVjLCBvcHRpb25zRGF0YS5wbHVnaW5Ib29rcywgb3B0aW9uc0RhdGEubG9jYWxlRGVmYXVsdHMsIG9wdGlvbk92ZXJyaWRlcywgZHluYW1pY09wdGlvbk92ZXJyaWRlcyk7XG4gICAgICAgIHdhcm5Vbmtub3duT3B0aW9ucyhleHRyYSk7XG4gICAgICAgIHRoaXMubm93TWFuYWdlci5oYW5kbGVJbnB1dChvcHRpb25zRGF0YS5kYXRlRW52LCByZWZpbmVkT3B0aW9ucy5ub3cpO1xuICAgICAgICBsZXQgZGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSB0aGlzLmJ1aWxkRGF0ZVByb2ZpbGVHZW5lcmF0b3Ioe1xuICAgICAgICAgICAgZGF0ZVByb2ZpbGVHZW5lcmF0b3JDbGFzczogdmlld1NwZWMub3B0aW9uRGVmYXVsdHMuZGF0ZVByb2ZpbGVHZW5lcmF0b3JDbGFzcyxcbiAgICAgICAgICAgIG5vd01hbmFnZXI6IHRoaXMubm93TWFuYWdlcixcbiAgICAgICAgICAgIGR1cmF0aW9uOiB2aWV3U3BlYy5kdXJhdGlvbixcbiAgICAgICAgICAgIGR1cmF0aW9uVW5pdDogdmlld1NwZWMuZHVyYXRpb25Vbml0LFxuICAgICAgICAgICAgdXNlc01pbk1heFRpbWU6IHZpZXdTcGVjLm9wdGlvbkRlZmF1bHRzLnVzZXNNaW5NYXhUaW1lLFxuICAgICAgICAgICAgZGF0ZUVudjogb3B0aW9uc0RhdGEuZGF0ZUVudixcbiAgICAgICAgICAgIGNhbGVuZGFyQXBpOiB0aGlzLnByb3BzLmNhbGVuZGFyQXBpLFxuICAgICAgICAgICAgc2xvdE1pblRpbWU6IHJlZmluZWRPcHRpb25zLnNsb3RNaW5UaW1lLFxuICAgICAgICAgICAgc2xvdE1heFRpbWU6IHJlZmluZWRPcHRpb25zLnNsb3RNYXhUaW1lLFxuICAgICAgICAgICAgc2hvd05vbkN1cnJlbnREYXRlczogcmVmaW5lZE9wdGlvbnMuc2hvd05vbkN1cnJlbnREYXRlcyxcbiAgICAgICAgICAgIGRheUNvdW50OiByZWZpbmVkT3B0aW9ucy5kYXlDb3VudCxcbiAgICAgICAgICAgIGRhdGVBbGlnbm1lbnQ6IHJlZmluZWRPcHRpb25zLmRhdGVBbGlnbm1lbnQsXG4gICAgICAgICAgICBkYXRlSW5jcmVtZW50OiByZWZpbmVkT3B0aW9ucy5kYXRlSW5jcmVtZW50LFxuICAgICAgICAgICAgaGlkZGVuRGF5czogcmVmaW5lZE9wdGlvbnMuaGlkZGVuRGF5cyxcbiAgICAgICAgICAgIHdlZWtlbmRzOiByZWZpbmVkT3B0aW9ucy53ZWVrZW5kcyxcbiAgICAgICAgICAgIHZhbGlkUmFuZ2VJbnB1dDogcmVmaW5lZE9wdGlvbnMudmFsaWRSYW5nZSxcbiAgICAgICAgICAgIHZpc2libGVSYW5nZUlucHV0OiByZWZpbmVkT3B0aW9ucy52aXNpYmxlUmFuZ2UsXG4gICAgICAgICAgICBmaXhlZFdlZWtDb3VudDogcmVmaW5lZE9wdGlvbnMuZml4ZWRXZWVrQ291bnQsXG4gICAgICAgIH0pO1xuICAgICAgICBsZXQgdmlld0FwaSA9IHRoaXMuYnVpbGRWaWV3QXBpKHZpZXdUeXBlLCB0aGlzLmdldEN1cnJlbnREYXRhLCBvcHRpb25zRGF0YS5kYXRlRW52KTtcbiAgICAgICAgcmV0dXJuIHsgdmlld1NwZWMsIG9wdGlvbnM6IHJlZmluZWRPcHRpb25zLCBkYXRlUHJvZmlsZUdlbmVyYXRvciwgdmlld0FwaSB9O1xuICAgIH1cbiAgICBwcm9jZXNzUmF3Vmlld09wdGlvbnModmlld1NwZWMsIHBsdWdpbkhvb2tzLCBsb2NhbGVEZWZhdWx0cywgb3B0aW9uT3ZlcnJpZGVzLCBkeW5hbWljT3B0aW9uT3ZlcnJpZGVzKSB7XG4gICAgICAgIGxldCByYXcgPSBtZXJnZVJhd09wdGlvbnMoW1xuICAgICAgICAgICAgQkFTRV9PUFRJT05fREVGQVVMVFMsXG4gICAgICAgICAgICB2aWV3U3BlYy5vcHRpb25EZWZhdWx0cyxcbiAgICAgICAgICAgIGxvY2FsZURlZmF1bHRzLFxuICAgICAgICAgICAgb3B0aW9uT3ZlcnJpZGVzLFxuICAgICAgICAgICAgdmlld1NwZWMub3B0aW9uT3ZlcnJpZGVzLFxuICAgICAgICAgICAgZHluYW1pY09wdGlvbk92ZXJyaWRlcyxcbiAgICAgICAgXSk7XG4gICAgICAgIGxldCByZWZpbmVycyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBCQVNFX09QVElPTl9SRUZJTkVSUyksIENBTEVOREFSX0xJU1RFTkVSX1JFRklORVJTKSwgQ0FMRU5EQVJfT1BUSU9OX1JFRklORVJTKSwgVklFV19PUFRJT05fUkVGSU5FUlMpLCBwbHVnaW5Ib29rcy5saXN0ZW5lclJlZmluZXJzKSwgcGx1Z2luSG9va3Mub3B0aW9uUmVmaW5lcnMpO1xuICAgICAgICBsZXQgcmVmaW5lZCA9IHt9O1xuICAgICAgICBsZXQgY3VycmVudFJhdyA9IHRoaXMuY3VycmVudFZpZXdPcHRpb25zSW5wdXQ7XG4gICAgICAgIGxldCBjdXJyZW50UmVmaW5lZCA9IHRoaXMuY3VycmVudFZpZXdPcHRpb25zUmVmaW5lZDtcbiAgICAgICAgbGV0IGFueUNoYW5nZXMgPSBmYWxzZTtcbiAgICAgICAgbGV0IGV4dHJhID0ge307XG4gICAgICAgIGZvciAobGV0IG9wdGlvbk5hbWUgaW4gcmF3KSB7XG4gICAgICAgICAgICBpZiAocmF3W29wdGlvbk5hbWVdID09PSBjdXJyZW50UmF3W29wdGlvbk5hbWVdIHx8XG4gICAgICAgICAgICAgICAgKENPTVBMRVhfT1BUSU9OX0NPTVBBUkFUT1JTW29wdGlvbk5hbWVdICYmXG4gICAgICAgICAgICAgICAgICAgIENPTVBMRVhfT1BUSU9OX0NPTVBBUkFUT1JTW29wdGlvbk5hbWVdKHJhd1tvcHRpb25OYW1lXSwgY3VycmVudFJhd1tvcHRpb25OYW1lXSkpKSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtvcHRpb25OYW1lXSA9IGN1cnJlbnRSZWZpbmVkW29wdGlvbk5hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHJhd1tvcHRpb25OYW1lXSA9PT0gdGhpcy5jdXJyZW50Q2FsZW5kYXJPcHRpb25zSW5wdXRbb3B0aW9uTmFtZV0gfHxcbiAgICAgICAgICAgICAgICAgICAgKENPTVBMRVhfT1BUSU9OX0NPTVBBUkFUT1JTW29wdGlvbk5hbWVdICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBDT01QTEVYX09QVElPTl9DT01QQVJBVE9SU1tvcHRpb25OYW1lXShyYXdbb3B0aW9uTmFtZV0sIHRoaXMuY3VycmVudENhbGVuZGFyT3B0aW9uc0lucHV0W29wdGlvbk5hbWVdKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbk5hbWUgaW4gdGhpcy5jdXJyZW50Q2FsZW5kYXJPcHRpb25zUmVmaW5lZCkgeyAvLyBtaWdodCBiZSBhbiBcImV4dHJhXCIgcHJvcFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmaW5lZFtvcHRpb25OYW1lXSA9IHRoaXMuY3VycmVudENhbGVuZGFyT3B0aW9uc1JlZmluZWRbb3B0aW9uTmFtZV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAocmVmaW5lcnNbb3B0aW9uTmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmaW5lZFtvcHRpb25OYW1lXSA9IHJlZmluZXJzW29wdGlvbk5hbWVdKHJhd1tvcHRpb25OYW1lXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBleHRyYVtvcHRpb25OYW1lXSA9IHJhd1tvcHRpb25OYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFueUNoYW5nZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdPcHRpb25zSW5wdXQgPSByYXc7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3T3B0aW9uc1JlZmluZWQgPSByZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByYXdPcHRpb25zOiB0aGlzLmN1cnJlbnRWaWV3T3B0aW9uc0lucHV0LFxuICAgICAgICAgICAgcmVmaW5lZE9wdGlvbnM6IHRoaXMuY3VycmVudFZpZXdPcHRpb25zUmVmaW5lZCxcbiAgICAgICAgICAgIGV4dHJhLFxuICAgICAgICB9O1xuICAgIH1cbn1cbmZ1bmN0aW9uIGJ1aWxkRGF0ZUVudiQxKHRpbWVab25lLCBleHBsaWNpdExvY2FsZSwgd2Vla051bWJlckNhbGN1bGF0aW9uLCBmaXJzdERheSwgd2Vla1RleHQsIHBsdWdpbkhvb2tzLCBhdmFpbGFibGVMb2NhbGVEYXRhLCBkZWZhdWx0U2VwYXJhdG9yKSB7XG4gICAgbGV0IGxvY2FsZSA9IGJ1aWxkTG9jYWxlKGV4cGxpY2l0TG9jYWxlIHx8IGF2YWlsYWJsZUxvY2FsZURhdGEuZGVmYXVsdENvZGUsIGF2YWlsYWJsZUxvY2FsZURhdGEubWFwKTtcbiAgICByZXR1cm4gbmV3IERhdGVFbnYoe1xuICAgICAgICBjYWxlbmRhclN5c3RlbTogJ2dyZWdvcnknLFxuICAgICAgICB0aW1lWm9uZSxcbiAgICAgICAgbmFtZWRUaW1lWm9uZUltcGw6IHBsdWdpbkhvb2tzLm5hbWVkVGltZVpvbmVkSW1wbCxcbiAgICAgICAgbG9jYWxlLFxuICAgICAgICB3ZWVrTnVtYmVyQ2FsY3VsYXRpb24sXG4gICAgICAgIGZpcnN0RGF5LFxuICAgICAgICB3ZWVrVGV4dCxcbiAgICAgICAgY21kRm9ybWF0dGVyOiBwbHVnaW5Ib29rcy5jbWRGb3JtYXR0ZXIsXG4gICAgICAgIGRlZmF1bHRTZXBhcmF0b3IsXG4gICAgfSk7XG59XG5mdW5jdGlvbiBidWlsZFRoZW1lKG9wdGlvbnMsIHBsdWdpbkhvb2tzKSB7XG4gICAgbGV0IFRoZW1lQ2xhc3MgPSBwbHVnaW5Ib29rcy50aGVtZUNsYXNzZXNbb3B0aW9ucy50aGVtZVN5c3RlbV0gfHwgU3RhbmRhcmRUaGVtZTtcbiAgICByZXR1cm4gbmV3IFRoZW1lQ2xhc3Mob3B0aW9ucyk7XG59XG5mdW5jdGlvbiBidWlsZERhdGVQcm9maWxlR2VuZXJhdG9yKHByb3BzKSB7XG4gICAgbGV0IERhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3MgPSBwcm9wcy5kYXRlUHJvZmlsZUdlbmVyYXRvckNsYXNzIHx8IERhdGVQcm9maWxlR2VuZXJhdG9yO1xuICAgIHJldHVybiBuZXcgRGF0ZVByb2ZpbGVHZW5lcmF0b3JDbGFzcyhwcm9wcyk7XG59XG5mdW5jdGlvbiBidWlsZFZpZXdBcGkodHlwZSwgZ2V0Q3VycmVudERhdGEsIGRhdGVFbnYpIHtcbiAgICByZXR1cm4gbmV3IFZpZXdJbXBsKHR5cGUsIGdldEN1cnJlbnREYXRhLCBkYXRlRW52KTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRXZlbnRVaUJ5U291cmNlKGV2ZW50U291cmNlcykge1xuICAgIHJldHVybiBtYXBIYXNoKGV2ZW50U291cmNlcywgKGV2ZW50U291cmNlKSA9PiBldmVudFNvdXJjZS51aSk7XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50VWlCYXNlcyhldmVudERlZnMsIGV2ZW50VWlTaW5nbGVCYXNlLCBldmVudFVpQnlTb3VyY2UpIHtcbiAgICBsZXQgZXZlbnRVaUJhc2VzID0geyAnJzogZXZlbnRVaVNpbmdsZUJhc2UgfTtcbiAgICBmb3IgKGxldCBkZWZJZCBpbiBldmVudERlZnMpIHtcbiAgICAgICAgbGV0IGRlZiA9IGV2ZW50RGVmc1tkZWZJZF07XG4gICAgICAgIGlmIChkZWYuc291cmNlSWQgJiYgZXZlbnRVaUJ5U291cmNlW2RlZi5zb3VyY2VJZF0pIHtcbiAgICAgICAgICAgIGV2ZW50VWlCYXNlc1tkZWZJZF0gPSBldmVudFVpQnlTb3VyY2VbZGVmLnNvdXJjZUlkXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXZlbnRVaUJhc2VzO1xufVxuZnVuY3Rpb24gYnVpbGRWaWV3VWlQcm9wcyhjYWxlbmRhckNvbnRleHQpIHtcbiAgICBsZXQgeyBvcHRpb25zIH0gPSBjYWxlbmRhckNvbnRleHQ7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZXZlbnRVaVNpbmdsZUJhc2U6IGNyZWF0ZUV2ZW50VWkoe1xuICAgICAgICAgICAgZGlzcGxheTogb3B0aW9ucy5ldmVudERpc3BsYXksXG4gICAgICAgICAgICBlZGl0YWJsZTogb3B0aW9ucy5lZGl0YWJsZSxcbiAgICAgICAgICAgIHN0YXJ0RWRpdGFibGU6IG9wdGlvbnMuZXZlbnRTdGFydEVkaXRhYmxlLFxuICAgICAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogb3B0aW9ucy5ldmVudER1cmF0aW9uRWRpdGFibGUsXG4gICAgICAgICAgICBjb25zdHJhaW50OiBvcHRpb25zLmV2ZW50Q29uc3RyYWludCxcbiAgICAgICAgICAgIG92ZXJsYXA6IHR5cGVvZiBvcHRpb25zLmV2ZW50T3ZlcmxhcCA9PT0gJ2Jvb2xlYW4nID8gb3B0aW9ucy5ldmVudE92ZXJsYXAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBhbGxvdzogb3B0aW9ucy5ldmVudEFsbG93LFxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiBvcHRpb25zLmV2ZW50QmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgYm9yZGVyQ29sb3I6IG9wdGlvbnMuZXZlbnRCb3JkZXJDb2xvcixcbiAgICAgICAgICAgIHRleHRDb2xvcjogb3B0aW9ucy5ldmVudFRleHRDb2xvcixcbiAgICAgICAgICAgIGNvbG9yOiBvcHRpb25zLmV2ZW50Q29sb3IsXG4gICAgICAgICAgICAvLyBjbGFzc05hbWVzOiBvcHRpb25zLmV2ZW50Q2xhc3NOYW1lcyAvLyByZW5kZXIgaG9vayB3aWxsIGhhbmRsZSB0aGlzXG4gICAgICAgIH0sIGNhbGVuZGFyQ29udGV4dCksXG4gICAgICAgIHNlbGVjdGlvbkNvbmZpZzogY3JlYXRlRXZlbnRVaSh7XG4gICAgICAgICAgICBjb25zdHJhaW50OiBvcHRpb25zLnNlbGVjdENvbnN0cmFpbnQsXG4gICAgICAgICAgICBvdmVybGFwOiB0eXBlb2Ygb3B0aW9ucy5zZWxlY3RPdmVybGFwID09PSAnYm9vbGVhbicgPyBvcHRpb25zLnNlbGVjdE92ZXJsYXAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBhbGxvdzogb3B0aW9ucy5zZWxlY3RBbGxvdyxcbiAgICAgICAgfSwgY2FsZW5kYXJDb250ZXh0KSxcbiAgICB9O1xufVxuZnVuY3Rpb24gY29tcHV0ZUlzTG9hZGluZyhzdGF0ZSwgY29udGV4dCkge1xuICAgIGZvciAobGV0IGlzTG9hZGluZ0Z1bmMgb2YgY29udGV4dC5wbHVnaW5Ib29rcy5pc0xvYWRpbmdGdW5jcykge1xuICAgICAgICBpZiAoaXNMb2FkaW5nRnVuYyhzdGF0ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIHBhcnNlQ29udGV4dEJ1c2luZXNzSG91cnMoY2FsZW5kYXJDb250ZXh0KSB7XG4gICAgcmV0dXJuIHBhcnNlQnVzaW5lc3NIb3VycyhjYWxlbmRhckNvbnRleHQub3B0aW9ucy5idXNpbmVzc0hvdXJzLCBjYWxlbmRhckNvbnRleHQpO1xufVxuZnVuY3Rpb24gd2FyblVua25vd25PcHRpb25zKG9wdGlvbnMsIHZpZXdOYW1lKSB7XG4gICAgZm9yIChsZXQgb3B0aW9uTmFtZSBpbiBvcHRpb25zKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgVW5rbm93biBvcHRpb24gJyR7b3B0aW9uTmFtZX0nYCArXG4gICAgICAgICAgICAodmlld05hbWUgPyBgIGZvciB2aWV3ICcke3ZpZXdOYW1lfSdgIDogJycpKTtcbiAgICB9XG59XG5cbmNsYXNzIFRvb2xiYXJTZWN0aW9uIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgY2hpbGRyZW4gPSB0aGlzLnByb3BzLndpZGdldEdyb3Vwcy5tYXAoKHdpZGdldEdyb3VwKSA9PiB0aGlzLnJlbmRlcldpZGdldEdyb3VwKHdpZGdldEdyb3VwKSk7XG4gICAgICAgIHJldHVybiBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLXRvb2xiYXItY2h1bmsnIH0sIC4uLmNoaWxkcmVuKTtcbiAgICB9XG4gICAgcmVuZGVyV2lkZ2V0R3JvdXAod2lkZ2V0R3JvdXApIHtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IHRoZW1lIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgIGxldCBjaGlsZHJlbiA9IFtdO1xuICAgICAgICBsZXQgaXNPbmx5QnV0dG9ucyA9IHRydWU7XG4gICAgICAgIGZvciAobGV0IHdpZGdldCBvZiB3aWRnZXRHcm91cCkge1xuICAgICAgICAgICAgbGV0IHsgYnV0dG9uTmFtZSwgYnV0dG9uQ2xpY2ssIGJ1dHRvblRleHQsIGJ1dHRvbkljb24sIGJ1dHRvbkhpbnQgfSA9IHdpZGdldDtcbiAgICAgICAgICAgIGlmIChidXR0b25OYW1lID09PSAndGl0bGUnKSB7XG4gICAgICAgICAgICAgICAgaXNPbmx5QnV0dG9ucyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGNoaWxkcmVuLnB1c2goY3JlYXRlRWxlbWVudChcImgyXCIsIHsgY2xhc3NOYW1lOiBcImZjLXRvb2xiYXItdGl0bGVcIiwgaWQ6IHByb3BzLnRpdGxlSWQgfSwgcHJvcHMudGl0bGUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxldCBpc1ByZXNzZWQgPSBidXR0b25OYW1lID09PSBwcm9wcy5hY3RpdmVCdXR0b247XG4gICAgICAgICAgICAgICAgbGV0IGlzRGlzYWJsZWQgPSAoIXByb3BzLmlzVG9kYXlFbmFibGVkICYmIGJ1dHRvbk5hbWUgPT09ICd0b2RheScpIHx8XG4gICAgICAgICAgICAgICAgICAgICghcHJvcHMuaXNQcmV2RW5hYmxlZCAmJiBidXR0b25OYW1lID09PSAncHJldicpIHx8XG4gICAgICAgICAgICAgICAgICAgICghcHJvcHMuaXNOZXh0RW5hYmxlZCAmJiBidXR0b25OYW1lID09PSAnbmV4dCcpO1xuICAgICAgICAgICAgICAgIGxldCBidXR0b25DbGFzc2VzID0gW2BmYy0ke2J1dHRvbk5hbWV9LWJ1dHRvbmAsIHRoZW1lLmdldENsYXNzKCdidXR0b24nKV07XG4gICAgICAgICAgICAgICAgaWYgKGlzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICBidXR0b25DbGFzc2VzLnB1c2godGhlbWUuZ2V0Q2xhc3MoJ2J1dHRvbkFjdGl2ZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2hpbGRyZW4ucHVzaChjcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIHsgdHlwZTogXCJidXR0b25cIiwgdGl0bGU6IHR5cGVvZiBidXR0b25IaW50ID09PSAnZnVuY3Rpb24nID8gYnV0dG9uSGludChwcm9wcy5uYXZVbml0KSA6IGJ1dHRvbkhpbnQsIGRpc2FibGVkOiBpc0Rpc2FibGVkLCBcImFyaWEtcHJlc3NlZFwiOiBpc1ByZXNzZWQsIGNsYXNzTmFtZTogYnV0dG9uQ2xhc3Nlcy5qb2luKCcgJyksIG9uQ2xpY2s6IGJ1dHRvbkNsaWNrIH0sIGJ1dHRvblRleHQgfHwgKGJ1dHRvbkljb24gPyBjcmVhdGVFbGVtZW50KFwic3BhblwiLCB7IGNsYXNzTmFtZTogYnV0dG9uSWNvbiwgcm9sZTogXCJpbWdcIiB9KSA6ICcnKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBsZXQgZ3JvdXBDbGFzc05hbWUgPSAoaXNPbmx5QnV0dG9ucyAmJiB0aGVtZS5nZXRDbGFzcygnYnV0dG9uR3JvdXAnKSkgfHwgJyc7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRWxlbWVudCgnZGl2JywgeyBjbGFzc05hbWU6IGdyb3VwQ2xhc3NOYW1lIH0sIC4uLmNoaWxkcmVuKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2hpbGRyZW5bMF07XG4gICAgfVxufVxuXG5jbGFzcyBUb29sYmFyIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBtb2RlbCwgZXh0cmFDbGFzc05hbWUgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgIGxldCBmb3JjZUx0ciA9IGZhbHNlO1xuICAgICAgICBsZXQgc3RhcnRDb250ZW50O1xuICAgICAgICBsZXQgZW5kQ29udGVudDtcbiAgICAgICAgbGV0IHNlY3Rpb25XaWRnZXRzID0gbW9kZWwuc2VjdGlvbldpZGdldHM7XG4gICAgICAgIGxldCBjZW50ZXJDb250ZW50ID0gc2VjdGlvbldpZGdldHMuY2VudGVyO1xuICAgICAgICBpZiAoc2VjdGlvbldpZGdldHMubGVmdCkge1xuICAgICAgICAgICAgZm9yY2VMdHIgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRDb250ZW50ID0gc2VjdGlvbldpZGdldHMubGVmdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHN0YXJ0Q29udGVudCA9IHNlY3Rpb25XaWRnZXRzLnN0YXJ0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZWN0aW9uV2lkZ2V0cy5yaWdodCkge1xuICAgICAgICAgICAgZm9yY2VMdHIgPSB0cnVlO1xuICAgICAgICAgICAgZW5kQ29udGVudCA9IHNlY3Rpb25XaWRnZXRzLnJpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZW5kQ29udGVudCA9IHNlY3Rpb25XaWRnZXRzLmVuZDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgY2xhc3NOYW1lcyA9IFtcbiAgICAgICAgICAgIGV4dHJhQ2xhc3NOYW1lIHx8ICcnLFxuICAgICAgICAgICAgJ2ZjLXRvb2xiYXInLFxuICAgICAgICAgICAgZm9yY2VMdHIgPyAnZmMtdG9vbGJhci1sdHInIDogJycsXG4gICAgICAgIF07XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogY2xhc3NOYW1lcy5qb2luKCcgJykgfSxcbiAgICAgICAgICAgIHRoaXMucmVuZGVyU2VjdGlvbignc3RhcnQnLCBzdGFydENvbnRlbnQgfHwgW10pLFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJTZWN0aW9uKCdjZW50ZXInLCBjZW50ZXJDb250ZW50IHx8IFtdKSxcbiAgICAgICAgICAgIHRoaXMucmVuZGVyU2VjdGlvbignZW5kJywgZW5kQ29udGVudCB8fCBbXSkpKTtcbiAgICB9XG4gICAgcmVuZGVyU2VjdGlvbihrZXksIHdpZGdldEdyb3Vwcykge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFRvb2xiYXJTZWN0aW9uLCB7IGtleToga2V5LCB3aWRnZXRHcm91cHM6IHdpZGdldEdyb3VwcywgdGl0bGU6IHByb3BzLnRpdGxlLCBuYXZVbml0OiBwcm9wcy5uYXZVbml0LCBhY3RpdmVCdXR0b246IHByb3BzLmFjdGl2ZUJ1dHRvbiwgaXNUb2RheUVuYWJsZWQ6IHByb3BzLmlzVG9kYXlFbmFibGVkLCBpc1ByZXZFbmFibGVkOiBwcm9wcy5pc1ByZXZFbmFibGVkLCBpc05leHRFbmFibGVkOiBwcm9wcy5pc05leHRFbmFibGVkLCB0aXRsZUlkOiBwcm9wcy50aXRsZUlkIH0pKTtcbiAgICB9XG59XG5cbmNsYXNzIFZpZXdIYXJuZXNzIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBhdmFpbGFibGVXaWR0aDogbnVsbCxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVFbCA9IChlbCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbCA9IGVsO1xuICAgICAgICAgICAgc2V0UmVmKHRoaXMucHJvcHMuZWxSZWYsIGVsKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQXZhaWxhYmxlV2lkdGgoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVSZXNpemUgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUF2YWlsYWJsZVdpZHRoKCk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIHN0YXRlIH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBhc3BlY3RSYXRpbyB9ID0gcHJvcHM7XG4gICAgICAgIGxldCBjbGFzc05hbWVzID0gW1xuICAgICAgICAgICAgJ2ZjLXZpZXctaGFybmVzcycsXG4gICAgICAgICAgICAoYXNwZWN0UmF0aW8gfHwgcHJvcHMubGlxdWlkIHx8IHByb3BzLmhlaWdodClcbiAgICAgICAgICAgICAgICA/ICdmYy12aWV3LWhhcm5lc3MtYWN0aXZlJyAvLyBoYXJuZXNzIGNvbnRyb2xzIHRoZSBoZWlnaHRcbiAgICAgICAgICAgICAgICA6ICdmYy12aWV3LWhhcm5lc3MtcGFzc2l2ZScsIC8vIGxldCB0aGUgdmlldyBkbyB0aGUgaGVpZ2h0XG4gICAgICAgIF07XG4gICAgICAgIGxldCBoZWlnaHQgPSAnJztcbiAgICAgICAgbGV0IHBhZGRpbmdCb3R0b20gPSAnJztcbiAgICAgICAgaWYgKGFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICBpZiAoc3RhdGUuYXZhaWxhYmxlV2lkdGggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSBzdGF0ZS5hdmFpbGFibGVXaWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gd2hpbGUgd2FpdGluZyB0byBrbm93IGF2YWlsYWJsZVdpZHRoLCB3ZSBjYW4ndCBzZXQgaGVpZ2h0IHRvICp6ZXJvKlxuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2Ugd2lsbCBjYXVzZSBsb3RzIG9mIHVubmVjZXNzYXJ5IHNjcm9sbGJhcnMgd2l0aGluIHNjcm9sbGdyaWQuXG4gICAgICAgICAgICAgICAgLy8gQkVUVEVSOiBkb24ndCBzdGFydCByZW5kZXJpbmcgQU5ZVEhJTkcgeWV0IHVudGlsIHdlIGtub3cgY29udGFpbmVyIHdpZHRoXG4gICAgICAgICAgICAgICAgLy8gTk9URTogd2h5IG5vdCBhbHdheXMgdXNlIHBhZGRpbmdCb3R0b20/IENhdXNlcyBoZWlnaHQgb3NjaWxsYXRpb24gKGlzc3VlIDU2MDYpXG4gICAgICAgICAgICAgICAgcGFkZGluZ0JvdHRvbSA9IGAkeygxIC8gYXNwZWN0UmF0aW8pICogMTAwfSVgO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaGVpZ2h0ID0gcHJvcHMuaGVpZ2h0IHx8ICcnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IFwiYXJpYS1sYWJlbGxlZGJ5XCI6IHByb3BzLmxhYmVsZWRCeUlkLCByZWY6IHRoaXMuaGFuZGxlRWwsIGNsYXNzTmFtZTogY2xhc3NOYW1lcy5qb2luKCcgJyksIHN0eWxlOiB7IGhlaWdodCwgcGFkZGluZ0JvdHRvbSB9IH0sIHByb3BzLmNoaWxkcmVuKSk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICB0aGlzLmNvbnRleHQuYWRkUmVzaXplSGFuZGxlcih0aGlzLmhhbmRsZVJlc2l6ZSk7XG4gICAgfVxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICB0aGlzLmNvbnRleHQucmVtb3ZlUmVzaXplSGFuZGxlcih0aGlzLmhhbmRsZVJlc2l6ZSk7XG4gICAgfVxuICAgIHVwZGF0ZUF2YWlsYWJsZVdpZHRoKCkge1xuICAgICAgICBpZiAodGhpcy5lbCAmJiAvLyBuZWVkZWQuIGJ1dCB3aHk/XG4gICAgICAgICAgICB0aGlzLnByb3BzLmFzcGVjdFJhdGlvIC8vIGFzcGVjdFJhdGlvIGlzIHRoZSBvbmx5IGhlaWdodCBzZXR0aW5nIHRoYXQgbmVlZHMgYXZhaWxhYmxlV2lkdGhcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgYXZhaWxhYmxlV2lkdGg6IHRoaXMuZWwub2Zmc2V0V2lkdGggfSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qXG5EZXRlY3RzIHdoZW4gdGhlIHVzZXIgY2xpY2tzIG9uIGFuIGV2ZW50IHdpdGhpbiBhIERhdGVDb21wb25lbnRcbiovXG5jbGFzcyBFdmVudENsaWNraW5nIGV4dGVuZHMgSW50ZXJhY3Rpb24ge1xuICAgIGNvbnN0cnVjdG9yKHNldHRpbmdzKSB7XG4gICAgICAgIHN1cGVyKHNldHRpbmdzKTtcbiAgICAgICAgdGhpcy5oYW5kbGVTZWdDbGljayA9IChldiwgc2VnRWwpID0+IHtcbiAgICAgICAgICAgIGxldCB7IGNvbXBvbmVudCB9ID0gdGhpcztcbiAgICAgICAgICAgIGxldCB7IGNvbnRleHQgfSA9IGNvbXBvbmVudDtcbiAgICAgICAgICAgIGxldCBzZWcgPSBnZXRFbFNlZyhzZWdFbCk7XG4gICAgICAgICAgICBpZiAoc2VnICYmIC8vIG1pZ2h0IGJlIHRoZSA8ZGl2PiBzdXJyb3VuZGluZyB0aGUgbW9yZSBsaW5rXG4gICAgICAgICAgICAgICAgY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwoZXYudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgIC8vIG91ciB3YXkgdG8gc2ltdWxhdGUgYSBsaW5rIGNsaWNrIGZvciBlbGVtZW50cyB0aGF0IGNhbid0IGJlIDxhPiB0YWdzXG4gICAgICAgICAgICAgICAgLy8gZ3JhYiBiZWZvcmUgdHJpZ2dlciBmaXJlZCBpbiBjYXNlIHRyaWdnZXIgdHJhc2hlcyBET00gdGhydSByZXJlbmRlcmluZ1xuICAgICAgICAgICAgICAgIGxldCBoYXNVcmxDb250YWluZXIgPSBlbGVtZW50Q2xvc2VzdChldi50YXJnZXQsICcuZmMtZXZlbnQtZm9yY2VkLXVybCcpO1xuICAgICAgICAgICAgICAgIGxldCB1cmwgPSBoYXNVcmxDb250YWluZXIgPyBoYXNVcmxDb250YWluZXIucXVlcnlTZWxlY3RvcignYVtocmVmXScpLmhyZWYgOiAnJztcbiAgICAgICAgICAgICAgICBjb250ZXh0LmVtaXR0ZXIudHJpZ2dlcignZXZlbnRDbGljaycsIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IHNlZ0VsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50SW1wbChjb21wb25lbnQuY29udGV4dCwgc2VnLmV2ZW50UmFuZ2UuZGVmLCBzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2LFxuICAgICAgICAgICAgICAgICAgICB2aWV3OiBjb250ZXh0LnZpZXdBcGksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHVybCAmJiAhZXYuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZGVzdHJveSA9IGxpc3RlbkJ5U2VsZWN0b3Ioc2V0dGluZ3MuZWwsICdjbGljaycsICcuZmMtZXZlbnQnLCAvLyBvbiBib3RoIGZnIGFuZCBiZyBldmVudHNcbiAgICAgICAgdGhpcy5oYW5kbGVTZWdDbGljayk7XG4gICAgfVxufVxuXG4vKlxuVHJpZ2dlcnMgZXZlbnRzIGFuZCBhZGRzL3JlbW92ZXMgY29yZSBjbGFzc05hbWVzIHdoZW4gdGhlIHVzZXIncyBwb2ludGVyXG5lbnRlcnMvbGVhdmVzIGV2ZW50LWVsZW1lbnRzIG9mIGEgY29tcG9uZW50LlxuKi9cbmNsYXNzIEV2ZW50SG92ZXJpbmcgZXh0ZW5kcyBJbnRlcmFjdGlvbiB7XG4gICAgY29uc3RydWN0b3Ioc2V0dGluZ3MpIHtcbiAgICAgICAgc3VwZXIoc2V0dGluZ3MpO1xuICAgICAgICAvLyBmb3Igc2ltdWxhdGluZyBhbiBldmVudE1vdXNlTGVhdmUgd2hlbiB0aGUgZXZlbnQgZWwgaXMgZGVzdHJveWVkIHdoaWxlIG1vdXNlIGlzIG92ZXIgaXRcbiAgICAgICAgdGhpcy5oYW5kbGVFdmVudEVsUmVtb3ZlID0gKGVsKSA9PiB7XG4gICAgICAgICAgICBpZiAoZWwgPT09IHRoaXMuY3VycmVudFNlZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVTZWdMZWF2ZShudWxsLCB0aGlzLmN1cnJlbnRTZWdFbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlU2VnRW50ZXIgPSAoZXYsIHNlZ0VsKSA9PiB7XG4gICAgICAgICAgICBpZiAoZ2V0RWxTZWcoc2VnRWwpKSB7IC8vIFRPRE86IGJldHRlciB3YXkgdG8gbWFrZSBzdXJlIG5vdCBob3ZlcmluZyBvdmVyIG1vcmUrIGxpbmsgb3IgaXRzIHdyYXBwZXJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRTZWdFbCA9IHNlZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlckV2ZW50KCdldmVudE1vdXNlRW50ZXInLCBldiwgc2VnRWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVNlZ0xlYXZlID0gKGV2LCBzZWdFbCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudFNlZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50U2VnRWwgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlckV2ZW50KCdldmVudE1vdXNlTGVhdmUnLCBldiwgc2VnRWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJlbW92ZUhvdmVyTGlzdGVuZXJzID0gbGlzdGVuVG9Ib3ZlckJ5U2VsZWN0b3Ioc2V0dGluZ3MuZWwsICcuZmMtZXZlbnQnLCAvLyBvbiBib3RoIGZnIGFuZCBiZyBldmVudHNcbiAgICAgICAgdGhpcy5oYW5kbGVTZWdFbnRlciwgdGhpcy5oYW5kbGVTZWdMZWF2ZSk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlSG92ZXJMaXN0ZW5lcnMoKTtcbiAgICB9XG4gICAgdHJpZ2dlckV2ZW50KHB1YmxpY0V2TmFtZSwgZXYsIHNlZ0VsKSB7XG4gICAgICAgIGxldCB7IGNvbXBvbmVudCB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgY29udGV4dCB9ID0gY29tcG9uZW50O1xuICAgICAgICBsZXQgc2VnID0gZ2V0RWxTZWcoc2VnRWwpO1xuICAgICAgICBpZiAoIWV2IHx8IGNvbXBvbmVudC5pc1ZhbGlkU2VnRG93bkVsKGV2LnRhcmdldCkpIHtcbiAgICAgICAgICAgIGNvbnRleHQuZW1pdHRlci50cmlnZ2VyKHB1YmxpY0V2TmFtZSwge1xuICAgICAgICAgICAgICAgIGVsOiBzZWdFbCxcbiAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50SW1wbChjb250ZXh0LCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICBqc0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICB2aWV3OiBjb250ZXh0LnZpZXdBcGksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuY2xhc3MgQ2FsZW5kYXJDb250ZW50IGV4dGVuZHMgUHVyZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuYnVpbGRWaWV3Q29udGV4dCA9IG1lbW9pemUoYnVpbGRWaWV3Q29udGV4dCk7XG4gICAgICAgIHRoaXMuYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyA9IG1lbW9pemUoYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyk7XG4gICAgICAgIHRoaXMuYnVpbGRUb29sYmFyUHJvcHMgPSBtZW1vaXplKGJ1aWxkVG9vbGJhclByb3BzKTtcbiAgICAgICAgdGhpcy5oZWFkZXJSZWYgPSBjcmVhdGVSZWYoKTtcbiAgICAgICAgdGhpcy5mb290ZXJSZWYgPSBjcmVhdGVSZWYoKTtcbiAgICAgICAgdGhpcy5pbnRlcmFjdGlvbnNTdG9yZSA9IHt9O1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHZpZXdMYWJlbElkOiBnZXRVbmlxdWVEb21JZCgpLFxuICAgICAgICB9O1xuICAgICAgICAvLyBDb21wb25lbnQgUmVnaXN0cmF0aW9uXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIHRoaXMucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCA9IChjb21wb25lbnQsIHNldHRpbmdzSW5wdXQpID0+IHtcbiAgICAgICAgICAgIGxldCBzZXR0aW5ncyA9IHBhcnNlSW50ZXJhY3Rpb25TZXR0aW5ncyhjb21wb25lbnQsIHNldHRpbmdzSW5wdXQpO1xuICAgICAgICAgICAgbGV0IERFRkFVTFRfSU5URVJBQ1RJT05TID0gW1xuICAgICAgICAgICAgICAgIEV2ZW50Q2xpY2tpbmcsXG4gICAgICAgICAgICAgICAgRXZlbnRIb3ZlcmluZyxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBsZXQgaW50ZXJhY3Rpb25DbGFzc2VzID0gREVGQVVMVF9JTlRFUkFDVElPTlMuY29uY2F0KHRoaXMucHJvcHMucGx1Z2luSG9va3MuY29tcG9uZW50SW50ZXJhY3Rpb25zKTtcbiAgICAgICAgICAgIGxldCBpbnRlcmFjdGlvbnMgPSBpbnRlcmFjdGlvbkNsYXNzZXMubWFwKChUaGVJbnRlcmFjdGlvbkNsYXNzKSA9PiBuZXcgVGhlSW50ZXJhY3Rpb25DbGFzcyhzZXR0aW5ncykpO1xuICAgICAgICAgICAgdGhpcy5pbnRlcmFjdGlvbnNTdG9yZVtjb21wb25lbnQudWlkXSA9IGludGVyYWN0aW9ucztcbiAgICAgICAgICAgIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZVtjb21wb25lbnQudWlkXSA9IHNldHRpbmdzO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnVucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCA9IChjb21wb25lbnQpID0+IHtcbiAgICAgICAgICAgIGxldCBsaXN0ZW5lcnMgPSB0aGlzLmludGVyYWN0aW9uc1N0b3JlW2NvbXBvbmVudC51aWRdO1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIGxpc3RlbmVycykge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lci5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmludGVyYWN0aW9uc1N0b3JlW2NvbXBvbmVudC51aWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZVtjb21wb25lbnQudWlkXTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gUmVzaXppbmdcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgdGhpcy5yZXNpemVSdW5uZXIgPSBuZXcgRGVsYXllZFJ1bm5lcigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLmVtaXR0ZXIudHJpZ2dlcignX3Jlc2l6ZScsIHRydWUpOyAvLyBzaG91bGQgd2luZG93IHJlc2l6ZXMgYmUgY29uc2lkZXJlZCBcImZvcmNlZFwiID9cbiAgICAgICAgICAgIHRoaXMucHJvcHMuZW1pdHRlci50cmlnZ2VyKCd3aW5kb3dSZXNpemUnLCB7IHZpZXc6IHRoaXMucHJvcHMudmlld0FwaSB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaGFuZGxlV2luZG93UmVzaXplID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBvcHRpb25zIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuaGFuZGxlV2luZG93UmVzaXplICYmXG4gICAgICAgICAgICAgICAgZXYudGFyZ2V0ID09PSB3aW5kb3cgLy8gYXZvaWQganF1aSBldmVudHNcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplUnVubmVyLnJlcXVlc3Qob3B0aW9ucy53aW5kb3dSZXNpemVEZWxheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qXG4gICAgcmVuZGVycyBJTlNJREUgb2YgYW4gb3V0ZXIgZGl2XG4gICAgKi9cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyB0b29sYmFyQ29uZmlnLCBvcHRpb25zIH0gPSBwcm9wcztcbiAgICAgICAgbGV0IHZpZXdWR3JvdyA9IGZhbHNlO1xuICAgICAgICBsZXQgdmlld0hlaWdodCA9ICcnO1xuICAgICAgICBsZXQgdmlld0FzcGVjdFJhdGlvO1xuICAgICAgICBpZiAocHJvcHMuaXNIZWlnaHRBdXRvIHx8IHByb3BzLmZvclByaW50KSB7XG4gICAgICAgICAgICB2aWV3SGVpZ2h0ID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3B0aW9ucy5oZWlnaHQgIT0gbnVsbCkge1xuICAgICAgICAgICAgdmlld1ZHcm93ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLmNvbnRlbnRIZWlnaHQgIT0gbnVsbCkge1xuICAgICAgICAgICAgdmlld0hlaWdodCA9IG9wdGlvbnMuY29udGVudEhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZpZXdBc3BlY3RSYXRpbyA9IE1hdGgubWF4KG9wdGlvbnMuYXNwZWN0UmF0aW8sIDAuNSk7IC8vIHByZXZlbnQgZnJvbSBnZXR0aW5nIHRvbyB0YWxsXG4gICAgICAgIH1cbiAgICAgICAgbGV0IHZpZXdDb250ZXh0ID0gdGhpcy5idWlsZFZpZXdDb250ZXh0KHByb3BzLnZpZXdTcGVjLCBwcm9wcy52aWV3QXBpLCBwcm9wcy5vcHRpb25zLCBwcm9wcy5kYXRlUHJvZmlsZUdlbmVyYXRvciwgcHJvcHMuZGF0ZUVudiwgcHJvcHMubm93TWFuYWdlciwgcHJvcHMudGhlbWUsIHByb3BzLnBsdWdpbkhvb2tzLCBwcm9wcy5kaXNwYXRjaCwgcHJvcHMuZ2V0Q3VycmVudERhdGEsIHByb3BzLmVtaXR0ZXIsIHByb3BzLmNhbGVuZGFyQXBpLCB0aGlzLnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQsIHRoaXMudW5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KTtcbiAgICAgICAgbGV0IHZpZXdMYWJlbElkID0gKHRvb2xiYXJDb25maWcuaGVhZGVyICYmIHRvb2xiYXJDb25maWcuaGVhZGVyLmhhc1RpdGxlKVxuICAgICAgICAgICAgPyB0aGlzLnN0YXRlLnZpZXdMYWJlbElkXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFZpZXdDb250ZXh0VHlwZS5Qcm92aWRlciwgeyB2YWx1ZTogdmlld0NvbnRleHQgfSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoTm93VGltZXIsIHsgdW5pdDogXCJkYXlcIiB9LCAobm93RGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCB0b29sYmFyUHJvcHMgPSB0aGlzLmJ1aWxkVG9vbGJhclByb3BzKHByb3BzLnZpZXdTcGVjLCBwcm9wcy5kYXRlUHJvZmlsZSwgcHJvcHMuZGF0ZVByb2ZpbGVHZW5lcmF0b3IsIHByb3BzLmN1cnJlbnREYXRlLCBub3dEYXRlLCBwcm9wcy52aWV3VGl0bGUpO1xuICAgICAgICAgICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChGcmFnbWVudCwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgdG9vbGJhckNvbmZpZy5oZWFkZXIgJiYgKGNyZWF0ZUVsZW1lbnQoVG9vbGJhciwgT2JqZWN0LmFzc2lnbih7IHJlZjogdGhpcy5oZWFkZXJSZWYsIGV4dHJhQ2xhc3NOYW1lOiBcImZjLWhlYWRlci10b29sYmFyXCIsIG1vZGVsOiB0b29sYmFyQ29uZmlnLmhlYWRlciwgdGl0bGVJZDogdmlld0xhYmVsSWQgfSwgdG9vbGJhclByb3BzKSkpLFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFZpZXdIYXJuZXNzLCB7IGxpcXVpZDogdmlld1ZHcm93LCBoZWlnaHQ6IHZpZXdIZWlnaHQsIGFzcGVjdFJhdGlvOiB2aWV3QXNwZWN0UmF0aW8sIGxhYmVsZWRCeUlkOiB2aWV3TGFiZWxJZCB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJWaWV3KHByb3BzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVpbGRBcHBlbmRDb250ZW50KCkpLFxuICAgICAgICAgICAgICAgICAgICB0b29sYmFyQ29uZmlnLmZvb3RlciAmJiAoY3JlYXRlRWxlbWVudChUb29sYmFyLCBPYmplY3QuYXNzaWduKHsgcmVmOiB0aGlzLmZvb3RlclJlZiwgZXh0cmFDbGFzc05hbWU6IFwiZmMtZm9vdGVyLXRvb2xiYXJcIiwgbW9kZWw6IHRvb2xiYXJDb25maWcuZm9vdGVyLCB0aXRsZUlkOiBcIlwiIH0sIHRvb2xiYXJQcm9wcykpKSkpO1xuICAgICAgICAgICAgfSkpKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICB0aGlzLmNhbGVuZGFySW50ZXJhY3Rpb25zID0gcHJvcHMucGx1Z2luSG9va3MuY2FsZW5kYXJJbnRlcmFjdGlvbnNcbiAgICAgICAgICAgIC5tYXAoKENhbGVuZGFySW50ZXJhY3Rpb25DbGFzcykgPT4gbmV3IENhbGVuZGFySW50ZXJhY3Rpb25DbGFzcyhwcm9wcykpO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5oYW5kbGVXaW5kb3dSZXNpemUpO1xuICAgICAgICBsZXQgeyBwcm9wU2V0SGFuZGxlcnMgfSA9IHByb3BzLnBsdWdpbkhvb2tzO1xuICAgICAgICBmb3IgKGxldCBwcm9wTmFtZSBpbiBwcm9wU2V0SGFuZGxlcnMpIHtcbiAgICAgICAgICAgIHByb3BTZXRIYW5kbGVyc1twcm9wTmFtZV0ocHJvcHNbcHJvcE5hbWVdLCBwcm9wcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29tcG9uZW50RGlkVXBkYXRlKHByZXZQcm9wcykge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgcHJvcFNldEhhbmRsZXJzIH0gPSBwcm9wcy5wbHVnaW5Ib29rcztcbiAgICAgICAgZm9yIChsZXQgcHJvcE5hbWUgaW4gcHJvcFNldEhhbmRsZXJzKSB7XG4gICAgICAgICAgICBpZiAocHJvcHNbcHJvcE5hbWVdICE9PSBwcmV2UHJvcHNbcHJvcE5hbWVdKSB7XG4gICAgICAgICAgICAgICAgcHJvcFNldEhhbmRsZXJzW3Byb3BOYW1lXShwcm9wc1twcm9wTmFtZV0sIHByb3BzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuaGFuZGxlV2luZG93UmVzaXplKTtcbiAgICAgICAgdGhpcy5yZXNpemVSdW5uZXIuY2xlYXIoKTtcbiAgICAgICAgZm9yIChsZXQgaW50ZXJhY3Rpb24gb2YgdGhpcy5jYWxlbmRhckludGVyYWN0aW9ucykge1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJvcHMuZW1pdHRlci50cmlnZ2VyKCdfdW5tb3VudCcpO1xuICAgIH1cbiAgICBidWlsZEFwcGVuZENvbnRlbnQoKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgY2hpbGRyZW4gPSBwcm9wcy5wbHVnaW5Ib29rcy52aWV3Q29udGFpbmVyQXBwZW5kcy5tYXAoKGJ1aWxkQXBwZW5kQ29udGVudCkgPT4gYnVpbGRBcHBlbmRDb250ZW50KHByb3BzKSk7XG4gICAgICAgIHJldHVybiBjcmVhdGVFbGVtZW50KEZyYWdtZW50LCB7fSwgLi4uY2hpbGRyZW4pO1xuICAgIH1cbiAgICByZW5kZXJWaWV3KHByb3BzKSB7XG4gICAgICAgIGxldCB7IHBsdWdpbkhvb2tzIH0gPSBwcm9wcztcbiAgICAgICAgbGV0IHsgdmlld1NwZWMgfSA9IHByb3BzO1xuICAgICAgICBsZXQgdmlld1Byb3BzID0ge1xuICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IHByb3BzLmRhdGVQcm9maWxlLFxuICAgICAgICAgICAgYnVzaW5lc3NIb3VyczogcHJvcHMuYnVzaW5lc3NIb3VycyxcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IHByb3BzLnJlbmRlcmFibGVFdmVudFN0b3JlLFxuICAgICAgICAgICAgZXZlbnRVaUJhc2VzOiBwcm9wcy5ldmVudFVpQmFzZXMsXG4gICAgICAgICAgICBkYXRlU2VsZWN0aW9uOiBwcm9wcy5kYXRlU2VsZWN0aW9uLFxuICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246IHByb3BzLmV2ZW50U2VsZWN0aW9uLFxuICAgICAgICAgICAgZXZlbnREcmFnOiBwcm9wcy5ldmVudERyYWcsXG4gICAgICAgICAgICBldmVudFJlc2l6ZTogcHJvcHMuZXZlbnRSZXNpemUsXG4gICAgICAgICAgICBpc0hlaWdodEF1dG86IHByb3BzLmlzSGVpZ2h0QXV0byxcbiAgICAgICAgICAgIGZvclByaW50OiBwcm9wcy5mb3JQcmludCxcbiAgICAgICAgfTtcbiAgICAgICAgbGV0IHRyYW5zZm9ybWVycyA9IHRoaXMuYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyhwbHVnaW5Ib29rcy52aWV3UHJvcHNUcmFuc2Zvcm1lcnMpO1xuICAgICAgICBmb3IgKGxldCB0cmFuc2Zvcm1lciBvZiB0cmFuc2Zvcm1lcnMpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odmlld1Byb3BzLCB0cmFuc2Zvcm1lci50cmFuc2Zvcm0odmlld1Byb3BzLCBwcm9wcykpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBWaWV3Q29tcG9uZW50ID0gdmlld1NwZWMuY29tcG9uZW50O1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoVmlld0NvbXBvbmVudCwgT2JqZWN0LmFzc2lnbih7fSwgdmlld1Byb3BzKSkpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGJ1aWxkVG9vbGJhclByb3BzKHZpZXdTcGVjLCBkYXRlUHJvZmlsZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IsIGN1cnJlbnREYXRlLCBub3csIHRpdGxlKSB7XG4gICAgLy8gZG9uJ3QgZm9yY2UgYW55IGRhdGUtcHJvZmlsZXMgdG8gdmFsaWQgZGF0ZSBwcm9maWxlcyAodGhlIGBmYWxzZWApIHNvIHRoYXQgd2UgY2FuIHRlbGwgaWYgaXQncyBpbnZhbGlkXG4gICAgbGV0IHRvZGF5SW5mbyA9IGRhdGVQcm9maWxlR2VuZXJhdG9yLmJ1aWxkKG5vdywgdW5kZWZpbmVkLCBmYWxzZSk7IC8vIFRPRE86IG5lZWQgYHVuZGVmaW5lZGAgb3IgZWxzZSBJTkZJTklURSBMT09QIGZvciBzb21lIHJlYXNvblxuICAgIGxldCBwcmV2SW5mbyA9IGRhdGVQcm9maWxlR2VuZXJhdG9yLmJ1aWxkUHJldihkYXRlUHJvZmlsZSwgY3VycmVudERhdGUsIGZhbHNlKTtcbiAgICBsZXQgbmV4dEluZm8gPSBkYXRlUHJvZmlsZUdlbmVyYXRvci5idWlsZE5leHQoZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlLCBmYWxzZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGl0bGUsXG4gICAgICAgIGFjdGl2ZUJ1dHRvbjogdmlld1NwZWMudHlwZSxcbiAgICAgICAgbmF2VW5pdDogdmlld1NwZWMuc2luZ2xlVW5pdCxcbiAgICAgICAgaXNUb2RheUVuYWJsZWQ6IHRvZGF5SW5mby5pc1ZhbGlkICYmICFyYW5nZUNvbnRhaW5zTWFya2VyKGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZSwgbm93KSxcbiAgICAgICAgaXNQcmV2RW5hYmxlZDogcHJldkluZm8uaXNWYWxpZCxcbiAgICAgICAgaXNOZXh0RW5hYmxlZDogbmV4dEluZm8uaXNWYWxpZCxcbiAgICB9O1xufVxuLy8gUGx1Z2luXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyh0aGVDbGFzc2VzKSB7XG4gICAgcmV0dXJuIHRoZUNsYXNzZXMubWFwKChUaGVDbGFzcykgPT4gbmV3IFRoZUNsYXNzKCkpO1xufVxuXG5jbGFzcyBDYWxlbmRhciBleHRlbmRzIENhbGVuZGFySW1wbCB7XG4gICAgY29uc3RydWN0b3IoZWwsIG9wdGlvbk92ZXJyaWRlcyA9IHt9KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuaXNSZW5kZXJpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1JlbmRlcmVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY3VycmVudENsYXNzTmFtZXMgPSBbXTtcbiAgICAgICAgdGhpcy5jdXN0b21Db250ZW50UmVuZGVySWQgPSAwO1xuICAgICAgICB0aGlzLmhhbmRsZUFjdGlvbiA9IChhY3Rpb24pID0+IHtcbiAgICAgICAgICAgIC8vIGFjdGlvbnMgd2Uga25vdyB3ZSB3YW50IHRvIHJlbmRlciBpbW1lZGlhdGVseVxuICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ1NFVF9FVkVOVF9EUkFHJzpcbiAgICAgICAgICAgICAgICBjYXNlICdTRVRfRVZFTlRfUkVTSVpFJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJSdW5uZXIudHJ5RHJhaW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVEYXRhID0gKGRhdGEpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudERhdGEgPSBkYXRhO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJSdW5uZXIucmVxdWVzdChkYXRhLmNhbGVuZGFyT3B0aW9ucy5yZXJlbmRlckRlbGF5KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVSZW5kZXJSZXF1ZXN0ID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNSZW5kZXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlzUmVuZGVyZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGxldCB7IGN1cnJlbnREYXRhIH0gPSB0aGlzO1xuICAgICAgICAgICAgICAgIGZsdXNoU3luYygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcihjcmVhdGVFbGVtZW50KENhbGVuZGFyUm9vdCwgeyBvcHRpb25zOiBjdXJyZW50RGF0YS5jYWxlbmRhck9wdGlvbnMsIHRoZW1lOiBjdXJyZW50RGF0YS50aGVtZSwgZW1pdHRlcjogY3VycmVudERhdGEuZW1pdHRlciB9LCAoY2xhc3NOYW1lcywgaGVpZ2h0LCBpc0hlaWdodEF1dG8sIGZvclByaW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldENsYXNzTmFtZXMoY2xhc3NOYW1lcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEhlaWdodChoZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFJlbmRlcklkLlByb3ZpZGVyLCB7IHZhbHVlOiB0aGlzLmN1c3RvbUNvbnRlbnRSZW5kZXJJZCB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoQ2FsZW5kYXJDb250ZW50LCBPYmplY3QuYXNzaWduKHsgaXNIZWlnaHRBdXRvOiBpc0hlaWdodEF1dG8sIGZvclByaW50OiBmb3JQcmludCB9LCBjdXJyZW50RGF0YSkpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLCB0aGlzLmVsKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuaXNSZW5kZXJlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNSZW5kZXJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlbmRlcihudWxsLCB0aGlzLmVsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldENsYXNzTmFtZXMoW10pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGVpZ2h0KCcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgZW5zdXJlRWxIYXNTdHlsZXMoZWwpO1xuICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgICAgIHRoaXMucmVuZGVyUnVubmVyID0gbmV3IERlbGF5ZWRSdW5uZXIodGhpcy5oYW5kbGVSZW5kZXJSZXF1ZXN0KTtcbiAgICAgICAgbmV3IENhbGVuZGFyRGF0YU1hbmFnZXIoe1xuICAgICAgICAgICAgb3B0aW9uT3ZlcnJpZGVzLFxuICAgICAgICAgICAgY2FsZW5kYXJBcGk6IHRoaXMsXG4gICAgICAgICAgICBvbkFjdGlvbjogdGhpcy5oYW5kbGVBY3Rpb24sXG4gICAgICAgICAgICBvbkRhdGE6IHRoaXMuaGFuZGxlRGF0YSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHdhc1JlbmRlcmluZyA9IHRoaXMuaXNSZW5kZXJpbmc7XG4gICAgICAgIGlmICghd2FzUmVuZGVyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmlzUmVuZGVyaW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY3VzdG9tQ29udGVudFJlbmRlcklkICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJSdW5uZXIucmVxdWVzdCgpO1xuICAgICAgICBpZiAod2FzUmVuZGVyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNpemUoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5pc1JlbmRlcmluZykge1xuICAgICAgICAgICAgdGhpcy5pc1JlbmRlcmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJSdW5uZXIucmVxdWVzdCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHVwZGF0ZVNpemUoKSB7XG4gICAgICAgIGZsdXNoU3luYygoKSA9PiB7XG4gICAgICAgICAgICBzdXBlci51cGRhdGVTaXplKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBiYXRjaFJlbmRlcmluZyhmdW5jKSB7XG4gICAgICAgIHRoaXMucmVuZGVyUnVubmVyLnBhdXNlKCdiYXRjaFJlbmRlcmluZycpO1xuICAgICAgICBmdW5jKCk7XG4gICAgICAgIHRoaXMucmVuZGVyUnVubmVyLnJlc3VtZSgnYmF0Y2hSZW5kZXJpbmcnKTtcbiAgICB9XG4gICAgcGF1c2VSZW5kZXJpbmcoKSB7XG4gICAgICAgIHRoaXMucmVuZGVyUnVubmVyLnBhdXNlKCdwYXVzZVJlbmRlcmluZycpO1xuICAgIH1cbiAgICByZXN1bWVSZW5kZXJpbmcoKSB7XG4gICAgICAgIHRoaXMucmVuZGVyUnVubmVyLnJlc3VtZSgncGF1c2VSZW5kZXJpbmcnLCB0cnVlKTtcbiAgICB9XG4gICAgcmVzZXRPcHRpb25zKG9wdGlvbk92ZXJyaWRlcywgY2hhbmdlZE9wdGlvbk5hbWVzKSB7XG4gICAgICAgIHRoaXMuY3VycmVudERhdGFNYW5hZ2VyLnJlc2V0T3B0aW9ucyhvcHRpb25PdmVycmlkZXMsIGNoYW5nZWRPcHRpb25OYW1lcyk7XG4gICAgfVxuICAgIHNldENsYXNzTmFtZXMoY2xhc3NOYW1lcykge1xuICAgICAgICBpZiAoIWlzQXJyYXlzRXF1YWwoY2xhc3NOYW1lcywgdGhpcy5jdXJyZW50Q2xhc3NOYW1lcykpIHtcbiAgICAgICAgICAgIGxldCB7IGNsYXNzTGlzdCB9ID0gdGhpcy5lbDtcbiAgICAgICAgICAgIGZvciAobGV0IGNsYXNzTmFtZSBvZiB0aGlzLmN1cnJlbnRDbGFzc05hbWVzKSB7XG4gICAgICAgICAgICAgICAgY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgY2xhc3NOYW1lIG9mIGNsYXNzTmFtZXMpIHtcbiAgICAgICAgICAgICAgICBjbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRDbGFzc05hbWVzID0gY2xhc3NOYW1lcztcbiAgICAgICAgfVxuICAgIH1cbiAgICBzZXRIZWlnaHQoaGVpZ2h0KSB7XG4gICAgICAgIGFwcGx5U3R5bGVQcm9wKHRoaXMuZWwsICdoZWlnaHQnLCBoZWlnaHQpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZm9ybWF0RGF0ZShkYXRlSW5wdXQsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBkYXRlRW52ID0gYnVpbGREYXRlRW52KG9wdGlvbnMpO1xuICAgIGxldCBmb3JtYXR0ZXIgPSBjcmVhdGVGb3JtYXR0ZXIob3B0aW9ucyk7XG4gICAgbGV0IGRhdGVNZXRhID0gZGF0ZUVudi5jcmVhdGVNYXJrZXJNZXRhKGRhdGVJbnB1dCk7XG4gICAgaWYgKCFkYXRlTWV0YSkgeyAvLyBUT0RPOiB3YXJuaW5nP1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiBkYXRlRW52LmZvcm1hdChkYXRlTWV0YS5tYXJrZXIsIGZvcm1hdHRlciwge1xuICAgICAgICBmb3JjZWRUem86IGRhdGVNZXRhLmZvcmNlZFR6byxcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGZvcm1hdFJhbmdlKHN0YXJ0SW5wdXQsIGVuZElucHV0LCBvcHRpb25zKSB7XG4gICAgbGV0IGRhdGVFbnYgPSBidWlsZERhdGVFbnYodHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnICYmIG9wdGlvbnMgPyBvcHRpb25zIDoge30pOyAvLyBwYXNzIGluIGlmIG5vbi1udWxsIG9iamVjdFxuICAgIGxldCBmb3JtYXR0ZXIgPSBjcmVhdGVGb3JtYXR0ZXIob3B0aW9ucyk7XG4gICAgbGV0IHN0YXJ0TWV0YSA9IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShzdGFydElucHV0KTtcbiAgICBsZXQgZW5kTWV0YSA9IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShlbmRJbnB1dCk7XG4gICAgaWYgKCFzdGFydE1ldGEgfHwgIWVuZE1ldGEpIHsgLy8gVE9ETzogd2FybmluZz9cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXRSYW5nZShzdGFydE1ldGEubWFya2VyLCBlbmRNZXRhLm1hcmtlciwgZm9ybWF0dGVyLCB7XG4gICAgICAgIGZvcmNlZFN0YXJ0VHpvOiBzdGFydE1ldGEuZm9yY2VkVHpvLFxuICAgICAgICBmb3JjZWRFbmRUem86IGVuZE1ldGEuZm9yY2VkVHpvLFxuICAgICAgICBpc0VuZEV4Y2x1c2l2ZTogb3B0aW9ucy5pc0VuZEV4Y2x1c2l2ZSxcbiAgICAgICAgZGVmYXVsdFNlcGFyYXRvcjogQkFTRV9PUFRJT05fREVGQVVMVFMuZGVmYXVsdFJhbmdlU2VwYXJhdG9yLFxuICAgIH0pO1xufVxuLy8gVE9ETzogbW9yZSBEUlkgYW5kIG9wdGltaXplZFxuZnVuY3Rpb24gYnVpbGREYXRlRW52KHNldHRpbmdzKSB7XG4gICAgbGV0IGxvY2FsZSA9IGJ1aWxkTG9jYWxlKHNldHRpbmdzLmxvY2FsZSB8fCAnZW4nLCBvcmdhbml6ZVJhd0xvY2FsZXMoW10pLm1hcCk7IC8vIFRPRE86IGRvbid0IGhhcmRjb2RlICdlbicgZXZlcnl3aGVyZVxuICAgIHJldHVybiBuZXcgRGF0ZUVudihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oeyB0aW1lWm9uZTogQkFTRV9PUFRJT05fREVGQVVMVFMudGltZVpvbmUsIGNhbGVuZGFyU3lzdGVtOiAnZ3JlZ29yeScgfSwgc2V0dGluZ3MpLCB7IGxvY2FsZSB9KSk7XG59XG5cbi8vIEhFTFBFUlNcbi8qXG5pZiBuZXh0RGF5VGhyZXNob2xkIGlzIHNwZWNpZmllZCwgc2xpY2luZyBpcyBkb25lIGluIGFuIGFsbC1kYXkgZmFzaGlvbi5cbnlvdSBjYW4gZ2V0IG5leHREYXlUaHJlc2hvbGQgZnJvbSBjb250ZXh0Lm5leHREYXlUaHJlc2hvbGRcbiovXG5mdW5jdGlvbiBzbGljZUV2ZW50cyhwcm9wcywgYWxsRGF5KSB7XG4gICAgcmV0dXJuIHNsaWNlRXZlbnRTdG9yZShwcm9wcy5ldmVudFN0b3JlLCBwcm9wcy5ldmVudFVpQmFzZXMsIHByb3BzLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBhbGxEYXkgPyBwcm9wcy5uZXh0RGF5VGhyZXNob2xkIDogbnVsbCkuZmc7XG59XG5cbmNvbnN0IHZlcnNpb24gPSAnNi4xLjE5JztcblxuZXhwb3J0IHsgQ2FsZW5kYXIsIGNyZWF0ZVBsdWdpbiwgZm9ybWF0RGF0ZSwgZm9ybWF0UmFuZ2UsIGdsb2JhbExvY2FsZXMsIGdsb2JhbFBsdWdpbnMsIHNsaWNlRXZlbnRzLCB2ZXJzaW9uIH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///112\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 113:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ $: () => (/* binding */ listenBySelector),\n/* harmony export */ A: () => (/* binding */ memoizeObjArg),\n/* harmony export */ B: () => (/* binding */ BaseComponent),\n/* harmony export */ C: () => (/* binding */ ContentContainer),\n/* harmony export */ D: () => (/* binding */ DelayedRunner),\n/* harmony export */ E: () => (/* binding */ isPropsEqual),\n/* harmony export */ F: () => (/* binding */ Emitter),\n/* harmony export */ G: () => (/* binding */ rangeContainsMarker),\n/* harmony export */ H: () => (/* binding */ createEmptyEventStore),\n/* harmony export */ I: () => (/* binding */ reduceEventStore),\n/* harmony export */ J: () => (/* binding */ rezoneEventStoreDates),\n/* harmony export */ K: () => (/* binding */ mergeRawOptions),\n/* harmony export */ L: () => (/* binding */ BASE_OPTION_REFINERS),\n/* harmony export */ M: () => (/* binding */ CALENDAR_LISTENER_REFINERS),\n/* harmony export */ N: () => (/* binding */ CALENDAR_OPTION_REFINERS),\n/* harmony export */ O: () => (/* binding */ COMPLEX_OPTION_COMPARATORS),\n/* harmony export */ P: () => (/* binding */ VIEW_OPTION_REFINERS),\n/* harmony export */ Q: () => (/* binding */ DateEnv),\n/* harmony export */ R: () => (/* binding */ DateProfileGenerator),\n/* harmony export */ S: () => (/* binding */ createEventUi),\n/* harmony export */ T: () => (/* binding */ Theme),\n/* harmony export */ U: () => (/* binding */ parseBusinessHours),\n/* harmony export */ V: () => (/* binding */ ViewContextType),\n/* harmony export */ W: () => (/* binding */ setRef),\n/* harmony export */ X: () => (/* binding */ Interaction),\n/* harmony export */ Y: () => (/* binding */ getElSeg),\n/* harmony export */ Z: () => (/* binding */ elementClosest),\n/* harmony export */ _: () => (/* binding */ EventImpl),\n/* harmony export */ a: () => (/* binding */ mapHash),\n/* harmony export */ a$: () => (/* binding */ preventDefault),\n/* harmony export */ a0: () => (/* binding */ listenToHoverBySelector),\n/* harmony export */ a1: () => (/* binding */ PureComponent),\n/* harmony export */ a2: () => (/* binding */ buildViewContext),\n/* harmony export */ a3: () => (/* binding */ getUniqueDomId),\n/* harmony export */ a4: () => (/* binding */ parseInteractionSettings),\n/* harmony export */ a5: () => (/* binding */ interactionSettingsStore),\n/* harmony export */ a6: () => (/* binding */ NowTimer),\n/* harmony export */ a7: () => (/* binding */ CalendarImpl),\n/* harmony export */ a8: () => (/* binding */ flushSync),\n/* harmony export */ a9: () => (/* binding */ CalendarRoot),\n/* harmony export */ aA: () => (/* binding */ memoizeArraylike),\n/* harmony export */ aB: () => (/* binding */ memoizeHashlike),\n/* harmony export */ aC: () => (/* binding */ intersectRects),\n/* harmony export */ aD: () => (/* binding */ pointInsideRect),\n/* harmony export */ aE: () => (/* binding */ constrainPoint),\n/* harmony export */ aF: () => (/* binding */ getRectCenter),\n/* harmony export */ aG: () => (/* binding */ diffPoints),\n/* harmony export */ aH: () => (/* binding */ translateRect),\n/* harmony export */ aI: () => (/* binding */ compareObjs),\n/* harmony export */ aJ: () => (/* binding */ collectFromHash),\n/* harmony export */ aK: () => (/* binding */ findElements),\n/* harmony export */ aL: () => (/* binding */ findDirectChildren),\n/* harmony export */ aM: () => (/* binding */ removeElement),\n/* harmony export */ aN: () => (/* binding */ applyStyle),\n/* harmony export */ aO: () => (/* binding */ elementMatches),\n/* harmony export */ aP: () => (/* binding */ getEventTargetViaRoot),\n/* harmony export */ aQ: () => (/* binding */ parseClassNames),\n/* harmony export */ aR: () => (/* binding */ getCanVGrowWithinCell),\n/* harmony export */ aS: () => (/* binding */ mergeEventStores),\n/* harmony export */ aT: () => (/* binding */ getRelevantEvents),\n/* harmony export */ aU: () => (/* binding */ eventTupleToStore),\n/* harmony export */ aV: () => (/* binding */ combineEventUis),\n/* harmony export */ aW: () => (/* binding */ Splitter),\n/* harmony export */ aX: () => (/* binding */ getDayClassNames),\n/* harmony export */ aY: () => (/* binding */ getDateMeta),\n/* harmony export */ aZ: () => (/* binding */ getSlotClassNames),\n/* harmony export */ a_: () => (/* binding */ buildNavLinkAttrs),\n/* harmony export */ aa: () => (/* binding */ RenderId),\n/* harmony export */ ab: () => (/* binding */ ensureElHasStyles),\n/* harmony export */ ac: () => (/* binding */ applyStyleProp),\n/* harmony export */ ad: () => (/* binding */ sliceEventStore),\n/* harmony export */ ae: () => (/* binding */ JsonRequestError),\n/* harmony export */ af: () => (/* binding */ createContext),\n/* harmony export */ ag: () => (/* binding */ refineProps),\n/* harmony export */ ah: () => (/* binding */ createEventInstance),\n/* harmony export */ ai: () => (/* binding */ parseEventDef),\n/* harmony export */ aj: () => (/* binding */ refineEventDef),\n/* harmony export */ ak: () => (/* binding */ padStart),\n/* harmony export */ al: () => (/* binding */ isInt),\n/* harmony export */ am: () => (/* binding */ parseFieldSpecs),\n/* harmony export */ an: () => (/* binding */ compareByFieldSpecs),\n/* harmony export */ ao: () => (/* binding */ flexibleCompare),\n/* harmony export */ ap: () => (/* binding */ preventSelection),\n/* harmony export */ aq: () => (/* binding */ allowSelection),\n/* harmony export */ ar: () => (/* binding */ preventContextMenu),\n/* harmony export */ as: () => (/* binding */ allowContextMenu),\n/* harmony export */ at: () => (/* binding */ compareNumbers),\n/* harmony export */ au: () => (/* binding */ enableCursor),\n/* harmony export */ av: () => (/* binding */ disableCursor),\n/* harmony export */ aw: () => (/* binding */ computeVisibleDayRange),\n/* harmony export */ ax: () => (/* binding */ isMultiDayRange),\n/* harmony export */ ay: () => (/* binding */ diffDates),\n/* harmony export */ az: () => (/* binding */ removeExact),\n/* harmony export */ b: () => (/* binding */ buildViewClassNames),\n/* harmony export */ b$: () => (/* binding */ renderMicroColGroup),\n/* harmony export */ b0: () => (/* binding */ whenTransitionDone),\n/* harmony export */ b1: () => (/* binding */ computeInnerRect),\n/* harmony export */ b2: () => (/* binding */ computeEdges),\n/* harmony export */ b3: () => (/* binding */ getClippingParents),\n/* harmony export */ b4: () => (/* binding */ computeRect),\n/* harmony export */ b5: () => (/* binding */ rangesEqual),\n/* harmony export */ b6: () => (/* binding */ rangesIntersect),\n/* harmony export */ b7: () => (/* binding */ rangeContainsRange),\n/* harmony export */ b8: () => (/* binding */ PositionCache),\n/* harmony export */ b9: () => (/* binding */ ScrollController),\n/* harmony export */ bA: () => (/* binding */ getEntrySpanEnd),\n/* harmony export */ bB: () => (/* binding */ binarySearch),\n/* harmony export */ bC: () => (/* binding */ groupIntersectingEntries),\n/* harmony export */ bD: () => (/* binding */ intersectSpans),\n/* harmony export */ bE: () => (/* binding */ interactionSettingsToStore),\n/* harmony export */ bF: () => (/* binding */ ElementDragging),\n/* harmony export */ bG: () => (/* binding */ config),\n/* harmony export */ bH: () => (/* binding */ parseDragMeta),\n/* harmony export */ bI: () => (/* binding */ DayHeader),\n/* harmony export */ bJ: () => (/* binding */ computeFallbackHeaderFormat),\n/* harmony export */ bK: () => (/* binding */ TableDateCell),\n/* harmony export */ bL: () => (/* binding */ TableDowCell),\n/* harmony export */ bM: () => (/* binding */ DaySeriesModel),\n/* harmony export */ bN: () => (/* binding */ hasBgRendering),\n/* harmony export */ bO: () => (/* binding */ buildSegTimeText),\n/* harmony export */ bP: () => (/* binding */ sortEventSegs),\n/* harmony export */ bQ: () => (/* binding */ getSegMeta),\n/* harmony export */ bR: () => (/* binding */ buildEventRangeKey),\n/* harmony export */ bS: () => (/* binding */ getSegAnchorAttrs),\n/* harmony export */ bT: () => (/* binding */ DayTableModel),\n/* harmony export */ bU: () => (/* binding */ Slicer),\n/* harmony export */ bV: () => (/* binding */ applyMutationToEventStore),\n/* harmony export */ bW: () => (/* binding */ isPropsValid),\n/* harmony export */ bX: () => (/* binding */ isInteractionValid),\n/* harmony export */ bY: () => (/* binding */ isDateSelectionValid),\n/* harmony export */ bZ: () => (/* binding */ SimpleScrollGrid),\n/* harmony export */ b_: () => (/* binding */ hasShrinkWidth),\n/* harmony export */ ba: () => (/* binding */ ElementScrollController),\n/* harmony export */ bb: () => (/* binding */ WindowScrollController),\n/* harmony export */ bc: () => (/* binding */ DateComponent),\n/* harmony export */ bd: () => (/* binding */ isDateSpansEqual),\n/* harmony export */ be: () => (/* binding */ addMs),\n/* harmony export */ bf: () => (/* binding */ addWeeks),\n/* harmony export */ bg: () => (/* binding */ diffWeeks),\n/* harmony export */ bh: () => (/* binding */ diffWholeWeeks),\n/* harmony export */ bi: () => (/* binding */ diffDayAndTime),\n/* harmony export */ bj: () => (/* binding */ diffDays),\n/* harmony export */ bk: () => (/* binding */ isValidDate),\n/* harmony export */ bl: () => (/* binding */ asCleanDays),\n/* harmony export */ bm: () => (/* binding */ multiplyDuration),\n/* harmony export */ bn: () => (/* binding */ addDurations),\n/* harmony export */ bo: () => (/* binding */ asRoughMinutes),\n/* harmony export */ bp: () => (/* binding */ asRoughSeconds),\n/* harmony export */ bq: () => (/* binding */ asRoughMs),\n/* harmony export */ br: () => (/* binding */ wholeDivideDurations),\n/* harmony export */ bs: () => (/* binding */ formatIsoTimeString),\n/* harmony export */ bt: () => (/* binding */ formatDayString),\n/* harmony export */ bu: () => (/* binding */ buildIsoString),\n/* harmony export */ bv: () => (/* binding */ formatIsoMonthStr),\n/* harmony export */ bw: () => (/* binding */ NamedTimeZoneImpl),\n/* harmony export */ bx: () => (/* binding */ parse),\n/* harmony export */ by: () => (/* binding */ SegHierarchy),\n/* harmony export */ bz: () => (/* binding */ buildEntryKey),\n/* harmony export */ c: () => (/* binding */ greatestDurationDenominator),\n/* harmony export */ c0: () => (/* binding */ getScrollGridClassNames),\n/* harmony export */ c1: () => (/* binding */ getSectionClassNames),\n/* harmony export */ c2: () => (/* binding */ getSectionHasLiquidHeight),\n/* harmony export */ c3: () => (/* binding */ getAllowYScrolling),\n/* harmony export */ c4: () => (/* binding */ renderChunkContent),\n/* harmony export */ c5: () => (/* binding */ computeShrinkWidth),\n/* harmony export */ c6: () => (/* binding */ sanitizeShrinkWidth),\n/* harmony export */ c7: () => (/* binding */ isColPropsEqual),\n/* harmony export */ c8: () => (/* binding */ renderScrollShim),\n/* harmony export */ c9: () => (/* binding */ getStickyFooterScrollbar),\n/* harmony export */ ca: () => (/* binding */ getStickyHeaderDates),\n/* harmony export */ cb: () => (/* binding */ Scroller),\n/* harmony export */ cc: () => (/* binding */ getScrollbarWidths),\n/* harmony export */ cd: () => (/* binding */ RefMap),\n/* harmony export */ ce: () => (/* binding */ getIsRtlScrollbarOnLeft),\n/* harmony export */ cf: () => (/* binding */ ScrollResponder),\n/* harmony export */ cg: () => (/* binding */ StandardEvent),\n/* harmony export */ ch: () => (/* binding */ NowIndicatorContainer),\n/* harmony export */ ci: () => (/* binding */ DayCellContainer),\n/* harmony export */ cj: () => (/* binding */ hasCustomDayCellContent),\n/* harmony export */ ck: () => (/* binding */ EventContainer),\n/* harmony export */ cl: () => (/* binding */ renderFill),\n/* harmony export */ cm: () => (/* binding */ BgEvent),\n/* harmony export */ cn: () => (/* binding */ WeekNumberContainer),\n/* harmony export */ co: () => (/* binding */ MoreLinkContainer),\n/* harmony export */ cp: () => (/* binding */ computeEarliestSegStart),\n/* harmony export */ cq: () => (/* binding */ ViewContainer),\n/* harmony export */ cr: () => (/* binding */ triggerDateSelect),\n/* harmony export */ cs: () => (/* binding */ getDefaultEventEnd),\n/* harmony export */ ct: () => (/* binding */ injectStyles),\n/* harmony export */ cu: () => (/* binding */ buildElAttrs),\n/* harmony export */ cv: () => (/* binding */ CustomRenderingStore),\n/* harmony export */ d: () => (/* binding */ createDuration),\n/* harmony export */ e: () => (/* binding */ BASE_OPTION_DEFAULTS),\n/* harmony export */ f: () => (/* binding */ arrayToHash),\n/* harmony export */ g: () => (/* binding */ guid),\n/* harmony export */ h: () => (/* binding */ filterHash),\n/* harmony export */ i: () => (/* binding */ isArraysEqual),\n/* harmony export */ j: () => (/* binding */ buildEventSourceRefiners),\n/* harmony export */ k: () => (/* binding */ formatWithOrdinals),\n/* harmony export */ l: () => (/* binding */ buildRangeApiWithTimeZone),\n/* harmony export */ m: () => (/* binding */ mergeProps),\n/* harmony export */ n: () => (/* binding */ identity),\n/* harmony export */ o: () => (/* binding */ intersectRanges),\n/* harmony export */ p: () => (/* binding */ parseEventSource),\n/* harmony export */ q: () => (/* binding */ startOfDay),\n/* harmony export */ r: () => (/* binding */ requestJson),\n/* harmony export */ s: () => (/* binding */ subtractDurations),\n/* harmony export */ t: () => (/* binding */ addDays),\n/* harmony export */ u: () => (/* binding */ unpromisify),\n/* harmony export */ v: () => (/* binding */ hashValuesToArray),\n/* harmony export */ w: () => (/* binding */ buildEventApis),\n/* harmony export */ x: () => (/* binding */ createFormatter),\n/* harmony export */ y: () => (/* binding */ diffWholeDays),\n/* harmony export */ z: () => (/* binding */ memoize)\n/* harmony export */ });\n/* harmony import */ var preact__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(114);\n/* harmony import */ var preact_compat__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(115);\n\n\n\n\nconst styleTexts = [];\nconst styleEls = new Map();\nfunction injectStyles(styleText) {\n styleTexts.push(styleText);\n styleEls.forEach((styleEl) => {\n appendStylesTo(styleEl, styleText);\n });\n}\nfunction ensureElHasStyles(el) {\n if (el.isConnected && // sometimes true if SSR system simulates DOM\n el.getRootNode // sometimes undefined if SSR system simulates DOM\n ) {\n registerStylesRoot(el.getRootNode());\n }\n}\nfunction registerStylesRoot(rootNode) {\n let styleEl = styleEls.get(rootNode);\n if (!styleEl || !styleEl.isConnected) {\n styleEl = rootNode.querySelector('style[data-fullcalendar]');\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.setAttribute('data-fullcalendar', '');\n const nonce = getNonceValue();\n if (nonce) {\n styleEl.nonce = nonce;\n }\n const parentEl = rootNode === document ? document.head : rootNode;\n const insertBefore = rootNode === document\n ? parentEl.querySelector('script,link[rel=stylesheet],link[as=style],style')\n : parentEl.firstChild;\n parentEl.insertBefore(styleEl, insertBefore);\n }\n styleEls.set(rootNode, styleEl);\n hydrateStylesRoot(styleEl);\n }\n}\nfunction hydrateStylesRoot(styleEl) {\n for (const styleText of styleTexts) {\n appendStylesTo(styleEl, styleText);\n }\n}\nfunction appendStylesTo(styleEl, styleText) {\n const { sheet } = styleEl;\n const ruleCnt = sheet.cssRules.length;\n styleText.split('}').forEach((styleStr, i) => {\n styleStr = styleStr.trim();\n if (styleStr) {\n sheet.insertRule(styleStr + '}', ruleCnt + i);\n }\n });\n}\n// nonce\n// -------------------------------------------------------------------------------------------------\nlet queriedNonceValue;\nfunction getNonceValue() {\n if (queriedNonceValue === undefined) {\n queriedNonceValue = queryNonceValue();\n }\n return queriedNonceValue;\n}\n/*\nTODO: discourage meta tag and instead put nonce attribute on placeholder <style> tag\n*/\nfunction queryNonceValue() {\n const metaWithNonce = document.querySelector('meta[name=\"csp-nonce\"]');\n if (metaWithNonce && metaWithNonce.hasAttribute('content')) {\n return metaWithNonce.getAttribute('content');\n }\n const elWithNonce = document.querySelector('script[nonce]');\n if (elWithNonce) {\n return elWithNonce.nonce || '';\n }\n return '';\n}\n// main\n// -------------------------------------------------------------------------------------------------\nif (typeof document !== 'undefined') {\n registerStylesRoot(document);\n}\n\nvar css_248z = \":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\\\"data:application/x-font-ttf;charset=utf-8;base64,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\\\") format(\\\"truetype\\\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\\\"\\\\e900\\\"}.fc-icon-chevron-right:before{content:\\\"\\\\e901\\\"}.fc-icon-chevrons-left:before{content:\\\"\\\\e902\\\"}.fc-icon-chevrons-right:before{content:\\\"\\\\e903\\\"}.fc-icon-minus-square:before{content:\\\"\\\\e904\\\"}.fc-icon-plus-square:before{content:\\\"\\\\e905\\\"}.fc-icon-x:before{content:\\\"\\\\e906\\\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\\\"\\\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\\\"\\\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\\\"\\\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}\";\ninjectStyles(css_248z);\n\nclass DelayedRunner {\n constructor(drainedOption) {\n this.drainedOption = drainedOption;\n this.isRunning = false;\n this.isDirty = false;\n this.pauseDepths = {};\n this.timeoutId = 0;\n }\n request(delay) {\n this.isDirty = true;\n if (!this.isPaused()) {\n this.clearTimeout();\n if (delay == null) {\n this.tryDrain();\n }\n else {\n this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce\n this.tryDrain.bind(this), delay);\n }\n }\n }\n pause(scope = '') {\n let { pauseDepths } = this;\n pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;\n this.clearTimeout();\n }\n resume(scope = '', force) {\n let { pauseDepths } = this;\n if (scope in pauseDepths) {\n if (force) {\n delete pauseDepths[scope];\n }\n else {\n pauseDepths[scope] -= 1;\n let depth = pauseDepths[scope];\n if (depth <= 0) {\n delete pauseDepths[scope];\n }\n }\n this.tryDrain();\n }\n }\n isPaused() {\n return Object.keys(this.pauseDepths).length;\n }\n tryDrain() {\n if (!this.isRunning && !this.isPaused()) {\n this.isRunning = true;\n while (this.isDirty) {\n this.isDirty = false;\n this.drained(); // might set isDirty to true again\n }\n this.isRunning = false;\n }\n }\n clear() {\n this.clearTimeout();\n this.isDirty = false;\n this.pauseDepths = {};\n }\n clearTimeout() {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = 0;\n }\n }\n drained() {\n if (this.drainedOption) {\n this.drainedOption();\n }\n }\n}\n\nfunction removeElement(el) {\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n }\n}\n// Querying\n// ----------------------------------------------------------------------------------------------------------------\nfunction elementClosest(el, selector) {\n if (el.closest) {\n return el.closest(selector);\n // really bad fallback for IE\n // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest\n }\n if (!document.documentElement.contains(el)) {\n return null;\n }\n do {\n if (elementMatches(el, selector)) {\n return el;\n }\n el = (el.parentElement || el.parentNode);\n } while (el !== null && el.nodeType === 1);\n return null;\n}\nfunction elementMatches(el, selector) {\n let method = el.matches || el.matchesSelector || el.msMatchesSelector;\n return method.call(el, selector);\n}\n// accepts multiple subject els\n// returns a real array. good for methods like forEach\n// TODO: accept the document\nfunction findElements(container, selector) {\n let containers = container instanceof HTMLElement ? [container] : container;\n let allMatches = [];\n for (let i = 0; i < containers.length; i += 1) {\n let matches = containers[i].querySelectorAll(selector);\n for (let j = 0; j < matches.length; j += 1) {\n allMatches.push(matches[j]);\n }\n }\n return allMatches;\n}\n// accepts multiple subject els\n// only queries direct child elements // TODO: rename to findDirectChildren!\nfunction findDirectChildren(parent, selector) {\n let parents = parent instanceof HTMLElement ? [parent] : parent;\n let allMatches = [];\n for (let i = 0; i < parents.length; i += 1) {\n let childNodes = parents[i].children; // only ever elements\n for (let j = 0; j < childNodes.length; j += 1) {\n let childNode = childNodes[j];\n if (!selector || elementMatches(childNode, selector)) {\n allMatches.push(childNode);\n }\n }\n }\n return allMatches;\n}\n// Style\n// ----------------------------------------------------------------------------------------------------------------\nconst PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;\nfunction applyStyle(el, props) {\n for (let propName in props) {\n applyStyleProp(el, propName, props[propName]);\n }\n}\nfunction applyStyleProp(el, name, val) {\n if (val == null) {\n el.style[name] = '';\n }\n else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {\n el.style[name] = `${val}px`;\n }\n else {\n el.style[name] = val;\n }\n}\n// Event Handling\n// ----------------------------------------------------------------------------------------------------------------\n// if intercepting bubbled events at the document/window/body level,\n// and want to see originating element (the 'target'), use this util instead\n// of `ev.target` because it goes within web-component boundaries.\nfunction getEventTargetViaRoot(ev) {\n var _a, _b;\n return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;\n}\n// Unique ID for DOM attribute\nlet guid$1 = 0;\nfunction getUniqueDomId() {\n guid$1 += 1;\n return 'fc-dom-' + guid$1;\n}\n\n// Stops a mouse/touch event from doing it's native browser action\nfunction preventDefault(ev) {\n ev.preventDefault();\n}\n// Event Delegation\n// ----------------------------------------------------------------------------------------------------------------\nfunction buildDelegationHandler(selector, handler) {\n return (ev) => {\n let matchedChild = elementClosest(ev.target, selector);\n if (matchedChild) {\n handler.call(matchedChild, ev, matchedChild);\n }\n };\n}\nfunction listenBySelector(container, eventType, selector, handler) {\n let attachedHandler = buildDelegationHandler(selector, handler);\n container.addEventListener(eventType, attachedHandler);\n return () => {\n container.removeEventListener(eventType, attachedHandler);\n };\n}\nfunction listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {\n let currentMatchedChild;\n return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {\n if (matchedChild !== currentMatchedChild) {\n currentMatchedChild = matchedChild;\n onMouseEnter(mouseOverEv, matchedChild);\n let realOnMouseLeave = (mouseLeaveEv) => {\n currentMatchedChild = null;\n onMouseLeave(mouseLeaveEv, matchedChild);\n matchedChild.removeEventListener('mouseleave', realOnMouseLeave);\n };\n // listen to the next mouseleave, and then unattach\n matchedChild.addEventListener('mouseleave', realOnMouseLeave);\n }\n });\n}\n// Animation\n// ----------------------------------------------------------------------------------------------------------------\nconst transitionEventNames = [\n 'webkitTransitionEnd',\n 'otransitionend',\n 'oTransitionEnd',\n 'msTransitionEnd',\n 'transitionend',\n];\n// triggered only when the next single subsequent transition finishes\nfunction whenTransitionDone(el, callback) {\n let realCallback = (ev) => {\n callback(ev);\n transitionEventNames.forEach((eventName) => {\n el.removeEventListener(eventName, realCallback);\n });\n };\n transitionEventNames.forEach((eventName) => {\n el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes\n });\n}\n// ARIA workarounds\n// ----------------------------------------------------------------------------------------------------------------\nfunction createAriaClickAttrs(handler) {\n return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler));\n}\nfunction createAriaKeyboardAttrs(handler) {\n return {\n tabIndex: 0,\n onKeyDown(ev) {\n if (ev.key === 'Enter' || ev.key === ' ') {\n handler(ev);\n ev.preventDefault(); // if space, don't scroll down page\n }\n },\n };\n}\n\nlet guidNumber = 0;\nfunction guid() {\n guidNumber += 1;\n return String(guidNumber);\n}\n/* FullCalendar-specific DOM Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n// Make the mouse cursor express that an event is not allowed in the current area\nfunction disableCursor() {\n document.body.classList.add('fc-not-allowed');\n}\n// Returns the mouse cursor to its original look\nfunction enableCursor() {\n document.body.classList.remove('fc-not-allowed');\n}\n/* Selection\n----------------------------------------------------------------------------------------------------------------------*/\nfunction preventSelection(el) {\n el.style.userSelect = 'none';\n el.style.webkitUserSelect = 'none';\n el.addEventListener('selectstart', preventDefault);\n}\nfunction allowSelection(el) {\n el.style.userSelect = '';\n el.style.webkitUserSelect = '';\n el.removeEventListener('selectstart', preventDefault);\n}\n/* Context Menu\n----------------------------------------------------------------------------------------------------------------------*/\nfunction preventContextMenu(el) {\n el.addEventListener('contextmenu', preventDefault);\n}\nfunction allowContextMenu(el) {\n el.removeEventListener('contextmenu', preventDefault);\n}\nfunction parseFieldSpecs(input) {\n let specs = [];\n let tokens = [];\n let i;\n let token;\n if (typeof input === 'string') {\n tokens = input.split(/\\s*,\\s*/);\n }\n else if (typeof input === 'function') {\n tokens = [input];\n }\n else if (Array.isArray(input)) {\n tokens = input;\n }\n for (i = 0; i < tokens.length; i += 1) {\n token = tokens[i];\n if (typeof token === 'string') {\n specs.push(token.charAt(0) === '-' ?\n { field: token.substring(1), order: -1 } :\n { field: token, order: 1 });\n }\n else if (typeof token === 'function') {\n specs.push({ func: token });\n }\n }\n return specs;\n}\nfunction compareByFieldSpecs(obj0, obj1, fieldSpecs) {\n let i;\n let cmp;\n for (i = 0; i < fieldSpecs.length; i += 1) {\n cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);\n if (cmp) {\n return cmp;\n }\n }\n return 0;\n}\nfunction compareByFieldSpec(obj0, obj1, fieldSpec) {\n if (fieldSpec.func) {\n return fieldSpec.func(obj0, obj1);\n }\n return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])\n * (fieldSpec.order || 1);\n}\nfunction flexibleCompare(a, b) {\n if (!a && !b) {\n return 0;\n }\n if (b == null) {\n return -1;\n }\n if (a == null) {\n return 1;\n }\n if (typeof a === 'string' || typeof b === 'string') {\n return String(a).localeCompare(String(b));\n }\n return a - b;\n}\n/* String Utilities\n----------------------------------------------------------------------------------------------------------------------*/\nfunction padStart(val, len) {\n let s = String(val);\n return '000'.substr(0, len - s.length) + s;\n}\nfunction formatWithOrdinals(formatter, args, fallbackText) {\n if (typeof formatter === 'function') {\n return formatter(...args);\n }\n if (typeof formatter === 'string') { // non-blank string\n return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);\n }\n return fallbackText;\n}\n/* Number Utilities\n----------------------------------------------------------------------------------------------------------------------*/\nfunction compareNumbers(a, b) {\n return a - b;\n}\nfunction isInt(n) {\n return n % 1 === 0;\n}\n/* FC-specific DOM dimension stuff\n----------------------------------------------------------------------------------------------------------------------*/\nfunction computeSmallestCellWidth(cellEl) {\n let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');\n let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');\n if (!allWidthEl) {\n throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const\n }\n if (!contentWidthEl) {\n throw new Error('needs fc-scrollgrid-shrink-cushion className');\n }\n return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border\n contentWidthEl.getBoundingClientRect().width;\n}\n\nconst INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];\nconst PARSE_RE = /^(-?)(?:(\\d+)\\.)?(\\d+):(\\d\\d)(?::(\\d\\d)(?:\\.(\\d\\d\\d))?)?/;\n// Parsing and Creation\nfunction createDuration(input, unit) {\n if (typeof input === 'string') {\n return parseString(input);\n }\n if (typeof input === 'object' && input) { // non-null object\n return parseObject(input);\n }\n if (typeof input === 'number') {\n return parseObject({ [unit || 'milliseconds']: input });\n }\n return null;\n}\nfunction parseString(s) {\n let m = PARSE_RE.exec(s);\n if (m) {\n let sign = m[1] ? -1 : 1;\n return {\n years: 0,\n months: 0,\n days: sign * (m[2] ? parseInt(m[2], 10) : 0),\n milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours\n (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes\n (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds\n (m[6] ? parseInt(m[6], 10) : 0) // ms\n ),\n };\n }\n return null;\n}\nfunction parseObject(obj) {\n let duration = {\n years: obj.years || obj.year || 0,\n months: obj.months || obj.month || 0,\n days: obj.days || obj.day || 0,\n milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours\n (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes\n (obj.seconds || obj.second || 0) * 1000 + // seconds\n (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms\n };\n let weeks = obj.weeks || obj.week;\n if (weeks) {\n duration.days += weeks * 7;\n duration.specifiedWeeks = true;\n }\n return duration;\n}\n// Equality\nfunction durationsEqual(d0, d1) {\n return d0.years === d1.years &&\n d0.months === d1.months &&\n d0.days === d1.days &&\n d0.milliseconds === d1.milliseconds;\n}\nfunction asCleanDays(dur) {\n if (!dur.years && !dur.months && !dur.milliseconds) {\n return dur.days;\n }\n return 0;\n}\n// Simple Math\nfunction addDurations(d0, d1) {\n return {\n years: d0.years + d1.years,\n months: d0.months + d1.months,\n days: d0.days + d1.days,\n milliseconds: d0.milliseconds + d1.milliseconds,\n };\n}\nfunction subtractDurations(d1, d0) {\n return {\n years: d1.years - d0.years,\n months: d1.months - d0.months,\n days: d1.days - d0.days,\n milliseconds: d1.milliseconds - d0.milliseconds,\n };\n}\nfunction multiplyDuration(d, n) {\n return {\n years: d.years * n,\n months: d.months * n,\n days: d.days * n,\n milliseconds: d.milliseconds * n,\n };\n}\n// Conversions\n// \"Rough\" because they are based on average-case Gregorian months/years\nfunction asRoughYears(dur) {\n return asRoughDays(dur) / 365;\n}\nfunction asRoughMonths(dur) {\n return asRoughDays(dur) / 30;\n}\nfunction asRoughDays(dur) {\n return asRoughMs(dur) / 864e5;\n}\nfunction asRoughMinutes(dur) {\n return asRoughMs(dur) / (1000 * 60);\n}\nfunction asRoughSeconds(dur) {\n return asRoughMs(dur) / 1000;\n}\nfunction asRoughMs(dur) {\n return dur.years * (365 * 864e5) +\n dur.months * (30 * 864e5) +\n dur.days * 864e5 +\n dur.milliseconds;\n}\n// Advanced Math\nfunction wholeDivideDurations(numerator, denominator) {\n let res = null;\n for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {\n let unit = INTERNAL_UNITS[i];\n if (denominator[unit]) {\n let localRes = numerator[unit] / denominator[unit];\n if (!isInt(localRes) || (res !== null && res !== localRes)) {\n return null;\n }\n res = localRes;\n }\n else if (numerator[unit]) {\n // needs to divide by something but can't!\n return null;\n }\n }\n return res;\n}\nfunction greatestDurationDenominator(dur) {\n let ms = dur.milliseconds;\n if (ms) {\n if (ms % 1000 !== 0) {\n return { unit: 'millisecond', value: ms };\n }\n if (ms % (1000 * 60) !== 0) {\n return { unit: 'second', value: ms / 1000 };\n }\n if (ms % (1000 * 60 * 60) !== 0) {\n return { unit: 'minute', value: ms / (1000 * 60) };\n }\n if (ms) {\n return { unit: 'hour', value: ms / (1000 * 60 * 60) };\n }\n }\n if (dur.days) {\n if (dur.specifiedWeeks && dur.days % 7 === 0) {\n return { unit: 'week', value: dur.days / 7 };\n }\n return { unit: 'day', value: dur.days };\n }\n if (dur.months) {\n return { unit: 'month', value: dur.months };\n }\n if (dur.years) {\n return { unit: 'year', value: dur.years };\n }\n return { unit: 'millisecond', value: 0 };\n}\n\n// TODO: new util arrayify?\nfunction removeExact(array, exactVal) {\n let removeCnt = 0;\n let i = 0;\n while (i < array.length) {\n if (array[i] === exactVal) {\n array.splice(i, 1);\n removeCnt += 1;\n }\n else {\n i += 1;\n }\n }\n return removeCnt;\n}\nfunction isArraysEqual(a0, a1, equalityFunc) {\n if (a0 === a1) {\n return true;\n }\n let len = a0.length;\n let i;\n if (len !== a1.length) { // not array? or not same length?\n return false;\n }\n for (i = 0; i < len; i += 1) {\n if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {\n return false;\n }\n }\n return true;\n}\n\nconst DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];\n// Adding\nfunction addWeeks(m, n) {\n let a = dateToUtcArray(m);\n a[2] += n * 7;\n return arrayToUtcDate(a);\n}\nfunction addDays(m, n) {\n let a = dateToUtcArray(m);\n a[2] += n;\n return arrayToUtcDate(a);\n}\nfunction addMs(m, n) {\n let a = dateToUtcArray(m);\n a[6] += n;\n return arrayToUtcDate(a);\n}\n// Diffing (all return floats)\n// TODO: why not use ranges?\nfunction diffWeeks(m0, m1) {\n return diffDays(m0, m1) / 7;\n}\nfunction diffDays(m0, m1) {\n return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);\n}\nfunction diffHours(m0, m1) {\n return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);\n}\nfunction diffMinutes(m0, m1) {\n return (m1.valueOf() - m0.valueOf()) / (1000 * 60);\n}\nfunction diffSeconds(m0, m1) {\n return (m1.valueOf() - m0.valueOf()) / 1000;\n}\nfunction diffDayAndTime(m0, m1) {\n let m0day = startOfDay(m0);\n let m1day = startOfDay(m1);\n return {\n years: 0,\n months: 0,\n days: Math.round(diffDays(m0day, m1day)),\n milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),\n };\n}\n// Diffing Whole Units\nfunction diffWholeWeeks(m0, m1) {\n let d = diffWholeDays(m0, m1);\n if (d !== null && d % 7 === 0) {\n return d / 7;\n }\n return null;\n}\nfunction diffWholeDays(m0, m1) {\n if (timeAsMs(m0) === timeAsMs(m1)) {\n return Math.round(diffDays(m0, m1));\n }\n return null;\n}\n// Start-Of\nfunction startOfDay(m) {\n return arrayToUtcDate([\n m.getUTCFullYear(),\n m.getUTCMonth(),\n m.getUTCDate(),\n ]);\n}\nfunction startOfHour(m) {\n return arrayToUtcDate([\n m.getUTCFullYear(),\n m.getUTCMonth(),\n m.getUTCDate(),\n m.getUTCHours(),\n ]);\n}\nfunction startOfMinute(m) {\n return arrayToUtcDate([\n m.getUTCFullYear(),\n m.getUTCMonth(),\n m.getUTCDate(),\n m.getUTCHours(),\n m.getUTCMinutes(),\n ]);\n}\nfunction startOfSecond(m) {\n return arrayToUtcDate([\n m.getUTCFullYear(),\n m.getUTCMonth(),\n m.getUTCDate(),\n m.getUTCHours(),\n m.getUTCMinutes(),\n m.getUTCSeconds(),\n ]);\n}\n// Week Computation\nfunction weekOfYear(marker, dow, doy) {\n let y = marker.getUTCFullYear();\n let w = weekOfGivenYear(marker, y, dow, doy);\n if (w < 1) {\n return weekOfGivenYear(marker, y - 1, dow, doy);\n }\n let nextW = weekOfGivenYear(marker, y + 1, dow, doy);\n if (nextW >= 1) {\n return Math.min(w, nextW);\n }\n return w;\n}\nfunction weekOfGivenYear(marker, year, dow, doy) {\n let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);\n let dayStart = startOfDay(marker);\n let days = Math.round(diffDays(firstWeekStart, dayStart));\n return Math.floor(days / 7) + 1; // zero-indexed\n}\n// start-of-first-week - start-of-year\nfunction firstWeekOffset(year, dow, doy) {\n // first-week day -- which january is always in the first week (4 for iso, 1 for other)\n let fwd = 7 + dow - doy;\n // first-week day local weekday -- which local weekday is fwd\n let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;\n return -fwdlw + fwd - 1;\n}\n// Array Conversion\nfunction dateToLocalArray(date) {\n return [\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n ];\n}\nfunction arrayToLocalDate(a) {\n return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month\n a[3] || 0, a[4] || 0, a[5] || 0);\n}\nfunction dateToUtcArray(date) {\n return [\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate(),\n date.getUTCHours(),\n date.getUTCMinutes(),\n date.getUTCSeconds(),\n date.getUTCMilliseconds(),\n ];\n}\nfunction arrayToUtcDate(a) {\n // according to web standards (and Safari), a month index is required.\n // massage if only given a year.\n if (a.length === 1) {\n a = a.concat([0]);\n }\n return new Date(Date.UTC(...a));\n}\n// Other Utils\nfunction isValidDate(m) {\n return !isNaN(m.valueOf());\n}\nfunction timeAsMs(m) {\n return m.getUTCHours() * 1000 * 60 * 60 +\n m.getUTCMinutes() * 1000 * 60 +\n m.getUTCSeconds() * 1000 +\n m.getUTCMilliseconds();\n}\n\n// timeZoneOffset is in minutes\nfunction buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {\n let s = marker.toISOString();\n s = s.replace('.000', '');\n if (stripZeroTime) {\n s = s.replace('T00:00:00Z', '');\n }\n if (s.length > 10) { // time part wasn't stripped, can add timezone info\n if (timeZoneOffset == null) {\n s = s.replace('Z', '');\n }\n else if (timeZoneOffset !== 0) {\n s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));\n }\n // otherwise, its UTC-0 and we want to keep the Z\n }\n return s;\n}\n// formats the date, but with no time part\n// TODO: somehow merge with buildIsoString and stripZeroTime\n// TODO: rename. omit \"string\"\nfunction formatDayString(marker) {\n return marker.toISOString().replace(/T.*$/, '');\n}\nfunction formatIsoMonthStr(marker) {\n return marker.toISOString().match(/^\\d{4}-\\d{2}/)[0];\n}\n// TODO: use Date::toISOString and use everything after the T?\nfunction formatIsoTimeString(marker) {\n return padStart(marker.getUTCHours(), 2) + ':' +\n padStart(marker.getUTCMinutes(), 2) + ':' +\n padStart(marker.getUTCSeconds(), 2);\n}\nfunction formatTimeZoneOffset(minutes, doIso = false) {\n let sign = minutes < 0 ? '-' : '+';\n let abs = Math.abs(minutes);\n let hours = Math.floor(abs / 60);\n let mins = Math.round(abs % 60);\n if (doIso) {\n return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;\n }\n return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;\n}\n\nfunction memoize(workerFunc, resEquality, teardownFunc) {\n let currentArgs;\n let currentRes;\n return function (...newArgs) {\n if (!currentArgs) {\n currentRes = workerFunc.apply(this, newArgs);\n }\n else if (!isArraysEqual(currentArgs, newArgs)) {\n if (teardownFunc) {\n teardownFunc(currentRes);\n }\n let res = workerFunc.apply(this, newArgs);\n if (!resEquality || !resEquality(res, currentRes)) {\n currentRes = res;\n }\n }\n currentArgs = newArgs;\n return currentRes;\n };\n}\nfunction memoizeObjArg(workerFunc, resEquality, teardownFunc) {\n let currentArg;\n let currentRes;\n return (newArg) => {\n if (!currentArg) {\n currentRes = workerFunc.call(this, newArg);\n }\n else if (!isPropsEqual(currentArg, newArg)) {\n if (teardownFunc) {\n teardownFunc(currentRes);\n }\n let res = workerFunc.call(this, newArg);\n if (!resEquality || !resEquality(res, currentRes)) {\n currentRes = res;\n }\n }\n currentArg = newArg;\n return currentRes;\n };\n}\nfunction memoizeArraylike(// used at all?\nworkerFunc, resEquality, teardownFunc) {\n let currentArgSets = [];\n let currentResults = [];\n return (newArgSets) => {\n let currentLen = currentArgSets.length;\n let newLen = newArgSets.length;\n let i = 0;\n for (; i < currentLen; i += 1) {\n if (!newArgSets[i]) { // one of the old sets no longer exists\n if (teardownFunc) {\n teardownFunc(currentResults[i]);\n }\n }\n else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {\n if (teardownFunc) {\n teardownFunc(currentResults[i]);\n }\n let res = workerFunc.apply(this, newArgSets[i]);\n if (!resEquality || !resEquality(res, currentResults[i])) {\n currentResults[i] = res;\n }\n }\n }\n for (; i < newLen; i += 1) {\n currentResults[i] = workerFunc.apply(this, newArgSets[i]);\n }\n currentArgSets = newArgSets;\n currentResults.splice(newLen); // remove excess\n return currentResults;\n };\n}\nfunction memoizeHashlike(workerFunc, resEquality, teardownFunc) {\n let currentArgHash = {};\n let currentResHash = {};\n return (newArgHash) => {\n let newResHash = {};\n for (let key in newArgHash) {\n if (!currentResHash[key]) {\n newResHash[key] = workerFunc.apply(this, newArgHash[key]);\n }\n else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {\n if (teardownFunc) {\n teardownFunc(currentResHash[key]);\n }\n let res = workerFunc.apply(this, newArgHash[key]);\n newResHash[key] = (resEquality && resEquality(res, currentResHash[key]))\n ? currentResHash[key]\n : res;\n }\n else {\n newResHash[key] = currentResHash[key];\n }\n }\n currentArgHash = newArgHash;\n currentResHash = newResHash;\n return newResHash;\n };\n}\n\nconst EXTENDED_SETTINGS_AND_SEVERITIES = {\n week: 3,\n separator: 9,\n omitZeroMinute: 9,\n meridiem: 9,\n omitCommas: 9,\n};\nconst STANDARD_DATE_PROP_SEVERITIES = {\n timeZoneName: 7,\n era: 6,\n year: 5,\n month: 4,\n day: 2,\n weekday: 2,\n hour: 1,\n minute: 1,\n second: 1,\n};\nconst MERIDIEM_RE = /\\s*([ap])\\.?m\\.?/i; // eats up leading spaces too\nconst COMMA_RE = /,/g; // we need re for globalness\nconst MULTI_SPACE_RE = /\\s+/g;\nconst LTR_RE = /\\u200e/g; // control character\nconst UTC_RE = /UTC|GMT/;\nclass NativeFormatter {\n constructor(formatSettings) {\n let standardDateProps = {};\n let extendedSettings = {};\n let smallestUnitNum = 9; // the smallest unit in the formatter (9 is a sentinel, beyond max)\n for (let name in formatSettings) {\n if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {\n extendedSettings[name] = formatSettings[name];\n const severity = EXTENDED_SETTINGS_AND_SEVERITIES[name];\n if (severity < 9) {\n smallestUnitNum = Math.min(EXTENDED_SETTINGS_AND_SEVERITIES[name], smallestUnitNum);\n }\n }\n else {\n standardDateProps[name] = formatSettings[name];\n if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity\n smallestUnitNum = Math.min(STANDARD_DATE_PROP_SEVERITIES[name], smallestUnitNum);\n }\n }\n }\n this.standardDateProps = standardDateProps;\n this.extendedSettings = extendedSettings;\n this.smallestUnitNum = smallestUnitNum;\n this.buildFormattingFunc = memoize(buildFormattingFunc);\n }\n format(date, context) {\n return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);\n }\n formatRange(start, end, context, betterDefaultSeparator) {\n let { standardDateProps, extendedSettings } = this;\n let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);\n if (!diffSeverity) {\n return this.format(start, context);\n }\n let biggestUnitForPartial = diffSeverity;\n if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time\n (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&\n (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&\n (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {\n biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time\n }\n let full0 = this.format(start, context);\n let full1 = this.format(end, context);\n if (full0 === full1) {\n return full0;\n }\n let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);\n let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);\n let partial0 = partialFormattingFunc(start);\n let partial1 = partialFormattingFunc(end);\n let insertion = findCommonInsertion(full0, partial0, full1, partial1);\n let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';\n if (insertion) {\n return insertion.before + partial0 + separator + partial1 + insertion.after;\n }\n return full0 + separator + full1;\n }\n getSmallestUnit() {\n switch (this.smallestUnitNum) {\n case 7:\n case 6:\n case 5:\n return 'year';\n case 4:\n return 'month';\n case 3:\n return 'week';\n case 2:\n return 'day';\n default:\n return 'time'; // really?\n }\n }\n}\nfunction buildFormattingFunc(standardDateProps, extendedSettings, context) {\n let standardDatePropCnt = Object.keys(standardDateProps).length;\n if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {\n return (date) => (formatTimeZoneOffset(date.timeZoneOffset));\n }\n if (standardDatePropCnt === 0 && extendedSettings.week) {\n return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));\n }\n return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);\n}\nfunction buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {\n standardDateProps = Object.assign({}, standardDateProps); // copy\n extendedSettings = Object.assign({}, extendedSettings); // copy\n sanitizeSettings(standardDateProps, extendedSettings);\n standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers\n let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);\n let zeroFormat; // needed?\n if (extendedSettings.omitZeroMinute) {\n let zeroProps = Object.assign({}, standardDateProps);\n delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings\n zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);\n }\n return (date) => {\n let { marker } = date;\n let format;\n if (zeroFormat && !marker.getUTCMinutes()) {\n format = zeroFormat;\n }\n else {\n format = normalFormat;\n }\n let s = format.format(marker);\n return postProcess(s, date, standardDateProps, extendedSettings, context);\n };\n}\nfunction sanitizeSettings(standardDateProps, extendedSettings) {\n // deal with a browser inconsistency where formatting the timezone\n // requires that the hour/minute be present.\n if (standardDateProps.timeZoneName) {\n if (!standardDateProps.hour) {\n standardDateProps.hour = '2-digit';\n }\n if (!standardDateProps.minute) {\n standardDateProps.minute = '2-digit';\n }\n }\n // only support short timezone names\n if (standardDateProps.timeZoneName === 'long') {\n standardDateProps.timeZoneName = 'short';\n }\n // if requesting to display seconds, MUST display minutes\n if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {\n delete extendedSettings.omitZeroMinute;\n }\n}\nfunction postProcess(s, date, standardDateProps, extendedSettings, context) {\n s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes\n if (standardDateProps.timeZoneName === 'short') {\n s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?\n 'UTC' : // important to normalize for IE, which does \"GMT\"\n formatTimeZoneOffset(date.timeZoneOffset));\n }\n if (extendedSettings.omitCommas) {\n s = s.replace(COMMA_RE, '').trim();\n }\n if (extendedSettings.omitZeroMinute) {\n s = s.replace(':00', ''); // zeroFormat doesn't always achieve this\n }\n // ^ do anything that might create adjacent spaces before this point,\n // because MERIDIEM_RE likes to eat up loading spaces\n if (extendedSettings.meridiem === false) {\n s = s.replace(MERIDIEM_RE, '').trim();\n }\n else if (extendedSettings.meridiem === 'narrow') { // a/p\n s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());\n }\n else if (extendedSettings.meridiem === 'short') { // am/pm\n s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);\n }\n else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase\n s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());\n }\n s = s.replace(MULTI_SPACE_RE, ' ');\n s = s.trim();\n return s;\n}\nfunction injectTzoStr(s, tzoStr) {\n let replaced = false;\n s = s.replace(UTC_RE, () => {\n replaced = true;\n return tzoStr;\n });\n // IE11 doesn't include UTC/GMT in the original string, so append to end\n if (!replaced) {\n s += ` ${tzoStr}`;\n }\n return s;\n}\nfunction formatWeekNumber(num, weekText, weekTextLong, locale, display) {\n let parts = [];\n if (display === 'long') {\n parts.push(weekTextLong);\n }\n else if (display === 'short' || display === 'narrow') {\n parts.push(weekText);\n }\n if (display === 'long' || display === 'short') {\n parts.push(' ');\n }\n parts.push(locale.simpleNumberFormat.format(num));\n if (locale.options.direction === 'rtl') { // TODO: use control characters instead?\n parts.reverse();\n }\n return parts.join('');\n}\n// Range Formatting Utils\n// 0 = exactly the same\n// 1 = different by time\n// and bigger\nfunction computeMarkerDiffSeverity(d0, d1, ca) {\n if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {\n return 5;\n }\n if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {\n return 4;\n }\n if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {\n return 2;\n }\n if (timeAsMs(d0) !== timeAsMs(d1)) {\n return 1;\n }\n return 0;\n}\nfunction computePartialFormattingOptions(options, biggestUnit) {\n let partialOptions = {};\n for (let name in options) {\n if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)\n STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {\n partialOptions[name] = options[name];\n }\n }\n return partialOptions;\n}\nfunction findCommonInsertion(full0, partial0, full1, partial1) {\n let i0 = 0;\n while (i0 < full0.length) {\n let found0 = full0.indexOf(partial0, i0);\n if (found0 === -1) {\n break;\n }\n let before0 = full0.substr(0, found0);\n i0 = found0 + partial0.length;\n let after0 = full0.substr(i0);\n let i1 = 0;\n while (i1 < full1.length) {\n let found1 = full1.indexOf(partial1, i1);\n if (found1 === -1) {\n break;\n }\n let before1 = full1.substr(0, found1);\n i1 = found1 + partial1.length;\n let after1 = full1.substr(i1);\n if (before0 === before1 && after0 === after1) {\n return {\n before: before0,\n after: after0,\n };\n }\n }\n }\n return null;\n}\n\nfunction expandZonedMarker(dateInfo, calendarSystem) {\n let a = calendarSystem.markerToArray(dateInfo.marker);\n return {\n marker: dateInfo.marker,\n timeZoneOffset: dateInfo.timeZoneOffset,\n array: a,\n year: a[0],\n month: a[1],\n day: a[2],\n hour: a[3],\n minute: a[4],\n second: a[5],\n millisecond: a[6],\n };\n}\n\nfunction createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {\n let startInfo = expandZonedMarker(start, context.calendarSystem);\n let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;\n return {\n date: startInfo,\n start: startInfo,\n end: endInfo,\n timeZone: context.timeZone,\n localeCodes: context.locale.codes,\n defaultSeparator: betterDefaultSeparator || context.defaultSeparator,\n };\n}\n\n/*\nTODO: fix the terminology of \"formatter\" vs \"formatting func\"\n*/\n/*\nAt the time of instantiation, this object does not know which cmd-formatting system it will use.\nIt receives this at the time of formatting, as a setting.\n*/\nclass CmdFormatter {\n constructor(cmdStr) {\n this.cmdStr = cmdStr;\n }\n format(date, context, betterDefaultSeparator) {\n return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));\n }\n formatRange(start, end, context, betterDefaultSeparator) {\n return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));\n }\n}\n\nclass FuncFormatter {\n constructor(func) {\n this.func = func;\n }\n format(date, context, betterDefaultSeparator) {\n return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));\n }\n formatRange(start, end, context, betterDefaultSeparator) {\n return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));\n }\n}\n\nfunction createFormatter(input) {\n if (typeof input === 'object' && input) { // non-null object\n return new NativeFormatter(input);\n }\n if (typeof input === 'string') {\n return new CmdFormatter(input);\n }\n if (typeof input === 'function') {\n return new FuncFormatter(input);\n }\n return null;\n}\n\n// base options\n// ------------\nconst BASE_OPTION_REFINERS = {\n navLinkDayClick: identity,\n navLinkWeekClick: identity,\n duration: createDuration,\n bootstrapFontAwesome: identity,\n buttonIcons: identity,\n customButtons: identity,\n defaultAllDayEventDuration: createDuration,\n defaultTimedEventDuration: createDuration,\n nextDayThreshold: createDuration,\n scrollTime: createDuration,\n scrollTimeReset: Boolean,\n slotMinTime: createDuration,\n slotMaxTime: createDuration,\n dayPopoverFormat: createFormatter,\n slotDuration: createDuration,\n snapDuration: createDuration,\n headerToolbar: identity,\n footerToolbar: identity,\n defaultRangeSeparator: String,\n titleRangeSeparator: String,\n forceEventDuration: Boolean,\n dayHeaders: Boolean,\n dayHeaderFormat: createFormatter,\n dayHeaderClassNames: identity,\n dayHeaderContent: identity,\n dayHeaderDidMount: identity,\n dayHeaderWillUnmount: identity,\n dayCellClassNames: identity,\n dayCellContent: identity,\n dayCellDidMount: identity,\n dayCellWillUnmount: identity,\n initialView: String,\n aspectRatio: Number,\n weekends: Boolean,\n weekNumberCalculation: identity,\n weekNumbers: Boolean,\n weekNumberClassNames: identity,\n weekNumberContent: identity,\n weekNumberDidMount: identity,\n weekNumberWillUnmount: identity,\n editable: Boolean,\n viewClassNames: identity,\n viewDidMount: identity,\n viewWillUnmount: identity,\n nowIndicator: Boolean,\n nowIndicatorSnap: identity,\n nowIndicatorClassNames: identity,\n nowIndicatorContent: identity,\n nowIndicatorDidMount: identity,\n nowIndicatorWillUnmount: identity,\n showNonCurrentDates: Boolean,\n lazyFetching: Boolean,\n startParam: String,\n endParam: String,\n timeZoneParam: String,\n timeZone: String,\n locales: identity,\n locale: identity,\n themeSystem: String,\n dragRevertDuration: Number,\n dragScroll: Boolean,\n allDayMaintainDuration: Boolean,\n unselectAuto: Boolean,\n dropAccept: identity,\n eventOrder: parseFieldSpecs,\n eventOrderStrict: Boolean,\n handleWindowResize: Boolean,\n windowResizeDelay: Number,\n longPressDelay: Number,\n eventDragMinDistance: Number,\n expandRows: Boolean,\n height: identity,\n contentHeight: identity,\n direction: String,\n weekNumberFormat: createFormatter,\n eventResizableFromStart: Boolean,\n displayEventTime: Boolean,\n displayEventEnd: Boolean,\n weekText: String,\n weekTextLong: String,\n progressiveEventRendering: Boolean,\n businessHours: identity,\n initialDate: identity,\n now: identity,\n eventDataTransform: identity,\n stickyHeaderDates: identity,\n stickyFooterScrollbar: identity,\n viewHeight: identity,\n defaultAllDay: Boolean,\n eventSourceFailure: identity,\n eventSourceSuccess: identity,\n eventDisplay: String,\n eventStartEditable: Boolean,\n eventDurationEditable: Boolean,\n eventOverlap: identity,\n eventConstraint: identity,\n eventAllow: identity,\n eventBackgroundColor: String,\n eventBorderColor: String,\n eventTextColor: String,\n eventColor: String,\n eventClassNames: identity,\n eventContent: identity,\n eventDidMount: identity,\n eventWillUnmount: identity,\n selectConstraint: identity,\n selectOverlap: identity,\n selectAllow: identity,\n droppable: Boolean,\n unselectCancel: String,\n slotLabelFormat: identity,\n slotLaneClassNames: identity,\n slotLaneContent: identity,\n slotLaneDidMount: identity,\n slotLaneWillUnmount: identity,\n slotLabelClassNames: identity,\n slotLabelContent: identity,\n slotLabelDidMount: identity,\n slotLabelWillUnmount: identity,\n dayMaxEvents: identity,\n dayMaxEventRows: identity,\n dayMinWidth: Number,\n slotLabelInterval: createDuration,\n allDayText: String,\n allDayClassNames: identity,\n allDayContent: identity,\n allDayDidMount: identity,\n allDayWillUnmount: identity,\n slotMinWidth: Number,\n navLinks: Boolean,\n eventTimeFormat: createFormatter,\n rerenderDelay: Number,\n moreLinkText: identity,\n moreLinkHint: identity,\n selectMinDistance: Number,\n selectable: Boolean,\n selectLongPressDelay: Number,\n eventLongPressDelay: Number,\n selectMirror: Boolean,\n eventMaxStack: Number,\n eventMinHeight: Number,\n eventMinWidth: Number,\n eventShortHeight: Number,\n slotEventOverlap: Boolean,\n plugins: identity,\n firstDay: Number,\n dayCount: Number,\n dateAlignment: String,\n dateIncrement: createDuration,\n hiddenDays: identity,\n fixedWeekCount: Boolean,\n validRange: identity,\n visibleRange: identity,\n titleFormat: identity,\n eventInteractive: Boolean,\n // only used by list-view, but languages define the value, so we need it in base options\n noEventsText: String,\n viewHint: identity,\n navLinkHint: identity,\n closeHint: String,\n timeHint: String,\n eventHint: String,\n moreLinkClick: identity,\n moreLinkClassNames: identity,\n moreLinkContent: identity,\n moreLinkDidMount: identity,\n moreLinkWillUnmount: identity,\n monthStartFormat: createFormatter,\n // for connectors\n // (can't be part of plugin system b/c must be provided at runtime)\n handleCustomRendering: identity,\n customRenderingMetaMap: identity,\n customRenderingReplaces: Boolean,\n};\n// do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.\n// raw values.\nconst BASE_OPTION_DEFAULTS = {\n eventDisplay: 'auto',\n defaultRangeSeparator: ' - ',\n titleRangeSeparator: ' \\u2013 ',\n defaultTimedEventDuration: '01:00:00',\n defaultAllDayEventDuration: { day: 1 },\n forceEventDuration: false,\n nextDayThreshold: '00:00:00',\n dayHeaders: true,\n initialView: '',\n aspectRatio: 1.35,\n headerToolbar: {\n start: 'title',\n center: '',\n end: 'today prev,next',\n },\n weekends: true,\n weekNumbers: false,\n weekNumberCalculation: 'local',\n editable: false,\n nowIndicator: false,\n scrollTime: '06:00:00',\n scrollTimeReset: true,\n slotMinTime: '00:00:00',\n slotMaxTime: '24:00:00',\n showNonCurrentDates: true,\n lazyFetching: true,\n startParam: 'start',\n endParam: 'end',\n timeZoneParam: 'timeZone',\n timeZone: 'local',\n locales: [],\n locale: '',\n themeSystem: 'standard',\n dragRevertDuration: 500,\n dragScroll: true,\n allDayMaintainDuration: false,\n unselectAuto: true,\n dropAccept: '*',\n eventOrder: 'start,-duration,allDay,title',\n dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },\n handleWindowResize: true,\n windowResizeDelay: 100,\n longPressDelay: 1000,\n eventDragMinDistance: 5,\n expandRows: false,\n navLinks: false,\n selectable: false,\n eventMinHeight: 15,\n eventMinWidth: 30,\n eventShortHeight: 30,\n monthStartFormat: { month: 'long', day: 'numeric' },\n nowIndicatorSnap: 'auto',\n};\n// calendar listeners\n// ------------------\nconst CALENDAR_LISTENER_REFINERS = {\n datesSet: identity,\n eventsSet: identity,\n eventAdd: identity,\n eventChange: identity,\n eventRemove: identity,\n windowResize: identity,\n eventClick: identity,\n eventMouseEnter: identity,\n eventMouseLeave: identity,\n select: identity,\n unselect: identity,\n loading: identity,\n // internal\n _unmount: identity,\n _beforeprint: identity,\n _afterprint: identity,\n _noEventDrop: identity,\n _noEventResize: identity,\n _resize: identity,\n _scrollRequest: identity,\n};\n// calendar-specific options\n// -------------------------\nconst CALENDAR_OPTION_REFINERS = {\n buttonText: identity,\n buttonHints: identity,\n views: identity,\n plugins: identity,\n initialEvents: identity,\n events: identity,\n eventSources: identity,\n};\nconst COMPLEX_OPTION_COMPARATORS = {\n headerToolbar: isMaybeObjectsEqual,\n footerToolbar: isMaybeObjectsEqual,\n buttonText: isMaybeObjectsEqual,\n buttonHints: isMaybeObjectsEqual,\n buttonIcons: isMaybeObjectsEqual,\n dateIncrement: isMaybeObjectsEqual,\n plugins: isMaybeArraysEqual,\n events: isMaybeArraysEqual,\n eventSources: isMaybeArraysEqual,\n ['resources']: isMaybeArraysEqual,\n};\nfunction isMaybeObjectsEqual(a, b) {\n if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects\n return isPropsEqual(a, b);\n }\n return a === b;\n}\nfunction isMaybeArraysEqual(a, b) {\n if (Array.isArray(a) && Array.isArray(b)) {\n return isArraysEqual(a, b);\n }\n return a === b;\n}\n// view-specific options\n// ---------------------\nconst VIEW_OPTION_REFINERS = {\n type: String,\n component: identity,\n buttonText: String,\n buttonTextKey: String,\n dateProfileGeneratorClass: identity,\n usesMinMaxTime: Boolean,\n classNames: identity,\n content: identity,\n didMount: identity,\n willUnmount: identity,\n};\n// util funcs\n// ----------------------------------------------------------------------------------------------------\nfunction mergeRawOptions(optionSets) {\n return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);\n}\nfunction refineProps(input, refiners) {\n let refined = {};\n let extra = {};\n for (let propName in refiners) {\n if (propName in input) {\n refined[propName] = refiners[propName](input[propName]);\n }\n }\n for (let propName in input) {\n if (!(propName in refiners)) {\n extra[propName] = input[propName];\n }\n }\n return { refined, extra };\n}\nfunction identity(raw) {\n return raw;\n}\n\nconst { hasOwnProperty } = Object.prototype;\n// Merges an array of objects into a single object.\n// The second argument allows for an array of property names who's object values will be merged together.\nfunction mergeProps(propObjs, complexPropsMap) {\n let dest = {};\n if (complexPropsMap) {\n for (let name in complexPropsMap) {\n if (complexPropsMap[name] === isMaybeObjectsEqual) { // implies that it's object-mergeable\n let complexObjs = [];\n // collect the trailing object values, stopping when a non-object is discovered\n for (let i = propObjs.length - 1; i >= 0; i -= 1) {\n let val = propObjs[i][name];\n if (typeof val === 'object' && val) { // non-null object\n complexObjs.unshift(val);\n }\n else if (val !== undefined) {\n dest[name] = val; // if there were no objects, this value will be used\n break;\n }\n }\n // if the trailing values were objects, use the merged value\n if (complexObjs.length) {\n dest[name] = mergeProps(complexObjs);\n }\n }\n }\n }\n // copy values into the destination, going from last to first\n for (let i = propObjs.length - 1; i >= 0; i -= 1) {\n let props = propObjs[i];\n for (let name in props) {\n if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign\n dest[name] = props[name];\n }\n }\n }\n return dest;\n}\nfunction filterHash(hash, func) {\n let filtered = {};\n for (let key in hash) {\n if (func(hash[key], key)) {\n filtered[key] = hash[key];\n }\n }\n return filtered;\n}\nfunction mapHash(hash, func) {\n let newHash = {};\n for (let key in hash) {\n newHash[key] = func(hash[key], key);\n }\n return newHash;\n}\nfunction arrayToHash(a) {\n let hash = {};\n for (let item of a) {\n hash[item] = true;\n }\n return hash;\n}\n// TODO: reassess browser support\n// https://caniuse.com/?search=object.values\nfunction hashValuesToArray(obj) {\n let a = [];\n for (let key in obj) {\n a.push(obj[key]);\n }\n return a;\n}\nfunction isPropsEqual(obj0, obj1) {\n if (obj0 === obj1) {\n return true;\n }\n for (let key in obj0) {\n if (hasOwnProperty.call(obj0, key)) {\n if (!(key in obj1)) {\n return false;\n }\n }\n }\n for (let key in obj1) {\n if (hasOwnProperty.call(obj1, key)) {\n if (obj0[key] !== obj1[key]) {\n return false;\n }\n }\n }\n return true;\n}\nconst HANDLER_RE = /^on[A-Z]/;\nfunction isNonHandlerPropsEqual(obj0, obj1) {\n const keys = getUnequalProps(obj0, obj1);\n for (let key of keys) {\n if (!HANDLER_RE.test(key)) {\n return false;\n }\n }\n return true;\n}\nfunction getUnequalProps(obj0, obj1) {\n let keys = [];\n for (let key in obj0) {\n if (hasOwnProperty.call(obj0, key)) {\n if (!(key in obj1)) {\n keys.push(key);\n }\n }\n }\n for (let key in obj1) {\n if (hasOwnProperty.call(obj1, key)) {\n if (obj0[key] !== obj1[key]) {\n keys.push(key);\n }\n }\n }\n return keys;\n}\nfunction compareObjs(oldProps, newProps, equalityFuncs = {}) {\n if (oldProps === newProps) {\n return true;\n }\n // if (debug) {\n // for (let key in newProps) {\n // if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) {\n // // equal\n // } else {\n // if (debug) {\n // console.log('prop difference', key, oldProps[key], newProps[key])\n // }\n // }\n // }\n // // check for props that were omitted in the new\n // for (let key in oldProps) {\n // if (!(key in newProps)) {\n // if (debug) {\n // console.log('prop absent', key)\n // }\n // }\n // }\n // }\n for (let key in newProps) {\n if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ;\n else {\n return false;\n }\n }\n // check for props that were omitted in the new\n for (let key in oldProps) {\n if (!(key in newProps)) {\n return false;\n }\n }\n return true;\n}\n/*\nassumed \"true\" equality for handler names like \"onReceiveSomething\"\n*/\nfunction isObjValsEqual(val0, val1, comparator) {\n if (val0 === val1 || comparator === true) {\n return true;\n }\n if (comparator) {\n return comparator(val0, val1);\n }\n return false;\n}\nfunction collectFromHash(hash, startIndex = 0, endIndex, step = 1) {\n let res = [];\n if (endIndex == null) {\n endIndex = Object.keys(hash).length;\n }\n for (let i = startIndex; i < endIndex; i += step) {\n let val = hash[i];\n if (val !== undefined) { // will disregard undefined for sparse arrays\n res.push(val);\n }\n }\n return res;\n}\n\nlet calendarSystemClassMap = {};\nfunction registerCalendarSystem(name, theClass) {\n calendarSystemClassMap[name] = theClass;\n}\nfunction createCalendarSystem(name) {\n return new calendarSystemClassMap[name]();\n}\nclass GregorianCalendarSystem {\n getMarkerYear(d) {\n return d.getUTCFullYear();\n }\n getMarkerMonth(d) {\n return d.getUTCMonth();\n }\n getMarkerDay(d) {\n return d.getUTCDate();\n }\n arrayToMarker(arr) {\n return arrayToUtcDate(arr);\n }\n markerToArray(marker) {\n return dateToUtcArray(marker);\n }\n}\nregisterCalendarSystem('gregory', GregorianCalendarSystem);\n\nconst ISO_RE = /^\\s*(\\d{4})(-?(\\d{2})(-?(\\d{2})([T ](\\d{2}):?(\\d{2})(:?(\\d{2})(\\.(\\d+))?)?(Z|(([-+])(\\d{2})(:?(\\d{2}))?))?)?)?)?$/;\nfunction parse(str) {\n let m = ISO_RE.exec(str);\n if (m) {\n let marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number(`0.${m[12]}`) * 1000 : 0));\n if (isValidDate(marker)) {\n let timeZoneOffset = null;\n if (m[13]) {\n timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +\n Number(m[18] || 0));\n }\n return {\n marker,\n isTimeUnspecified: !m[6],\n timeZoneOffset,\n };\n }\n }\n return null;\n}\n\nclass DateEnv {\n constructor(settings) {\n let timeZone = this.timeZone = settings.timeZone;\n let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';\n if (settings.namedTimeZoneImpl && isNamedTimeZone) {\n this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);\n }\n this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);\n this.calendarSystem = createCalendarSystem(settings.calendarSystem);\n this.locale = settings.locale;\n this.weekDow = settings.locale.week.dow;\n this.weekDoy = settings.locale.week.doy;\n if (settings.weekNumberCalculation === 'ISO') {\n this.weekDow = 1;\n this.weekDoy = 4;\n }\n if (typeof settings.firstDay === 'number') {\n this.weekDow = settings.firstDay;\n }\n if (typeof settings.weekNumberCalculation === 'function') {\n this.weekNumberFunc = settings.weekNumberCalculation;\n }\n this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;\n this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;\n this.cmdFormatter = settings.cmdFormatter;\n this.defaultSeparator = settings.defaultSeparator;\n }\n // Creating / Parsing\n createMarker(input) {\n let meta = this.createMarkerMeta(input);\n if (meta === null) {\n return null;\n }\n return meta.marker;\n }\n createNowMarker() {\n if (this.canComputeOffset) {\n return this.timestampToMarker(new Date().valueOf());\n }\n // if we can't compute the current date val for a timezone,\n // better to give the current local date vals than UTC\n return arrayToUtcDate(dateToLocalArray(new Date()));\n }\n createMarkerMeta(input) {\n if (typeof input === 'string') {\n return this.parse(input);\n }\n let marker = null;\n if (typeof input === 'number') {\n marker = this.timestampToMarker(input);\n }\n else if (input instanceof Date) {\n input = input.valueOf();\n if (!isNaN(input)) {\n marker = this.timestampToMarker(input);\n }\n }\n else if (Array.isArray(input)) {\n marker = arrayToUtcDate(input);\n }\n if (marker === null || !isValidDate(marker)) {\n return null;\n }\n return { marker, isTimeUnspecified: false, forcedTzo: null };\n }\n parse(s) {\n let parts = parse(s);\n if (parts === null) {\n return null;\n }\n let { marker } = parts;\n let forcedTzo = null;\n if (parts.timeZoneOffset !== null) {\n if (this.canComputeOffset) {\n marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);\n }\n else {\n forcedTzo = parts.timeZoneOffset;\n }\n }\n return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };\n }\n // Accessors\n getYear(marker) {\n return this.calendarSystem.getMarkerYear(marker);\n }\n getMonth(marker) {\n return this.calendarSystem.getMarkerMonth(marker);\n }\n getDay(marker) {\n return this.calendarSystem.getMarkerDay(marker);\n }\n // Adding / Subtracting\n add(marker, dur) {\n let a = this.calendarSystem.markerToArray(marker);\n a[0] += dur.years;\n a[1] += dur.months;\n a[2] += dur.days;\n a[6] += dur.milliseconds;\n return this.calendarSystem.arrayToMarker(a);\n }\n subtract(marker, dur) {\n let a = this.calendarSystem.markerToArray(marker);\n a[0] -= dur.years;\n a[1] -= dur.months;\n a[2] -= dur.days;\n a[6] -= dur.milliseconds;\n return this.calendarSystem.arrayToMarker(a);\n }\n addYears(marker, n) {\n let a = this.calendarSystem.markerToArray(marker);\n a[0] += n;\n return this.calendarSystem.arrayToMarker(a);\n }\n addMonths(marker, n) {\n let a = this.calendarSystem.markerToArray(marker);\n a[1] += n;\n return this.calendarSystem.arrayToMarker(a);\n }\n // Diffing Whole Units\n diffWholeYears(m0, m1) {\n let { calendarSystem } = this;\n if (timeAsMs(m0) === timeAsMs(m1) &&\n calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&\n calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {\n return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);\n }\n return null;\n }\n diffWholeMonths(m0, m1) {\n let { calendarSystem } = this;\n if (timeAsMs(m0) === timeAsMs(m1) &&\n calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {\n return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +\n (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;\n }\n return null;\n }\n // Range / Duration\n greatestWholeUnit(m0, m1) {\n let n = this.diffWholeYears(m0, m1);\n if (n !== null) {\n return { unit: 'year', value: n };\n }\n n = this.diffWholeMonths(m0, m1);\n if (n !== null) {\n return { unit: 'month', value: n };\n }\n n = diffWholeWeeks(m0, m1);\n if (n !== null) {\n return { unit: 'week', value: n };\n }\n n = diffWholeDays(m0, m1);\n if (n !== null) {\n return { unit: 'day', value: n };\n }\n n = diffHours(m0, m1);\n if (isInt(n)) {\n return { unit: 'hour', value: n };\n }\n n = diffMinutes(m0, m1);\n if (isInt(n)) {\n return { unit: 'minute', value: n };\n }\n n = diffSeconds(m0, m1);\n if (isInt(n)) {\n return { unit: 'second', value: n };\n }\n return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };\n }\n countDurationsBetween(m0, m1, d) {\n // TODO: can use greatestWholeUnit\n let diff;\n if (d.years) {\n diff = this.diffWholeYears(m0, m1);\n if (diff !== null) {\n return diff / asRoughYears(d);\n }\n }\n if (d.months) {\n diff = this.diffWholeMonths(m0, m1);\n if (diff !== null) {\n return diff / asRoughMonths(d);\n }\n }\n if (d.days) {\n diff = diffWholeDays(m0, m1);\n if (diff !== null) {\n return diff / asRoughDays(d);\n }\n }\n return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);\n }\n // Start-Of\n // these DON'T return zoned-dates. only UTC start-of dates\n startOf(m, unit) {\n if (unit === 'year') {\n return this.startOfYear(m);\n }\n if (unit === 'month') {\n return this.startOfMonth(m);\n }\n if (unit === 'week') {\n return this.startOfWeek(m);\n }\n if (unit === 'day') {\n return startOfDay(m);\n }\n if (unit === 'hour') {\n return startOfHour(m);\n }\n if (unit === 'minute') {\n return startOfMinute(m);\n }\n if (unit === 'second') {\n return startOfSecond(m);\n }\n return null;\n }\n startOfYear(m) {\n return this.calendarSystem.arrayToMarker([\n this.calendarSystem.getMarkerYear(m),\n ]);\n }\n startOfMonth(m) {\n return this.calendarSystem.arrayToMarker([\n this.calendarSystem.getMarkerYear(m),\n this.calendarSystem.getMarkerMonth(m),\n ]);\n }\n startOfWeek(m) {\n return this.calendarSystem.arrayToMarker([\n this.calendarSystem.getMarkerYear(m),\n this.calendarSystem.getMarkerMonth(m),\n m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),\n ]);\n }\n // Week Number\n computeWeekNumber(marker) {\n if (this.weekNumberFunc) {\n return this.weekNumberFunc(this.toDate(marker));\n }\n return weekOfYear(marker, this.weekDow, this.weekDoy);\n }\n // TODO: choke on timeZoneName: long\n format(marker, formatter, dateOptions = {}) {\n return formatter.format({\n marker,\n timeZoneOffset: dateOptions.forcedTzo != null ?\n dateOptions.forcedTzo :\n this.offsetForMarker(marker),\n }, this);\n }\n formatRange(start, end, formatter, dateOptions = {}) {\n if (dateOptions.isEndExclusive) {\n end = addMs(end, -1);\n }\n return formatter.formatRange({\n marker: start,\n timeZoneOffset: dateOptions.forcedStartTzo != null ?\n dateOptions.forcedStartTzo :\n this.offsetForMarker(start),\n }, {\n marker: end,\n timeZoneOffset: dateOptions.forcedEndTzo != null ?\n dateOptions.forcedEndTzo :\n this.offsetForMarker(end),\n }, this, dateOptions.defaultSeparator);\n }\n /*\n DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,\n might as well use buildIsoString or some other util directly\n */\n formatIso(marker, extraOptions = {}) {\n let timeZoneOffset = null;\n if (!extraOptions.omitTimeZoneOffset) {\n if (extraOptions.forcedTzo != null) {\n timeZoneOffset = extraOptions.forcedTzo;\n }\n else {\n timeZoneOffset = this.offsetForMarker(marker);\n }\n }\n return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);\n }\n // TimeZone\n timestampToMarker(ms) {\n if (this.timeZone === 'local') {\n return arrayToUtcDate(dateToLocalArray(new Date(ms)));\n }\n if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {\n return new Date(ms);\n }\n return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));\n }\n offsetForMarker(m) {\n if (this.timeZone === 'local') {\n return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert \"inverse\" offset to \"normal\" offset\n }\n if (this.timeZone === 'UTC') {\n return 0;\n }\n if (this.namedTimeZoneImpl) {\n return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));\n }\n return null;\n }\n // Conversion\n toDate(m, forcedTzo) {\n if (this.timeZone === 'local') {\n return arrayToLocalDate(dateToUtcArray(m));\n }\n if (this.timeZone === 'UTC') {\n return new Date(m.valueOf()); // make sure it's a copy\n }\n if (!this.namedTimeZoneImpl) {\n return new Date(m.valueOf() - (forcedTzo || 0));\n }\n return new Date(m.valueOf() -\n this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);\n }\n}\n\nclass Theme {\n constructor(calendarOptions) {\n if (this.iconOverrideOption) {\n this.setIconOverride(calendarOptions[this.iconOverrideOption]);\n }\n }\n setIconOverride(iconOverrideHash) {\n let iconClassesCopy;\n let buttonName;\n if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object\n iconClassesCopy = Object.assign({}, this.iconClasses);\n for (buttonName in iconOverrideHash) {\n iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);\n }\n this.iconClasses = iconClassesCopy;\n }\n else if (iconOverrideHash === false) {\n this.iconClasses = {};\n }\n }\n applyIconOverridePrefix(className) {\n let prefix = this.iconOverridePrefix;\n if (prefix && className.indexOf(prefix) !== 0) { // if not already present\n className = prefix + className;\n }\n return className;\n }\n getClass(key) {\n return this.classes[key] || '';\n }\n getIconClass(buttonName, isRtl) {\n let className;\n if (isRtl && this.rtlIconClasses) {\n className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];\n }\n else {\n className = this.iconClasses[buttonName];\n }\n if (className) {\n return `${this.baseIconClass} ${className}`;\n }\n return '';\n }\n getCustomButtonIconClass(customButtonProps) {\n let className;\n if (this.iconOverrideCustomButtonOption) {\n className = customButtonProps[this.iconOverrideCustomButtonOption];\n if (className) {\n return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;\n }\n }\n return '';\n }\n}\nTheme.prototype.classes = {};\nTheme.prototype.iconClasses = {};\nTheme.prototype.baseIconClass = '';\nTheme.prototype.iconOverridePrefix = '';\n\n/*\nNOTE: this can be a public API, especially createElement for hooks.\nSee examples/typescript-scheduler/src/index.ts\n*/\nfunction flushSync(runBeforeFlush) {\n runBeforeFlush();\n let oldDebounceRendering = preact__WEBPACK_IMPORTED_MODULE_0__.options.debounceRendering; // orig\n let callbackQ = [];\n function execCallbackSync(callback) {\n callbackQ.push(callback);\n }\n preact__WEBPACK_IMPORTED_MODULE_0__.options.debounceRendering = execCallbackSync;\n preact__WEBPACK_IMPORTED_MODULE_0__.render(preact__WEBPACK_IMPORTED_MODULE_0__.createElement(FakeComponent, {}), document.createElement('div'));\n while (callbackQ.length) {\n callbackQ.shift()();\n }\n preact__WEBPACK_IMPORTED_MODULE_0__.options.debounceRendering = oldDebounceRendering;\n}\nclass FakeComponent extends preact__WEBPACK_IMPORTED_MODULE_0__.Component {\n render() { return preact__WEBPACK_IMPORTED_MODULE_0__.createElement('div', {}); }\n componentDidMount() { this.setState({}); }\n}\n// TODO: use preact/compat instead?\nfunction createContext(defaultValue) {\n let ContextType = preact__WEBPACK_IMPORTED_MODULE_0__.createContext(defaultValue);\n let origProvider = ContextType.Provider;\n ContextType.Provider = function () {\n let isNew = !this.getChildContext;\n let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params\n if (isNew) {\n let subs = [];\n this.shouldComponentUpdate = (_props) => {\n if (this.props.value !== _props.value) {\n subs.forEach((c) => {\n c.context = _props.value;\n c.forceUpdate();\n });\n }\n };\n this.sub = (c) => {\n subs.push(c);\n let old = c.componentWillUnmount;\n c.componentWillUnmount = () => {\n subs.splice(subs.indexOf(c), 1);\n old && old.call(c);\n };\n };\n }\n return children;\n };\n return ContextType;\n}\n\nclass ScrollResponder {\n constructor(execFunc, emitter, scrollTime, scrollTimeReset) {\n this.execFunc = execFunc;\n this.emitter = emitter;\n this.scrollTime = scrollTime;\n this.scrollTimeReset = scrollTimeReset;\n this.handleScrollRequest = (request) => {\n this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);\n this.drain();\n };\n emitter.on('_scrollRequest', this.handleScrollRequest);\n this.fireInitialScroll();\n }\n detach() {\n this.emitter.off('_scrollRequest', this.handleScrollRequest);\n }\n update(isDatesNew) {\n if (isDatesNew && this.scrollTimeReset) {\n this.fireInitialScroll(); // will drain\n }\n else {\n this.drain();\n }\n }\n fireInitialScroll() {\n this.handleScrollRequest({\n time: this.scrollTime,\n });\n }\n drain() {\n if (this.queuedRequest && this.execFunc(this.queuedRequest)) {\n this.queuedRequest = null;\n }\n }\n}\n\nconst ViewContextType = createContext({}); // for Components\nfunction buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, nowManager, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {\n return {\n dateEnv,\n nowManager,\n options: viewOptions,\n pluginHooks,\n emitter,\n dispatch,\n getCurrentData,\n calendarApi,\n viewSpec,\n viewApi,\n dateProfileGenerator,\n theme,\n isRtl: viewOptions.direction === 'rtl',\n addResizeHandler(handler) {\n emitter.on('_resize', handler);\n },\n removeResizeHandler(handler) {\n emitter.off('_resize', handler);\n },\n createScrollResponder(execFunc) {\n return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);\n },\n registerInteractiveComponent,\n unregisterInteractiveComponent,\n };\n}\n\n/* eslint max-classes-per-file: off */\nclass PureComponent extends preact__WEBPACK_IMPORTED_MODULE_0__.Component {\n // debug: boolean\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !compareObjs(this.props, nextProps, this.propEquality /*, this.debug */) ||\n !compareObjs(this.state, nextState, this.stateEquality /*, this.debug */);\n // if (this.debug && shouldUpdate) {\n // console.log('shouldUpdate!')\n // }\n return shouldUpdate;\n }\n // HACK for freakin' React StrictMode\n safeSetState(newState) {\n if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {\n this.setState(newState);\n }\n }\n}\nPureComponent.addPropsEquality = addPropsEquality;\nPureComponent.addStateEquality = addStateEquality;\nPureComponent.contextType = ViewContextType;\nPureComponent.prototype.propEquality = {};\nPureComponent.prototype.stateEquality = {};\nclass BaseComponent extends PureComponent {\n}\nBaseComponent.contextType = ViewContextType;\nfunction addPropsEquality(propEquality) {\n let hash = Object.create(this.prototype.propEquality);\n Object.assign(hash, propEquality);\n this.prototype.propEquality = hash;\n}\nfunction addStateEquality(stateEquality) {\n let hash = Object.create(this.prototype.stateEquality);\n Object.assign(hash, stateEquality);\n this.prototype.stateEquality = hash;\n}\n// use other one\nfunction setRef(ref, current) {\n if (typeof ref === 'function') {\n ref(current);\n }\n else if (ref) {\n // see https://github.com/facebook/react/issues/13029\n ref.current = current;\n }\n}\n\nclass ContentInjector extends BaseComponent {\n constructor() {\n super(...arguments);\n this.id = guid();\n this.queuedDomNodes = [];\n this.currentDomNodes = [];\n this.handleEl = (el) => {\n const { options } = this.context;\n const { generatorName } = this.props;\n if (!options.customRenderingReplaces || !hasCustomRenderingHandler(generatorName, options)) {\n this.updateElRef(el);\n }\n };\n this.updateElRef = (el) => {\n if (this.props.elRef) {\n setRef(this.props.elRef, el);\n }\n };\n }\n render() {\n const { props, context } = this;\n const { options } = context;\n const { customGenerator, defaultGenerator, renderProps } = props;\n const attrs = buildElAttrs(props, [], this.handleEl);\n let useDefault = false;\n let innerContent;\n let queuedDomNodes = [];\n let currentGeneratorMeta;\n if (customGenerator != null) {\n const customGeneratorRes = typeof customGenerator === 'function' ?\n customGenerator(renderProps, preact__WEBPACK_IMPORTED_MODULE_0__.createElement) :\n customGenerator;\n if (customGeneratorRes === true) {\n useDefault = true;\n }\n else {\n const isObject = customGeneratorRes && typeof customGeneratorRes === 'object'; // non-null\n if (isObject && ('html' in customGeneratorRes)) {\n attrs.dangerouslySetInnerHTML = { __html: customGeneratorRes.html };\n }\n else if (isObject && ('domNodes' in customGeneratorRes)) {\n queuedDomNodes = Array.prototype.slice.call(customGeneratorRes.domNodes);\n }\n else if (isObject\n ? (0,preact__WEBPACK_IMPORTED_MODULE_0__.isValidElement)(customGeneratorRes) // vdom node\n : typeof customGeneratorRes !== 'function' // primitive value (like string or number)\n ) {\n // use in vdom\n innerContent = customGeneratorRes;\n }\n else {\n // an exotic object for handleCustomRendering\n currentGeneratorMeta = customGeneratorRes;\n }\n }\n }\n else {\n useDefault = !hasCustomRenderingHandler(props.generatorName, options);\n }\n if (useDefault && defaultGenerator) {\n innerContent = defaultGenerator(renderProps);\n }\n this.queuedDomNodes = queuedDomNodes;\n this.currentGeneratorMeta = currentGeneratorMeta;\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(props.elTag, attrs, innerContent);\n }\n componentDidMount() {\n this.applyQueueudDomNodes();\n this.triggerCustomRendering(true);\n }\n componentDidUpdate() {\n this.applyQueueudDomNodes();\n this.triggerCustomRendering(true);\n }\n componentWillUnmount() {\n this.triggerCustomRendering(false); // TODO: different API for removal?\n }\n triggerCustomRendering(isActive) {\n var _a;\n const { props, context } = this;\n const { handleCustomRendering, customRenderingMetaMap } = context.options;\n if (handleCustomRendering) {\n const generatorMeta = (_a = this.currentGeneratorMeta) !== null && _a !== void 0 ? _a : customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];\n if (generatorMeta) {\n handleCustomRendering(Object.assign(Object.assign({ id: this.id, isActive, containerEl: this.base, reportNewContainerEl: this.updateElRef, // front-end framework tells us about new container els\n generatorMeta }, props), { elClasses: (props.elClasses || []).filter(isTruthy) }));\n }\n }\n }\n applyQueueudDomNodes() {\n const { queuedDomNodes, currentDomNodes } = this;\n const el = this.base;\n if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {\n currentDomNodes.forEach(removeElement);\n for (let newNode of queuedDomNodes) {\n el.appendChild(newNode);\n }\n this.currentDomNodes = queuedDomNodes;\n }\n }\n}\nContentInjector.addPropsEquality({\n elClasses: isArraysEqual,\n elStyle: isPropsEqual,\n elAttrs: isNonHandlerPropsEqual,\n renderProps: isPropsEqual,\n});\n// Util\n/*\nDoes UI-framework provide custom way of rendering that does not use Preact VDOM\nAND does the calendar's options define custom rendering?\nAKA. Should we NOT render the default content?\n*/\nfunction hasCustomRenderingHandler(generatorName, options) {\n var _a;\n return Boolean(options.handleCustomRendering &&\n generatorName &&\n ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));\n}\nfunction buildElAttrs(props, extraClassNames, elRef) {\n const attrs = Object.assign(Object.assign({}, props.elAttrs), { ref: elRef });\n if (props.elClasses || extraClassNames) {\n attrs.className = (props.elClasses || [])\n .concat(extraClassNames || [])\n .concat(attrs.className || [])\n .filter(Boolean)\n .join(' ');\n }\n if (props.elStyle) {\n attrs.style = props.elStyle;\n }\n return attrs;\n}\nfunction isTruthy(val) {\n return Boolean(val);\n}\n\nconst RenderId = createContext(0);\n\nclass ContentContainer extends preact__WEBPACK_IMPORTED_MODULE_0__.Component {\n constructor() {\n super(...arguments);\n this.InnerContent = InnerContentInjector.bind(undefined, this);\n this.handleEl = (el) => {\n this.el = el;\n if (this.props.elRef) {\n setRef(this.props.elRef, el);\n if (el && this.didMountMisfire) {\n this.componentDidMount();\n }\n }\n };\n }\n render() {\n const { props } = this;\n const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);\n if (props.children) {\n const elAttrs = buildElAttrs(props, generatedClassNames, this.handleEl);\n const children = props.children(this.InnerContent, props.renderProps, elAttrs);\n if (props.elTag) {\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(props.elTag, elAttrs, children);\n }\n else {\n return children;\n }\n }\n else {\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)((ContentInjector), Object.assign(Object.assign({}, props), { elRef: this.handleEl, elTag: props.elTag || 'div', elClasses: (props.elClasses || []).concat(generatedClassNames), renderId: this.context }));\n }\n }\n componentDidMount() {\n var _a, _b;\n if (this.el) {\n (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));\n }\n else {\n this.didMountMisfire = true;\n }\n }\n componentWillUnmount() {\n var _a, _b;\n (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));\n }\n}\nContentContainer.contextType = RenderId;\nfunction InnerContentInjector(containerComponent, props) {\n const parentProps = containerComponent.props;\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)((ContentInjector), Object.assign({ renderProps: parentProps.renderProps, generatorName: parentProps.generatorName, customGenerator: parentProps.customGenerator, defaultGenerator: parentProps.defaultGenerator, renderId: containerComponent.context }, props));\n}\n// Utils\nfunction generateClassNames(classNameGenerator, renderProps) {\n const classNames = typeof classNameGenerator === 'function' ?\n classNameGenerator(renderProps) :\n classNameGenerator || [];\n return typeof classNames === 'string' ? [classNames] : classNames;\n}\n\nclass ViewContainer extends BaseComponent {\n render() {\n let { props, context } = this;\n let { options } = context;\n let renderProps = { view: context.viewApi };\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elRef: props.elRef, elTag: props.elTag || 'div', elAttrs: props.elAttrs, elClasses: [\n ...buildViewClassNames(props.viewSpec),\n ...(props.elClasses || []),\n ], elStyle: props.elStyle, renderProps: renderProps, classNameGenerator: options.viewClassNames, generatorName: undefined, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount }, () => props.children));\n }\n}\nfunction buildViewClassNames(viewSpec) {\n return [\n `fc-${viewSpec.type}-view`,\n 'fc-view',\n ];\n}\n\nfunction parseRange(input, dateEnv) {\n let start = null;\n let end = null;\n if (input.start) {\n start = dateEnv.createMarker(input.start);\n }\n if (input.end) {\n end = dateEnv.createMarker(input.end);\n }\n if (!start && !end) {\n return null;\n }\n if (start && end && end < start) {\n return null;\n }\n return { start, end };\n}\n// SIDE-EFFECT: will mutate ranges.\n// Will return a new array result.\nfunction invertRanges(ranges, constraintRange) {\n let invertedRanges = [];\n let { start } = constraintRange; // the end of the previous range. the start of the new range\n let i;\n let dateRange;\n // ranges need to be in order. required for our date-walking algorithm\n ranges.sort(compareRanges);\n for (i = 0; i < ranges.length; i += 1) {\n dateRange = ranges[i];\n // add the span of time before the event (if there is any)\n if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)\n invertedRanges.push({ start, end: dateRange.start });\n }\n if (dateRange.end > start) {\n start = dateRange.end;\n }\n }\n // add the span of time after the last event (if there is any)\n if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)\n invertedRanges.push({ start, end: constraintRange.end });\n }\n return invertedRanges;\n}\nfunction compareRanges(range0, range1) {\n return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first\n}\nfunction intersectRanges(range0, range1) {\n let { start, end } = range0;\n let newRange = null;\n if (range1.start !== null) {\n if (start === null) {\n start = range1.start;\n }\n else {\n start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));\n }\n }\n if (range1.end != null) {\n if (end === null) {\n end = range1.end;\n }\n else {\n end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));\n }\n }\n if (start === null || end === null || start < end) {\n newRange = { start, end };\n }\n return newRange;\n}\nfunction rangesEqual(range0, range1) {\n return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&\n (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());\n}\nfunction rangesIntersect(range0, range1) {\n return (range0.end === null || range1.start === null || range0.end > range1.start) &&\n (range0.start === null || range1.end === null || range0.start < range1.end);\n}\nfunction rangeContainsRange(outerRange, innerRange) {\n return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&\n (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));\n}\nfunction rangeContainsMarker(range, date) {\n return (range.start === null || date >= range.start) &&\n (range.end === null || date < range.end);\n}\n// If the given date is not within the given range, move it inside.\n// (If it's past the end, make it one millisecond before the end).\nfunction constrainMarkerToRange(date, range) {\n if (range.start != null && date < range.start) {\n return range.start;\n }\n if (range.end != null && date >= range.end) {\n return new Date(range.end.valueOf() - 1);\n }\n return date;\n}\n\n/* Date stuff that doesn't belong in datelib core\n----------------------------------------------------------------------------------------------------------------------*/\n// given a timed range, computes an all-day range that has the same exact duration,\n// but whose start time is aligned with the start of the day.\nfunction computeAlignedDayRange(timedRange) {\n let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;\n let start = startOfDay(timedRange.start);\n let end = addDays(start, dayCnt);\n return { start, end };\n}\n// given a timed range, computes an all-day range based on how for the end date bleeds into the next day\n// TODO: give nextDayThreshold a default arg\nfunction computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {\n let startDay = null;\n let endDay = null;\n if (timedRange.end) {\n endDay = startOfDay(timedRange.end);\n let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`\n // If the end time is actually inclusively part of the next day and is equal to or\n // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.\n // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.\n if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {\n endDay = addDays(endDay, 1);\n }\n }\n if (timedRange.start) {\n startDay = startOfDay(timedRange.start); // the beginning of the day the range starts\n // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.\n if (endDay && endDay <= startDay) {\n endDay = addDays(startDay, 1);\n }\n }\n return { start: startDay, end: endDay };\n}\n// spans from one day into another?\nfunction isMultiDayRange(range) {\n let visibleRange = computeVisibleDayRange(range);\n return diffDays(visibleRange.start, visibleRange.end) > 1;\n}\nfunction diffDates(date0, date1, dateEnv, largeUnit) {\n if (largeUnit === 'year') {\n return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');\n }\n if (largeUnit === 'month') {\n return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');\n }\n return diffDayAndTime(date0, date1); // returns a duration\n}\n\nclass DateProfileGenerator {\n constructor(props) {\n this.props = props;\n this.initHiddenDays();\n }\n /* Date Range Computation\n ------------------------------------------------------------------------------------------------------------------*/\n // Builds a structure with info about what the dates/ranges will be for the \"prev\" view.\n buildPrev(currentDateProfile, currentDate, forceToValid) {\n let { dateEnv } = this.props;\n let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month\n currentDateProfile.dateIncrement);\n return this.build(prevDate, -1, forceToValid);\n }\n // Builds a structure with info about what the dates/ranges will be for the \"next\" view.\n buildNext(currentDateProfile, currentDate, forceToValid) {\n let { dateEnv } = this.props;\n let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month\n currentDateProfile.dateIncrement);\n return this.build(nextDate, 1, forceToValid);\n }\n // Builds a structure holding dates/ranges for rendering around the given date.\n // Optional direction param indicates whether the date is being incremented/decremented\n // from its previous value. decremented = -1, incremented = 1 (default).\n build(currentDate, direction, forceToValid = true) {\n let { props } = this;\n let validRange;\n let currentInfo;\n let isRangeAllDay;\n let renderRange;\n let activeRange;\n let isValid;\n validRange = this.buildValidRange();\n validRange = this.trimHiddenDays(validRange);\n if (forceToValid) {\n currentDate = constrainMarkerToRange(currentDate, validRange);\n }\n currentInfo = this.buildCurrentRangeInfo(currentDate, direction);\n isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);\n renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);\n renderRange = this.trimHiddenDays(renderRange);\n activeRange = renderRange;\n if (!props.showNonCurrentDates) {\n activeRange = intersectRanges(activeRange, currentInfo.range);\n }\n activeRange = this.adjustActiveRange(activeRange);\n activeRange = intersectRanges(activeRange, validRange); // might return null\n // it's invalid if the originally requested date is not contained,\n // or if the range is completely outside of the valid range.\n isValid = rangesIntersect(currentInfo.range, validRange);\n // HACK: constrain to render-range so `currentDate` is more useful to view rendering\n if (!rangeContainsMarker(renderRange, currentDate)) {\n currentDate = renderRange.start;\n }\n return {\n currentDate,\n // constraint for where prev/next operations can go and where events can be dragged/resized to.\n // an object with optional start and end properties.\n validRange,\n // range the view is formally responsible for.\n // for example, a month view might have 1st-31st, excluding padded dates\n currentRange: currentInfo.range,\n // name of largest unit being displayed, like \"month\" or \"week\"\n currentRangeUnit: currentInfo.unit,\n isRangeAllDay,\n // dates that display events and accept drag-n-drop\n // will be `null` if no dates accept events\n activeRange,\n // date range with a rendered skeleton\n // includes not-active days that need some sort of DOM\n renderRange,\n // Duration object that denotes the first visible time of any given day\n slotMinTime: props.slotMinTime,\n // Duration object that denotes the exclusive visible end time of any given day\n slotMaxTime: props.slotMaxTime,\n isValid,\n // how far the current date will move for a prev/next operation\n dateIncrement: this.buildDateIncrement(currentInfo.duration),\n // pass a fallback (might be null) ^\n };\n }\n // Builds an object with optional start/end properties.\n // Indicates the minimum/maximum dates to display.\n // not responsible for trimming hidden days.\n buildValidRange() {\n let input = this.props.validRangeInput;\n let simpleInput = typeof input === 'function'\n ? input.call(this.props.calendarApi, this.props.dateEnv.toDate(this.props.nowManager.getDateMarker()))\n : input;\n return this.refineRange(simpleInput) ||\n { start: null, end: null }; // completely open-ended\n }\n // Builds a structure with info about the \"current\" range, the range that is\n // highlighted as being the current month for example.\n // See build() for a description of `direction`.\n // Guaranteed to have `range` and `unit` properties. `duration` is optional.\n buildCurrentRangeInfo(date, direction) {\n let { props } = this;\n let duration = null;\n let unit = null;\n let range = null;\n let dayCount;\n if (props.duration) {\n duration = props.duration;\n unit = props.durationUnit;\n range = this.buildRangeFromDuration(date, direction, duration, unit);\n }\n else if ((dayCount = this.props.dayCount)) {\n unit = 'day';\n range = this.buildRangeFromDayCount(date, direction, dayCount);\n }\n else if ((range = this.buildCustomVisibleRange(date))) {\n unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;\n }\n else {\n duration = this.getFallbackDuration();\n unit = greatestDurationDenominator(duration).unit;\n range = this.buildRangeFromDuration(date, direction, duration, unit);\n }\n return { duration, unit, range };\n }\n getFallbackDuration() {\n return createDuration({ day: 1 });\n }\n // Returns a new activeRange to have time values (un-ambiguate)\n // slotMinTime or slotMaxTime causes the range to expand.\n adjustActiveRange(range) {\n let { dateEnv, usesMinMaxTime, slotMinTime, slotMaxTime } = this.props;\n let { start, end } = range;\n if (usesMinMaxTime) {\n // expand active range if slotMinTime is negative (why not when positive?)\n if (asRoughDays(slotMinTime) < 0) {\n start = startOfDay(start); // necessary?\n start = dateEnv.add(start, slotMinTime);\n }\n // expand active range if slotMaxTime is beyond one day (why not when negative?)\n if (asRoughDays(slotMaxTime) > 1) {\n end = startOfDay(end); // necessary?\n end = addDays(end, -1);\n end = dateEnv.add(end, slotMaxTime);\n }\n }\n return { start, end };\n }\n // Builds the \"current\" range when it is specified as an explicit duration.\n // `unit` is the already-computed greatestDurationDenominator unit of duration.\n buildRangeFromDuration(date, direction, duration, unit) {\n let { dateEnv, dateAlignment } = this.props;\n let start;\n let end;\n let res;\n // compute what the alignment should be\n if (!dateAlignment) {\n let { dateIncrement } = this.props;\n if (dateIncrement) {\n // use the smaller of the two units\n if (asRoughMs(dateIncrement) < asRoughMs(duration)) {\n dateAlignment = greatestDurationDenominator(dateIncrement).unit;\n }\n else {\n dateAlignment = unit;\n }\n }\n else {\n dateAlignment = unit;\n }\n }\n // if the view displays a single day or smaller\n if (asRoughDays(duration) <= 1) {\n if (this.isHiddenDay(start)) {\n start = this.skipHiddenDays(start, direction);\n start = startOfDay(start);\n }\n }\n function computeRes() {\n start = dateEnv.startOf(date, dateAlignment);\n end = dateEnv.add(start, duration);\n res = { start, end };\n }\n computeRes();\n // if range is completely enveloped by hidden days, go past the hidden days\n if (!this.trimHiddenDays(res)) {\n date = this.skipHiddenDays(date, direction);\n computeRes();\n }\n return res;\n }\n // Builds the \"current\" range when a dayCount is specified.\n buildRangeFromDayCount(date, direction, dayCount) {\n let { dateEnv, dateAlignment } = this.props;\n let runningCount = 0;\n let start = date;\n let end;\n if (dateAlignment) {\n start = dateEnv.startOf(start, dateAlignment);\n }\n start = startOfDay(start);\n start = this.skipHiddenDays(start, direction);\n end = start;\n do {\n end = addDays(end, 1);\n if (!this.isHiddenDay(end)) {\n runningCount += 1;\n }\n } while (runningCount < dayCount);\n return { start, end };\n }\n // Builds a normalized range object for the \"visible\" range,\n // which is a way to define the currentRange and activeRange at the same time.\n buildCustomVisibleRange(date) {\n let { props } = this;\n let input = props.visibleRangeInput;\n let simpleInput = typeof input === 'function'\n ? input.call(props.calendarApi, props.dateEnv.toDate(date))\n : input;\n let range = this.refineRange(simpleInput);\n if (range && (range.start == null || range.end == null)) {\n return null;\n }\n return range;\n }\n // Computes the range that will represent the element/cells for *rendering*,\n // but which may have voided days/times.\n // not responsible for trimming hidden days.\n buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {\n return currentRange;\n }\n // Compute the duration value that should be added/substracted to the current date\n // when a prev/next operation happens.\n buildDateIncrement(fallback) {\n let { dateIncrement } = this.props;\n let customAlignment;\n if (dateIncrement) {\n return dateIncrement;\n }\n if ((customAlignment = this.props.dateAlignment)) {\n return createDuration(1, customAlignment);\n }\n if (fallback) {\n return fallback;\n }\n return createDuration({ days: 1 });\n }\n refineRange(rangeInput) {\n if (rangeInput) {\n let range = parseRange(rangeInput, this.props.dateEnv);\n if (range) {\n range = computeVisibleDayRange(range);\n }\n return range;\n }\n return null;\n }\n /* Hidden Days\n ------------------------------------------------------------------------------------------------------------------*/\n // Initializes internal variables related to calculating hidden days-of-week\n initHiddenDays() {\n let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden\n let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)\n let dayCnt = 0;\n let i;\n if (this.props.weekends === false) {\n hiddenDays.push(0, 6); // 0=sunday, 6=saturday\n }\n for (i = 0; i < 7; i += 1) {\n if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {\n dayCnt += 1;\n }\n }\n if (!dayCnt) {\n throw new Error('invalid hiddenDays'); // all days were hidden? bad.\n }\n this.isHiddenDayHash = isHiddenDayHash;\n }\n // Remove days from the beginning and end of the range that are computed as hidden.\n // If the whole range is trimmed off, returns null\n trimHiddenDays(range) {\n let { start, end } = range;\n if (start) {\n start = this.skipHiddenDays(start);\n }\n if (end) {\n end = this.skipHiddenDays(end, -1, true);\n }\n if (start == null || end == null || start < end) {\n return { start, end };\n }\n return null;\n }\n // Is the current day hidden?\n // `day` is a day-of-week index (0-6), or a Date (used for UTC)\n isHiddenDay(day) {\n if (day instanceof Date) {\n day = day.getUTCDay();\n }\n return this.isHiddenDayHash[day];\n }\n // Incrementing the current day until it is no longer a hidden day, returning a copy.\n // DOES NOT CONSIDER validRange!\n // If the initial value of `date` is not a hidden day, don't do anything.\n // Pass `isExclusive` as `true` if you are dealing with an end date.\n // `inc` defaults to `1` (increment one day forward each time)\n skipHiddenDays(date, inc = 1, isExclusive = false) {\n while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {\n date = addDays(date, inc);\n }\n return date;\n }\n}\n\nfunction createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {\n return {\n instanceId: guid(),\n defId,\n range,\n forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,\n forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,\n };\n}\n\nfunction parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {\n for (let i = 0; i < recurringTypes.length; i += 1) {\n let parsed = recurringTypes[i].parse(refined, dateEnv);\n if (parsed) {\n let { allDay } = refined;\n if (allDay == null) {\n allDay = defaultAllDay;\n if (allDay == null) {\n allDay = parsed.allDayGuess;\n if (allDay == null) {\n allDay = false;\n }\n }\n }\n return {\n allDay,\n duration: parsed.duration,\n typeData: parsed.typeData,\n typeId: i,\n };\n }\n }\n return null;\n}\nfunction expandRecurring(eventStore, framingRange, context) {\n let { dateEnv, pluginHooks, options } = context;\n let { defs, instances } = eventStore;\n // remove existing recurring instances\n // TODO: bad. always expand events as a second step\n instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);\n for (let defId in defs) {\n let def = defs[defId];\n if (def.recurringDef) {\n let { duration } = def.recurringDef;\n if (!duration) {\n duration = def.allDay ?\n options.defaultAllDayEventDuration :\n options.defaultTimedEventDuration;\n }\n let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);\n for (let start of starts) {\n let instance = createEventInstance(defId, {\n start,\n end: dateEnv.add(start, duration),\n });\n instances[instance.instanceId] = instance;\n }\n }\n }\n return { defs, instances };\n}\n/*\nEvent MUST have a recurringDef\n*/\nfunction expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {\n let typeDef = recurringTypes[eventDef.recurringDef.typeId];\n let markers = typeDef.expand(eventDef.recurringDef.typeData, {\n start: dateEnv.subtract(framingRange.start, duration),\n end: framingRange.end,\n }, dateEnv);\n // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to\n if (eventDef.allDay) {\n markers = markers.map(startOfDay);\n }\n return markers;\n}\n\nconst EVENT_NON_DATE_REFINERS = {\n id: String,\n groupId: String,\n title: String,\n url: String,\n interactive: Boolean,\n};\nconst EVENT_DATE_REFINERS = {\n start: identity,\n end: identity,\n date: identity,\n allDay: Boolean,\n};\nconst EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity });\nfunction parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context), defIdMap, instanceIdMap) {\n let { refined, extra } = refineEventDef(raw, context, refiners);\n let defaultAllDay = computeIsDefaultAllDay(eventSource, context);\n let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);\n if (recurringRes) {\n let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context, defIdMap);\n def.recurringDef = {\n typeId: recurringRes.typeId,\n typeData: recurringRes.typeData,\n duration: recurringRes.duration,\n };\n return { def, instance: null };\n }\n let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);\n if (singleRes) {\n let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context, defIdMap);\n let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);\n if (instanceIdMap && def.publicId && instanceIdMap[def.publicId]) {\n instance.instanceId = instanceIdMap[def.publicId];\n }\n return { def, instance };\n }\n return null;\n}\nfunction refineEventDef(raw, context, refiners = buildEventRefiners(context)) {\n return refineProps(raw, refiners);\n}\nfunction buildEventRefiners(context) {\n return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);\n}\n/*\nWill NOT populate extendedProps with the leftover properties.\nWill NOT populate date-related props.\n*/\nfunction parseEventDef(refined, extra, sourceId, allDay, hasEnd, context, defIdMap) {\n let def = {\n title: refined.title || '',\n groupId: refined.groupId || '',\n publicId: refined.id || '',\n url: refined.url || '',\n recurringDef: null,\n defId: ((defIdMap && refined.id) ? defIdMap[refined.id] : '') || guid(),\n sourceId,\n allDay,\n hasEnd,\n interactive: refined.interactive,\n ui: createEventUi(refined, context),\n extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),\n };\n for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {\n Object.assign(def, memberAdder(refined));\n }\n // help out EventImpl from having user modify props\n Object.freeze(def.ui.classNames);\n Object.freeze(def.extendedProps);\n return def;\n}\nfunction parseSingle(refined, defaultAllDay, context, allowOpenRange) {\n let { allDay } = refined;\n let startMeta;\n let startMarker = null;\n let hasEnd = false;\n let endMeta;\n let endMarker = null;\n let startInput = refined.start != null ? refined.start : refined.date;\n startMeta = context.dateEnv.createMarkerMeta(startInput);\n if (startMeta) {\n startMarker = startMeta.marker;\n }\n else if (!allowOpenRange) {\n return null;\n }\n if (refined.end != null) {\n endMeta = context.dateEnv.createMarkerMeta(refined.end);\n }\n if (allDay == null) {\n if (defaultAllDay != null) {\n allDay = defaultAllDay;\n }\n else {\n // fall back to the date props LAST\n allDay = (!startMeta || startMeta.isTimeUnspecified) &&\n (!endMeta || endMeta.isTimeUnspecified);\n }\n }\n if (allDay && startMarker) {\n startMarker = startOfDay(startMarker);\n }\n if (endMeta) {\n endMarker = endMeta.marker;\n if (allDay) {\n endMarker = startOfDay(endMarker);\n }\n if (startMarker && endMarker <= startMarker) {\n endMarker = null;\n }\n }\n if (endMarker) {\n hasEnd = true;\n }\n else if (!allowOpenRange) {\n hasEnd = context.options.forceEventDuration || false;\n endMarker = context.dateEnv.add(startMarker, allDay ?\n context.options.defaultAllDayEventDuration :\n context.options.defaultTimedEventDuration);\n }\n return {\n allDay,\n hasEnd,\n range: { start: startMarker, end: endMarker },\n forcedStartTzo: startMeta ? startMeta.forcedTzo : null,\n forcedEndTzo: endMeta ? endMeta.forcedTzo : null,\n };\n}\nfunction computeIsDefaultAllDay(eventSource, context) {\n let res = null;\n if (eventSource) {\n res = eventSource.defaultAllDay;\n }\n if (res == null) {\n res = context.options.defaultAllDay;\n }\n return res;\n}\n\nfunction parseEvents(rawEvents, eventSource, context, allowOpenRange, defIdMap, instanceIdMap) {\n let eventStore = createEmptyEventStore();\n let eventRefiners = buildEventRefiners(context);\n for (let rawEvent of rawEvents) {\n let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners, defIdMap, instanceIdMap);\n if (tuple) {\n eventTupleToStore(tuple, eventStore);\n }\n }\n return eventStore;\n}\nfunction eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {\n eventStore.defs[tuple.def.defId] = tuple.def;\n if (tuple.instance) {\n eventStore.instances[tuple.instance.instanceId] = tuple.instance;\n }\n return eventStore;\n}\n// retrieves events that have the same groupId as the instance specified by `instanceId`\n// or they are the same as the instance.\n// why might instanceId not be in the store? an event from another calendar?\nfunction getRelevantEvents(eventStore, instanceId) {\n let instance = eventStore.instances[instanceId];\n if (instance) {\n let def = eventStore.defs[instance.defId];\n // get events/instances with same group\n let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));\n // add the original\n // TODO: wish we could use eventTupleToStore or something like it\n newStore.defs[def.defId] = def;\n newStore.instances[instance.instanceId] = instance;\n return newStore;\n }\n return createEmptyEventStore();\n}\nfunction isEventDefsGrouped(def0, def1) {\n return Boolean(def0.groupId && def0.groupId === def1.groupId);\n}\nfunction createEmptyEventStore() {\n return { defs: {}, instances: {} };\n}\nfunction mergeEventStores(store0, store1) {\n return {\n defs: Object.assign(Object.assign({}, store0.defs), store1.defs),\n instances: Object.assign(Object.assign({}, store0.instances), store1.instances),\n };\n}\nfunction filterEventStoreDefs(eventStore, filterFunc) {\n let defs = filterHash(eventStore.defs, filterFunc);\n let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?\n ));\n return { defs, instances };\n}\nfunction excludeSubEventStore(master, sub) {\n let { defs, instances } = master;\n let filteredDefs = {};\n let filteredInstances = {};\n for (let defId in defs) {\n if (!sub.defs[defId]) { // not explicitly excluded\n filteredDefs[defId] = defs[defId];\n }\n }\n for (let instanceId in instances) {\n if (!sub.instances[instanceId] && // not explicitly excluded\n filteredDefs[instances[instanceId].defId] // def wasn't filtered away\n ) {\n filteredInstances[instanceId] = instances[instanceId];\n }\n }\n return {\n defs: filteredDefs,\n instances: filteredInstances,\n };\n}\n\nfunction normalizeConstraint(input, context) {\n if (Array.isArray(input)) {\n return parseEvents(input, null, context, true); // allowOpenRange=true\n }\n if (typeof input === 'object' && input) { // non-null object\n return parseEvents([input], null, context, true); // allowOpenRange=true\n }\n if (input != null) {\n return String(input);\n }\n return null;\n}\n\nfunction parseClassNames(raw) {\n if (Array.isArray(raw)) {\n return raw;\n }\n if (typeof raw === 'string') {\n return raw.split(/\\s+/);\n }\n return [];\n}\n\n// TODO: better called \"EventSettings\" or \"EventConfig\"\n// TODO: move this file into structs\n// TODO: separate constraint/overlap/allow, because selection uses only that, not other props\nconst EVENT_UI_REFINERS = {\n display: String,\n editable: Boolean,\n startEditable: Boolean,\n durationEditable: Boolean,\n constraint: identity,\n overlap: identity,\n allow: identity,\n className: parseClassNames,\n classNames: parseClassNames,\n color: String,\n backgroundColor: String,\n borderColor: String,\n textColor: String,\n};\nconst EMPTY_EVENT_UI = {\n display: null,\n startEditable: null,\n durationEditable: null,\n constraints: [],\n overlap: null,\n allows: [],\n backgroundColor: '',\n borderColor: '',\n textColor: '',\n classNames: [],\n};\nfunction createEventUi(refined, context) {\n let constraint = normalizeConstraint(refined.constraint, context);\n return {\n display: refined.display || null,\n startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,\n durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,\n constraints: constraint != null ? [constraint] : [],\n overlap: refined.overlap != null ? refined.overlap : null,\n allows: refined.allow != null ? [refined.allow] : [],\n backgroundColor: refined.backgroundColor || refined.color || '',\n borderColor: refined.borderColor || refined.color || '',\n textColor: refined.textColor || '',\n classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural\n };\n}\n// TODO: prevent against problems with <2 args!\nfunction combineEventUis(uis) {\n return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);\n}\nfunction combineTwoEventUis(item0, item1) {\n return {\n display: item1.display != null ? item1.display : item0.display,\n startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,\n durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,\n constraints: item0.constraints.concat(item1.constraints),\n overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,\n allows: item0.allows.concat(item1.allows),\n backgroundColor: item1.backgroundColor || item0.backgroundColor,\n borderColor: item1.borderColor || item0.borderColor,\n textColor: item1.textColor || item0.textColor,\n classNames: item0.classNames.concat(item1.classNames),\n };\n}\n\nconst EVENT_SOURCE_REFINERS = {\n id: String,\n defaultAllDay: Boolean,\n url: String,\n format: String,\n events: identity,\n eventDataTransform: identity,\n // for any network-related sources\n success: identity,\n failure: identity,\n};\nfunction parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {\n let rawObj;\n if (typeof raw === 'string') {\n rawObj = { url: raw };\n }\n else if (typeof raw === 'function' || Array.isArray(raw)) {\n rawObj = { events: raw };\n }\n else if (typeof raw === 'object' && raw) { // not null\n rawObj = raw;\n }\n if (rawObj) {\n let { refined, extra } = refineProps(rawObj, refiners);\n let metaRes = buildEventSourceMeta(refined, context);\n if (metaRes) {\n return {\n _raw: raw,\n isFetching: false,\n latestFetchId: '',\n fetchRange: null,\n defaultAllDay: refined.defaultAllDay,\n eventDataTransform: refined.eventDataTransform,\n success: refined.success,\n failure: refined.failure,\n publicId: refined.id || '',\n sourceId: guid(),\n sourceDefId: metaRes.sourceDefId,\n meta: metaRes.meta,\n ui: createEventUi(refined, context),\n extendedProps: extra,\n };\n }\n }\n return null;\n}\nfunction buildEventSourceRefiners(context) {\n return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);\n}\nfunction buildEventSourceMeta(raw, context) {\n let defs = context.pluginHooks.eventSourceDefs;\n for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence\n let def = defs[i];\n let meta = def.parseMeta(raw);\n if (meta) {\n return { sourceDefId: i, meta };\n }\n }\n return null;\n}\n\nfunction reduceEventStore(eventStore, action, eventSources, dateProfile, context) {\n switch (action.type) {\n case 'RECEIVE_EVENTS': // raw\n return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);\n case 'RESET_RAW_EVENTS':\n return resetRawEvents(eventStore, eventSources[action.sourceId], action.rawEvents, dateProfile.activeRange, context);\n case 'ADD_EVENTS': // already parsed, but not expanded\n return addEvent(eventStore, action.eventStore, // new ones\n dateProfile ? dateProfile.activeRange : null, context);\n case 'RESET_EVENTS':\n return action.eventStore;\n case 'MERGE_EVENTS': // already parsed and expanded\n return mergeEventStores(eventStore, action.eventStore);\n case 'PREV': // TODO: how do we track all actions that affect dateProfile :(\n case 'NEXT':\n case 'CHANGE_DATE':\n case 'CHANGE_VIEW_TYPE':\n if (dateProfile) {\n return expandRecurring(eventStore, dateProfile.activeRange, context);\n }\n return eventStore;\n case 'REMOVE_EVENTS':\n return excludeSubEventStore(eventStore, action.eventStore);\n case 'REMOVE_EVENT_SOURCE':\n return excludeEventsBySourceId(eventStore, action.sourceId);\n case 'REMOVE_ALL_EVENT_SOURCES':\n return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id\n ));\n case 'REMOVE_ALL_EVENTS':\n return createEmptyEventStore();\n default:\n return eventStore;\n }\n}\nfunction receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {\n if (eventSource && // not already removed\n fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources\n ) {\n let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);\n if (fetchRange) {\n subset = expandRecurring(subset, fetchRange, context);\n }\n return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);\n }\n return eventStore;\n}\nfunction resetRawEvents(existingEventStore, eventSource, rawEvents, activeRange, context) {\n const { defIdMap, instanceIdMap } = buildPublicIdMaps(existingEventStore);\n let newEventStore = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context, false, defIdMap, instanceIdMap);\n return expandRecurring(newEventStore, activeRange, context);\n}\nfunction transformRawEvents(rawEvents, eventSource, context) {\n let calEachTransform = context.options.eventDataTransform;\n let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;\n if (sourceEachTransform) {\n rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);\n }\n if (calEachTransform) {\n rawEvents = transformEachRawEvent(rawEvents, calEachTransform);\n }\n return rawEvents;\n}\nfunction transformEachRawEvent(rawEvents, func) {\n let refinedEvents;\n if (!func) {\n refinedEvents = rawEvents;\n }\n else {\n refinedEvents = [];\n for (let rawEvent of rawEvents) {\n let refinedEvent = func(rawEvent);\n if (refinedEvent) {\n refinedEvents.push(refinedEvent);\n }\n else if (refinedEvent == null) {\n refinedEvents.push(rawEvent);\n } // if a different falsy value, do nothing\n }\n }\n return refinedEvents;\n}\nfunction addEvent(eventStore, subset, expandRange, context) {\n if (expandRange) {\n subset = expandRecurring(subset, expandRange, context);\n }\n return mergeEventStores(eventStore, subset);\n}\nfunction rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {\n let { defs } = eventStore;\n let instances = mapHash(eventStore.instances, (instance) => {\n let def = defs[instance.defId];\n if (def.allDay) {\n return instance; // isn't dependent on timezone\n }\n return Object.assign(Object.assign({}, instance), { range: {\n start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),\n end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),\n }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });\n });\n return { defs, instances };\n}\nfunction excludeEventsBySourceId(eventStore, sourceId) {\n return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);\n}\n// QUESTION: why not just return instances? do a general object-property-exclusion util\nfunction excludeInstances(eventStore, removals) {\n return {\n defs: eventStore.defs,\n instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),\n };\n}\nfunction buildPublicIdMaps(eventStore) {\n const { defs, instances } = eventStore;\n const defIdMap = {};\n const instanceIdMap = {};\n for (let defId in defs) {\n const def = defs[defId];\n const { publicId } = def;\n if (publicId) {\n defIdMap[publicId] = defId;\n }\n }\n for (let instanceId in instances) {\n const instance = instances[instanceId];\n const def = defs[instance.defId];\n const { publicId } = def;\n if (publicId) {\n instanceIdMap[publicId] = instanceId;\n }\n }\n return { defIdMap, instanceIdMap };\n}\n\nclass Emitter {\n constructor() {\n this.handlers = {};\n this.thisContext = null;\n }\n setThisContext(thisContext) {\n this.thisContext = thisContext;\n }\n setOptions(options) {\n this.options = options;\n }\n on(type, handler) {\n addToHash(this.handlers, type, handler);\n }\n off(type, handler) {\n removeFromHash(this.handlers, type, handler);\n }\n trigger(type, ...args) {\n let attachedHandlers = this.handlers[type] || [];\n let optionHandler = this.options && this.options[type];\n let handlers = [].concat(optionHandler || [], attachedHandlers);\n for (let handler of handlers) {\n handler.apply(this.thisContext, args);\n }\n }\n hasHandlers(type) {\n return Boolean((this.handlers[type] && this.handlers[type].length) ||\n (this.options && this.options[type]));\n }\n}\nfunction addToHash(hash, type, handler) {\n (hash[type] || (hash[type] = []))\n .push(handler);\n}\nfunction removeFromHash(hash, type, handler) {\n if (handler) {\n if (hash[type]) {\n hash[type] = hash[type].filter((func) => func !== handler);\n }\n }\n else {\n delete hash[type]; // remove all handler funcs for this type\n }\n}\n\nconst DEF_DEFAULTS = {\n startTime: '09:00',\n endTime: '17:00',\n daysOfWeek: [1, 2, 3, 4, 5],\n display: 'inverse-background',\n classNames: 'fc-non-business',\n groupId: '_businessHours', // so multiple defs get grouped\n};\n/*\nTODO: pass around as EventDefHash!!!\n*/\nfunction parseBusinessHours(input, context) {\n return parseEvents(refineInputs(input), null, context);\n}\nfunction refineInputs(input) {\n let rawDefs;\n if (input === true) {\n rawDefs = [{}]; // will get DEF_DEFAULTS verbatim\n }\n else if (Array.isArray(input)) {\n // if specifying an array, every sub-definition NEEDS a day-of-week\n rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);\n }\n else if (typeof input === 'object' && input) { // non-null object\n rawDefs = [input];\n }\n else { // is probably false\n rawDefs = [];\n }\n rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));\n return rawDefs;\n}\n\nfunction triggerDateSelect(selection, pev, context) {\n context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view }));\n}\nfunction triggerDateUnselect(pev, context) {\n context.emitter.trigger('unselect', {\n jsEvent: pev ? pev.origEvent : null,\n view: context.viewApi || context.calendarApi.view,\n });\n}\nfunction buildDateSpanApiWithContext(dateSpan, context) {\n let props = {};\n for (let transform of context.pluginHooks.dateSpanTransforms) {\n Object.assign(props, transform(dateSpan, context));\n }\n Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));\n return props;\n}\n// Given an event's allDay status and start date, return what its fallback end date should be.\n// TODO: rename to computeDefaultEventEnd\nfunction getDefaultEventEnd(allDay, marker, context) {\n let { dateEnv, options } = context;\n let end = marker;\n if (allDay) {\n end = startOfDay(end);\n end = dateEnv.add(end, options.defaultAllDayEventDuration);\n }\n else {\n end = dateEnv.add(end, options.defaultTimedEventDuration);\n }\n return end;\n}\n\n// applies the mutation to ALL defs/instances within the event store\nfunction applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {\n let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);\n let dest = createEmptyEventStore();\n for (let defId in eventStore.defs) {\n let def = eventStore.defs[defId];\n dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);\n }\n for (let instanceId in eventStore.instances) {\n let instance = eventStore.instances[instanceId];\n let def = dest.defs[instance.defId]; // important to grab the newly modified def\n dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);\n }\n return dest;\n}\nfunction applyMutationToEventDef(eventDef, eventConfig, mutation, context) {\n let standardProps = mutation.standardProps || {};\n // if hasEnd has not been specified, guess a good value based on deltas.\n // if duration will change, there's no way the default duration will persist,\n // and thus, we need to mark the event as having a real end\n if (standardProps.hasEnd == null &&\n eventConfig.durationEditable &&\n (mutation.startDelta || mutation.endDelta)) {\n standardProps.hasEnd = true; // TODO: is this mutation okay?\n }\n let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), { ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui) });\n if (mutation.extendedProps) {\n copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);\n }\n for (let applier of context.pluginHooks.eventDefMutationAppliers) {\n applier(copy, mutation, context);\n }\n if (!copy.hasEnd && context.options.forceEventDuration) {\n copy.hasEnd = true;\n }\n return copy;\n}\nfunction applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef\neventConfig, mutation, context) {\n let { dateEnv } = context;\n let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;\n let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;\n let copy = Object.assign({}, eventInstance);\n if (forceAllDay) {\n copy.range = computeAlignedDayRange(copy.range);\n }\n if (mutation.datesDelta && eventConfig.startEditable) {\n copy.range = {\n start: dateEnv.add(copy.range.start, mutation.datesDelta),\n end: dateEnv.add(copy.range.end, mutation.datesDelta),\n };\n }\n if (mutation.startDelta && eventConfig.durationEditable) {\n copy.range = {\n start: dateEnv.add(copy.range.start, mutation.startDelta),\n end: copy.range.end,\n };\n }\n if (mutation.endDelta && eventConfig.durationEditable) {\n copy.range = {\n start: copy.range.start,\n end: dateEnv.add(copy.range.end, mutation.endDelta),\n };\n }\n if (clearEnd) {\n copy.range = {\n start: copy.range.start,\n end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),\n };\n }\n // in case event was all-day but the supplied deltas were not\n // better util for this?\n if (eventDef.allDay) {\n copy.range = {\n start: startOfDay(copy.range.start),\n end: startOfDay(copy.range.end),\n };\n }\n // handle invalid durations\n if (copy.range.end < copy.range.start) {\n copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);\n }\n return copy;\n}\n\nclass EventSourceImpl {\n constructor(context, internalEventSource) {\n this.context = context;\n this.internalEventSource = internalEventSource;\n }\n remove() {\n this.context.dispatch({\n type: 'REMOVE_EVENT_SOURCE',\n sourceId: this.internalEventSource.sourceId,\n });\n }\n refetch() {\n this.context.dispatch({\n type: 'FETCH_EVENT_SOURCES',\n sourceIds: [this.internalEventSource.sourceId],\n isRefetch: true,\n });\n }\n get id() {\n return this.internalEventSource.publicId;\n }\n get url() {\n return this.internalEventSource.meta.url;\n }\n get format() {\n return this.internalEventSource.meta.format; // TODO: bad. not guaranteed\n }\n}\n\nclass EventImpl {\n // instance will be null if expressing a recurring event that has no current instances,\n // OR if trying to validate an incoming external event that has no dates assigned\n constructor(context, def, instance) {\n this._context = context;\n this._def = def;\n this._instance = instance || null;\n }\n /*\n TODO: make event struct more responsible for this\n */\n setProp(name, val) {\n if (name in EVENT_DATE_REFINERS) {\n console.warn('Could not set date-related prop \\'name\\'. Use one of the date-related methods instead.');\n // TODO: make proper aliasing system?\n }\n else if (name === 'id') {\n val = EVENT_NON_DATE_REFINERS[name](val);\n this.mutate({\n standardProps: { publicId: val }, // hardcoded internal name\n });\n }\n else if (name in EVENT_NON_DATE_REFINERS) {\n val = EVENT_NON_DATE_REFINERS[name](val);\n this.mutate({\n standardProps: { [name]: val },\n });\n }\n else if (name in EVENT_UI_REFINERS) {\n let ui = EVENT_UI_REFINERS[name](val);\n if (name === 'color') {\n ui = { backgroundColor: val, borderColor: val };\n }\n else if (name === 'editable') {\n ui = { startEditable: val, durationEditable: val };\n }\n else {\n ui = { [name]: val };\n }\n this.mutate({\n standardProps: { ui },\n });\n }\n else {\n console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);\n }\n }\n setExtendedProp(name, val) {\n this.mutate({\n extendedProps: { [name]: val },\n });\n }\n setStart(startInput, options = {}) {\n let { dateEnv } = this._context;\n let start = dateEnv.createMarker(startInput);\n if (start && this._instance) { // TODO: warning if parsed bad\n let instanceRange = this._instance.range;\n let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?\n if (options.maintainDuration) {\n this.mutate({ datesDelta: startDelta });\n }\n else {\n this.mutate({ startDelta });\n }\n }\n }\n setEnd(endInput, options = {}) {\n let { dateEnv } = this._context;\n let end;\n if (endInput != null) {\n end = dateEnv.createMarker(endInput);\n if (!end) {\n return; // TODO: warning if parsed bad\n }\n }\n if (this._instance) {\n if (end) {\n let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);\n this.mutate({ endDelta });\n }\n else {\n this.mutate({ standardProps: { hasEnd: false } });\n }\n }\n }\n setDates(startInput, endInput, options = {}) {\n let { dateEnv } = this._context;\n let standardProps = { allDay: options.allDay };\n let start = dateEnv.createMarker(startInput);\n let end;\n if (!start) {\n return; // TODO: warning if parsed bad\n }\n if (endInput != null) {\n end = dateEnv.createMarker(endInput);\n if (!end) { // TODO: warning if parsed bad\n return;\n }\n }\n if (this._instance) {\n let instanceRange = this._instance.range;\n // when computing the diff for an event being converted to all-day,\n // compute diff off of the all-day values the way event-mutation does.\n if (options.allDay === true) {\n instanceRange = computeAlignedDayRange(instanceRange);\n }\n let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);\n if (end) {\n let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);\n if (durationsEqual(startDelta, endDelta)) {\n this.mutate({ datesDelta: startDelta, standardProps });\n }\n else {\n this.mutate({ startDelta, endDelta, standardProps });\n }\n }\n else { // means \"clear the end\"\n standardProps.hasEnd = false;\n this.mutate({ datesDelta: startDelta, standardProps });\n }\n }\n }\n moveStart(deltaInput) {\n let delta = createDuration(deltaInput);\n if (delta) { // TODO: warning if parsed bad\n this.mutate({ startDelta: delta });\n }\n }\n moveEnd(deltaInput) {\n let delta = createDuration(deltaInput);\n if (delta) { // TODO: warning if parsed bad\n this.mutate({ endDelta: delta });\n }\n }\n moveDates(deltaInput) {\n let delta = createDuration(deltaInput);\n if (delta) { // TODO: warning if parsed bad\n this.mutate({ datesDelta: delta });\n }\n }\n setAllDay(allDay, options = {}) {\n let standardProps = { allDay };\n let { maintainDuration } = options;\n if (maintainDuration == null) {\n maintainDuration = this._context.options.allDayMaintainDuration;\n }\n if (this._def.allDay !== allDay) {\n standardProps.hasEnd = maintainDuration;\n }\n this.mutate({ standardProps });\n }\n formatRange(formatInput) {\n let { dateEnv } = this._context;\n let instance = this._instance;\n let formatter = createFormatter(formatInput);\n if (this._def.hasEnd) {\n return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {\n forcedStartTzo: instance.forcedStartTzo,\n forcedEndTzo: instance.forcedEndTzo,\n });\n }\n return dateEnv.format(instance.range.start, formatter, {\n forcedTzo: instance.forcedStartTzo,\n });\n }\n mutate(mutation) {\n let instance = this._instance;\n if (instance) {\n let def = this._def;\n let context = this._context;\n let { eventStore } = context.getCurrentData();\n let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);\n let eventConfigBase = {\n '': {\n display: '',\n startEditable: true,\n durationEditable: true,\n constraints: [],\n overlap: null,\n allows: [],\n backgroundColor: '',\n borderColor: '',\n textColor: '',\n classNames: [],\n },\n };\n relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);\n let oldEvent = new EventImpl(context, def, instance); // snapshot\n this._def = relevantEvents.defs[def.defId];\n this._instance = relevantEvents.instances[instance.instanceId];\n context.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: relevantEvents,\n });\n context.emitter.trigger('eventChange', {\n oldEvent,\n event: this,\n relatedEvents: buildEventApis(relevantEvents, context, instance),\n revert() {\n context.dispatch({\n type: 'RESET_EVENTS',\n eventStore, // the ORIGINAL store\n });\n },\n });\n }\n }\n remove() {\n let context = this._context;\n let asStore = eventApiToStore(this);\n context.dispatch({\n type: 'REMOVE_EVENTS',\n eventStore: asStore,\n });\n context.emitter.trigger('eventRemove', {\n event: this,\n relatedEvents: [],\n revert() {\n context.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: asStore,\n });\n },\n });\n }\n get source() {\n let { sourceId } = this._def;\n if (sourceId) {\n return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);\n }\n return null;\n }\n get start() {\n return this._instance ?\n this._context.dateEnv.toDate(this._instance.range.start) :\n null;\n }\n get end() {\n return (this._instance && this._def.hasEnd) ?\n this._context.dateEnv.toDate(this._instance.range.end) :\n null;\n }\n get startStr() {\n let instance = this._instance;\n if (instance) {\n return this._context.dateEnv.formatIso(instance.range.start, {\n omitTime: this._def.allDay,\n forcedTzo: instance.forcedStartTzo,\n });\n }\n return '';\n }\n get endStr() {\n let instance = this._instance;\n if (instance && this._def.hasEnd) {\n return this._context.dateEnv.formatIso(instance.range.end, {\n omitTime: this._def.allDay,\n forcedTzo: instance.forcedEndTzo,\n });\n }\n return '';\n }\n // computable props that all access the def\n // TODO: find a TypeScript-compatible way to do this at scale\n get id() { return this._def.publicId; }\n get groupId() { return this._def.groupId; }\n get allDay() { return this._def.allDay; }\n get title() { return this._def.title; }\n get url() { return this._def.url; }\n get display() { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier\n get startEditable() { return this._def.ui.startEditable; }\n get durationEditable() { return this._def.ui.durationEditable; }\n get constraint() { return this._def.ui.constraints[0] || null; }\n get overlap() { return this._def.ui.overlap; }\n get allow() { return this._def.ui.allows[0] || null; }\n get backgroundColor() { return this._def.ui.backgroundColor; }\n get borderColor() { return this._def.ui.borderColor; }\n get textColor() { return this._def.ui.textColor; }\n // NOTE: user can't modify these because Object.freeze was called in event-def parsing\n get classNames() { return this._def.ui.classNames; }\n get extendedProps() { return this._def.extendedProps; }\n toPlainObject(settings = {}) {\n let def = this._def;\n let { ui } = def;\n let { startStr, endStr } = this;\n let res = {\n allDay: def.allDay,\n };\n if (def.title) {\n res.title = def.title;\n }\n if (startStr) {\n res.start = startStr;\n }\n if (endStr) {\n res.end = endStr;\n }\n if (def.publicId) {\n res.id = def.publicId;\n }\n if (def.groupId) {\n res.groupId = def.groupId;\n }\n if (def.url) {\n res.url = def.url;\n }\n if (ui.display && ui.display !== 'auto') {\n res.display = ui.display;\n }\n // TODO: what about recurring-event properties???\n // TODO: include startEditable/durationEditable/constraint/overlap/allow\n if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {\n res.color = ui.backgroundColor;\n }\n else {\n if (ui.backgroundColor) {\n res.backgroundColor = ui.backgroundColor;\n }\n if (ui.borderColor) {\n res.borderColor = ui.borderColor;\n }\n }\n if (ui.textColor) {\n res.textColor = ui.textColor;\n }\n if (ui.classNames.length) {\n res.classNames = ui.classNames;\n }\n if (Object.keys(def.extendedProps).length) {\n if (settings.collapseExtendedProps) {\n Object.assign(res, def.extendedProps);\n }\n else {\n res.extendedProps = def.extendedProps;\n }\n }\n return res;\n }\n toJSON() {\n return this.toPlainObject();\n }\n}\nfunction eventApiToStore(eventApi) {\n let def = eventApi._def;\n let instance = eventApi._instance;\n return {\n defs: { [def.defId]: def },\n instances: instance\n ? { [instance.instanceId]: instance }\n : {},\n };\n}\nfunction buildEventApis(eventStore, context, excludeInstance) {\n let { defs, instances } = eventStore;\n let eventApis = [];\n let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';\n for (let id in instances) {\n let instance = instances[id];\n let def = defs[instance.defId];\n if (instance.instanceId !== excludeInstanceId) {\n eventApis.push(new EventImpl(context, def, instance));\n }\n }\n return eventApis;\n}\n\n/*\nSpecifying nextDayThreshold signals that all-day ranges should be sliced.\n*/\nfunction sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {\n let inverseBgByGroupId = {};\n let inverseBgByDefId = {};\n let defByGroupId = {};\n let bgRanges = [];\n let fgRanges = [];\n let eventUis = compileEventUis(eventStore.defs, eventUiBases);\n for (let defId in eventStore.defs) {\n let def = eventStore.defs[defId];\n let ui = eventUis[def.defId];\n if (ui.display === 'inverse-background') {\n if (def.groupId) {\n inverseBgByGroupId[def.groupId] = [];\n if (!defByGroupId[def.groupId]) {\n defByGroupId[def.groupId] = def;\n }\n }\n else {\n inverseBgByDefId[defId] = [];\n }\n }\n }\n for (let instanceId in eventStore.instances) {\n let instance = eventStore.instances[instanceId];\n let def = eventStore.defs[instance.defId];\n let ui = eventUis[def.defId];\n let origRange = instance.range;\n let normalRange = (!def.allDay && nextDayThreshold) ?\n computeVisibleDayRange(origRange, nextDayThreshold) :\n origRange;\n let slicedRange = intersectRanges(normalRange, framingRange);\n if (slicedRange) {\n if (ui.display === 'inverse-background') {\n if (def.groupId) {\n inverseBgByGroupId[def.groupId].push(slicedRange);\n }\n else {\n inverseBgByDefId[instance.defId].push(slicedRange);\n }\n }\n else if (ui.display !== 'none') {\n (ui.display === 'background' ? bgRanges : fgRanges).push({\n def,\n ui,\n instance,\n range: slicedRange,\n isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),\n isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),\n });\n }\n }\n }\n for (let groupId in inverseBgByGroupId) { // BY GROUP\n let ranges = inverseBgByGroupId[groupId];\n let invertedRanges = invertRanges(ranges, framingRange);\n for (let invertedRange of invertedRanges) {\n let def = defByGroupId[groupId];\n let ui = eventUis[def.defId];\n bgRanges.push({\n def,\n ui,\n instance: null,\n range: invertedRange,\n isStart: false,\n isEnd: false,\n });\n }\n }\n for (let defId in inverseBgByDefId) {\n let ranges = inverseBgByDefId[defId];\n let invertedRanges = invertRanges(ranges, framingRange);\n for (let invertedRange of invertedRanges) {\n bgRanges.push({\n def: eventStore.defs[defId],\n ui: eventUis[defId],\n instance: null,\n range: invertedRange,\n isStart: false,\n isEnd: false,\n });\n }\n }\n return { bg: bgRanges, fg: fgRanges };\n}\nfunction hasBgRendering(def) {\n return def.ui.display === 'background' || def.ui.display === 'inverse-background';\n}\nfunction setElSeg(el, seg) {\n el.fcSeg = seg;\n}\nfunction getElSeg(el) {\n return el.fcSeg ||\n el.parentNode.fcSeg || // for the harness\n null;\n}\n// event ui computation\nfunction compileEventUis(eventDefs, eventUiBases) {\n return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));\n}\nfunction compileEventUi(eventDef, eventUiBases) {\n let uis = [];\n if (eventUiBases['']) {\n uis.push(eventUiBases['']);\n }\n if (eventUiBases[eventDef.defId]) {\n uis.push(eventUiBases[eventDef.defId]);\n }\n uis.push(eventDef.ui);\n return combineEventUis(uis);\n}\nfunction sortEventSegs(segs, eventOrderSpecs) {\n let objs = segs.map(buildSegCompareObj);\n objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));\n return objs.map((c) => c._seg);\n}\n// returns a object with all primitive props that can be compared\nfunction buildSegCompareObj(seg) {\n let { eventRange } = seg;\n let eventDef = eventRange.def;\n let range = eventRange.instance ? eventRange.instance.range : eventRange.range;\n let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events\n let end = range.end ? range.end.valueOf() : 0; // \"\n return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,\n end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });\n}\nfunction computeSegDraggable(seg, context) {\n let { pluginHooks } = context;\n let transformers = pluginHooks.isDraggableTransformers;\n let { def, ui } = seg.eventRange;\n let val = ui.startEditable;\n for (let transformer of transformers) {\n val = transformer(val, def, ui, context);\n }\n return val;\n}\nfunction computeSegStartResizable(seg, context) {\n return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;\n}\nfunction computeSegEndResizable(seg, context) {\n return seg.isEnd && seg.eventRange.ui.durationEditable;\n}\nfunction buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true\ndefaultDisplayEventEnd, // defaults to true\nstartOverride, endOverride) {\n let { dateEnv, options } = context;\n let { displayEventTime, displayEventEnd } = options;\n let eventDef = seg.eventRange.def;\n let eventInstance = seg.eventRange.instance;\n if (displayEventTime == null) {\n displayEventTime = defaultDisplayEventTime !== false;\n }\n if (displayEventEnd == null) {\n displayEventEnd = defaultDisplayEventEnd !== false;\n }\n let wholeEventStart = eventInstance.range.start;\n let wholeEventEnd = eventInstance.range.end;\n let segStart = startOverride || seg.start || seg.eventRange.range.start;\n let segEnd = endOverride || seg.end || seg.eventRange.range.end;\n let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();\n let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();\n if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {\n segStart = isStartDay ? wholeEventStart : segStart;\n segEnd = isEndDay ? wholeEventEnd : segEnd;\n if (displayEventEnd && eventDef.hasEnd) {\n return dateEnv.formatRange(segStart, segEnd, timeFormat, {\n forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,\n forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,\n });\n }\n return dateEnv.format(segStart, timeFormat, {\n forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same\n });\n }\n return '';\n}\nfunction getSegMeta(seg, todayRange, nowDate) {\n let segRange = seg.eventRange.range;\n return {\n isPast: segRange.end <= (nowDate || todayRange.start),\n isFuture: segRange.start >= (nowDate || todayRange.end),\n isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),\n };\n}\nfunction getEventClassNames(props) {\n let classNames = ['fc-event'];\n if (props.isMirror) {\n classNames.push('fc-event-mirror');\n }\n if (props.isDraggable) {\n classNames.push('fc-event-draggable');\n }\n if (props.isStartResizable || props.isEndResizable) {\n classNames.push('fc-event-resizable');\n }\n if (props.isDragging) {\n classNames.push('fc-event-dragging');\n }\n if (props.isResizing) {\n classNames.push('fc-event-resizing');\n }\n if (props.isSelected) {\n classNames.push('fc-event-selected');\n }\n if (props.isStart) {\n classNames.push('fc-event-start');\n }\n if (props.isEnd) {\n classNames.push('fc-event-end');\n }\n if (props.isPast) {\n classNames.push('fc-event-past');\n }\n if (props.isToday) {\n classNames.push('fc-event-today');\n }\n if (props.isFuture) {\n classNames.push('fc-event-future');\n }\n return classNames;\n}\nfunction buildEventRangeKey(eventRange) {\n return eventRange.instance\n ? eventRange.instance.instanceId\n : `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;\n // inverse-background events don't have specific instances. TODO: better solution\n}\nfunction getSegAnchorAttrs(seg, context) {\n let { def, instance } = seg.eventRange;\n let { url } = def;\n if (url) {\n return { href: url };\n }\n let { emitter, options } = context;\n let { eventInteractive } = options;\n if (eventInteractive == null) {\n eventInteractive = def.interactive;\n if (eventInteractive == null) {\n eventInteractive = Boolean(emitter.hasHandlers('eventClick'));\n }\n }\n // mock what happens in EventClicking\n if (eventInteractive) {\n // only attach keyboard-related handlers because click handler is already done in EventClicking\n return createAriaKeyboardAttrs((ev) => {\n emitter.trigger('eventClick', {\n el: ev.target,\n event: new EventImpl(context, def, instance),\n jsEvent: ev,\n view: context.viewApi,\n });\n });\n }\n return {};\n}\n\nconst STANDARD_PROPS = {\n start: identity,\n end: identity,\n allDay: Boolean,\n};\nfunction parseDateSpan(raw, dateEnv, defaultDuration) {\n let span = parseOpenDateSpan(raw, dateEnv);\n let { range } = span;\n if (!range.start) {\n return null;\n }\n if (!range.end) {\n if (defaultDuration == null) {\n return null;\n }\n range.end = dateEnv.add(range.start, defaultDuration);\n }\n return span;\n}\n/*\nTODO: somehow combine with parseRange?\nWill return null if the start/end props were present but parsed invalidly.\n*/\nfunction parseOpenDateSpan(raw, dateEnv) {\n let { refined: standardProps, extra } = refineProps(raw, STANDARD_PROPS);\n let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;\n let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;\n let { allDay } = standardProps;\n if (allDay == null) {\n allDay = (startMeta && startMeta.isTimeUnspecified) &&\n (!endMeta || endMeta.isTimeUnspecified);\n }\n return Object.assign({ range: {\n start: startMeta ? startMeta.marker : null,\n end: endMeta ? endMeta.marker : null,\n }, allDay }, extra);\n}\nfunction isDateSpansEqual(span0, span1) {\n return rangesEqual(span0.range, span1.range) &&\n span0.allDay === span1.allDay &&\n isSpanPropsEqual(span0, span1);\n}\n// the NON-DATE-RELATED props\nfunction isSpanPropsEqual(span0, span1) {\n for (let propName in span1) {\n if (propName !== 'range' && propName !== 'allDay') {\n if (span0[propName] !== span1[propName]) {\n return false;\n }\n }\n }\n // are there any props that span0 has that span1 DOESN'T have?\n // both have range/allDay, so no need to special-case.\n for (let propName in span0) {\n if (!(propName in span1)) {\n return false;\n }\n }\n return true;\n}\nfunction buildDateSpanApi(span, dateEnv) {\n return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay });\n}\nfunction buildRangeApiWithTimeZone(range, dateEnv, omitTime) {\n return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone });\n}\nfunction buildRangeApi(range, dateEnv, omitTime) {\n return {\n start: dateEnv.toDate(range.start),\n end: dateEnv.toDate(range.end),\n startStr: dateEnv.formatIso(range.start, { omitTime }),\n endStr: dateEnv.formatIso(range.end, { omitTime }),\n };\n}\nfunction fabricateEventRange(dateSpan, eventUiBases, context) {\n let res = refineEventDef({ editable: false }, context);\n let def = parseEventDef(res.refined, res.extra, '', // sourceId\n dateSpan.allDay, true, // hasEnd\n context);\n return {\n def,\n ui: compileEventUi(def, eventUiBases),\n instance: createEventInstance(def.defId, dateSpan.range),\n range: dateSpan.range,\n isStart: true,\n isEnd: true,\n };\n}\n\n/*\ngiven a function that resolves a result asynchronously.\nthe function can either call passed-in success and failure callbacks,\nor it can return a promise.\nif you need to pass additional params to func, bind them first.\n*/\nfunction unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {\n // guard against success/failure callbacks being called more than once\n // and guard against a promise AND callback being used together.\n let isResolved = false;\n let wrappedSuccess = function (res) {\n if (!isResolved) {\n isResolved = true;\n normalizedSuccessCallback(res);\n }\n };\n let wrappedFailure = function (error) {\n if (!isResolved) {\n isResolved = true;\n normalizedFailureCallback(error);\n }\n };\n let res = func(wrappedSuccess, wrappedFailure);\n if (res && typeof res.then === 'function') {\n res.then(wrappedSuccess, wrappedFailure);\n }\n}\n\nclass JsonRequestError extends Error {\n constructor(message, response) {\n super(message);\n this.response = response;\n }\n}\nfunction requestJson(method, url, params) {\n method = method.toUpperCase();\n const fetchOptions = {\n method,\n };\n if (method === 'GET') {\n url += (url.indexOf('?') === -1 ? '?' : '&') +\n new URLSearchParams(params);\n }\n else {\n fetchOptions.body = new URLSearchParams(params);\n fetchOptions.headers = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n }\n return fetch(url, fetchOptions).then((fetchRes) => {\n if (fetchRes.ok) {\n return fetchRes.json().then((parsedResponse) => {\n return [parsedResponse, fetchRes];\n }, () => {\n throw new JsonRequestError('Failure parsing JSON', fetchRes);\n });\n }\n else {\n throw new JsonRequestError('Request failed', fetchRes);\n }\n });\n}\n\nlet canVGrowWithinCell;\nfunction getCanVGrowWithinCell() {\n if (canVGrowWithinCell == null) {\n canVGrowWithinCell = computeCanVGrowWithinCell();\n }\n return canVGrowWithinCell;\n}\nfunction computeCanVGrowWithinCell() {\n // for SSR, because this function is call immediately at top-level\n // TODO: just make this logic execute top-level, immediately, instead of doing lazily\n if (typeof document === 'undefined') {\n return true;\n }\n let el = document.createElement('div');\n el.style.position = 'absolute';\n el.style.top = '0px';\n el.style.left = '0px';\n el.innerHTML = '<table><tr><td><div></div></td></tr></table>';\n el.querySelector('table').style.height = '100px';\n el.querySelector('div').style.height = '100%';\n document.body.appendChild(el);\n let div = el.querySelector('div');\n let possible = div.offsetHeight > 0;\n document.body.removeChild(el);\n return possible;\n}\n\nclass CalendarRoot extends BaseComponent {\n constructor() {\n super(...arguments);\n this.state = {\n forPrint: false,\n };\n this.handleBeforePrint = () => {\n flushSync(() => {\n this.setState({ forPrint: true });\n });\n };\n this.handleAfterPrint = () => {\n flushSync(() => {\n this.setState({ forPrint: false });\n });\n };\n }\n render() {\n let { props } = this;\n let { options } = props;\n let { forPrint } = this.state;\n let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';\n let height = (!isHeightAuto && options.height != null) ? options.height : '';\n let classNames = [\n 'fc',\n forPrint ? 'fc-media-print' : 'fc-media-screen',\n `fc-direction-${options.direction}`,\n props.theme.getClass('root'),\n ];\n if (!getCanVGrowWithinCell()) {\n classNames.push('fc-liquid-hack');\n }\n return props.children(classNames, height, isHeightAuto, forPrint);\n }\n componentDidMount() {\n let { emitter } = this.props;\n emitter.on('_beforeprint', this.handleBeforePrint);\n emitter.on('_afterprint', this.handleAfterPrint);\n }\n componentWillUnmount() {\n let { emitter } = this.props;\n emitter.off('_beforeprint', this.handleBeforePrint);\n emitter.off('_afterprint', this.handleAfterPrint);\n }\n}\n\nclass Interaction {\n constructor(settings) {\n this.component = settings.component;\n this.isHitComboAllowed = settings.isHitComboAllowed || null;\n }\n destroy() {\n }\n}\nfunction parseInteractionSettings(component, input) {\n return {\n component,\n el: input.el,\n useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,\n isHitComboAllowed: input.isHitComboAllowed || null,\n };\n}\nfunction interactionSettingsToStore(settings) {\n return {\n [settings.component.uid]: settings,\n };\n}\n// global state\nconst interactionSettingsStore = {};\n\nclass NowTimer extends preact__WEBPACK_IMPORTED_MODULE_0__.Component {\n constructor(props, context) {\n super(props, context);\n this.handleRefresh = () => {\n let timing = this.computeTiming();\n if (timing.state.nowDate.valueOf() !== this.state.nowDate.valueOf()) {\n this.setState(timing.state);\n }\n this.clearTimeout();\n this.setTimeout(timing.waitMs);\n };\n this.handleVisibilityChange = () => {\n if (!document.hidden) {\n this.handleRefresh();\n }\n };\n this.state = this.computeTiming().state;\n }\n render() {\n let { props, state } = this;\n return props.children(state.nowDate, state.todayRange);\n }\n componentDidMount() {\n this.setTimeout();\n this.context.nowManager.addResetListener(this.handleRefresh);\n // fired tab becomes visible after being hidden\n document.addEventListener('visibilitychange', this.handleVisibilityChange);\n }\n componentDidUpdate(prevProps) {\n if (prevProps.unit !== this.props.unit) {\n this.clearTimeout();\n this.setTimeout();\n }\n }\n componentWillUnmount() {\n this.clearTimeout();\n this.context.nowManager.removeResetListener(this.handleRefresh);\n document.removeEventListener('visibilitychange', this.handleVisibilityChange);\n }\n computeTiming() {\n let { props, context } = this;\n let unroundedNow = context.nowManager.getDateMarker();\n let { nowIndicatorSnap } = context.options;\n if (nowIndicatorSnap === 'auto') {\n nowIndicatorSnap =\n // large unit?\n /year|month|week|day/.test(props.unit) ||\n // if slotDuration 30 mins for example, would NOT appear to snap (legacy behavior)\n (props.unitValue || 1) === 1;\n }\n let nowDate;\n let waitMs;\n if (nowIndicatorSnap) {\n nowDate = context.dateEnv.startOf(unroundedNow, props.unit); // aka currentUnitStart\n let nextUnitStart = context.dateEnv.add(nowDate, createDuration(1, props.unit));\n waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();\n }\n else {\n nowDate = unroundedNow;\n waitMs = 1000 * 60; // 1 minute\n }\n // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)\n // ensure no longer than a day\n waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);\n return {\n state: { nowDate, todayRange: buildDayRange(nowDate) },\n waitMs,\n };\n }\n setTimeout(waitMs = this.computeTiming().waitMs) {\n // NOTE: timeout could take longer than expected if tab sleeps,\n // which is why we listen to 'visibilitychange'\n this.timeoutId = setTimeout(() => {\n // NOTE: timeout could also return *earlier* than expected, and we need to wait 2 ms more\n // This is why use use same waitMs from computeTiming, so we don't skip an interval while\n // .setState() is executing\n const timing = this.computeTiming();\n this.setState(timing.state, () => {\n this.setTimeout(timing.waitMs);\n });\n }, waitMs);\n }\n clearTimeout() {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n }\n}\nNowTimer.contextType = ViewContextType;\nfunction buildDayRange(date) {\n let start = startOfDay(date);\n let end = addDays(start, 1);\n return { start, end };\n}\n\nclass CalendarImpl {\n getCurrentData() {\n return this.currentDataManager.getCurrentData();\n }\n dispatch(action) {\n this.currentDataManager.dispatch(action);\n }\n get view() { return this.getCurrentData().viewApi; }\n batchRendering(callback) {\n callback();\n }\n updateSize() {\n this.trigger('_resize', true);\n }\n // Options\n // -----------------------------------------------------------------------------------------------------------------\n setOption(name, val) {\n this.dispatch({\n type: 'SET_OPTION',\n optionName: name,\n rawOptionValue: val,\n });\n }\n getOption(name) {\n return this.currentDataManager.currentCalendarOptionsInput[name];\n }\n getAvailableLocaleCodes() {\n return Object.keys(this.getCurrentData().availableRawLocales);\n }\n // Trigger\n // -----------------------------------------------------------------------------------------------------------------\n on(handlerName, handler) {\n let { currentDataManager } = this;\n if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {\n currentDataManager.emitter.on(handlerName, handler);\n }\n else {\n console.warn(`Unknown listener name '${handlerName}'`);\n }\n }\n off(handlerName, handler) {\n this.currentDataManager.emitter.off(handlerName, handler);\n }\n // not meant for public use\n trigger(handlerName, ...args) {\n this.currentDataManager.emitter.trigger(handlerName, ...args);\n }\n // View\n // -----------------------------------------------------------------------------------------------------------------\n changeView(viewType, dateOrRange) {\n this.batchRendering(() => {\n this.unselect();\n if (dateOrRange) {\n if (dateOrRange.start && dateOrRange.end) { // a range\n this.dispatch({\n type: 'CHANGE_VIEW_TYPE',\n viewType,\n });\n this.dispatch({\n type: 'SET_OPTION',\n optionName: 'visibleRange',\n rawOptionValue: dateOrRange,\n });\n }\n else {\n let { dateEnv } = this.getCurrentData();\n this.dispatch({\n type: 'CHANGE_VIEW_TYPE',\n viewType,\n dateMarker: dateEnv.createMarker(dateOrRange),\n });\n }\n }\n else {\n this.dispatch({\n type: 'CHANGE_VIEW_TYPE',\n viewType,\n });\n }\n });\n }\n // Forces navigation to a view for the given date.\n // `viewType` can be a specific view name or a generic one like \"week\" or \"day\".\n // needs to change\n zoomTo(dateMarker, viewType) {\n let state = this.getCurrentData();\n let spec;\n viewType = viewType || 'day'; // day is default zoom\n spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);\n this.unselect();\n if (spec) {\n this.dispatch({\n type: 'CHANGE_VIEW_TYPE',\n viewType: spec.type,\n dateMarker,\n });\n }\n else {\n this.dispatch({\n type: 'CHANGE_DATE',\n dateMarker,\n });\n }\n }\n // Given a duration singular unit, like \"week\" or \"day\", finds a matching view spec.\n // Preference is given to views that have corresponding buttons.\n getUnitViewSpec(unit) {\n let { viewSpecs, toolbarConfig } = this.getCurrentData();\n let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);\n let i;\n let spec;\n for (let viewType in viewSpecs) {\n viewTypes.push(viewType);\n }\n for (i = 0; i < viewTypes.length; i += 1) {\n spec = viewSpecs[viewTypes[i]];\n if (spec) {\n if (spec.singleUnit === unit) {\n return spec;\n }\n }\n }\n return null;\n }\n // Current Date\n // -----------------------------------------------------------------------------------------------------------------\n prev() {\n this.unselect();\n this.dispatch({ type: 'PREV' });\n }\n next() {\n this.unselect();\n this.dispatch({ type: 'NEXT' });\n }\n prevYear() {\n let state = this.getCurrentData();\n this.unselect();\n this.dispatch({\n type: 'CHANGE_DATE',\n dateMarker: state.dateEnv.addYears(state.currentDate, -1),\n });\n }\n nextYear() {\n let state = this.getCurrentData();\n this.unselect();\n this.dispatch({\n type: 'CHANGE_DATE',\n dateMarker: state.dateEnv.addYears(state.currentDate, 1),\n });\n }\n today() {\n let state = this.getCurrentData();\n this.unselect();\n this.dispatch({\n type: 'CHANGE_DATE',\n dateMarker: state.nowManager.getDateMarker(),\n });\n }\n gotoDate(zonedDateInput) {\n let state = this.getCurrentData();\n this.unselect();\n this.dispatch({\n type: 'CHANGE_DATE',\n dateMarker: state.dateEnv.createMarker(zonedDateInput),\n });\n }\n incrementDate(deltaInput) {\n let state = this.getCurrentData();\n let delta = createDuration(deltaInput);\n if (delta) { // else, warn about invalid input?\n this.unselect();\n this.dispatch({\n type: 'CHANGE_DATE',\n dateMarker: state.dateEnv.add(state.currentDate, delta),\n });\n }\n }\n getDate() {\n let state = this.getCurrentData();\n return state.dateEnv.toDate(state.currentDate);\n }\n // Date Formatting Utils\n // -----------------------------------------------------------------------------------------------------------------\n formatDate(d, formatter) {\n let { dateEnv } = this.getCurrentData();\n return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));\n }\n // `settings` is for formatter AND isEndExclusive\n formatRange(d0, d1, settings) {\n let { dateEnv } = this.getCurrentData();\n return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);\n }\n formatIso(d, omitTime) {\n let { dateEnv } = this.getCurrentData();\n return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });\n }\n // Date Selection / Event Selection / DayClick\n // -----------------------------------------------------------------------------------------------------------------\n select(dateOrObj, endDate) {\n let selectionInput;\n if (endDate == null) {\n if (dateOrObj.start != null) {\n selectionInput = dateOrObj;\n }\n else {\n selectionInput = {\n start: dateOrObj,\n end: null,\n };\n }\n }\n else {\n selectionInput = {\n start: dateOrObj,\n end: endDate,\n };\n }\n let state = this.getCurrentData();\n let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));\n if (selection) { // throw parse error otherwise?\n this.dispatch({ type: 'SELECT_DATES', selection });\n triggerDateSelect(selection, null, state);\n }\n }\n unselect(pev) {\n let state = this.getCurrentData();\n if (state.dateSelection) {\n this.dispatch({ type: 'UNSELECT_DATES' });\n triggerDateUnselect(pev, state);\n }\n }\n // Public Events API\n // -----------------------------------------------------------------------------------------------------------------\n addEvent(eventInput, sourceInput) {\n if (eventInput instanceof EventImpl) {\n let def = eventInput._def;\n let instance = eventInput._instance;\n let currentData = this.getCurrentData();\n // not already present? don't want to add an old snapshot\n if (!currentData.eventStore.defs[def.defId]) {\n this.dispatch({\n type: 'ADD_EVENTS',\n eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?\n });\n this.triggerEventAdd(eventInput);\n }\n return eventInput;\n }\n let state = this.getCurrentData();\n let eventSource;\n if (sourceInput instanceof EventSourceImpl) {\n eventSource = sourceInput.internalEventSource;\n }\n else if (typeof sourceInput === 'boolean') {\n if (sourceInput) { // true. part of the first event source\n [eventSource] = hashValuesToArray(state.eventSources);\n }\n }\n else if (sourceInput != null) { // an ID. accepts a number too\n let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function\n if (!sourceApi) {\n console.warn(`Could not find an event source with ID \"${sourceInput}\"`); // TODO: test\n return null;\n }\n eventSource = sourceApi.internalEventSource;\n }\n let tuple = parseEvent(eventInput, eventSource, state, false);\n if (tuple) {\n let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);\n this.dispatch({\n type: 'ADD_EVENTS',\n eventStore: eventTupleToStore(tuple),\n });\n this.triggerEventAdd(newEventApi);\n return newEventApi;\n }\n return null;\n }\n triggerEventAdd(eventApi) {\n let { emitter } = this.getCurrentData();\n emitter.trigger('eventAdd', {\n event: eventApi,\n relatedEvents: [],\n revert: () => {\n this.dispatch({\n type: 'REMOVE_EVENTS',\n eventStore: eventApiToStore(eventApi),\n });\n },\n });\n }\n // TODO: optimize\n getEventById(id) {\n let state = this.getCurrentData();\n let { defs, instances } = state.eventStore;\n id = String(id);\n for (let defId in defs) {\n let def = defs[defId];\n if (def.publicId === id) {\n if (def.recurringDef) {\n return new EventImpl(state, def, null);\n }\n for (let instanceId in instances) {\n let instance = instances[instanceId];\n if (instance.defId === def.defId) {\n return new EventImpl(state, def, instance);\n }\n }\n }\n }\n return null;\n }\n getEvents() {\n let currentData = this.getCurrentData();\n return buildEventApis(currentData.eventStore, currentData);\n }\n removeAllEvents() {\n this.dispatch({ type: 'REMOVE_ALL_EVENTS' });\n }\n // Public Event Sources API\n // -----------------------------------------------------------------------------------------------------------------\n getEventSources() {\n let state = this.getCurrentData();\n let sourceHash = state.eventSources;\n let sourceApis = [];\n for (let internalId in sourceHash) {\n sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));\n }\n return sourceApis;\n }\n getEventSourceById(id) {\n let state = this.getCurrentData();\n let sourceHash = state.eventSources;\n id = String(id);\n for (let sourceId in sourceHash) {\n if (sourceHash[sourceId].publicId === id) {\n return new EventSourceImpl(state, sourceHash[sourceId]);\n }\n }\n return null;\n }\n addEventSource(sourceInput) {\n let state = this.getCurrentData();\n if (sourceInput instanceof EventSourceImpl) {\n // not already present? don't want to add an old snapshot\n if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {\n this.dispatch({\n type: 'ADD_EVENT_SOURCES',\n sources: [sourceInput.internalEventSource],\n });\n }\n return sourceInput;\n }\n let eventSource = parseEventSource(sourceInput, state);\n if (eventSource) { // TODO: error otherwise?\n this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });\n return new EventSourceImpl(state, eventSource);\n }\n return null;\n }\n removeAllEventSources() {\n this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });\n }\n refetchEvents() {\n this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });\n }\n // Scroll\n // -----------------------------------------------------------------------------------------------------------------\n scrollToTime(timeInput) {\n let time = createDuration(timeInput);\n if (time) {\n this.trigger('_scrollRequest', { time });\n }\n }\n}\n\nfunction pointInsideRect(point, rect) {\n return point.left >= rect.left &&\n point.left < rect.right &&\n point.top >= rect.top &&\n point.top < rect.bottom;\n}\n// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false\nfunction intersectRects(rect1, rect2) {\n let res = {\n left: Math.max(rect1.left, rect2.left),\n right: Math.min(rect1.right, rect2.right),\n top: Math.max(rect1.top, rect2.top),\n bottom: Math.min(rect1.bottom, rect2.bottom),\n };\n if (res.left < res.right && res.top < res.bottom) {\n return res;\n }\n return false;\n}\nfunction translateRect(rect, deltaX, deltaY) {\n return {\n left: rect.left + deltaX,\n right: rect.right + deltaX,\n top: rect.top + deltaY,\n bottom: rect.bottom + deltaY,\n };\n}\n// Returns a new point that will have been moved to reside within the given rectangle\nfunction constrainPoint(point, rect) {\n return {\n left: Math.min(Math.max(point.left, rect.left), rect.right),\n top: Math.min(Math.max(point.top, rect.top), rect.bottom),\n };\n}\n// Returns a point that is the center of the given rectangle\nfunction getRectCenter(rect) {\n return {\n left: (rect.left + rect.right) / 2,\n top: (rect.top + rect.bottom) / 2,\n };\n}\n// Subtracts point2's coordinates from point1's coordinates, returning a delta\nfunction diffPoints(point1, point2) {\n return {\n left: point1.left - point2.left,\n top: point1.top - point2.top,\n };\n}\n\nconst EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere\nclass Splitter {\n constructor() {\n this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);\n this.splitDateSelection = memoize(this._splitDateSpan);\n this.splitEventStore = memoize(this._splitEventStore);\n this.splitIndividualUi = memoize(this._splitIndividualUi);\n this.splitEventDrag = memoize(this._splitInteraction);\n this.splitEventResize = memoize(this._splitInteraction);\n this.eventUiBuilders = {}; // TODO: typescript protection\n }\n splitProps(props) {\n let keyInfos = this.getKeyInfo(props);\n let defKeys = this.getKeysForEventDefs(props.eventStore);\n let dateSelections = this.splitDateSelection(props.dateSelection);\n let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*\n let eventStores = this.splitEventStore(props.eventStore, defKeys);\n let eventDrags = this.splitEventDrag(props.eventDrag);\n let eventResizes = this.splitEventResize(props.eventResize);\n let splitProps = {};\n this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));\n for (let key in keyInfos) {\n let keyInfo = keyInfos[key];\n let eventStore = eventStores[key] || EMPTY_EVENT_STORE;\n let buildEventUi = this.eventUiBuilders[key];\n splitProps[key] = {\n businessHours: keyInfo.businessHours || props.businessHours,\n dateSelection: dateSelections[key] || null,\n eventStore,\n eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),\n eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',\n eventDrag: eventDrags[key] || null,\n eventResize: eventResizes[key] || null,\n };\n }\n return splitProps;\n }\n _splitDateSpan(dateSpan) {\n let dateSpans = {};\n if (dateSpan) {\n let keys = this.getKeysForDateSpan(dateSpan);\n for (let key of keys) {\n dateSpans[key] = dateSpan;\n }\n }\n return dateSpans;\n }\n _getKeysForEventDefs(eventStore) {\n return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));\n }\n _splitEventStore(eventStore, defKeys) {\n let { defs, instances } = eventStore;\n let splitStores = {};\n for (let defId in defs) {\n for (let key of defKeys[defId]) {\n if (!splitStores[key]) {\n splitStores[key] = createEmptyEventStore();\n }\n splitStores[key].defs[defId] = defs[defId];\n }\n }\n for (let instanceId in instances) {\n let instance = instances[instanceId];\n for (let key of defKeys[instance.defId]) {\n if (splitStores[key]) { // must have already been created\n splitStores[key].instances[instanceId] = instance;\n }\n }\n }\n return splitStores;\n }\n _splitIndividualUi(eventUiBases, defKeys) {\n let splitHashes = {};\n for (let defId in eventUiBases) {\n if (defId) { // not the '' key\n for (let key of defKeys[defId]) {\n if (!splitHashes[key]) {\n splitHashes[key] = {};\n }\n splitHashes[key][defId] = eventUiBases[defId];\n }\n }\n }\n return splitHashes;\n }\n _splitInteraction(interaction) {\n let splitStates = {};\n if (interaction) {\n let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));\n // can't rely on defKeys because event data is mutated\n let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);\n let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);\n let populate = (key) => {\n if (!splitStates[key]) {\n splitStates[key] = {\n affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,\n mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,\n isEvent: interaction.isEvent,\n };\n }\n };\n for (let key in affectedStores) {\n populate(key);\n }\n for (let key in mutatedStores) {\n populate(key);\n }\n }\n return splitStates;\n }\n}\nfunction buildEventUiForKey(allUi, eventUiForKey, individualUi) {\n let baseParts = [];\n if (allUi) {\n baseParts.push(allUi);\n }\n if (eventUiForKey) {\n baseParts.push(eventUiForKey);\n }\n let stuff = {\n '': combineEventUis(baseParts),\n };\n if (individualUi) {\n Object.assign(stuff, individualUi);\n }\n return stuff;\n}\n\nfunction getDateMeta(date, todayRange, nowDate, dateProfile) {\n return {\n dow: date.getUTCDay(),\n isDisabled: Boolean(dateProfile && (!dateProfile.activeRange || !rangeContainsMarker(dateProfile.activeRange, date))),\n isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),\n isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),\n isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),\n isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),\n };\n}\nfunction getDayClassNames(meta, theme) {\n let classNames = [\n 'fc-day',\n `fc-day-${DAY_IDS[meta.dow]}`,\n ];\n if (meta.isDisabled) {\n classNames.push('fc-day-disabled');\n }\n else {\n if (meta.isToday) {\n classNames.push('fc-day-today');\n classNames.push(theme.getClass('today'));\n }\n if (meta.isPast) {\n classNames.push('fc-day-past');\n }\n if (meta.isFuture) {\n classNames.push('fc-day-future');\n }\n if (meta.isOther) {\n classNames.push('fc-day-other');\n }\n }\n return classNames;\n}\nfunction getSlotClassNames(meta, theme) {\n let classNames = [\n 'fc-slot',\n `fc-slot-${DAY_IDS[meta.dow]}`,\n ];\n if (meta.isDisabled) {\n classNames.push('fc-slot-disabled');\n }\n else {\n if (meta.isToday) {\n classNames.push('fc-slot-today');\n classNames.push(theme.getClass('today'));\n }\n if (meta.isPast) {\n classNames.push('fc-slot-past');\n }\n if (meta.isFuture) {\n classNames.push('fc-slot-future');\n }\n }\n return classNames;\n}\n\nconst DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });\nconst WEEK_FORMAT = createFormatter({ week: 'long' });\nfunction buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {\n const { dateEnv, options, calendarApi } = context;\n let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);\n if (options.navLinks) {\n let zonedDate = dateEnv.toDate(dateMarker);\n const handleInteraction = (ev) => {\n let customAction = viewType === 'day' ? options.navLinkDayClick :\n viewType === 'week' ? options.navLinkWeekClick : null;\n if (typeof customAction === 'function') {\n customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);\n }\n else {\n if (typeof customAction === 'string') {\n viewType = customAction;\n }\n calendarApi.zoomTo(dateMarker, viewType);\n }\n };\n return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable\n ? createAriaClickAttrs(handleInteraction)\n : { onClick: handleInteraction }));\n }\n return { 'aria-label': dateStr };\n}\n\nlet _isRtlScrollbarOnLeft = null;\nfunction getIsRtlScrollbarOnLeft() {\n if (_isRtlScrollbarOnLeft === null) {\n _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();\n }\n return _isRtlScrollbarOnLeft;\n}\nfunction computeIsRtlScrollbarOnLeft() {\n let outerEl = document.createElement('div');\n applyStyle(outerEl, {\n position: 'absolute',\n top: -1000,\n left: 0,\n border: 0,\n padding: 0,\n overflow: 'scroll',\n direction: 'rtl',\n });\n outerEl.innerHTML = '<div></div>';\n document.body.appendChild(outerEl);\n let innerEl = outerEl.firstChild;\n let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;\n removeElement(outerEl);\n return res;\n}\n\nlet _scrollbarWidths;\nfunction getScrollbarWidths() {\n if (!_scrollbarWidths) {\n _scrollbarWidths = computeScrollbarWidths();\n }\n return _scrollbarWidths;\n}\nfunction computeScrollbarWidths() {\n let el = document.createElement('div');\n el.style.overflow = 'scroll';\n el.style.position = 'absolute';\n el.style.top = '-9999px';\n el.style.left = '-9999px';\n document.body.appendChild(el);\n let res = computeScrollbarWidthsForEl(el);\n document.body.removeChild(el);\n return res;\n}\n// WARNING: will include border\nfunction computeScrollbarWidthsForEl(el) {\n return {\n x: el.offsetHeight - el.clientHeight,\n y: el.offsetWidth - el.clientWidth,\n };\n}\n\nfunction computeEdges(el, getPadding = false) {\n let computedStyle = window.getComputedStyle(el);\n let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;\n let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;\n let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;\n let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;\n let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!\n let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;\n let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;\n let res = {\n borderLeft,\n borderRight,\n borderTop,\n borderBottom,\n scrollbarBottom,\n scrollbarLeft: 0,\n scrollbarRight: 0,\n };\n if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?\n res.scrollbarLeft = scrollbarLeftRight;\n }\n else {\n res.scrollbarRight = scrollbarLeftRight;\n }\n if (getPadding) {\n res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;\n res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;\n res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;\n res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;\n }\n return res;\n}\nfunction computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {\n let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);\n let edges = computeEdges(el, goWithinPadding);\n let res = {\n left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,\n right: outerRect.right - edges.borderRight - edges.scrollbarRight,\n top: outerRect.top + edges.borderTop,\n bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,\n };\n if (goWithinPadding) {\n res.left += edges.paddingLeft;\n res.right -= edges.paddingRight;\n res.top += edges.paddingTop;\n res.bottom -= edges.paddingBottom;\n }\n return res;\n}\nfunction computeRect(el) {\n let rect = el.getBoundingClientRect();\n return {\n left: rect.left + window.scrollX,\n top: rect.top + window.scrollY,\n right: rect.right + window.scrollX,\n bottom: rect.bottom + window.scrollY,\n };\n}\nfunction computeClippedClientRect(el) {\n let clippingParents = getClippingParents(el);\n let rect = el.getBoundingClientRect();\n for (let clippingParent of clippingParents) {\n let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());\n if (intersection) {\n rect = intersection;\n }\n else {\n return null;\n }\n }\n return rect;\n}\n// does not return window\nfunction getClippingParents(el) {\n let parents = [];\n while (el instanceof HTMLElement) { // will stop when gets to document or null\n let computedStyle = window.getComputedStyle(el);\n if (computedStyle.position === 'fixed') {\n break;\n }\n if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {\n parents.push(el);\n }\n el = el.parentNode;\n }\n return parents;\n}\n\n/*\nRecords offset information for a set of elements, relative to an origin element.\nCan record the left/right OR the top/bottom OR both.\nProvides methods for querying the cache by position.\n*/\nclass PositionCache {\n constructor(originEl, els, isHorizontal, isVertical) {\n this.els = els;\n let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left\n if (isHorizontal) {\n this.buildElHorizontals(originClientRect.left);\n }\n if (isVertical) {\n this.buildElVerticals(originClientRect.top);\n }\n }\n // Populates the left/right internal coordinate arrays\n buildElHorizontals(originClientLeft) {\n let lefts = [];\n let rights = [];\n for (let el of this.els) {\n let rect = el.getBoundingClientRect();\n lefts.push(rect.left - originClientLeft);\n rights.push(rect.right - originClientLeft);\n }\n this.lefts = lefts;\n this.rights = rights;\n }\n // Populates the top/bottom internal coordinate arrays\n buildElVerticals(originClientTop) {\n let tops = [];\n let bottoms = [];\n for (let el of this.els) {\n let rect = el.getBoundingClientRect();\n tops.push(rect.top - originClientTop);\n bottoms.push(rect.bottom - originClientTop);\n }\n this.tops = tops;\n this.bottoms = bottoms;\n }\n // Given a left offset (from document left), returns the index of the el that it horizontally intersects.\n // If no intersection is made, returns undefined.\n leftToIndex(leftPosition) {\n let { lefts, rights } = this;\n let len = lefts.length;\n let i;\n for (i = 0; i < len; i += 1) {\n if (leftPosition >= lefts[i] && leftPosition < rights[i]) {\n return i;\n }\n }\n return undefined; // TODO: better\n }\n // Given a top offset (from document top), returns the index of the el that it vertically intersects.\n // If no intersection is made, returns undefined.\n topToIndex(topPosition) {\n let { tops, bottoms } = this;\n let len = tops.length;\n let i;\n for (i = 0; i < len; i += 1) {\n if (topPosition >= tops[i] && topPosition < bottoms[i]) {\n return i;\n }\n }\n return undefined; // TODO: better\n }\n // Gets the width of the element at the given index\n getWidth(leftIndex) {\n return this.rights[leftIndex] - this.lefts[leftIndex];\n }\n // Gets the height of the element at the given index\n getHeight(topIndex) {\n return this.bottoms[topIndex] - this.tops[topIndex];\n }\n similarTo(otherCache) {\n return similarNumArrays(this.tops || [], otherCache.tops || []) &&\n similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&\n similarNumArrays(this.lefts || [], otherCache.lefts || []) &&\n similarNumArrays(this.rights || [], otherCache.rights || []);\n }\n}\nfunction similarNumArrays(a, b) {\n const len = a.length;\n if (len !== b.length) {\n return false;\n }\n for (let i = 0; i < len; i++) {\n if (Math.round(a[i]) !== Math.round(b[i])) {\n return false;\n }\n }\n return true;\n}\n\n/* eslint max-classes-per-file: \"off\" */\n/*\nAn object for getting/setting scroll-related information for an element.\nInternally, this is done very differently for window versus DOM element,\nso this object serves as a common interface.\n*/\nclass ScrollController {\n getMaxScrollTop() {\n return this.getScrollHeight() - this.getClientHeight();\n }\n getMaxScrollLeft() {\n return this.getScrollWidth() - this.getClientWidth();\n }\n canScrollVertically() {\n return this.getMaxScrollTop() > 0;\n }\n canScrollHorizontally() {\n return this.getMaxScrollLeft() > 0;\n }\n canScrollUp() {\n return this.getScrollTop() > 0;\n }\n canScrollDown() {\n return this.getScrollTop() < this.getMaxScrollTop();\n }\n canScrollLeft() {\n return this.getScrollLeft() > 0;\n }\n canScrollRight() {\n return this.getScrollLeft() < this.getMaxScrollLeft();\n }\n}\nclass ElementScrollController extends ScrollController {\n constructor(el) {\n super();\n this.el = el;\n }\n getScrollTop() {\n return this.el.scrollTop;\n }\n getScrollLeft() {\n return this.el.scrollLeft;\n }\n setScrollTop(top) {\n this.el.scrollTop = top;\n }\n setScrollLeft(left) {\n this.el.scrollLeft = left;\n }\n getScrollWidth() {\n return this.el.scrollWidth;\n }\n getScrollHeight() {\n return this.el.scrollHeight;\n }\n getClientHeight() {\n return this.el.clientHeight;\n }\n getClientWidth() {\n return this.el.clientWidth;\n }\n}\nclass WindowScrollController extends ScrollController {\n getScrollTop() {\n return window.scrollY;\n }\n getScrollLeft() {\n return window.scrollX;\n }\n setScrollTop(n) {\n window.scroll(window.scrollX, n);\n }\n setScrollLeft(n) {\n window.scroll(n, window.scrollY);\n }\n getScrollWidth() {\n return document.documentElement.scrollWidth;\n }\n getScrollHeight() {\n return document.documentElement.scrollHeight;\n }\n getClientHeight() {\n return document.documentElement.clientHeight;\n }\n getClientWidth() {\n return document.documentElement.clientWidth;\n }\n}\n\n/*\nan INTERACTABLE date component\n\nPURPOSES:\n- hook up to fg, fill, and mirror renderers\n- interface for dragging and hits\n*/\nclass DateComponent extends BaseComponent {\n constructor() {\n super(...arguments);\n this.uid = guid();\n }\n // Hit System\n // -----------------------------------------------------------------------------------------------------------------\n prepareHits() {\n }\n queryHit(positionLeft, positionTop, elWidth, elHeight) {\n return null; // this should be abstract\n }\n // Pointer Interaction Utils\n // -----------------------------------------------------------------------------------------------------------------\n isValidSegDownEl(el) {\n return !this.props.eventDrag && // HACK\n !this.props.eventResize && // HACK\n !elementClosest(el, '.fc-event-mirror');\n }\n isValidDateDownEl(el) {\n return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&\n !elementClosest(el, '.fc-more-link') && // a \"more..\" link\n !elementClosest(el, 'a[data-navlink]') && // a clickable nav link\n !elementClosest(el, '.fc-popover'); // hack\n }\n}\n\nclass NamedTimeZoneImpl {\n constructor(timeZoneName) {\n this.timeZoneName = timeZoneName;\n }\n}\n\nclass SegHierarchy {\n constructor(getEntryThickness = (entry) => {\n // if no thickness known, assume 1 (if 0, so small it always fits)\n return entry.thickness || 1;\n }) {\n this.getEntryThickness = getEntryThickness;\n // settings\n this.strictOrder = false;\n this.allowReslicing = false;\n this.maxCoord = -1; // -1 means no max\n this.maxStackCnt = -1; // -1 means no max\n this.levelCoords = []; // ordered\n this.entriesByLevel = []; // parallel with levelCoords\n this.stackCnts = {}; // TODO: use better technique!?\n }\n addSegs(inputs) {\n let hiddenEntries = [];\n for (let input of inputs) {\n this.insertEntry(input, hiddenEntries);\n }\n return hiddenEntries;\n }\n insertEntry(entry, hiddenEntries) {\n let insertion = this.findInsertion(entry);\n if (this.isInsertionValid(insertion, entry)) {\n this.insertEntryAt(entry, insertion);\n }\n else {\n this.handleInvalidInsertion(insertion, entry, hiddenEntries);\n }\n }\n isInsertionValid(insertion, entry) {\n return (this.maxCoord === -1 || insertion.levelCoord + this.getEntryThickness(entry) <= this.maxCoord) &&\n (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);\n }\n handleInvalidInsertion(insertion, entry, hiddenEntries) {\n if (this.allowReslicing && insertion.touchingEntry) {\n const hiddenEntry = Object.assign(Object.assign({}, entry), { span: intersectSpans(entry.span, insertion.touchingEntry.span) });\n hiddenEntries.push(hiddenEntry);\n this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);\n }\n else {\n hiddenEntries.push(entry);\n }\n }\n /*\n Does NOT add what hit the `barrier` into hiddenEntries. Should already be done.\n */\n splitEntry(entry, barrier, hiddenEntries) {\n let entrySpan = entry.span;\n let barrierSpan = barrier.span;\n if (entrySpan.start < barrierSpan.start) {\n this.insertEntry({\n index: entry.index,\n thickness: entry.thickness,\n span: { start: entrySpan.start, end: barrierSpan.start },\n }, hiddenEntries);\n }\n if (entrySpan.end > barrierSpan.end) {\n this.insertEntry({\n index: entry.index,\n thickness: entry.thickness,\n span: { start: barrierSpan.end, end: entrySpan.end },\n }, hiddenEntries);\n }\n }\n insertEntryAt(entry, insertion) {\n let { entriesByLevel, levelCoords } = this;\n if (insertion.lateral === -1) {\n // create a new level\n insertAt(levelCoords, insertion.level, insertion.levelCoord);\n insertAt(entriesByLevel, insertion.level, [entry]);\n }\n else {\n // insert into existing level\n insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);\n }\n this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;\n }\n /*\n does not care about limits\n */\n findInsertion(newEntry) {\n let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;\n let levelCnt = levelCoords.length;\n let candidateCoord = 0;\n let touchingLevel = -1;\n let touchingLateral = -1;\n let touchingEntry = null;\n let stackCnt = 0;\n for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {\n const trackingCoord = levelCoords[trackingLevel];\n // if the current level is past the placed entry, we have found a good empty space and can stop.\n // if strictOrder, keep finding more lateral intersections.\n if (!strictOrder && trackingCoord >= candidateCoord + this.getEntryThickness(newEntry)) {\n break;\n }\n let trackingEntries = entriesByLevel[trackingLevel];\n let trackingEntry;\n let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end\n let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one\n while ( // loop through entries that horizontally intersect\n (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list\n trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry\n ) {\n let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);\n // intersects into the top of the candidate?\n if (trackingEntryBottom > candidateCoord) {\n candidateCoord = trackingEntryBottom;\n touchingEntry = trackingEntry;\n touchingLevel = trackingLevel;\n touchingLateral = lateralIndex;\n }\n // butts up against top of candidate? (will happen if just intersected as well)\n if (trackingEntryBottom === candidateCoord) {\n // accumulate the highest possible stackCnt of the trackingEntries that butt up\n stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);\n }\n lateralIndex += 1;\n }\n }\n // the destination level will be after touchingEntry's level. find it\n let destLevel = 0;\n if (touchingEntry) {\n destLevel = touchingLevel + 1;\n while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {\n destLevel += 1;\n }\n }\n // if adding to an existing level, find where to insert\n let destLateral = -1;\n if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {\n destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];\n }\n return {\n touchingLevel,\n touchingLateral,\n touchingEntry,\n stackCnt,\n levelCoord: candidateCoord,\n level: destLevel,\n lateral: destLateral,\n };\n }\n // sorted by levelCoord (lowest to highest)\n toRects() {\n let { entriesByLevel, levelCoords } = this;\n let levelCnt = entriesByLevel.length;\n let rects = [];\n for (let level = 0; level < levelCnt; level += 1) {\n let entries = entriesByLevel[level];\n let levelCoord = levelCoords[level];\n for (let entry of entries) {\n rects.push(Object.assign(Object.assign({}, entry), { thickness: this.getEntryThickness(entry), levelCoord }));\n }\n }\n return rects;\n }\n}\nfunction getEntrySpanEnd(entry) {\n return entry.span.end;\n}\nfunction buildEntryKey(entry) {\n return entry.index + ':' + entry.span.start;\n}\n// returns groups with entries sorted by input order\nfunction groupIntersectingEntries(entries) {\n let merges = [];\n for (let entry of entries) {\n let filteredMerges = [];\n let hungryMerge = {\n span: entry.span,\n entries: [entry],\n };\n for (let merge of merges) {\n if (intersectSpans(merge.span, hungryMerge.span)) {\n hungryMerge = {\n entries: merge.entries.concat(hungryMerge.entries),\n span: joinSpans(merge.span, hungryMerge.span),\n };\n }\n else {\n filteredMerges.push(merge);\n }\n }\n filteredMerges.push(hungryMerge);\n merges = filteredMerges;\n }\n return merges;\n}\nfunction joinSpans(span0, span1) {\n return {\n start: Math.min(span0.start, span1.start),\n end: Math.max(span0.end, span1.end),\n };\n}\nfunction intersectSpans(span0, span1) {\n let start = Math.max(span0.start, span1.start);\n let end = Math.min(span0.end, span1.end);\n if (start < end) {\n return { start, end };\n }\n return null;\n}\n// general util\n// ---------------------------------------------------------------------------------------------------------------------\nfunction insertAt(arr, index, item) {\n arr.splice(index, 0, item);\n}\nfunction binarySearch(a, searchVal, getItemVal) {\n let startIndex = 0;\n let endIndex = a.length; // exclusive\n if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item\n return [0, 0];\n }\n if (searchVal > getItemVal(a[endIndex - 1])) { // after last item\n return [endIndex, 0];\n }\n while (startIndex < endIndex) {\n let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);\n let middleVal = getItemVal(a[middleIndex]);\n if (searchVal < middleVal) {\n endIndex = middleIndex;\n }\n else if (searchVal > middleVal) {\n startIndex = middleIndex + 1;\n }\n else { // equal!\n return [middleIndex, 1];\n }\n }\n return [startIndex, 0];\n}\n\n/*\nAn abstraction for a dragging interaction originating on an event.\nDoes higher-level things than PointerDragger, such as possibly:\n- a \"mirror\" that moves with the pointer\n- a minimum number of pixels or other criteria for a true drag to begin\n\nsubclasses must emit:\n- pointerdown\n- dragstart\n- dragmove\n- pointerup\n- dragend\n*/\nclass ElementDragging {\n constructor(el, selector) {\n this.emitter = new Emitter();\n }\n destroy() {\n }\n setMirrorIsVisible(bool) {\n // optional if subclass doesn't want to support a mirror\n }\n setMirrorNeedsRevert(bool) {\n // optional if subclass doesn't want to support a mirror\n }\n setAutoScrollEnabled(bool) {\n // optional\n }\n}\n\n// TODO: get rid of this in favor of options system,\n// tho it's really easy to access this globally rather than pass thru options.\nconst config = {};\n\n/*\nInformation about what will happen when an external element is dragged-and-dropped\nonto a calendar. Contains information for creating an event.\n*/\nconst DRAG_META_REFINERS = {\n startTime: createDuration,\n duration: createDuration,\n create: Boolean,\n sourceId: String,\n};\nfunction parseDragMeta(raw) {\n let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);\n return {\n startTime: refined.startTime || null,\n duration: refined.duration || null,\n create: refined.create != null ? refined.create : true,\n sourceId: refined.sourceId,\n leftoverProps: extra,\n };\n}\n\n// Computes a default column header formatting string if `colFormat` is not explicitly defined\nfunction computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {\n // if more than one week row, or if there are a lot of columns with not much space,\n // put just the day numbers will be in each cell\n if (!datesRepDistinctDays || dayCnt > 10) {\n return createFormatter({ weekday: 'short' }); // \"Sat\"\n }\n if (dayCnt > 1) {\n return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // \"Sat 11/12\"\n }\n return createFormatter({ weekday: 'long' }); // \"Saturday\"\n}\n\nconst CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no\nfunction renderInner$1(renderProps) {\n return renderProps.text;\n}\n\n// BAD name for this class now. used in the Header\nclass TableDateCell extends BaseComponent {\n render() {\n let { dateEnv, options, theme, viewApi } = this.context;\n let { props } = this;\n let { date, dateProfile } = props;\n let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);\n let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));\n let text = dateEnv.format(date, props.dayHeaderFormat);\n // if colCnt is 1, we are already in a day-view and don't need a navlink\n let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)\n ? buildNavLinkAttrs(this.context, date)\n : {};\n let publicDate = dateEnv.toDate(date);\n // workaround for Luxon (and maybe moment) returning prior-days when start-of-day\n // in DST gap: https://github.com/fullcalendar/fullcalendar/issues/7633\n if (dateEnv.namedTimeZoneImpl) {\n publicDate = addMs(publicDate, 3600000); // add an hour\n }\n let renderProps = Object.assign(Object.assign(Object.assign({ date: publicDate, view: viewApi }, props.extraRenderProps), { text }), dayMeta);\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elTag: \"th\", elClasses: classNames, elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan, 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, props.extraDataAttrs), renderProps: renderProps, generatorName: \"dayHeaderContent\", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-scrollgrid-sync-inner\" }, !dayMeta.isDisabled && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(InnerContainer, { elTag: \"a\", elAttrs: navLinkAttrs, elClasses: [\n 'fc-col-header-cell-cushion',\n props.isSticky && 'fc-sticky',\n ] }))))));\n }\n}\n\nconst WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });\nclass TableDowCell extends BaseComponent {\n render() {\n let { props } = this;\n let { dateEnv, theme, viewApi, options } = this.context;\n let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT\n let dateMeta = {\n dow: props.dow,\n isDisabled: false,\n isFuture: false,\n isPast: false,\n isToday: false,\n isOther: false,\n };\n let text = dateEnv.format(date, props.dayHeaderFormat);\n let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?\n date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elTag: \"th\", elClasses: [\n CLASS_NAME,\n ...getDayClassNames(dateMeta, theme),\n ...(props.extraClassNames || []),\n ], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: \"dayHeaderContent\", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-scrollgrid-sync-inner\" },\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(InnerContent, { elTag: \"a\", elClasses: [\n 'fc-col-header-cell-cushion',\n props.isSticky && 'fc-sticky',\n ], elAttrs: {\n 'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),\n } })))));\n }\n}\n\nclass DayHeader extends BaseComponent {\n constructor() {\n super(...arguments);\n this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);\n }\n render() {\n let { context } = this;\n let { dates, dateProfile, datesRepDistinctDays, renderIntro } = this.props;\n let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(NowTimer, { unit: \"day\" }, (nowDate, todayRange) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"tr\", { role: \"row\" },\n renderIntro && renderIntro('day'),\n dates.map((date) => (datesRepDistinctDays ? ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))))))));\n }\n}\nfunction createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {\n return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);\n}\n\nclass DaySeriesModel {\n constructor(range, dateProfileGenerator) {\n let date = range.start;\n let { end } = range;\n let indices = [];\n let dates = [];\n let dayIndex = -1;\n while (date < end) { // loop each day from start to end\n if (dateProfileGenerator.isHiddenDay(date)) {\n indices.push(dayIndex + 0.5); // mark that it's between indices\n }\n else {\n dayIndex += 1;\n indices.push(dayIndex);\n dates.push(date);\n }\n date = addDays(date, 1);\n }\n this.dates = dates;\n this.indices = indices;\n this.cnt = dates.length;\n }\n sliceRange(range) {\n let firstIndex = this.getDateDayIndex(range.start); // inclusive first index\n let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index\n let clippedFirstIndex = Math.max(0, firstIndex);\n let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);\n // deal with in-between indices\n clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell\n clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell\n if (clippedFirstIndex <= clippedLastIndex) {\n return {\n firstIndex: clippedFirstIndex,\n lastIndex: clippedLastIndex,\n isStart: firstIndex === clippedFirstIndex,\n isEnd: lastIndex === clippedLastIndex,\n };\n }\n return null;\n }\n // Given a date, returns its chronolocial cell-index from the first cell of the grid.\n // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.\n // If before the first offset, returns a negative number.\n // If after the last offset, returns an offset past the last cell offset.\n // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.\n getDateDayIndex(date) {\n let { indices } = this;\n let dayOffset = Math.floor(diffDays(this.dates[0], date));\n if (dayOffset < 0) {\n return indices[0] - 1;\n }\n if (dayOffset >= indices.length) {\n return indices[indices.length - 1] + 1;\n }\n return indices[dayOffset];\n }\n}\n\nclass DayTableModel {\n constructor(daySeries, breakOnWeeks) {\n let { dates } = daySeries;\n let daysPerRow;\n let firstDay;\n let rowCnt;\n if (breakOnWeeks) {\n // count columns until the day-of-week repeats\n firstDay = dates[0].getUTCDay();\n for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {\n if (dates[daysPerRow].getUTCDay() === firstDay) {\n break;\n }\n }\n rowCnt = Math.ceil(dates.length / daysPerRow);\n }\n else {\n rowCnt = 1;\n daysPerRow = dates.length;\n }\n this.rowCnt = rowCnt;\n this.colCnt = daysPerRow;\n this.daySeries = daySeries;\n this.cells = this.buildCells();\n this.headerDates = this.buildHeaderDates();\n }\n buildCells() {\n let rows = [];\n for (let row = 0; row < this.rowCnt; row += 1) {\n let cells = [];\n for (let col = 0; col < this.colCnt; col += 1) {\n cells.push(this.buildCell(row, col));\n }\n rows.push(cells);\n }\n return rows;\n }\n buildCell(row, col) {\n let date = this.daySeries.dates[row * this.colCnt + col];\n return {\n key: date.toISOString(),\n date,\n };\n }\n buildHeaderDates() {\n let dates = [];\n for (let col = 0; col < this.colCnt; col += 1) {\n dates.push(this.cells[0][col].date);\n }\n return dates;\n }\n sliceRange(range) {\n let { colCnt } = this;\n let seriesSeg = this.daySeries.sliceRange(range);\n let segs = [];\n if (seriesSeg) {\n let { firstIndex, lastIndex } = seriesSeg;\n let index = firstIndex;\n while (index <= lastIndex) {\n let row = Math.floor(index / colCnt);\n let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);\n segs.push({\n row,\n firstCol: index % colCnt,\n lastCol: (nextIndex - 1) % colCnt,\n isStart: seriesSeg.isStart && index === firstIndex,\n isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,\n });\n index = nextIndex;\n }\n }\n return segs;\n }\n}\n\nclass Slicer {\n constructor() {\n this.sliceBusinessHours = memoize(this._sliceBusinessHours);\n this.sliceDateSelection = memoize(this._sliceDateSpan);\n this.sliceEventStore = memoize(this._sliceEventStore);\n this.sliceEventDrag = memoize(this._sliceInteraction);\n this.sliceEventResize = memoize(this._sliceInteraction);\n this.forceDayIfListItem = false; // hack\n }\n sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {\n let { eventUiBases } = props;\n let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);\n return {\n dateSelectionSegs: this.sliceDateSelection(props.dateSelection, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs),\n businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),\n fgEventSegs: eventSegs.fg,\n bgEventSegs: eventSegs.bg,\n eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),\n eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),\n eventSelection: props.eventSelection,\n }; // TODO: give interactionSegs?\n }\n sliceNowDate(// does not memoize\n date, dateProfile, nextDayThreshold, context, ...extraArgs) {\n return this._sliceDateSpan({ range: { start: date, end: addMs(date, 1) }, allDay: false }, // add 1 ms, protect against null range\n dateProfile, nextDayThreshold, {}, context, ...extraArgs);\n }\n _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {\n if (!businessHours) {\n return [];\n }\n return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;\n }\n _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {\n if (eventStore) {\n let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);\n return {\n bg: this.sliceEventRanges(rangeRes.bg, extraArgs),\n fg: this.sliceEventRanges(rangeRes.fg, extraArgs),\n };\n }\n return { bg: [], fg: [] };\n }\n _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {\n if (!interaction) {\n return null;\n }\n let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);\n return {\n segs: this.sliceEventRanges(rangeRes.fg, extraArgs),\n affectedInstances: interaction.affectedEvents.instances,\n isEvent: interaction.isEvent,\n };\n }\n _sliceDateSpan(dateSpan, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs) {\n if (!dateSpan) {\n return [];\n }\n let activeRange = computeActiveRange(dateProfile, Boolean(nextDayThreshold));\n let activeDateSpanRange = intersectRanges(dateSpan.range, activeRange);\n if (activeDateSpanRange) {\n dateSpan = Object.assign(Object.assign({}, dateSpan), { range: activeDateSpanRange });\n let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);\n let segs = this.sliceRange(dateSpan.range, ...extraArgs);\n for (let seg of segs) {\n seg.eventRange = eventRange;\n }\n return segs;\n }\n return [];\n }\n /*\n \"complete\" seg means it has component and eventRange\n */\n sliceEventRanges(eventRanges, extraArgs) {\n let segs = [];\n for (let eventRange of eventRanges) {\n segs.push(...this.sliceEventRange(eventRange, extraArgs));\n }\n return segs;\n }\n /*\n \"complete\" seg means it has component and eventRange\n */\n sliceEventRange(eventRange, extraArgs) {\n let dateRange = eventRange.range;\n // hack to make multi-day events that are being force-displayed as list-items to take up only one day\n if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {\n dateRange = {\n start: dateRange.start,\n end: addDays(dateRange.start, 1),\n };\n }\n let segs = this.sliceRange(dateRange, ...extraArgs);\n for (let seg of segs) {\n seg.eventRange = eventRange;\n seg.isStart = eventRange.isStart && seg.isStart;\n seg.isEnd = eventRange.isEnd && seg.isEnd;\n }\n return segs;\n }\n}\n/*\nfor incorporating slotMinTime/slotMaxTime if appropriate\nTODO: should be part of DateProfile!\nTimelineDateProfile already does this btw\n*/\nfunction computeActiveRange(dateProfile, isComponentAllDay) {\n let range = dateProfile.activeRange;\n if (isComponentAllDay) {\n return range;\n }\n return {\n start: addMs(range.start, dateProfile.slotMinTime.milliseconds),\n end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day\n };\n}\n\n// high-level segmenting-aware tester functions\n// ------------------------------------------------------------------------------------------------------------------------\nfunction isInteractionValid(interaction, dateProfile, context) {\n let { instances } = interaction.mutatedEvents;\n for (let instanceId in instances) {\n if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {\n return false;\n }\n }\n return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions\n}\nfunction isDateSelectionValid(dateSelection, dateProfile, context) {\n if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {\n return false;\n }\n return isNewPropsValid({ dateSelection }, context);\n}\nfunction isNewPropsValid(newProps, context) {\n let calendarState = context.getCurrentData();\n let props = Object.assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);\n return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);\n}\nfunction isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {\n if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {\n return false;\n }\n if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {\n return false;\n }\n return true;\n}\n// Moving Event Validation\n// ------------------------------------------------------------------------------------------------------------------------\nfunction isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {\n let currentState = context.getCurrentData();\n let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions\n let subjectEventStore = interaction.mutatedEvents;\n let subjectDefs = subjectEventStore.defs;\n let subjectInstances = subjectEventStore.instances;\n let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?\n state.eventUiBases :\n { '': currentState.selectionConfig });\n if (filterConfig) {\n subjectConfigs = mapHash(subjectConfigs, filterConfig);\n }\n // exclude the subject events. TODO: exclude defs too?\n let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);\n let otherDefs = otherEventStore.defs;\n let otherInstances = otherEventStore.instances;\n let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);\n for (let subjectInstanceId in subjectInstances) {\n let subjectInstance = subjectInstances[subjectInstanceId];\n let subjectRange = subjectInstance.range;\n let subjectConfig = subjectConfigs[subjectInstance.defId];\n let subjectDef = subjectDefs[subjectInstance.defId];\n // constraint\n if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {\n return false;\n }\n // overlap\n let { eventOverlap } = context.options;\n let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;\n for (let otherInstanceId in otherInstances) {\n let otherInstance = otherInstances[otherInstanceId];\n // intersect! evaluate\n if (rangesIntersect(subjectRange, otherInstance.range)) {\n let otherOverlap = otherConfigs[otherInstance.defId].overlap;\n // consider the other event's overlap. only do this if the subject event is a \"real\" event\n if (otherOverlap === false && interaction.isEvent) {\n return false;\n }\n if (subjectConfig.overlap === false) {\n return false;\n }\n if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event\n new EventImpl(context, subjectDef, subjectInstance))) {\n return false;\n }\n }\n }\n // allow (a function)\n let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state\n for (let subjectAllow of subjectConfig.allows) {\n let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });\n let origDef = calendarEventStore.defs[subjectDef.defId];\n let origInstance = calendarEventStore.instances[subjectInstanceId];\n let eventApi;\n if (origDef) { // was previously in the calendar\n eventApi = new EventImpl(context, origDef, origInstance);\n }\n else { // was an external event\n eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates\n }\n if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {\n return false;\n }\n }\n }\n return true;\n}\n// Date Selection Validation\n// ------------------------------------------------------------------------------------------------------------------------\nfunction isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {\n let relevantEventStore = state.eventStore;\n let relevantDefs = relevantEventStore.defs;\n let relevantInstances = relevantEventStore.instances;\n let selection = state.dateSelection;\n let selectionRange = selection.range;\n let { selectionConfig } = context.getCurrentData();\n if (filterConfig) {\n selectionConfig = filterConfig(selectionConfig);\n }\n // constraint\n if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {\n return false;\n }\n // overlap\n let { selectOverlap } = context.options;\n let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;\n for (let relevantInstanceId in relevantInstances) {\n let relevantInstance = relevantInstances[relevantInstanceId];\n // intersect! evaluate\n if (rangesIntersect(selectionRange, relevantInstance.range)) {\n if (selectionConfig.overlap === false) {\n return false;\n }\n if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {\n return false;\n }\n }\n }\n // allow (a function)\n for (let selectionAllow of selectionConfig.allows) {\n let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);\n if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {\n return false;\n }\n }\n return true;\n}\n// Constraint Utils\n// ------------------------------------------------------------------------------------------------------------------------\nfunction allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {\n for (let constraint of constraints) {\n if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {\n return false;\n }\n }\n return true;\n}\nfunction constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours\notherEventStore, // for if constraint is an even group ID\nbusinessHoursUnexpanded, // for if constraint is 'businessHours'\ncontext) {\n if (constraint === 'businessHours') {\n return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));\n }\n if (typeof constraint === 'string') { // an group ID\n return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));\n }\n if (typeof constraint === 'object' && constraint) { // non-null object\n return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));\n }\n return []; // if it's false\n}\n// TODO: move to event-store file?\nfunction eventStoreToRanges(eventStore) {\n let { instances } = eventStore;\n let ranges = [];\n for (let instanceId in instances) {\n ranges.push(instances[instanceId].range);\n }\n return ranges;\n}\n// TODO: move to geom file?\nfunction anyRangesContainRange(outerRanges, innerRange) {\n for (let outerRange of outerRanges) {\n if (rangeContainsRange(outerRange, innerRange)) {\n return true;\n }\n }\n return false;\n}\n\nconst VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;\nclass Scroller extends BaseComponent {\n constructor() {\n super(...arguments);\n this.handleEl = (el) => {\n this.el = el;\n setRef(this.props.elRef, el);\n };\n }\n render() {\n let { props } = this;\n let { liquid, liquidIsAbsolute } = props;\n let isAbsolute = liquid && liquidIsAbsolute;\n let className = ['fc-scroller'];\n if (liquid) {\n if (liquidIsAbsolute) {\n className.push('fc-scroller-liquid-absolute');\n }\n else {\n className.push('fc-scroller-liquid');\n }\n }\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { ref: this.handleEl, className: className.join(' '), style: {\n overflowX: props.overflowX,\n overflowY: props.overflowY,\n left: (isAbsolute && -(props.overcomeLeft || 0)) || '',\n right: (isAbsolute && -(props.overcomeRight || 0)) || '',\n bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',\n marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',\n marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',\n marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',\n maxHeight: props.maxHeight || '',\n } }, props.children));\n }\n needsXScrolling() {\n if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {\n return false;\n }\n // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.\n // much more reliable to see if children are taller than the scroller, even tho doesn't account for\n // inner-child margins and absolute positioning\n let { el } = this;\n let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();\n let { children } = el;\n for (let i = 0; i < children.length; i += 1) {\n let childEl = children[i];\n if (childEl.getBoundingClientRect().width > realClientWidth) {\n return true;\n }\n }\n return false;\n }\n needsYScrolling() {\n if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {\n return false;\n }\n // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.\n // much more reliable to see if children are taller than the scroller, even tho doesn't account for\n // inner-child margins and absolute positioning\n let { el } = this;\n let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();\n let { children } = el;\n for (let i = 0; i < children.length; i += 1) {\n let childEl = children[i];\n if (childEl.getBoundingClientRect().height > realClientHeight) {\n return true;\n }\n }\n return false;\n }\n getXScrollbarWidth() {\n if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {\n return 0;\n }\n return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?\n }\n getYScrollbarWidth() {\n if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {\n return 0;\n }\n return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?\n }\n}\n\n/*\nTODO: somehow infer OtherArgs from masterCallback?\nTODO: infer RefType from masterCallback if provided\n*/\nclass RefMap {\n constructor(masterCallback) {\n this.masterCallback = masterCallback;\n this.currentMap = {};\n this.depths = {};\n this.callbackMap = {};\n this.handleValue = (val, key) => {\n let { depths, currentMap } = this;\n let removed = false;\n let added = false;\n if (val !== null) {\n // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore\n removed = (key in currentMap);\n currentMap[key] = val;\n depths[key] = (depths[key] || 0) + 1;\n added = true;\n }\n else {\n depths[key] -= 1;\n if (!depths[key]) {\n delete currentMap[key];\n delete this.callbackMap[key];\n removed = true;\n }\n }\n if (this.masterCallback) {\n if (removed) {\n this.masterCallback(null, String(key));\n }\n if (added) {\n this.masterCallback(val, String(key));\n }\n }\n };\n }\n createRef(key) {\n let refCallback = this.callbackMap[key];\n if (!refCallback) {\n refCallback = this.callbackMap[key] = (val) => {\n this.handleValue(val, String(key));\n };\n }\n return refCallback;\n }\n // TODO: check callers that don't care about order. should use getAll instead\n // NOTE: this method has become less valuable now that we are encouraged to map order by some other index\n // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and \"collect\"\n collect(startIndex, endIndex, step) {\n return collectFromHash(this.currentMap, startIndex, endIndex, step);\n }\n getAll() {\n return hashValuesToArray(this.currentMap);\n }\n}\n\nfunction computeShrinkWidth(chunkEls) {\n let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');\n let largestWidth = 0;\n for (let shrinkCell of shrinkCells) {\n largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));\n }\n return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits\n}\nfunction getSectionHasLiquidHeight(props, sectionConfig) {\n return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)\n}\nfunction getAllowYScrolling(props, sectionConfig) {\n return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars\n getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars\n}\n// TODO: ONLY use `arg`. force out internal function to use same API\nfunction renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {\n let { expandRows } = arg;\n let content = typeof chunkConfig.content === 'function' ?\n chunkConfig.content(arg) :\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('table', {\n role: 'presentation',\n className: [\n chunkConfig.tableClassName,\n sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',\n ].join(' '),\n style: {\n minWidth: arg.tableMinWidth,\n width: arg.clientWidth,\n height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height\n },\n }, arg.tableColGroupNode, (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(isHeader ? 'thead' : 'tbody', {\n role: 'presentation',\n }, typeof chunkConfig.rowContent === 'function'\n ? chunkConfig.rowContent(arg)\n : chunkConfig.rowContent));\n return content;\n}\nfunction isColPropsEqual(cols0, cols1) {\n return isArraysEqual(cols0, cols1, isPropsEqual);\n}\nfunction renderMicroColGroup(cols, shrinkWidth) {\n let colNodes = [];\n /*\n for ColProps with spans, it would have been great to make a single <col span=\"\">\n HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.\n SOLUTION: making individual <col> elements makes Chrome behave.\n */\n for (let colProps of cols) {\n let span = colProps.span || 1;\n for (let i = 0; i < span; i += 1) {\n colNodes.push((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"col\", { style: {\n width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),\n minWidth: colProps.minWidth || '',\n } }));\n }\n }\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('colgroup', {}, ...colNodes);\n}\nfunction sanitizeShrinkWidth(shrinkWidth) {\n /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth\n 4 accounts for 2 2-pixel borders. TODO: better solution? */\n return shrinkWidth == null ? 4 : shrinkWidth;\n}\nfunction hasShrinkWidth(cols) {\n for (let col of cols) {\n if (col.width === 'shrink') {\n return true;\n }\n }\n return false;\n}\nfunction getScrollGridClassNames(liquid, context) {\n let classNames = [\n 'fc-scrollgrid',\n context.theme.getClass('table'),\n ];\n if (liquid) {\n classNames.push('fc-scrollgrid-liquid');\n }\n return classNames;\n}\nfunction getSectionClassNames(sectionConfig, wholeTableVGrow) {\n let classNames = [\n 'fc-scrollgrid-section',\n `fc-scrollgrid-section-${sectionConfig.type}`,\n sectionConfig.className, // used?\n ];\n if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {\n classNames.push('fc-scrollgrid-section-liquid');\n }\n if (sectionConfig.isSticky) {\n classNames.push('fc-scrollgrid-section-sticky');\n }\n return classNames;\n}\nfunction renderScrollShim(arg) {\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-scrollgrid-sticky-shim\", style: {\n width: arg.clientWidth,\n minWidth: arg.tableMinWidth,\n } }));\n}\nfunction getStickyHeaderDates(options) {\n let { stickyHeaderDates } = options;\n if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {\n stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';\n }\n return stickyHeaderDates;\n}\nfunction getStickyFooterScrollbar(options) {\n let { stickyFooterScrollbar } = options;\n if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {\n stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';\n }\n return stickyFooterScrollbar;\n}\n\nclass SimpleScrollGrid extends BaseComponent {\n constructor() {\n super(...arguments);\n this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time\n // yucky to memoize VNodes, but much more efficient for consumers\n this.renderMicroColGroup = memoize(renderMicroColGroup);\n this.scrollerRefs = new RefMap();\n this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));\n this.state = {\n shrinkWidth: null,\n forceYScrollbars: false,\n scrollerClientWidths: {},\n scrollerClientHeights: {},\n };\n // TODO: can do a really simple print-view. dont need to join rows\n this.handleSizing = () => {\n this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));\n };\n }\n render() {\n let { props, state, context } = this;\n let sectionConfigs = props.sections || [];\n let cols = this.processCols(props.cols);\n let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);\n let classNames = getScrollGridClassNames(props.liquid, context);\n if (props.collapsibleWidth) {\n classNames.push('fc-scrollgrid-collapsible');\n }\n // TODO: make DRY\n let configCnt = sectionConfigs.length;\n let configI = 0;\n let currentConfig;\n let headSectionNodes = [];\n let bodySectionNodes = [];\n let footSectionNodes = [];\n while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {\n headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));\n configI += 1;\n }\n while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {\n bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));\n configI += 1;\n }\n while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {\n footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));\n configI += 1;\n }\n // firefox bug: when setting height on table and there is a thead or tfoot,\n // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)\n // use getCanVGrowWithinCell as a way to detect table-stupid firefox.\n // if so, use a simpler dom structure, jam everything into a lone tbody.\n let isBuggy = !getCanVGrowWithinCell();\n const roleAttrs = { role: 'rowgroup' };\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('table', {\n role: 'grid',\n className: classNames.join(' '),\n style: { height: props.height },\n }, Boolean(!isBuggy && headSectionNodes.length) && (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('tfoot', roleAttrs, ...footSectionNodes), isBuggy && (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));\n }\n renderSection(sectionConfig, microColGroupNode, isHeader) {\n if ('outerContent' in sectionConfig) {\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(preact__WEBPACK_IMPORTED_MODULE_0__.Fragment, { key: sectionConfig.key }, sectionConfig.outerContent));\n }\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"tr\", { key: sectionConfig.key, role: \"presentation\", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));\n }\n renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {\n if ('outerContent' in chunkConfig) {\n return chunkConfig.outerContent;\n }\n let { props } = this;\n let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;\n let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?\n let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);\n // for `!props.liquid` - is WHOLE scrollgrid natural height?\n // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars\n let overflowY = !props.liquid ? 'visible' :\n forceYScrollbars ? 'scroll' :\n !needsYScrolling ? 'hidden' :\n 'auto';\n let sectionKey = sectionConfig.key;\n let content = renderChunkContent(sectionConfig, chunkConfig, {\n tableColGroupNode: microColGroupNode,\n tableMinWidth: '',\n clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,\n clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,\n expandRows: sectionConfig.expandRows,\n syncRowHeights: false,\n rowSyncHeights: [],\n reportRowHeightChange: () => { },\n }, isHeader);\n return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(isHeader ? 'th' : 'td', {\n ref: chunkConfig.elRef,\n role: 'presentation',\n }, (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(Scroller, { ref: this.scrollerRefs.createRef(sectionKey), elRef: this.scrollerElRefs.createRef(sectionKey), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute // because its within a harness\n : true }, content)));\n }\n _handleScrollerEl(scrollerEl, key) {\n let section = getSectionByKey(this.props.sections, key);\n if (section) {\n setRef(section.chunk.scrollerElRef, scrollerEl);\n }\n }\n componentDidMount() {\n this.handleSizing();\n this.context.addResizeHandler(this.handleSizing);\n }\n componentDidUpdate() {\n // TODO: need better solution when state contains non-sizing things\n this.handleSizing();\n }\n componentWillUnmount() {\n this.context.removeResizeHandler(this.handleSizing);\n }\n computeShrinkWidth() {\n return hasShrinkWidth(this.props.cols)\n ? computeShrinkWidth(this.scrollerElRefs.getAll())\n : 0;\n }\n computeScrollerDims() {\n let scrollbarWidth = getScrollbarWidths();\n let { scrollerRefs, scrollerElRefs } = this;\n let forceYScrollbars = false;\n let scrollerClientWidths = {};\n let scrollerClientHeights = {};\n for (let sectionKey in scrollerRefs.currentMap) {\n let scroller = scrollerRefs.currentMap[sectionKey];\n if (scroller && scroller.needsYScrolling()) {\n forceYScrollbars = true;\n break;\n }\n }\n for (let section of this.props.sections) {\n let sectionKey = section.key;\n let scrollerEl = scrollerElRefs.currentMap[sectionKey];\n if (scrollerEl) {\n let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders\n scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars\n ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future\n : 0));\n scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);\n }\n }\n return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };\n }\n}\nSimpleScrollGrid.addStateEquality({\n scrollerClientWidths: isPropsEqual,\n scrollerClientHeights: isPropsEqual,\n});\nfunction getSectionByKey(sections, key) {\n for (let section of sections) {\n if (section.key === key) {\n return section;\n }\n }\n return null;\n}\n\nclass EventContainer extends BaseComponent {\n constructor() {\n super(...arguments);\n // memo\n this.buildPublicEvent = memoize((context, eventDef, eventInstance) => new EventImpl(context, eventDef, eventInstance));\n this.handleEl = (el) => {\n this.el = el;\n setRef(this.props.elRef, el);\n if (el) {\n setElSeg(el, this.props.seg);\n }\n };\n }\n render() {\n const { props, context } = this;\n const { options } = context;\n const { seg } = props;\n const { eventRange } = seg;\n const { ui } = eventRange;\n const renderProps = {\n event: this.buildPublicEvent(context, eventRange.def, eventRange.instance),\n view: context.viewApi,\n timeText: props.timeText,\n textColor: ui.textColor,\n backgroundColor: ui.backgroundColor,\n borderColor: ui.borderColor,\n isDraggable: !props.disableDragging && computeSegDraggable(seg, context),\n isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),\n isEndResizable: !props.disableResizing && computeSegEndResizable(seg),\n isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),\n isStart: Boolean(seg.isStart),\n isEnd: Boolean(seg.isEnd),\n isPast: Boolean(props.isPast),\n isFuture: Boolean(props.isFuture),\n isToday: Boolean(props.isToday),\n isSelected: Boolean(props.isSelected),\n isDragging: Boolean(props.isDragging),\n isResizing: Boolean(props.isResizing),\n };\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elRef: this.handleEl, elTag: props.elTag, elAttrs: props.elAttrs, elClasses: [\n ...getEventClassNames(renderProps),\n ...seg.eventRange.ui.classNames,\n ...(props.elClasses || []),\n ], elStyle: props.elStyle, renderProps: renderProps, generatorName: \"eventContent\", customGenerator: options.eventContent, defaultGenerator: props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount }, props.children));\n }\n componentDidUpdate(prevProps) {\n if (this.el && this.props.seg !== prevProps.seg) {\n setElSeg(this.el, this.props.seg);\n }\n }\n}\n\n// should not be a purecomponent\nclass StandardEvent extends BaseComponent {\n render() {\n let { props, context } = this;\n let { options } = context;\n let { seg } = props;\n let { ui } = seg.eventRange;\n let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;\n let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: \"a\", elStyle: {\n borderColor: ui.borderColor,\n backgroundColor: ui.backgroundColor,\n }, elAttrs: getSegAnchorAttrs(seg, context), defaultGenerator: renderInnerContent$1, timeText: timeText }), (InnerContent, eventContentArg) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(preact__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(InnerContent, { elTag: \"div\", elClasses: ['fc-event-main'], elStyle: { color: eventContentArg.textColor } }),\n Boolean(eventContentArg.isStartResizable) && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-resizer fc-event-resizer-start\" })),\n Boolean(eventContentArg.isEndResizable) && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-resizer fc-event-resizer-end\" }))))));\n }\n}\nStandardEvent.addPropsEquality({\n seg: isPropsEqual,\n});\nfunction renderInnerContent$1(innerProps) {\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-main-frame\" },\n innerProps.timeText && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-time\" }, innerProps.timeText)),\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-title-container\" },\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-title fc-sticky\" }, innerProps.event.title || (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(preact__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, \"\\u00A0\")))));\n}\n\nconst NowIndicatorContainer = (props) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ViewContextType.Consumer, null, (context) => {\n let { options } = context;\n let renderProps = {\n isAxis: props.isAxis,\n date: context.dateEnv.toDate(props.date),\n view: context.viewApi,\n };\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elRef: props.elRef, elTag: props.elTag || 'div', elAttrs: props.elAttrs, elClasses: props.elClasses, elStyle: props.elStyle, renderProps: renderProps, generatorName: \"nowIndicatorContent\", customGenerator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount }, props.children));\n}));\n\nconst DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });\nclass DayCellContainer extends BaseComponent {\n constructor() {\n super(...arguments);\n this.refineRenderProps = memoizeObjArg(refineRenderProps);\n }\n render() {\n let { props, context } = this;\n let { options } = context;\n let renderProps = this.refineRenderProps({\n date: props.date,\n dateProfile: props.dateProfile,\n todayRange: props.todayRange,\n isMonthStart: props.isMonthStart || false,\n showDayNumber: props.showDayNumber,\n extraRenderProps: props.extraRenderProps,\n viewApi: context.viewApi,\n dateEnv: context.dateEnv,\n monthStartFormat: options.monthStartFormat,\n });\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elRef: props.elRef, elTag: props.elTag, elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), elClasses: [\n ...getDayClassNames(renderProps, context.theme),\n ...(props.elClasses || []),\n ], elStyle: props.elStyle, renderProps: renderProps, generatorName: \"dayCellContent\", customGenerator: options.dayCellContent, defaultGenerator: props.defaultGenerator, classNameGenerator: \n // don't use custom classNames if disabled\n renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount }, props.children));\n }\n}\nfunction hasCustomDayCellContent(options) {\n return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));\n}\nfunction refineRenderProps(raw) {\n let { date, dateEnv, dateProfile, isMonthStart } = raw;\n let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);\n let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';\n return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { isMonthStart,\n dayNumberText }), raw.extraRenderProps);\n}\n\nclass BgEvent extends BaseComponent {\n render() {\n let { props } = this;\n let { seg } = props;\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(EventContainer, { elTag: \"div\", elClasses: ['fc-bg-event'], elStyle: { backgroundColor: seg.eventRange.ui.backgroundColor }, defaultGenerator: renderInnerContent, seg: seg, timeText: \"\", isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, disableDragging: true, disableResizing: true }));\n }\n}\nfunction renderInnerContent(props) {\n let { title } = props.event;\n return title && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: \"fc-event-title\" }, props.event.title));\n}\nfunction renderFill(fillType) {\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: `fc-${fillType}` }));\n}\n\nconst WeekNumberContainer = (props) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ViewContextType.Consumer, null, (context) => {\n let { dateEnv, options } = context;\n let { date } = props;\n let format = options.weekNumberFormat || props.defaultFormat;\n let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?\n let text = dateEnv.format(date, format);\n let renderProps = { num, text, date };\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer // why isn't WeekNumberContentArg being auto-detected?\n , { elRef: props.elRef, elTag: props.elTag, elAttrs: props.elAttrs, elClasses: props.elClasses, elStyle: props.elStyle, renderProps: renderProps, generatorName: \"weekNumberContent\", customGenerator: options.weekNumberContent, defaultGenerator: renderInner, classNameGenerator: options.weekNumberClassNames, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount }, props.children));\n}));\nfunction renderInner(innerProps) {\n return innerProps.text;\n}\n\nconst PADDING_FROM_VIEWPORT = 10;\nclass Popover extends BaseComponent {\n constructor() {\n super(...arguments);\n this.state = {\n titleId: getUniqueDomId(),\n };\n this.handleRootEl = (el) => {\n this.rootEl = el;\n if (this.props.elRef) {\n setRef(this.props.elRef, el);\n }\n };\n // Triggered when the user clicks *anywhere* in the document, for the autoHide feature\n this.handleDocumentMouseDown = (ev) => {\n // only hide the popover if the click happened outside the popover\n const target = getEventTargetViaRoot(ev);\n if (!this.rootEl.contains(target)) {\n this.handleCloseClick();\n }\n };\n this.handleDocumentKeyDown = (ev) => {\n if (ev.key === 'Escape') {\n this.handleCloseClick();\n }\n };\n this.handleCloseClick = () => {\n let { onClose } = this.props;\n if (onClose) {\n onClose();\n }\n };\n }\n render() {\n let { theme, options } = this.context;\n let { props, state } = this;\n let classNames = [\n 'fc-popover',\n theme.getClass('popover'),\n ].concat(props.extraClassNames || []);\n return (0,preact_compat__WEBPACK_IMPORTED_MODULE_1__.createPortal)((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), \"aria-labelledby\": state.titleId, ref: this.handleRootEl }),\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"span\", { className: \"fc-popover-title\", id: state.titleId }, props.title),\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"span\", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),\n (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(\"div\", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);\n }\n componentDidMount() {\n document.addEventListener('mousedown', this.handleDocumentMouseDown);\n document.addEventListener('keydown', this.handleDocumentKeyDown);\n this.updateSize();\n }\n componentWillUnmount() {\n document.removeEventListener('mousedown', this.handleDocumentMouseDown);\n document.removeEventListener('keydown', this.handleDocumentKeyDown);\n }\n updateSize() {\n let { isRtl } = this.context;\n let { alignmentEl, alignGridTop } = this.props;\n let { rootEl } = this;\n let alignmentRect = computeClippedClientRect(alignmentEl);\n if (alignmentRect) {\n let popoverDims = rootEl.getBoundingClientRect();\n // position relative to viewport\n let popoverTop = alignGridTop\n ? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top\n : alignmentRect.top;\n let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;\n // constrain\n popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);\n popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);\n popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);\n let origin = rootEl.offsetParent.getBoundingClientRect();\n applyStyle(rootEl, {\n top: popoverTop - origin.top,\n left: popoverLeft - origin.left,\n });\n }\n }\n}\n\nclass MorePopover extends DateComponent {\n constructor() {\n super(...arguments);\n this.handleRootEl = (rootEl) => {\n this.rootEl = rootEl;\n if (rootEl) {\n this.context.registerInteractiveComponent(this, {\n el: rootEl,\n useEventCenter: false,\n });\n }\n else {\n this.context.unregisterInteractiveComponent(this);\n }\n };\n }\n render() {\n let { options, dateEnv } = this.context;\n let { props } = this;\n let { startDate, todayRange, dateProfile } = props;\n let title = dateEnv.format(startDate, options.dayPopoverFormat);\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(Popover, { elRef: elAttrs.ref, id: props.id, title: title, extraClassNames: ['fc-more-popover'].concat(elAttrs.className || []), extraAttrs: elAttrs /* TODO: make these time-based when not whole-day? */, parentEl: props.parentEl, alignmentEl: props.alignmentEl, alignGridTop: props.alignGridTop, onClose: props.onClose },\n hasCustomDayCellContent(options) && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(InnerContent, { elTag: \"div\", elClasses: ['fc-more-popover-misc'] })),\n props.children))));\n }\n queryHit(positionLeft, positionTop, elWidth, elHeight) {\n let { rootEl, props } = this;\n if (positionLeft >= 0 && positionLeft < elWidth &&\n positionTop >= 0 && positionTop < elHeight) {\n return {\n dateProfile: props.dateProfile,\n dateSpan: Object.assign({ allDay: !props.forceTimed, range: {\n start: props.startDate,\n end: props.endDate,\n } }, props.extraDateSpan),\n dayEl: rootEl,\n rect: {\n left: 0,\n top: 0,\n right: elWidth,\n bottom: elHeight,\n },\n layer: 1, // important when comparing with hits from other components\n };\n }\n return null;\n }\n}\n\nclass MoreLinkContainer extends BaseComponent {\n constructor() {\n super(...arguments);\n this.state = {\n isPopoverOpen: false,\n popoverId: getUniqueDomId(),\n };\n this.handleLinkEl = (linkEl) => {\n this.linkEl = linkEl;\n if (this.props.elRef) {\n setRef(this.props.elRef, linkEl);\n }\n };\n this.handleClick = (ev) => {\n let { props, context } = this;\n let { moreLinkClick } = context.options;\n let date = computeRange(props).start;\n function buildPublicSeg(seg) {\n let { def, instance, range } = seg.eventRange;\n return {\n event: new EventImpl(context, def, instance),\n start: context.dateEnv.toDate(range.start),\n end: context.dateEnv.toDate(range.end),\n isStart: seg.isStart,\n isEnd: seg.isEnd,\n };\n }\n if (typeof moreLinkClick === 'function') {\n moreLinkClick = moreLinkClick({\n date,\n allDay: Boolean(props.allDayDate),\n allSegs: props.allSegs.map(buildPublicSeg),\n hiddenSegs: props.hiddenSegs.map(buildPublicSeg),\n jsEvent: ev,\n view: context.viewApi,\n });\n }\n if (!moreLinkClick || moreLinkClick === 'popover') {\n this.setState({ isPopoverOpen: true });\n }\n else if (typeof moreLinkClick === 'string') { // a view name\n context.calendarApi.zoomTo(date, moreLinkClick);\n }\n };\n this.handlePopoverClose = () => {\n this.setState({ isPopoverOpen: false });\n };\n }\n render() {\n let { props, state } = this;\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ViewContextType.Consumer, null, (context) => {\n let { viewApi, options, calendarApi } = context;\n let { moreLinkText } = options;\n let { moreCnt } = props;\n let range = computeRange(props);\n let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals\n ? moreLinkText.call(calendarApi, moreCnt)\n : `+${moreCnt} ${moreLinkText}`;\n let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);\n let renderProps = {\n num: moreCnt,\n shortText: `+${moreCnt}`,\n text,\n view: viewApi,\n };\n return ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(preact__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n Boolean(props.moreCnt) && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [\n ...(props.elClasses || []),\n 'fc-more-link',\n ], elStyle: props.elStyle, elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), { title: hint, 'aria-expanded': state.isPopoverOpen, 'aria-controls': state.isPopoverOpen ? state.popoverId : '' }), renderProps: renderProps, generatorName: \"moreLinkContent\", customGenerator: options.moreLinkContent, defaultGenerator: props.defaultGenerator || renderMoreLinkInner, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),\n state.isPopoverOpen && ((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(MorePopover, { id: state.popoverId, startDate: range.start, endDate: range.end, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: props.extraDateSpan, parentEl: this.parentEl, alignmentEl: props.alignmentElRef ?\n props.alignmentElRef.current :\n this.linkEl, alignGridTop: props.alignGridTop, forceTimed: props.forceTimed, onClose: this.handlePopoverClose }, props.popoverContent()))));\n }));\n }\n componentDidMount() {\n this.updateParentEl();\n }\n componentDidUpdate() {\n this.updateParentEl();\n }\n updateParentEl() {\n if (this.linkEl) {\n this.parentEl = elementClosest(this.linkEl, '.fc-view-harness');\n }\n }\n}\nfunction renderMoreLinkInner(props) {\n return props.text;\n}\nfunction computeRange(props) {\n if (props.allDayDate) {\n return {\n start: props.allDayDate,\n end: addDays(props.allDayDate, 1),\n };\n }\n let { hiddenSegs } = props;\n return {\n start: computeEarliestSegStart(hiddenSegs),\n end: computeLatestSegEnd(hiddenSegs),\n };\n}\nfunction computeEarliestSegStart(segs) {\n return segs.reduce(pickEarliestStart).eventRange.range.start;\n}\nfunction pickEarliestStart(seg0, seg1) {\n return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;\n}\nfunction computeLatestSegEnd(segs) {\n return segs.reduce(pickLatestEnd).eventRange.range.end;\n}\nfunction pickLatestEnd(seg0, seg1) {\n return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;\n}\n\nclass Store {\n constructor() {\n this.handlers = [];\n }\n set(value) {\n this.currentValue = value;\n for (let handler of this.handlers) {\n handler(value);\n }\n }\n subscribe(handler) {\n this.handlers.push(handler);\n if (this.currentValue !== undefined) {\n handler(this.currentValue);\n }\n }\n}\n\n/*\nSubscribers will get a LIST of CustomRenderings\n*/\nclass CustomRenderingStore extends Store {\n constructor() {\n super(...arguments);\n this.map = new Map();\n }\n // for consistent order\n handle(customRendering) {\n const { map } = this;\n let updated = false;\n if (customRendering.isActive) {\n map.set(customRendering.id, customRendering);\n updated = true;\n }\n else if (map.has(customRendering.id)) {\n map.delete(customRendering.id);\n updated = true;\n }\n if (updated) {\n this.set(map);\n }\n }\n}\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QXFCO0FBQ3JCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBLGdCQUFnQixTQUFTO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsUUFBUTtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLGdEQUFnRDtBQUN4RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QiwrQkFBK0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9FQUFvRTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxpQkFBaUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0E7QUFDQSxrREFBa0QsUUFBUTtBQUMxRDtBQUNBLDBEQUEwRDtBQUMxRDtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxRQUFRO0FBQzlDO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRDtBQUMzRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsY0FBYztBQUMzQztBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHdCQUF3QixFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsMkJBQTJCLEVBQUUsUUFBUSxFQUFFO0FBQ3BIO0FBQ0E7QUFDQTtBQUNBLG1MQUFtTCxNQUFNO0FBQ3pMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsaUJBQWlCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGlCQUFpQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQTtBQUNBO0FBQ0EsY0FBYyxpQkFBaUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RDtBQUN2RDtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsUUFBUSxVQUFVO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwwQkFBMEI7QUFDdEM7QUFDQTtBQUNB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsZ0JBQWdCO0FBQzlCO0FBQ0E7QUFDQSxvQkFBb0IsU0FBUztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsZ0JBQWdCO0FBQzlCO0FBQ0E7QUFDQSxvQkFBb0IsU0FBUztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsU0FBUztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7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O0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxhQUFhO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixNQUFNO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRW12SiIsInNvdXJjZXMiOlsid2VicGFjazovL2FyY2hpdGVjdHVpLWh0bWwtZnJlZS8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2NvcmUvaW50ZXJuYWwtY29tbW9uLmpzPzY4OTYiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcHJlYWN0IGZyb20gJ3ByZWFjdCc7XG5pbXBvcnQgeyBDb21wb25lbnQsIGNyZWF0ZUVsZW1lbnQsIGlzVmFsaWRFbGVtZW50LCBGcmFnbWVudCB9IGZyb20gJ3ByZWFjdCc7XG5pbXBvcnQgeyBjcmVhdGVQb3J0YWwgfSBmcm9tICdwcmVhY3QvY29tcGF0JztcblxuY29uc3Qgc3R5bGVUZXh0cyA9IFtdO1xuY29uc3Qgc3R5bGVFbHMgPSBuZXcgTWFwKCk7XG5mdW5jdGlvbiBpbmplY3RTdHlsZXMoc3R5bGVUZXh0KSB7XG4gICAgc3R5bGVUZXh0cy5wdXNoKHN0eWxlVGV4dCk7XG4gICAgc3R5bGVFbHMuZm9yRWFjaCgoc3R5bGVFbCkgPT4ge1xuICAgICAgICBhcHBlbmRTdHlsZXNUbyhzdHlsZUVsLCBzdHlsZVRleHQpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gZW5zdXJlRWxIYXNTdHlsZXMoZWwpIHtcbiAgICBpZiAoZWwuaXNDb25uZWN0ZWQgJiYgLy8gc29tZXRpbWVzIHRydWUgaWYgU1NSIHN5c3RlbSBzaW11bGF0ZXMgRE9NXG4gICAgICAgIGVsLmdldFJvb3ROb2RlIC8vIHNvbWV0aW1lcyB1bmRlZmluZWQgaWYgU1NSIHN5c3RlbSBzaW11bGF0ZXMgRE9NXG4gICAgKSB7XG4gICAgICAgIHJlZ2lzdGVyU3R5bGVzUm9vdChlbC5nZXRSb290Tm9kZSgpKTtcbiAgICB9XG59XG5mdW5jdGlvbiByZWdpc3RlclN0eWxlc1Jvb3Qocm9vdE5vZGUpIHtcbiAgICBsZXQgc3R5bGVFbCA9IHN0eWxlRWxzLmdldChyb290Tm9kZSk7XG4gICAgaWYgKCFzdHlsZUVsIHx8ICFzdHlsZUVsLmlzQ29ubmVjdGVkKSB7XG4gICAgICAgIHN0eWxlRWwgPSByb290Tm9kZS5xdWVyeVNlbGVjdG9yKCdzdHlsZVtkYXRhLWZ1bGxjYWxlbmRhcl0nKTtcbiAgICAgICAgaWYgKCFzdHlsZUVsKSB7XG4gICAgICAgICAgICBzdHlsZUVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgICAgICAgICAgIHN0eWxlRWwuc2V0QXR0cmlidXRlKCdkYXRhLWZ1bGxjYWxlbmRhcicsICcnKTtcbiAgICAgICAgICAgIGNvbnN0IG5vbmNlID0gZ2V0Tm9uY2VWYWx1ZSgpO1xuICAgICAgICAgICAgaWYgKG5vbmNlKSB7XG4gICAgICAgICAgICAgICAgc3R5bGVFbC5ub25jZSA9IG5vbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcGFyZW50RWwgPSByb290Tm9kZSA9PT0gZG9jdW1lbnQgPyBkb2N1bWVudC5oZWFkIDogcm9vdE5vZGU7XG4gICAgICAgICAgICBjb25zdCBpbnNlcnRCZWZvcmUgPSByb290Tm9kZSA9PT0gZG9jdW1lbnRcbiAgICAgICAgICAgICAgICA/IHBhcmVudEVsLnF1ZXJ5U2VsZWN0b3IoJ3NjcmlwdCxsaW5rW3JlbD1zdHlsZXNoZWV0XSxsaW5rW2FzPXN0eWxlXSxzdHlsZScpXG4gICAgICAgICAgICAgICAgOiBwYXJlbnRFbC5maXJzdENoaWxkO1xuICAgICAgICAgICAgcGFyZW50RWwuaW5zZXJ0QmVmb3JlKHN0eWxlRWwsIGluc2VydEJlZm9yZSk7XG4gICAgICAgIH1cbiAgICAgICAgc3R5bGVFbHMuc2V0KHJvb3ROb2RlLCBzdHlsZUVsKTtcbiAgICAgICAgaHlkcmF0ZVN0eWxlc1Jvb3Qoc3R5bGVFbCk7XG4gICAgfVxufVxuZnVuY3Rpb24gaHlkcmF0ZVN0eWxlc1Jvb3Qoc3R5bGVFbCkge1xuICAgIGZvciAoY29uc3Qgc3R5bGVUZXh0IG9mIHN0eWxlVGV4dHMpIHtcbiAgICAgICAgYXBwZW5kU3R5bGVzVG8oc3R5bGVFbCwgc3R5bGVUZXh0KTtcbiAgICB9XG59XG5mdW5jdGlvbiBhcHBlbmRTdHlsZXNUbyhzdHlsZUVsLCBzdHlsZVRleHQpIHtcbiAgICBjb25zdCB7IHNoZWV0IH0gPSBzdHlsZUVsO1xuICAgIGNvbnN0IHJ1bGVDbnQgPSBzaGVldC5jc3NSdWxlcy5sZW5ndGg7XG4gICAgc3R5bGVUZXh0LnNwbGl0KCd9JykuZm9yRWFjaCgoc3R5bGVTdHIsIGkpID0+IHtcbiAgICAgICAgc3R5bGVTdHIgPSBzdHlsZVN0ci50cmltKCk7XG4gICAgICAgIGlmIChzdHlsZVN0cikge1xuICAgICAgICAgICAgc2hlZXQuaW5zZXJ0UnVsZShzdHlsZVN0ciArICd9JywgcnVsZUNudCArIGkpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG4vLyBub25jZVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxubGV0IHF1ZXJpZWROb25jZVZhbHVlO1xuZnVuY3Rpb24gZ2V0Tm9uY2VWYWx1ZSgpIHtcbiAgICBpZiAocXVlcmllZE5vbmNlVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBxdWVyaWVkTm9uY2VWYWx1ZSA9IHF1ZXJ5Tm9uY2VWYWx1ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gcXVlcmllZE5vbmNlVmFsdWU7XG59XG4vKlxuVE9ETzogZGlzY291cmFnZSBtZXRhIHRhZyBhbmQgaW5zdGVhZCBwdXQgbm9uY2UgYXR0cmlidXRlIG9uIHBsYWNlaG9sZGVyIDxzdHlsZT4gdGFnXG4qL1xuZnVuY3Rpb24gcXVlcnlOb25jZVZhbHVlKCkge1xuICAgIGNvbnN0IG1ldGFXaXRoTm9uY2UgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9XCJjc3Atbm9uY2VcIl0nKTtcbiAgICBpZiAobWV0YVdpdGhOb25jZSAmJiBtZXRhV2l0aE5vbmNlLmhhc0F0dHJpYnV0ZSgnY29udGVudCcpKSB7XG4gICAgICAgIHJldHVybiBtZXRhV2l0aE5vbmNlLmdldEF0dHJpYnV0ZSgnY29udGVudCcpO1xuICAgIH1cbiAgICBjb25zdCBlbFdpdGhOb25jZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NjcmlwdFtub25jZV0nKTtcbiAgICBpZiAoZWxXaXRoTm9uY2UpIHtcbiAgICAgICAgcmV0dXJuIGVsV2l0aE5vbmNlLm5vbmNlIHx8ICcnO1xuICAgIH1cbiAgICByZXR1cm4gJyc7XG59XG4vLyBtYWluXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJlZ2lzdGVyU3R5bGVzUm9vdChkb2N1bWVudCk7XG59XG5cbnZhciBjc3NfMjQ4eiA9IFwiOnJvb3R7LS1mYy1zbWFsbC1mb250LXNpemU6Ljg1ZW07LS1mYy1wYWdlLWJnLWNvbG9yOiNmZmY7LS1mYy1uZXV0cmFsLWJnLWNvbG9yOmhzbGEoMCwwJSw4MiUsLjMpOy0tZmMtbmV1dHJhbC10ZXh0LWNvbG9yOmdyZXk7LS1mYy1ib3JkZXItY29sb3I6I2RkZDstLWZjLWJ1dHRvbi10ZXh0LWNvbG9yOiNmZmY7LS1mYy1idXR0b24tYmctY29sb3I6IzJjM2U1MDstLWZjLWJ1dHRvbi1ib3JkZXItY29sb3I6IzJjM2U1MDstLWZjLWJ1dHRvbi1ob3Zlci1iZy1jb2xvcjojMWUyYjM3Oy0tZmMtYnV0dG9uLWhvdmVyLWJvcmRlci1jb2xvcjojMWEyNTJmOy0tZmMtYnV0dG9uLWFjdGl2ZS1iZy1jb2xvcjojMWEyNTJmOy0tZmMtYnV0dG9uLWFjdGl2ZS1ib3JkZXItY29sb3I6IzE1MWUyNzstLWZjLWV2ZW50LWJnLWNvbG9yOiMzNzg4ZDg7LS1mYy1ldmVudC1ib3JkZXItY29sb3I6IzM3ODhkODstLWZjLWV2ZW50LXRleHQtY29sb3I6I2ZmZjstLWZjLWV2ZW50LXNlbGVjdGVkLW92ZXJsYXktY29sb3I6cmdiYSgwLDAsMCwuMjUpOy0tZmMtbW9yZS1saW5rLWJnLWNvbG9yOiNkMGQwZDA7LS1mYy1tb3JlLWxpbmstdGV4dC1jb2xvcjppbmhlcml0Oy0tZmMtZXZlbnQtcmVzaXplci10aGlja25lc3M6OHB4Oy0tZmMtZXZlbnQtcmVzaXplci1kb3QtdG90YWwtd2lkdGg6OHB4Oy0tZmMtZXZlbnQtcmVzaXplci1kb3QtYm9yZGVyLXdpZHRoOjFweDstLWZjLW5vbi1idXNpbmVzcy1jb2xvcjpoc2xhKDAsMCUsODQlLC4zKTstLWZjLWJnLWV2ZW50LWNvbG9yOiM4ZmRmODI7LS1mYy1iZy1ldmVudC1vcGFjaXR5OjAuMzstLWZjLWhpZ2hsaWdodC1jb2xvcjpyZ2JhKDE4OCwyMzIsMjQxLC4zKTstLWZjLXRvZGF5LWJnLWNvbG9yOnJnYmEoMjU1LDIyMCw0MCwuMTUpOy0tZmMtbm93LWluZGljYXRvci1jb2xvcjpyZWR9LmZjLW5vdC1hbGxvd2VkLC5mYy1ub3QtYWxsb3dlZCAuZmMtZXZlbnR7Y3Vyc29yOm5vdC1hbGxvd2VkfS5mY3tkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246Y29sdW1uO2ZvbnQtc2l6ZToxZW19LmZjLC5mYyAqLC5mYyA6YWZ0ZXIsLmZjIDpiZWZvcmV7Ym94LXNpemluZzpib3JkZXItYm94fS5mYyB0YWJsZXtib3JkZXItY29sbGFwc2U6Y29sbGFwc2U7Ym9yZGVyLXNwYWNpbmc6MDtmb250LXNpemU6MWVtfS5mYyB0aHt0ZXh0LWFsaWduOmNlbnRlcn0uZmMgdGQsLmZjIHRoe3BhZGRpbmc6MDt2ZXJ0aWNhbC1hbGlnbjp0b3B9LmZjIGFbZGF0YS1uYXZsaW5rXXtjdXJzb3I6cG9pbnRlcn0uZmMgYVtkYXRhLW5hdmxpbmtdOmhvdmVye3RleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmV9LmZjLWRpcmVjdGlvbi1sdHJ7ZGlyZWN0aW9uOmx0cjt0ZXh0LWFsaWduOmxlZnR9LmZjLWRpcmVjdGlvbi1ydGx7ZGlyZWN0aW9uOnJ0bDt0ZXh0LWFsaWduOnJpZ2h0fS5mYy10aGVtZS1zdGFuZGFyZCB0ZCwuZmMtdGhlbWUtc3RhbmRhcmQgdGh7Ym9yZGVyOjFweCBzb2xpZCB2YXIoLS1mYy1ib3JkZXItY29sb3IpfS5mYy1saXF1aWQtaGFjayB0ZCwuZmMtbGlxdWlkLWhhY2sgdGh7cG9zaXRpb246cmVsYXRpdmV9QGZvbnQtZmFjZXtmb250LWZhbWlseTpmY2ljb25zO2ZvbnQtc3R5bGU6bm9ybWFsO2ZvbnQtd2VpZ2h0OjQwMDtzcmM6dXJsKFxcXCJkYXRhOmFwcGxpY2F0aW9uL3gtZm9udC10dGY7Y2hhcnNldD11dGYtODtiYXNlNjQsQUFFQUFBQUxBSUFBQXdBd1QxTXZNZzhTQmZBQUFBQzhBQUFBWUdOdFlYQVhWdEtOQUFBQkhBQUFBRlJuWVhOd0FBQUFFQUFBQVhBQUFBQUlaMng1WmdZeWR4SUFBQUY0QUFBRk5HaGxZV1FVSjdjSUFBQUdyQUFBQURab2FHVmhCMjBEekFBQUJ1UUFBQUFrYUcxMGVDSUFCaFFBQUFjSUFBQUFMR3h2WTJFRDRBVTZBQUFITkFBQUFCaHRZWGh3QUE4QWpBQUFCMHdBQUFBZ2JtRnRaWHNyNjkwQUFBZHNBQUFCaG5CdmMzUUFBd0FBQUFBSTlBQUFBQ0FBQXdQQUFaQUFCUUFBQXBrQ3pBQUFBSThDbVFMTUFBQUI2d0F6QVFrQUFBQUFBQUFBQUFBQUFBQUFBQUFCRUFBQUFBQUFBQUFBQUFBQUFBQUFBQUJBQUFEcEJnUEEvOEFBUUFQQUFFQUFBQUFCQUFBQUFBQUFBQUFBQUFBZ0FBQUFBQUFEQUFBQUF3QUFBQndBQVFBREFBQUFIQUFEQUFFQUFBQWNBQVFBT0FBQUFBb0FDQUFDQUFJQUFRQWc2UWIvL2YvL0FBQUFBQUFnNlFELy9mLy9BQUgvNHhjRUFBTUFBUUFBQUFBQUFBQUFBQUFBQVFBQi8vOEFEd0FCQUFBQUFBQUFBQUFBQWdBQU56a0JBQUFBQUFFQUFBQUFBQUFBQUFBQ0FBQTNPUUVBQUFBQUFRQUFBQUFBQUFBQUFBSUFBRGM1QVFBQUFBQUJBV0lBalFLZUFza0FFd0FBSlNjM05qUW5KaUlIQVFZVUZ3RVdNamMyTkNjQ251TGlEUTBNSkF6L0FBME5BUUFNSkF3TkRjbmk0Z3dqRFF3TS93QU5Jd3ovQUEwTkRDTU5BQUFBQVFGaUFJMENuZ0xKQUJNQUFDVUJOalFuQVNZaUJ3WVVId0VIQmhRWEZqSTNBWjRCQUEwTi93QU1KQXdORGVMaURRME1KQXlOQVFBTUl3MEJBQXdNRFNNTTR1SU5Jd3dORFFBQUFBSUE0Z0MzQXg0Q25nQVRBQ2NBQUNVbk56WTBKeVlpRHdFR0ZCOEJGakkzTmpRbklTYzNOalFuSmlJUEFRWVVId0VXTWpjMk5DY0I4N2UzRFEwTUl3M1ZEUTNWRFNNTURRMEJLN2UzRFEwTUpBelZEUTNWRENRTURRM3p1TGNNSkF3TkRkVU5Jd3pXREF3Tkl3eTR0d3drREEwTjFRMGpETllNREEwakRBQUFBZ0RpQUxjREhnS2VBQk1BSndBQUpUYzJOQzhCSmlJSEJoUWZBUWNHRkJjV01qY2hOelkwTHdFbUlnY0dGQjhCQndZVUZ4WXlOd0pKMVEwTjFRMGpEQTBOdDdjTkRRd2pEZjdWMVEwTjFRd2tEQTBOdDdjTkRRd2tETGZXRENNTjFRME5EQ1FNdDdnTUl3ME1ETllNSXczVkRRME1KQXkzdUF3akRRd01BQUFEQUZVQUFBT3JBMVVBTXdCb0FIY0FBQk1pQmdjT0FRY09BUWNPQVJVUkZCWVhIZ0VYSGdFWEhnRXpJVEkyTno0Qk56NEJOejRCTlJFMEppY3VBU2N1QVNjdUFTTUZJVElXRng0QkZ4NEJGeDRCRlJFVUJnY09BUWNPQVFjT0FTTWhJaVluTGdFbkxnRW5MZ0UxRVRRMk56NEJOejRCTno0Qk14TWhNalkxTkNZaklTSUdGUlFXTTlVTkdBd0xGUWtKRGdVRkJRVUZCUTRKQ1JVTERCZ05BbFlOR0F3TEZRa0pEZ1VGQlFVRkJRNEpDUlVMREJnTi9hb0NWZ1FJQkFRSEF3TUZBUUlCQVFJQkJRTURCd1FFQ0FUOXFnUUlCQVFIQXdNRkFRSUJBUUlCQlFNREJ3UUVDQVNBQVZZUkdSa1IvcW9SR1JrUkExVUZCQVVPQ1FrVkRBc1pEZjJyRFJrTERCVUpDQTRGQlFVRkJRVU9DUWdWREFzWkRRSlZEUmtMREJVSkNRNEZCQVZWQWdFQ0JRTUNCd1FFQ0FYOXF3UUpBd1FIQXdNRkFRSUNBZ0lCQlFNREJ3UURDUVFDVlFVSUJBUUhBZ01GQWdFQy9vQVpFaEVaR1JFU0dRQUFBQUFEQUZVQUFBT3JBMVVBTXdCb0FJa0FBQk1pQmdjT0FRY09BUWNPQVJVUkZCWVhIZ0VYSGdFWEhnRXpJVEkyTno0Qk56NEJOejRCTlJFMEppY3VBU2N1QVNjdUFTTUZJVElXRng0QkZ4NEJGeDRCRlJFVUJnY09BUWNPQVFjT0FTTWhJaVluTGdFbkxnRW5MZ0UxRVRRMk56NEJOejRCTno0Qk14TXpGUlFXTXpJMlBRRXpNalkxTkNZckFUVTBKaU1pQmgwQkl5SUdGUlFXTTlVTkdBd0xGUWtKRGdVRkJRVUZCUTRKQ1JVTERCZ05BbFlOR0F3TEZRa0pEZ1VGQlFVRkJRNEpDUlVMREJnTi9hb0NWZ1FJQkFRSEF3TUZBUUlCQVFJQkJRTURCd1FFQ0FUOXFnUUlCQVFIQXdNRkFRSUJBUUlCQlFNREJ3UUVDQVNBZ0JrU0VobUFFUmtaRVlBWkVoSVpnQkVaR1JFRFZRVUVCUTRKQ1JVTUN4a04vYXNOR1FzTUZRa0lEZ1VGQlFVRkJRNEpDQlVNQ3hrTkFsVU5HUXNNRlFrSkRnVUVCVlVDQVFJRkF3SUhCQVFJQmYyckJBa0RCQWNEQXdVQkFnSUNBZ0VGQXdNSEJBTUpCQUpWQlFnRUJBY0NBd1VDQVFMK2dJQVNHUmtTZ0JrU0VSbUFFaGtaRW9BWkVSSVpBQUFCQU9JQWpRTWVBc2tBSUFBQUV4Y0hCaFFYRmpJL0FSY1dNamMyTkM4Qk56WTBKeVlpRHdFbkppSUhCaFFYNHVMaURRME1KQXppNGd3a0RBME40dUlORFF3a0RPTGlEQ1FNRFEwQ2plTGlEU01NRFEzaDRRME5EQ01ONHVJTUl3ME1ET0xpREF3Tkl3d0FBQUFCQUFBQUFRQUFhNW4weTE4UFBQVUFDd1FBQUFBQUFOaXZPVnNBQUFBQTJLODVXd0FBQUFBRHF3TlZBQUFBQ0FBQ0FBQUFBQUFBQUFFQUFBUEEvOEFBQUFRQUFBQUFBQU9yQUFFQUFBQUFBQUFBQUFBQUFBQUFBQUFMQkFBQUFBQUFBQUFBQUFBQUFnQUFBQVFBQVdJRUFBRmlCQUFBNGdRQUFPSUVBQUJWQkFBQVZRUUFBT0lBQUFBQUFBb0FGQUFlQUVRQWFnQ3FBT29CbmdKa0Fwb0FBUUFBQUFzQWlnQURBQUFBQUFBQ0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBNEFyZ0FCQUFBQUFBQUJBQWNBQUFBQkFBQUFBQUFDQUFjQVlBQUJBQUFBQUFBREFBY0FOZ0FCQUFBQUFBQUVBQWNBZFFBQkFBQUFBQUFGQUFzQUZRQUJBQUFBQUFBR0FBY0FTd0FCQUFBQUFBQUtBQm9BaWdBREFBRUVDUUFCQUE0QUJ3QURBQUVFQ1FBQ0FBNEFad0FEQUFFRUNRQURBQTRBUFFBREFBRUVDUUFFQUE0QWZBQURBQUVFQ1FBRkFCWUFJQUFEQUFFRUNRQUdBQTRBVWdBREFBRUVDUUFLQURRQXBHWmphV052Ym5NQVpnQmpBR2tBWXdCdkFHNEFjMVpsY25OcGIyNGdNUzR3QUZZQVpRQnlBSE1BYVFCdkFHNEFJQUF4QUM0QU1HWmphV052Ym5NQVpnQmpBR2tBWXdCdkFHNEFjMlpqYVdOdmJuTUFaZ0JqQUdrQVl3QnZBRzRBYzFKbFozVnNZWElBVWdCbEFHY0FkUUJzQUdFQWNtWmphV052Ym5NQVpnQmpBR2tBWXdCdkFHNEFjMFp2Ym5RZ1oyVnVaWEpoZEdWa0lHSjVJRWxqYjAxdmIyNHVBRVlBYndCdUFIUUFJQUJuQUdVQWJnQmxBSElBWVFCMEFHVUFaQUFnQUdJQWVRQWdBRWtBWXdCdkFFMEFid0J2QUc0QUxnQUFBQU1BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBPVxcXCIpIGZvcm1hdChcXFwidHJ1ZXR5cGVcXFwiKX0uZmMtaWNvbntzcGVhazpub25lOy13ZWJraXQtZm9udC1zbW9vdGhpbmc6YW50aWFsaWFzZWQ7LW1vei1vc3gtZm9udC1zbW9vdGhpbmc6Z3JheXNjYWxlO2Rpc3BsYXk6aW5saW5lLWJsb2NrO2ZvbnQtZmFtaWx5OmZjaWNvbnMhaW1wb3J0YW50O2ZvbnQtc3R5bGU6bm9ybWFsO2ZvbnQtdmFyaWFudDpub3JtYWw7Zm9udC13ZWlnaHQ6NDAwO2hlaWdodDoxZW07bGluZS1oZWlnaHQ6MTt0ZXh0LWFsaWduOmNlbnRlcjt0ZXh0LXRyYW5zZm9ybTpub25lOy13ZWJraXQtdXNlci1zZWxlY3Q6bm9uZTstbW96LXVzZXItc2VsZWN0Om5vbmU7dXNlci1zZWxlY3Q6bm9uZTt3aWR0aDoxZW19LmZjLWljb24tY2hldnJvbi1sZWZ0OmJlZm9yZXtjb250ZW50OlxcXCJcXFxcZTkwMFxcXCJ9LmZjLWljb24tY2hldnJvbi1yaWdodDpiZWZvcmV7Y29udGVudDpcXFwiXFxcXGU5MDFcXFwifS5mYy1pY29uLWNoZXZyb25zLWxlZnQ6YmVmb3Jle2NvbnRlbnQ6XFxcIlxcXFxlOTAyXFxcIn0uZmMtaWNvbi1jaGV2cm9ucy1yaWdodDpiZWZvcmV7Y29udGVudDpcXFwiXFxcXGU5MDNcXFwifS5mYy1pY29uLW1pbnVzLXNxdWFyZTpiZWZvcmV7Y29udGVudDpcXFwiXFxcXGU5MDRcXFwifS5mYy1pY29uLXBsdXMtc3F1YXJlOmJlZm9yZXtjb250ZW50OlxcXCJcXFxcZTkwNVxcXCJ9LmZjLWljb24teDpiZWZvcmV7Y29udGVudDpcXFwiXFxcXGU5MDZcXFwifS5mYyAuZmMtYnV0dG9ue2JvcmRlci1yYWRpdXM6MDtmb250LWZhbWlseTppbmhlcml0O2ZvbnQtc2l6ZTppbmhlcml0O2xpbmUtaGVpZ2h0OmluaGVyaXQ7bWFyZ2luOjA7b3ZlcmZsb3c6dmlzaWJsZTt0ZXh0LXRyYW5zZm9ybTpub25lfS5mYyAuZmMtYnV0dG9uOmZvY3Vze291dGxpbmU6MXB4IGRvdHRlZDtvdXRsaW5lOjVweCBhdXRvIC13ZWJraXQtZm9jdXMtcmluZy1jb2xvcn0uZmMgLmZjLWJ1dHRvbnstd2Via2l0LWFwcGVhcmFuY2U6YnV0dG9ufS5mYyAuZmMtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpe2N1cnNvcjpwb2ludGVyfS5mYyAuZmMtYnV0dG9ue2JhY2tncm91bmQtY29sb3I6dHJhbnNwYXJlbnQ7Ym9yZGVyOjFweCBzb2xpZCB0cmFuc3BhcmVudDtib3JkZXItcmFkaXVzOi4yNWVtO2Rpc3BsYXk6aW5saW5lLWJsb2NrO2ZvbnQtc2l6ZToxZW07Zm9udC13ZWlnaHQ6NDAwO2xpbmUtaGVpZ2h0OjEuNTtwYWRkaW5nOi40ZW0gLjY1ZW07dGV4dC1hbGlnbjpjZW50ZXI7LXdlYmtpdC11c2VyLXNlbGVjdDpub25lOy1tb3otdXNlci1zZWxlY3Q6bm9uZTt1c2VyLXNlbGVjdDpub25lO3ZlcnRpY2FsLWFsaWduOm1pZGRsZX0uZmMgLmZjLWJ1dHRvbjpob3Zlcnt0ZXh0LWRlY29yYXRpb246bm9uZX0uZmMgLmZjLWJ1dHRvbjpmb2N1c3tib3gtc2hhZG93OjAgMCAwIC4ycmVtIHJnYmEoNDQsNjIsODAsLjI1KTtvdXRsaW5lOjB9LmZjIC5mYy1idXR0b246ZGlzYWJsZWR7b3BhY2l0eTouNjV9LmZjIC5mYy1idXR0b24tcHJpbWFyeXtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLWZjLWJ1dHRvbi1iZy1jb2xvcik7Ym9yZGVyLWNvbG9yOnZhcigtLWZjLWJ1dHRvbi1ib3JkZXItY29sb3IpO2NvbG9yOnZhcigtLWZjLWJ1dHRvbi10ZXh0LWNvbG9yKX0uZmMgLmZjLWJ1dHRvbi1wcmltYXJ5OmhvdmVye2JhY2tncm91bmQtY29sb3I6dmFyKC0tZmMtYnV0dG9uLWhvdmVyLWJnLWNvbG9yKTtib3JkZXItY29sb3I6dmFyKC0tZmMtYnV0dG9uLWhvdmVyLWJvcmRlci1jb2xvcik7Y29sb3I6dmFyKC0tZmMtYnV0dG9uLXRleHQtY29sb3IpfS5mYyAuZmMtYnV0dG9uLXByaW1hcnk6ZGlzYWJsZWR7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1mYy1idXR0b24tYmctY29sb3IpO2JvcmRlci1jb2xvcjp2YXIoLS1mYy1idXR0b24tYm9yZGVyLWNvbG9yKTtjb2xvcjp2YXIoLS1mYy1idXR0b24tdGV4dC1jb2xvcil9LmZjIC5mYy1idXR0b24tcHJpbWFyeTpmb2N1c3tib3gtc2hhZG93OjAgMCAwIC4ycmVtIHJnYmEoNzYsOTEsMTA2LC41KX0uZmMgLmZjLWJ1dHRvbi1wcmltYXJ5Om5vdCg6ZGlzYWJsZWQpLmZjLWJ1dHRvbi1hY3RpdmUsLmZjIC5mYy1idXR0b24tcHJpbWFyeTpub3QoOmRpc2FibGVkKTphY3RpdmV7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1mYy1idXR0b24tYWN0aXZlLWJnLWNvbG9yKTtib3JkZXItY29sb3I6dmFyKC0tZmMtYnV0dG9uLWFjdGl2ZS1ib3JkZXItY29sb3IpO2NvbG9yOnZhcigtLWZjLWJ1dHRvbi10ZXh0LWNvbG9yKX0uZmMgLmZjLWJ1dHRvbi1wcmltYXJ5Om5vdCg6ZGlzYWJsZWQpLmZjLWJ1dHRvbi1hY3RpdmU6Zm9jdXMsLmZjIC5mYy1idXR0b24tcHJpbWFyeTpub3QoOmRpc2FibGVkKTphY3RpdmU6Zm9jdXN7Ym94LXNoYWRvdzowIDAgMCAuMnJlbSByZ2JhKDc2LDkxLDEwNiwuNSl9LmZjIC5mYy1idXR0b24gLmZjLWljb257Zm9udC1zaXplOjEuNWVtO3ZlcnRpY2FsLWFsaWduOm1pZGRsZX0uZmMgLmZjLWJ1dHRvbi1ncm91cHtkaXNwbGF5OmlubGluZS1mbGV4O3Bvc2l0aW9uOnJlbGF0aXZlO3ZlcnRpY2FsLWFsaWduOm1pZGRsZX0uZmMgLmZjLWJ1dHRvbi1ncm91cD4uZmMtYnV0dG9ue2ZsZXg6MSAxIGF1dG87cG9zaXRpb246cmVsYXRpdmV9LmZjIC5mYy1idXR0b24tZ3JvdXA+LmZjLWJ1dHRvbi5mYy1idXR0b24tYWN0aXZlLC5mYyAuZmMtYnV0dG9uLWdyb3VwPi5mYy1idXR0b246YWN0aXZlLC5mYyAuZmMtYnV0dG9uLWdyb3VwPi5mYy1idXR0b246Zm9jdXMsLmZjIC5mYy1idXR0b24tZ3JvdXA+LmZjLWJ1dHRvbjpob3Zlcnt6LWluZGV4OjF9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWJ1dHRvbi1ncm91cD4uZmMtYnV0dG9uOm5vdCg6Zmlyc3QtY2hpbGQpe2JvcmRlci1ib3R0b20tbGVmdC1yYWRpdXM6MDtib3JkZXItdG9wLWxlZnQtcmFkaXVzOjA7bWFyZ2luLWxlZnQ6LTFweH0uZmMtZGlyZWN0aW9uLWx0ciAuZmMtYnV0dG9uLWdyb3VwPi5mYy1idXR0b246bm90KDpsYXN0LWNoaWxkKXtib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czowO2JvcmRlci10b3AtcmlnaHQtcmFkaXVzOjB9LmZjLWRpcmVjdGlvbi1ydGwgLmZjLWJ1dHRvbi1ncm91cD4uZmMtYnV0dG9uOm5vdCg6Zmlyc3QtY2hpbGQpe2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjA7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MDttYXJnaW4tcmlnaHQ6LTFweH0uZmMtZGlyZWN0aW9uLXJ0bCAuZmMtYnV0dG9uLWdyb3VwPi5mYy1idXR0b246bm90KDpsYXN0LWNoaWxkKXtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjA7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czowfS5mYyAuZmMtdG9vbGJhcnthbGlnbi1pdGVtczpjZW50ZXI7ZGlzcGxheTpmbGV4O2p1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVufS5mYyAuZmMtdG9vbGJhci5mYy1oZWFkZXItdG9vbGJhcnttYXJnaW4tYm90dG9tOjEuNWVtfS5mYyAuZmMtdG9vbGJhci5mYy1mb290ZXItdG9vbGJhcnttYXJnaW4tdG9wOjEuNWVtfS5mYyAuZmMtdG9vbGJhci10aXRsZXtmb250LXNpemU6MS43NWVtO21hcmdpbjowfS5mYy1kaXJlY3Rpb24tbHRyIC5mYy10b29sYmFyPio+Om5vdCg6Zmlyc3QtY2hpbGQpe21hcmdpbi1sZWZ0Oi43NWVtfS5mYy1kaXJlY3Rpb24tcnRsIC5mYy10b29sYmFyPio+Om5vdCg6Zmlyc3QtY2hpbGQpe21hcmdpbi1yaWdodDouNzVlbX0uZmMtZGlyZWN0aW9uLXJ0bCAuZmMtdG9vbGJhci1sdHJ7ZmxleC1kaXJlY3Rpb246cm93LXJldmVyc2V9LmZjIC5mYy1zY3JvbGxlcnstd2Via2l0LW92ZXJmbG93LXNjcm9sbGluZzp0b3VjaDtwb3NpdGlvbjpyZWxhdGl2ZX0uZmMgLmZjLXNjcm9sbGVyLWxpcXVpZHtoZWlnaHQ6MTAwJX0uZmMgLmZjLXNjcm9sbGVyLWxpcXVpZC1hYnNvbHV0ZXtib3R0b206MDtsZWZ0OjA7cG9zaXRpb246YWJzb2x1dGU7cmlnaHQ6MDt0b3A6MH0uZmMgLmZjLXNjcm9sbGVyLWhhcm5lc3N7ZGlyZWN0aW9uOmx0cjtvdmVyZmxvdzpoaWRkZW47cG9zaXRpb246cmVsYXRpdmV9LmZjIC5mYy1zY3JvbGxlci1oYXJuZXNzLWxpcXVpZHtoZWlnaHQ6MTAwJX0uZmMtZGlyZWN0aW9uLXJ0bCAuZmMtc2Nyb2xsZXItaGFybmVzcz4uZmMtc2Nyb2xsZXJ7ZGlyZWN0aW9uOnJ0bH0uZmMtdGhlbWUtc3RhbmRhcmQgLmZjLXNjcm9sbGdyaWR7Ym9yZGVyOjFweCBzb2xpZCB2YXIoLS1mYy1ib3JkZXItY29sb3IpfS5mYyAuZmMtc2Nyb2xsZ3JpZCwuZmMgLmZjLXNjcm9sbGdyaWQgdGFibGV7dGFibGUtbGF5b3V0OmZpeGVkO3dpZHRoOjEwMCV9LmZjIC5mYy1zY3JvbGxncmlkIHRhYmxle2JvcmRlci1sZWZ0LXN0eWxlOmhpZGRlbjtib3JkZXItcmlnaHQtc3R5bGU6aGlkZGVuO2JvcmRlci10b3Atc3R5bGU6aGlkZGVufS5mYyAuZmMtc2Nyb2xsZ3JpZHtib3JkZXItYm90dG9tLXdpZHRoOjA7Ym9yZGVyLWNvbGxhcHNlOnNlcGFyYXRlO2JvcmRlci1yaWdodC13aWR0aDowfS5mYyAuZmMtc2Nyb2xsZ3JpZC1saXF1aWR7aGVpZ2h0OjEwMCV9LmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24sLmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24gdGFibGUsLmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24+dGR7aGVpZ2h0OjFweH0uZmMgLmZjLXNjcm9sbGdyaWQtc2VjdGlvbi1saXF1aWQ+dGR7aGVpZ2h0OjEwMCV9LmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24+Kntib3JkZXItbGVmdC13aWR0aDowO2JvcmRlci10b3Atd2lkdGg6MH0uZmMgLmZjLXNjcm9sbGdyaWQtc2VjdGlvbi1mb290ZXI+KiwuZmMgLmZjLXNjcm9sbGdyaWQtc2VjdGlvbi1oZWFkZXI+Kntib3JkZXItYm90dG9tLXdpZHRoOjB9LmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24tYm9keSB0YWJsZSwuZmMgLmZjLXNjcm9sbGdyaWQtc2VjdGlvbi1mb290ZXIgdGFibGV7Ym9yZGVyLWJvdHRvbS1zdHlsZTpoaWRkZW59LmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24tc3RpY2t5Pip7YmFja2dyb3VuZDp2YXIoLS1mYy1wYWdlLWJnLWNvbG9yKTtwb3NpdGlvbjpzdGlja3k7ei1pbmRleDozfS5mYyAuZmMtc2Nyb2xsZ3JpZC1zZWN0aW9uLWhlYWRlci5mYy1zY3JvbGxncmlkLXNlY3Rpb24tc3RpY2t5Pip7dG9wOjB9LmZjIC5mYy1zY3JvbGxncmlkLXNlY3Rpb24tZm9vdGVyLmZjLXNjcm9sbGdyaWQtc2VjdGlvbi1zdGlja3k+Kntib3R0b206MH0uZmMgLmZjLXNjcm9sbGdyaWQtc3RpY2t5LXNoaW17aGVpZ2h0OjFweDttYXJnaW4tYm90dG9tOi0xcHh9LmZjLXN0aWNreXtwb3NpdGlvbjpzdGlja3l9LmZjIC5mYy12aWV3LWhhcm5lc3N7ZmxleC1ncm93OjE7cG9zaXRpb246cmVsYXRpdmV9LmZjIC5mYy12aWV3LWhhcm5lc3MtYWN0aXZlPi5mYy12aWV3e2JvdHRvbTowO2xlZnQ6MDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3RvcDowfS5mYyAuZmMtY29sLWhlYWRlci1jZWxsLWN1c2hpb257ZGlzcGxheTppbmxpbmUtYmxvY2s7cGFkZGluZzoycHggNHB4fS5mYyAuZmMtYmctZXZlbnQsLmZjIC5mYy1oaWdobGlnaHQsLmZjIC5mYy1ub24tYnVzaW5lc3N7Ym90dG9tOjA7bGVmdDowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjB9LmZjIC5mYy1ub24tYnVzaW5lc3N7YmFja2dyb3VuZDp2YXIoLS1mYy1ub24tYnVzaW5lc3MtY29sb3IpfS5mYyAuZmMtYmctZXZlbnR7YmFja2dyb3VuZDp2YXIoLS1mYy1iZy1ldmVudC1jb2xvcik7b3BhY2l0eTp2YXIoLS1mYy1iZy1ldmVudC1vcGFjaXR5KX0uZmMgLmZjLWJnLWV2ZW50IC5mYy1ldmVudC10aXRsZXtmb250LXNpemU6dmFyKC0tZmMtc21hbGwtZm9udC1zaXplKTtmb250LXN0eWxlOml0YWxpYzttYXJnaW46LjVlbX0uZmMgLmZjLWhpZ2hsaWdodHtiYWNrZ3JvdW5kOnZhcigtLWZjLWhpZ2hsaWdodC1jb2xvcil9LmZjIC5mYy1jZWxsLXNoYWRlZCwuZmMgLmZjLWRheS1kaXNhYmxlZHtiYWNrZ3JvdW5kOnZhcigtLWZjLW5ldXRyYWwtYmctY29sb3IpfWEuZmMtZXZlbnQsYS5mYy1ldmVudDpob3Zlcnt0ZXh0LWRlY29yYXRpb246bm9uZX0uZmMtZXZlbnQuZmMtZXZlbnQtZHJhZ2dhYmxlLC5mYy1ldmVudFtocmVmXXtjdXJzb3I6cG9pbnRlcn0uZmMtZXZlbnQgLmZjLWV2ZW50LW1haW57cG9zaXRpb246cmVsYXRpdmU7ei1pbmRleDoyfS5mYy1ldmVudC1kcmFnZ2luZzpub3QoLmZjLWV2ZW50LXNlbGVjdGVkKXtvcGFjaXR5Oi43NX0uZmMtZXZlbnQtZHJhZ2dpbmcuZmMtZXZlbnQtc2VsZWN0ZWR7Ym94LXNoYWRvdzowIDJweCA3cHggcmdiYSgwLDAsMCwuMyl9LmZjLWV2ZW50IC5mYy1ldmVudC1yZXNpemVye2Rpc3BsYXk6bm9uZTtwb3NpdGlvbjphYnNvbHV0ZTt6LWluZGV4OjR9LmZjLWV2ZW50LXNlbGVjdGVkIC5mYy1ldmVudC1yZXNpemVyLC5mYy1ldmVudDpob3ZlciAuZmMtZXZlbnQtcmVzaXplcntkaXNwbGF5OmJsb2NrfS5mYy1ldmVudC1zZWxlY3RlZCAuZmMtZXZlbnQtcmVzaXplcntiYWNrZ3JvdW5kOnZhcigtLWZjLXBhZ2UtYmctY29sb3IpO2JvcmRlci1jb2xvcjppbmhlcml0O2JvcmRlci1yYWRpdXM6Y2FsYyh2YXIoLS1mYy1ldmVudC1yZXNpemVyLWRvdC10b3RhbC13aWR0aCkvMik7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDp2YXIoLS1mYy1ldmVudC1yZXNpemVyLWRvdC1ib3JkZXItd2lkdGgpO2hlaWdodDp2YXIoLS1mYy1ldmVudC1yZXNpemVyLWRvdC10b3RhbC13aWR0aCk7d2lkdGg6dmFyKC0tZmMtZXZlbnQtcmVzaXplci1kb3QtdG90YWwtd2lkdGgpfS5mYy1ldmVudC1zZWxlY3RlZCAuZmMtZXZlbnQtcmVzaXplcjpiZWZvcmV7Ym90dG9tOi0yMHB4O2NvbnRlbnQ6XFxcIlxcXCI7bGVmdDotMjBweDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDotMjBweDt0b3A6LTIwcHh9LmZjLWV2ZW50LXNlbGVjdGVkLC5mYy1ldmVudDpmb2N1c3tib3gtc2hhZG93OjAgMnB4IDVweCByZ2JhKDAsMCwwLC4yKX0uZmMtZXZlbnQtc2VsZWN0ZWQ6YmVmb3JlLC5mYy1ldmVudDpmb2N1czpiZWZvcmV7Ym90dG9tOjA7Y29udGVudDpcXFwiXFxcIjtsZWZ0OjA7cG9zaXRpb246YWJzb2x1dGU7cmlnaHQ6MDt0b3A6MDt6LWluZGV4OjN9LmZjLWV2ZW50LXNlbGVjdGVkOmFmdGVyLC5mYy1ldmVudDpmb2N1czphZnRlcntiYWNrZ3JvdW5kOnZhcigtLWZjLWV2ZW50LXNlbGVjdGVkLW92ZXJsYXktY29sb3IpO2JvdHRvbTotMXB4O2NvbnRlbnQ6XFxcIlxcXCI7bGVmdDotMXB4O3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0Oi0xcHg7dG9wOi0xcHg7ei1pbmRleDoxfS5mYy1oLWV2ZW50e2JhY2tncm91bmQtY29sb3I6dmFyKC0tZmMtZXZlbnQtYmctY29sb3IpO2JvcmRlcjoxcHggc29saWQgdmFyKC0tZmMtZXZlbnQtYm9yZGVyLWNvbG9yKTtkaXNwbGF5OmJsb2NrfS5mYy1oLWV2ZW50IC5mYy1ldmVudC1tYWlue2NvbG9yOnZhcigtLWZjLWV2ZW50LXRleHQtY29sb3IpfS5mYy1oLWV2ZW50IC5mYy1ldmVudC1tYWluLWZyYW1le2Rpc3BsYXk6ZmxleH0uZmMtaC1ldmVudCAuZmMtZXZlbnQtdGltZXttYXgtd2lkdGg6MTAwJTtvdmVyZmxvdzpoaWRkZW59LmZjLWgtZXZlbnQgLmZjLWV2ZW50LXRpdGxlLWNvbnRhaW5lcntmbGV4LWdyb3c6MTtmbGV4LXNocmluazoxO21pbi13aWR0aDowfS5mYy1oLWV2ZW50IC5mYy1ldmVudC10aXRsZXtkaXNwbGF5OmlubGluZS1ibG9jaztsZWZ0OjA7bWF4LXdpZHRoOjEwMCU7b3ZlcmZsb3c6aGlkZGVuO3JpZ2h0OjA7dmVydGljYWwtYWxpZ246dG9wfS5mYy1oLWV2ZW50LmZjLWV2ZW50LXNlbGVjdGVkOmJlZm9yZXtib3R0b206LTEwcHg7dG9wOi0xMHB4fS5mYy1kaXJlY3Rpb24tbHRyIC5mYy1kYXlncmlkLWJsb2NrLWV2ZW50Om5vdCguZmMtZXZlbnQtc3RhcnQpLC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1kYXlncmlkLWJsb2NrLWV2ZW50Om5vdCguZmMtZXZlbnQtZW5kKXtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjA7Ym9yZGVyLWxlZnQtd2lkdGg6MDtib3JkZXItdG9wLWxlZnQtcmFkaXVzOjB9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWRheWdyaWQtYmxvY2stZXZlbnQ6bm90KC5mYy1ldmVudC1lbmQpLC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1kYXlncmlkLWJsb2NrLWV2ZW50Om5vdCguZmMtZXZlbnQtc3RhcnQpe2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjA7Ym9yZGVyLXJpZ2h0LXdpZHRoOjA7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MH0uZmMtaC1ldmVudDpub3QoLmZjLWV2ZW50LXNlbGVjdGVkKSAuZmMtZXZlbnQtcmVzaXplcntib3R0b206MDt0b3A6MDt3aWR0aDp2YXIoLS1mYy1ldmVudC1yZXNpemVyLXRoaWNrbmVzcyl9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWgtZXZlbnQ6bm90KC5mYy1ldmVudC1zZWxlY3RlZCkgLmZjLWV2ZW50LXJlc2l6ZXItc3RhcnQsLmZjLWRpcmVjdGlvbi1ydGwgLmZjLWgtZXZlbnQ6bm90KC5mYy1ldmVudC1zZWxlY3RlZCkgLmZjLWV2ZW50LXJlc2l6ZXItZW5ke2N1cnNvcjp3LXJlc2l6ZTtsZWZ0OmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci10aGlja25lc3MpKi0uNSl9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWgtZXZlbnQ6bm90KC5mYy1ldmVudC1zZWxlY3RlZCkgLmZjLWV2ZW50LXJlc2l6ZXItZW5kLC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1oLWV2ZW50Om5vdCguZmMtZXZlbnQtc2VsZWN0ZWQpIC5mYy1ldmVudC1yZXNpemVyLXN0YXJ0e2N1cnNvcjplLXJlc2l6ZTtyaWdodDpjYWxjKHZhcigtLWZjLWV2ZW50LXJlc2l6ZXItdGhpY2tuZXNzKSotLjUpfS5mYy1oLWV2ZW50LmZjLWV2ZW50LXNlbGVjdGVkIC5mYy1ldmVudC1yZXNpemVye21hcmdpbi10b3A6Y2FsYyh2YXIoLS1mYy1ldmVudC1yZXNpemVyLWRvdC10b3RhbC13aWR0aCkqLS41KTt0b3A6NTAlfS5mYy1kaXJlY3Rpb24tbHRyIC5mYy1oLWV2ZW50LmZjLWV2ZW50LXNlbGVjdGVkIC5mYy1ldmVudC1yZXNpemVyLXN0YXJ0LC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1oLWV2ZW50LmZjLWV2ZW50LXNlbGVjdGVkIC5mYy1ldmVudC1yZXNpemVyLWVuZHtsZWZ0OmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci1kb3QtdG90YWwtd2lkdGgpKi0uNSl9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWgtZXZlbnQuZmMtZXZlbnQtc2VsZWN0ZWQgLmZjLWV2ZW50LXJlc2l6ZXItZW5kLC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1oLWV2ZW50LmZjLWV2ZW50LXNlbGVjdGVkIC5mYy1ldmVudC1yZXNpemVyLXN0YXJ0e3JpZ2h0OmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci1kb3QtdG90YWwtd2lkdGgpKi0uNSl9LmZjIC5mYy1wb3BvdmVye2JveC1zaGFkb3c6MCAycHggNnB4IHJnYmEoMCwwLDAsLjE1KTtwb3NpdGlvbjphYnNvbHV0ZTt6LWluZGV4Ojk5OTl9LmZjIC5mYy1wb3BvdmVyLWhlYWRlcnthbGlnbi1pdGVtczpjZW50ZXI7ZGlzcGxheTpmbGV4O2ZsZXgtZGlyZWN0aW9uOnJvdztqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjtwYWRkaW5nOjNweCA0cHh9LmZjIC5mYy1wb3BvdmVyLXRpdGxle21hcmdpbjowIDJweH0uZmMgLmZjLXBvcG92ZXItY2xvc2V7Y3Vyc29yOnBvaW50ZXI7Zm9udC1zaXplOjEuMWVtO29wYWNpdHk6LjY1fS5mYy10aGVtZS1zdGFuZGFyZCAuZmMtcG9wb3ZlcntiYWNrZ3JvdW5kOnZhcigtLWZjLXBhZ2UtYmctY29sb3IpO2JvcmRlcjoxcHggc29saWQgdmFyKC0tZmMtYm9yZGVyLWNvbG9yKX0uZmMtdGhlbWUtc3RhbmRhcmQgLmZjLXBvcG92ZXItaGVhZGVye2JhY2tncm91bmQ6dmFyKC0tZmMtbmV1dHJhbC1iZy1jb2xvcil9XCI7XG5pbmplY3RTdHlsZXMoY3NzXzI0OHopO1xuXG5jbGFzcyBEZWxheWVkUnVubmVyIHtcbiAgICBjb25zdHJ1Y3RvcihkcmFpbmVkT3B0aW9uKSB7XG4gICAgICAgIHRoaXMuZHJhaW5lZE9wdGlvbiA9IGRyYWluZWRPcHRpb247XG4gICAgICAgIHRoaXMuaXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNEaXJ0eSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhdXNlRGVwdGhzID0ge307XG4gICAgICAgIHRoaXMudGltZW91dElkID0gMDtcbiAgICB9XG4gICAgcmVxdWVzdChkZWxheSkge1xuICAgICAgICB0aGlzLmlzRGlydHkgPSB0cnVlO1xuICAgICAgICBpZiAoIXRoaXMuaXNQYXVzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgICAgICAgICAgIGlmIChkZWxheSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50cnlEcmFpbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lb3V0SWQgPSBzZXRUaW1lb3V0KC8vIE5PVCBPUFRJTUFMISBUT0RPOiBsb29rIGF0IGRlYm91bmNlXG4gICAgICAgICAgICAgICAgdGhpcy50cnlEcmFpbi5iaW5kKHRoaXMpLCBkZWxheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcGF1c2Uoc2NvcGUgPSAnJykge1xuICAgICAgICBsZXQgeyBwYXVzZURlcHRocyB9ID0gdGhpcztcbiAgICAgICAgcGF1c2VEZXB0aHNbc2NvcGVdID0gKHBhdXNlRGVwdGhzW3Njb3BlXSB8fCAwKSArIDE7XG4gICAgICAgIHRoaXMuY2xlYXJUaW1lb3V0KCk7XG4gICAgfVxuICAgIHJlc3VtZShzY29wZSA9ICcnLCBmb3JjZSkge1xuICAgICAgICBsZXQgeyBwYXVzZURlcHRocyB9ID0gdGhpcztcbiAgICAgICAgaWYgKHNjb3BlIGluIHBhdXNlRGVwdGhzKSB7XG4gICAgICAgICAgICBpZiAoZm9yY2UpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgcGF1c2VEZXB0aHNbc2NvcGVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcGF1c2VEZXB0aHNbc2NvcGVdIC09IDE7XG4gICAgICAgICAgICAgICAgbGV0IGRlcHRoID0gcGF1c2VEZXB0aHNbc2NvcGVdO1xuICAgICAgICAgICAgICAgIGlmIChkZXB0aCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBwYXVzZURlcHRoc1tzY29wZV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy50cnlEcmFpbigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlzUGF1c2VkKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5wYXVzZURlcHRocykubGVuZ3RoO1xuICAgIH1cbiAgICB0cnlEcmFpbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzUnVubmluZyAmJiAhdGhpcy5pc1BhdXNlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmlzUnVubmluZyA9IHRydWU7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5pc0RpcnR5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmFpbmVkKCk7IC8vIG1pZ2h0IHNldCBpc0RpcnR5IHRvIHRydWUgYWdhaW5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY2xlYXIoKSB7XG4gICAgICAgIHRoaXMuY2xlYXJUaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuaXNEaXJ0eSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhdXNlRGVwdGhzID0ge307XG4gICAgfVxuICAgIGNsZWFyVGltZW91dCgpIHtcbiAgICAgICAgaWYgKHRoaXMudGltZW91dElkKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0SWQpO1xuICAgICAgICAgICAgdGhpcy50aW1lb3V0SWQgPSAwO1xuICAgICAgICB9XG4gICAgfVxuICAgIGRyYWluZWQoKSB7XG4gICAgICAgIGlmICh0aGlzLmRyYWluZWRPcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZHJhaW5lZE9wdGlvbigpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVFbGVtZW50KGVsKSB7XG4gICAgaWYgKGVsLnBhcmVudE5vZGUpIHtcbiAgICAgICAgZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlbCk7XG4gICAgfVxufVxuLy8gUXVlcnlpbmdcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGVsZW1lbnRDbG9zZXN0KGVsLCBzZWxlY3Rvcikge1xuICAgIGlmIChlbC5jbG9zZXN0KSB7XG4gICAgICAgIHJldHVybiBlbC5jbG9zZXN0KHNlbGVjdG9yKTtcbiAgICAgICAgLy8gcmVhbGx5IGJhZCBmYWxsYmFjayBmb3IgSUVcbiAgICAgICAgLy8gZnJvbSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRWxlbWVudC9jbG9zZXN0XG4gICAgfVxuICAgIGlmICghZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNvbnRhaW5zKGVsKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZG8ge1xuICAgICAgICBpZiAoZWxlbWVudE1hdGNoZXMoZWwsIHNlbGVjdG9yKSkge1xuICAgICAgICAgICAgcmV0dXJuIGVsO1xuICAgICAgICB9XG4gICAgICAgIGVsID0gKGVsLnBhcmVudEVsZW1lbnQgfHwgZWwucGFyZW50Tm9kZSk7XG4gICAgfSB3aGlsZSAoZWwgIT09IG51bGwgJiYgZWwubm9kZVR5cGUgPT09IDEpO1xuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXMoZWwsIHNlbGVjdG9yKSB7XG4gICAgbGV0IG1ldGhvZCA9IGVsLm1hdGNoZXMgfHwgZWwubWF0Y2hlc1NlbGVjdG9yIHx8IGVsLm1zTWF0Y2hlc1NlbGVjdG9yO1xuICAgIHJldHVybiBtZXRob2QuY2FsbChlbCwgc2VsZWN0b3IpO1xufVxuLy8gYWNjZXB0cyBtdWx0aXBsZSBzdWJqZWN0IGVsc1xuLy8gcmV0dXJucyBhIHJlYWwgYXJyYXkuIGdvb2QgZm9yIG1ldGhvZHMgbGlrZSBmb3JFYWNoXG4vLyBUT0RPOiBhY2NlcHQgdGhlIGRvY3VtZW50XG5mdW5jdGlvbiBmaW5kRWxlbWVudHMoY29udGFpbmVyLCBzZWxlY3Rvcikge1xuICAgIGxldCBjb250YWluZXJzID0gY29udGFpbmVyIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQgPyBbY29udGFpbmVyXSA6IGNvbnRhaW5lcjtcbiAgICBsZXQgYWxsTWF0Y2hlcyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29udGFpbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBsZXQgbWF0Y2hlcyA9IGNvbnRhaW5lcnNbaV0ucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbWF0Y2hlcy5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgICAgYWxsTWF0Y2hlcy5wdXNoKG1hdGNoZXNbal0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhbGxNYXRjaGVzO1xufVxuLy8gYWNjZXB0cyBtdWx0aXBsZSBzdWJqZWN0IGVsc1xuLy8gb25seSBxdWVyaWVzIGRpcmVjdCBjaGlsZCBlbGVtZW50cyAvLyBUT0RPOiByZW5hbWUgdG8gZmluZERpcmVjdENoaWxkcmVuIVxuZnVuY3Rpb24gZmluZERpcmVjdENoaWxkcmVuKHBhcmVudCwgc2VsZWN0b3IpIHtcbiAgICBsZXQgcGFyZW50cyA9IHBhcmVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ID8gW3BhcmVudF0gOiBwYXJlbnQ7XG4gICAgbGV0IGFsbE1hdGNoZXMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmVudHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgbGV0IGNoaWxkTm9kZXMgPSBwYXJlbnRzW2ldLmNoaWxkcmVuOyAvLyBvbmx5IGV2ZXIgZWxlbWVudHNcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjaGlsZE5vZGVzLmxlbmd0aDsgaiArPSAxKSB7XG4gICAgICAgICAgICBsZXQgY2hpbGROb2RlID0gY2hpbGROb2Rlc1tqXTtcbiAgICAgICAgICAgIGlmICghc2VsZWN0b3IgfHwgZWxlbWVudE1hdGNoZXMoY2hpbGROb2RlLCBzZWxlY3RvcikpIHtcbiAgICAgICAgICAgICAgICBhbGxNYXRjaGVzLnB1c2goY2hpbGROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYWxsTWF0Y2hlcztcbn1cbi8vIFN0eWxlXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5jb25zdCBQSVhFTF9QUk9QX1JFID0gLyh0b3B8bGVmdHxyaWdodHxib3R0b218d2lkdGh8aGVpZ2h0KSQvaTtcbmZ1bmN0aW9uIGFwcGx5U3R5bGUoZWwsIHByb3BzKSB7XG4gICAgZm9yIChsZXQgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgYXBwbHlTdHlsZVByb3AoZWwsIHByb3BOYW1lLCBwcm9wc1twcm9wTmFtZV0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFwcGx5U3R5bGVQcm9wKGVsLCBuYW1lLCB2YWwpIHtcbiAgICBpZiAodmFsID09IG51bGwpIHtcbiAgICAgICAgZWwuc3R5bGVbbmFtZV0gPSAnJztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicgJiYgUElYRUxfUFJPUF9SRS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gYCR7dmFsfXB4YDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gdmFsO1xuICAgIH1cbn1cbi8vIEV2ZW50IEhhbmRsaW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBpZiBpbnRlcmNlcHRpbmcgYnViYmxlZCBldmVudHMgYXQgdGhlIGRvY3VtZW50L3dpbmRvdy9ib2R5IGxldmVsLFxuLy8gYW5kIHdhbnQgdG8gc2VlIG9yaWdpbmF0aW5nIGVsZW1lbnQgKHRoZSAndGFyZ2V0JyksIHVzZSB0aGlzIHV0aWwgaW5zdGVhZFxuLy8gb2YgYGV2LnRhcmdldGAgYmVjYXVzZSBpdCBnb2VzIHdpdGhpbiB3ZWItY29tcG9uZW50IGJvdW5kYXJpZXMuXG5mdW5jdGlvbiBnZXRFdmVudFRhcmdldFZpYVJvb3QoZXYpIHtcbiAgICB2YXIgX2EsIF9iO1xuICAgIHJldHVybiAoX2IgPSAoX2EgPSBldi5jb21wb3NlZFBhdGgpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jYWxsKGV2KVswXSkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogZXYudGFyZ2V0O1xufVxuLy8gVW5pcXVlIElEIGZvciBET00gYXR0cmlidXRlXG5sZXQgZ3VpZCQxID0gMDtcbmZ1bmN0aW9uIGdldFVuaXF1ZURvbUlkKCkge1xuICAgIGd1aWQkMSArPSAxO1xuICAgIHJldHVybiAnZmMtZG9tLScgKyBndWlkJDE7XG59XG5cbi8vIFN0b3BzIGEgbW91c2UvdG91Y2ggZXZlbnQgZnJvbSBkb2luZyBpdCdzIG5hdGl2ZSBicm93c2VyIGFjdGlvblxuZnVuY3Rpb24gcHJldmVudERlZmF1bHQoZXYpIHtcbiAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xufVxuLy8gRXZlbnQgRGVsZWdhdGlvblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYnVpbGREZWxlZ2F0aW9uSGFuZGxlcihzZWxlY3RvciwgaGFuZGxlcikge1xuICAgIHJldHVybiAoZXYpID0+IHtcbiAgICAgICAgbGV0IG1hdGNoZWRDaGlsZCA9IGVsZW1lbnRDbG9zZXN0KGV2LnRhcmdldCwgc2VsZWN0b3IpO1xuICAgICAgICBpZiAobWF0Y2hlZENoaWxkKSB7XG4gICAgICAgICAgICBoYW5kbGVyLmNhbGwobWF0Y2hlZENoaWxkLCBldiwgbWF0Y2hlZENoaWxkKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5mdW5jdGlvbiBsaXN0ZW5CeVNlbGVjdG9yKGNvbnRhaW5lciwgZXZlbnRUeXBlLCBzZWxlY3RvciwgaGFuZGxlcikge1xuICAgIGxldCBhdHRhY2hlZEhhbmRsZXIgPSBidWlsZERlbGVnYXRpb25IYW5kbGVyKHNlbGVjdG9yLCBoYW5kbGVyKTtcbiAgICBjb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGF0dGFjaGVkSGFuZGxlcik7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgY29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBhdHRhY2hlZEhhbmRsZXIpO1xuICAgIH07XG59XG5mdW5jdGlvbiBsaXN0ZW5Ub0hvdmVyQnlTZWxlY3Rvcihjb250YWluZXIsIHNlbGVjdG9yLCBvbk1vdXNlRW50ZXIsIG9uTW91c2VMZWF2ZSkge1xuICAgIGxldCBjdXJyZW50TWF0Y2hlZENoaWxkO1xuICAgIHJldHVybiBsaXN0ZW5CeVNlbGVjdG9yKGNvbnRhaW5lciwgJ21vdXNlb3ZlcicsIHNlbGVjdG9yLCAobW91c2VPdmVyRXYsIG1hdGNoZWRDaGlsZCkgPT4ge1xuICAgICAgICBpZiAobWF0Y2hlZENoaWxkICE9PSBjdXJyZW50TWF0Y2hlZENoaWxkKSB7XG4gICAgICAgICAgICBjdXJyZW50TWF0Y2hlZENoaWxkID0gbWF0Y2hlZENoaWxkO1xuICAgICAgICAgICAgb25Nb3VzZUVudGVyKG1vdXNlT3ZlckV2LCBtYXRjaGVkQ2hpbGQpO1xuICAgICAgICAgICAgbGV0IHJlYWxPbk1vdXNlTGVhdmUgPSAobW91c2VMZWF2ZUV2KSA9PiB7XG4gICAgICAgICAgICAgICAgY3VycmVudE1hdGNoZWRDaGlsZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgb25Nb3VzZUxlYXZlKG1vdXNlTGVhdmVFdiwgbWF0Y2hlZENoaWxkKTtcbiAgICAgICAgICAgICAgICBtYXRjaGVkQ2hpbGQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIHJlYWxPbk1vdXNlTGVhdmUpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8vIGxpc3RlbiB0byB0aGUgbmV4dCBtb3VzZWxlYXZlLCBhbmQgdGhlbiB1bmF0dGFjaFxuICAgICAgICAgICAgbWF0Y2hlZENoaWxkLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCByZWFsT25Nb3VzZUxlYXZlKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLy8gQW5pbWF0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5jb25zdCB0cmFuc2l0aW9uRXZlbnROYW1lcyA9IFtcbiAgICAnd2Via2l0VHJhbnNpdGlvbkVuZCcsXG4gICAgJ290cmFuc2l0aW9uZW5kJyxcbiAgICAnb1RyYW5zaXRpb25FbmQnLFxuICAgICdtc1RyYW5zaXRpb25FbmQnLFxuICAgICd0cmFuc2l0aW9uZW5kJyxcbl07XG4vLyB0cmlnZ2VyZWQgb25seSB3aGVuIHRoZSBuZXh0IHNpbmdsZSBzdWJzZXF1ZW50IHRyYW5zaXRpb24gZmluaXNoZXNcbmZ1bmN0aW9uIHdoZW5UcmFuc2l0aW9uRG9uZShlbCwgY2FsbGJhY2spIHtcbiAgICBsZXQgcmVhbENhbGxiYWNrID0gKGV2KSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKGV2KTtcbiAgICAgICAgdHJhbnNpdGlvbkV2ZW50TmFtZXMuZm9yRWFjaCgoZXZlbnROYW1lKSA9PiB7XG4gICAgICAgICAgICBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgcmVhbENhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICB0cmFuc2l0aW9uRXZlbnROYW1lcy5mb3JFYWNoKChldmVudE5hbWUpID0+IHtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIHJlYWxDYWxsYmFjayk7IC8vIGNyb3NzLWJyb3dzZXIgd2F5IHRvIGRldGVybWluZSB3aGVuIHRoZSB0cmFuc2l0aW9uIGZpbmlzaGVzXG4gICAgfSk7XG59XG4vLyBBUklBIHdvcmthcm91bmRzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBjcmVhdGVBcmlhQ2xpY2tBdHRycyhoYW5kbGVyKSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oeyBvbkNsaWNrOiBoYW5kbGVyIH0sIGNyZWF0ZUFyaWFLZXlib2FyZEF0dHJzKGhhbmRsZXIpKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUFyaWFLZXlib2FyZEF0dHJzKGhhbmRsZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB0YWJJbmRleDogMCxcbiAgICAgICAgb25LZXlEb3duKGV2KSB7XG4gICAgICAgICAgICBpZiAoZXYua2V5ID09PSAnRW50ZXInIHx8IGV2LmtleSA9PT0gJyAnKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlcihldik7XG4gICAgICAgICAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTsgLy8gaWYgc3BhY2UsIGRvbid0IHNjcm9sbCBkb3duIHBhZ2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICB9O1xufVxuXG5sZXQgZ3VpZE51bWJlciA9IDA7XG5mdW5jdGlvbiBndWlkKCkge1xuICAgIGd1aWROdW1iZXIgKz0gMTtcbiAgICByZXR1cm4gU3RyaW5nKGd1aWROdW1iZXIpO1xufVxuLyogRnVsbENhbGVuZGFyLXNwZWNpZmljIERPTSBVdGlsaXRpZXNcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLy8gTWFrZSB0aGUgbW91c2UgY3Vyc29yIGV4cHJlc3MgdGhhdCBhbiBldmVudCBpcyBub3QgYWxsb3dlZCBpbiB0aGUgY3VycmVudCBhcmVhXG5mdW5jdGlvbiBkaXNhYmxlQ3Vyc29yKCkge1xuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgnZmMtbm90LWFsbG93ZWQnKTtcbn1cbi8vIFJldHVybnMgdGhlIG1vdXNlIGN1cnNvciB0byBpdHMgb3JpZ2luYWwgbG9va1xuZnVuY3Rpb24gZW5hYmxlQ3Vyc29yKCkge1xuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnZmMtbm90LWFsbG93ZWQnKTtcbn1cbi8qIFNlbGVjdGlvblxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5mdW5jdGlvbiBwcmV2ZW50U2VsZWN0aW9uKGVsKSB7XG4gICAgZWwuc3R5bGUudXNlclNlbGVjdCA9ICdub25lJztcbiAgICBlbC5zdHlsZS53ZWJraXRVc2VyU2VsZWN0ID0gJ25vbmUnO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xufVxuZnVuY3Rpb24gYWxsb3dTZWxlY3Rpb24oZWwpIHtcbiAgICBlbC5zdHlsZS51c2VyU2VsZWN0ID0gJyc7XG4gICAgZWwuc3R5bGUud2Via2l0VXNlclNlbGVjdCA9ICcnO1xuICAgIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xufVxuLyogQ29udGV4dCBNZW51XG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIHByZXZlbnRDb250ZXh0TWVudShlbCkge1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgcHJldmVudERlZmF1bHQpO1xufVxuZnVuY3Rpb24gYWxsb3dDb250ZXh0TWVudShlbCkge1xuICAgIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgcHJldmVudERlZmF1bHQpO1xufVxuZnVuY3Rpb24gcGFyc2VGaWVsZFNwZWNzKGlucHV0KSB7XG4gICAgbGV0IHNwZWNzID0gW107XG4gICAgbGV0IHRva2VucyA9IFtdO1xuICAgIGxldCBpO1xuICAgIGxldCB0b2tlbjtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICB0b2tlbnMgPSBpbnB1dC5zcGxpdCgvXFxzKixcXHMqLyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0b2tlbnMgPSBbaW5wdXRdO1xuICAgIH1cbiAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICB0b2tlbnMgPSBpbnB1dDtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHNwZWNzLnB1c2godG9rZW4uY2hhckF0KDApID09PSAnLScgP1xuICAgICAgICAgICAgICAgIHsgZmllbGQ6IHRva2VuLnN1YnN0cmluZygxKSwgb3JkZXI6IC0xIH0gOlxuICAgICAgICAgICAgICAgIHsgZmllbGQ6IHRva2VuLCBvcmRlcjogMSB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdG9rZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHNwZWNzLnB1c2goeyBmdW5jOiB0b2tlbiB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3BlY3M7XG59XG5mdW5jdGlvbiBjb21wYXJlQnlGaWVsZFNwZWNzKG9iajAsIG9iajEsIGZpZWxkU3BlY3MpIHtcbiAgICBsZXQgaTtcbiAgICBsZXQgY21wO1xuICAgIGZvciAoaSA9IDA7IGkgPCBmaWVsZFNwZWNzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNtcCA9IGNvbXBhcmVCeUZpZWxkU3BlYyhvYmowLCBvYmoxLCBmaWVsZFNwZWNzW2ldKTtcbiAgICAgICAgaWYgKGNtcCkge1xuICAgICAgICAgICAgcmV0dXJuIGNtcDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIGNvbXBhcmVCeUZpZWxkU3BlYyhvYmowLCBvYmoxLCBmaWVsZFNwZWMpIHtcbiAgICBpZiAoZmllbGRTcGVjLmZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIGZpZWxkU3BlYy5mdW5jKG9iajAsIG9iajEpO1xuICAgIH1cbiAgICByZXR1cm4gZmxleGlibGVDb21wYXJlKG9iajBbZmllbGRTcGVjLmZpZWxkXSwgb2JqMVtmaWVsZFNwZWMuZmllbGRdKVxuICAgICAgICAqIChmaWVsZFNwZWMub3JkZXIgfHwgMSk7XG59XG5mdW5jdGlvbiBmbGV4aWJsZUNvbXBhcmUoYSwgYikge1xuICAgIGlmICghYSAmJiAhYikge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKGIgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmIChhID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoYSkubG9jYWxlQ29tcGFyZShTdHJpbmcoYikpO1xuICAgIH1cbiAgICByZXR1cm4gYSAtIGI7XG59XG4vKiBTdHJpbmcgVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIHBhZFN0YXJ0KHZhbCwgbGVuKSB7XG4gICAgbGV0IHMgPSBTdHJpbmcodmFsKTtcbiAgICByZXR1cm4gJzAwMCcuc3Vic3RyKDAsIGxlbiAtIHMubGVuZ3RoKSArIHM7XG59XG5mdW5jdGlvbiBmb3JtYXRXaXRoT3JkaW5hbHMoZm9ybWF0dGVyLCBhcmdzLCBmYWxsYmFja1RleHQpIHtcbiAgICBpZiAodHlwZW9mIGZvcm1hdHRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gZm9ybWF0dGVyKC4uLmFyZ3MpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGZvcm1hdHRlciA9PT0gJ3N0cmluZycpIHsgLy8gbm9uLWJsYW5rIHN0cmluZ1xuICAgICAgICByZXR1cm4gYXJncy5yZWR1Y2UoKHN0ciwgYXJnLCBpbmRleCkgPT4gKHN0ci5yZXBsYWNlKCckJyArIGluZGV4LCBhcmcgfHwgJycpKSwgZm9ybWF0dGVyKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbGxiYWNrVGV4dDtcbn1cbi8qIE51bWJlciBVdGlsaXRpZXNcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gY29tcGFyZU51bWJlcnMoYSwgYikge1xuICAgIHJldHVybiBhIC0gYjtcbn1cbmZ1bmN0aW9uIGlzSW50KG4pIHtcbiAgICByZXR1cm4gbiAlIDEgPT09IDA7XG59XG4vKiBGQy1zcGVjaWZpYyBET00gZGltZW5zaW9uIHN0dWZmXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIGNvbXB1dGVTbWFsbGVzdENlbGxXaWR0aChjZWxsRWwpIHtcbiAgICBsZXQgYWxsV2lkdGhFbCA9IGNlbGxFbC5xdWVyeVNlbGVjdG9yKCcuZmMtc2Nyb2xsZ3JpZC1zaHJpbmstZnJhbWUnKTtcbiAgICBsZXQgY29udGVudFdpZHRoRWwgPSBjZWxsRWwucXVlcnlTZWxlY3RvcignLmZjLXNjcm9sbGdyaWQtc2hyaW5rLWN1c2hpb24nKTtcbiAgICBpZiAoIWFsbFdpZHRoRWwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCduZWVkcyBmYy1zY3JvbGxncmlkLXNocmluay1mcmFtZSBjbGFzc05hbWUnKTsgLy8gVE9ETzogdXNlIGNvbnN0XG4gICAgfVxuICAgIGlmICghY29udGVudFdpZHRoRWwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCduZWVkcyBmYy1zY3JvbGxncmlkLXNocmluay1jdXNoaW9uIGNsYXNzTmFtZScpO1xuICAgIH1cbiAgICByZXR1cm4gY2VsbEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC0gYWxsV2lkdGhFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCArIC8vIHRoZSBjZWxsIHBhZGRpbmcrYm9yZGVyXG4gICAgICAgIGNvbnRlbnRXaWR0aEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoO1xufVxuXG5jb25zdCBJTlRFUk5BTF9VTklUUyA9IFsneWVhcnMnLCAnbW9udGhzJywgJ2RheXMnLCAnbWlsbGlzZWNvbmRzJ107XG5jb25zdCBQQVJTRV9SRSA9IC9eKC0/KSg/OihcXGQrKVxcLik/KFxcZCspOihcXGRcXGQpKD86OihcXGRcXGQpKD86XFwuKFxcZFxcZFxcZCkpPyk/Lztcbi8vIFBhcnNpbmcgYW5kIENyZWF0aW9uXG5mdW5jdGlvbiBjcmVhdGVEdXJhdGlvbihpbnB1dCwgdW5pdCkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVN0cmluZyhpbnB1dCk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gcGFyc2VPYmplY3QoaW5wdXQpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gcGFyc2VPYmplY3QoeyBbdW5pdCB8fCAnbWlsbGlzZWNvbmRzJ106IGlucHV0IH0pO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIHBhcnNlU3RyaW5nKHMpIHtcbiAgICBsZXQgbSA9IFBBUlNFX1JFLmV4ZWMocyk7XG4gICAgaWYgKG0pIHtcbiAgICAgICAgbGV0IHNpZ24gPSBtWzFdID8gLTEgOiAxO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeWVhcnM6IDAsXG4gICAgICAgICAgICBtb250aHM6IDAsXG4gICAgICAgICAgICBkYXlzOiBzaWduICogKG1bMl0gPyBwYXJzZUludChtWzJdLCAxMCkgOiAwKSxcbiAgICAgICAgICAgIG1pbGxpc2Vjb25kczogc2lnbiAqICgobVszXSA/IHBhcnNlSW50KG1bM10sIDEwKSA6IDApICogNjAgKiA2MCAqIDEwMDAgKyAvLyBob3Vyc1xuICAgICAgICAgICAgICAgIChtWzRdID8gcGFyc2VJbnQobVs0XSwgMTApIDogMCkgKiA2MCAqIDEwMDAgKyAvLyBtaW51dGVzXG4gICAgICAgICAgICAgICAgKG1bNV0gPyBwYXJzZUludChtWzVdLCAxMCkgOiAwKSAqIDEwMDAgKyAvLyBzZWNvbmRzXG4gICAgICAgICAgICAgICAgKG1bNl0gPyBwYXJzZUludChtWzZdLCAxMCkgOiAwKSAvLyBtc1xuICAgICAgICAgICAgKSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBwYXJzZU9iamVjdChvYmopIHtcbiAgICBsZXQgZHVyYXRpb24gPSB7XG4gICAgICAgIHllYXJzOiBvYmoueWVhcnMgfHwgb2JqLnllYXIgfHwgMCxcbiAgICAgICAgbW9udGhzOiBvYmoubW9udGhzIHx8IG9iai5tb250aCB8fCAwLFxuICAgICAgICBkYXlzOiBvYmouZGF5cyB8fCBvYmouZGF5IHx8IDAsXG4gICAgICAgIG1pbGxpc2Vjb25kczogKG9iai5ob3VycyB8fCBvYmouaG91ciB8fCAwKSAqIDYwICogNjAgKiAxMDAwICsgLy8gaG91cnNcbiAgICAgICAgICAgIChvYmoubWludXRlcyB8fCBvYmoubWludXRlIHx8IDApICogNjAgKiAxMDAwICsgLy8gbWludXRlc1xuICAgICAgICAgICAgKG9iai5zZWNvbmRzIHx8IG9iai5zZWNvbmQgfHwgMCkgKiAxMDAwICsgLy8gc2Vjb25kc1xuICAgICAgICAgICAgKG9iai5taWxsaXNlY29uZHMgfHwgb2JqLm1pbGxpc2Vjb25kIHx8IG9iai5tcyB8fCAwKSwgLy8gbXNcbiAgICB9O1xuICAgIGxldCB3ZWVrcyA9IG9iai53ZWVrcyB8fCBvYmoud2VlaztcbiAgICBpZiAod2Vla3MpIHtcbiAgICAgICAgZHVyYXRpb24uZGF5cyArPSB3ZWVrcyAqIDc7XG4gICAgICAgIGR1cmF0aW9uLnNwZWNpZmllZFdlZWtzID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGR1cmF0aW9uO1xufVxuLy8gRXF1YWxpdHlcbmZ1bmN0aW9uIGR1cmF0aW9uc0VxdWFsKGQwLCBkMSkge1xuICAgIHJldHVybiBkMC55ZWFycyA9PT0gZDEueWVhcnMgJiZcbiAgICAgICAgZDAubW9udGhzID09PSBkMS5tb250aHMgJiZcbiAgICAgICAgZDAuZGF5cyA9PT0gZDEuZGF5cyAmJlxuICAgICAgICBkMC5taWxsaXNlY29uZHMgPT09IGQxLm1pbGxpc2Vjb25kcztcbn1cbmZ1bmN0aW9uIGFzQ2xlYW5EYXlzKGR1cikge1xuICAgIGlmICghZHVyLnllYXJzICYmICFkdXIubW9udGhzICYmICFkdXIubWlsbGlzZWNvbmRzKSB7XG4gICAgICAgIHJldHVybiBkdXIuZGF5cztcbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG4vLyBTaW1wbGUgTWF0aFxuZnVuY3Rpb24gYWRkRHVyYXRpb25zKGQwLCBkMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHllYXJzOiBkMC55ZWFycyArIGQxLnllYXJzLFxuICAgICAgICBtb250aHM6IGQwLm1vbnRocyArIGQxLm1vbnRocyxcbiAgICAgICAgZGF5czogZDAuZGF5cyArIGQxLmRheXMsXG4gICAgICAgIG1pbGxpc2Vjb25kczogZDAubWlsbGlzZWNvbmRzICsgZDEubWlsbGlzZWNvbmRzLFxuICAgIH07XG59XG5mdW5jdGlvbiBzdWJ0cmFjdER1cmF0aW9ucyhkMSwgZDApIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZDEueWVhcnMgLSBkMC55ZWFycyxcbiAgICAgICAgbW9udGhzOiBkMS5tb250aHMgLSBkMC5tb250aHMsXG4gICAgICAgIGRheXM6IGQxLmRheXMgLSBkMC5kYXlzLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQxLm1pbGxpc2Vjb25kcyAtIGQwLm1pbGxpc2Vjb25kcyxcbiAgICB9O1xufVxuZnVuY3Rpb24gbXVsdGlwbHlEdXJhdGlvbihkLCBuKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IGQueWVhcnMgKiBuLFxuICAgICAgICBtb250aHM6IGQubW9udGhzICogbixcbiAgICAgICAgZGF5czogZC5kYXlzICogbixcbiAgICAgICAgbWlsbGlzZWNvbmRzOiBkLm1pbGxpc2Vjb25kcyAqIG4sXG4gICAgfTtcbn1cbi8vIENvbnZlcnNpb25zXG4vLyBcIlJvdWdoXCIgYmVjYXVzZSB0aGV5IGFyZSBiYXNlZCBvbiBhdmVyYWdlLWNhc2UgR3JlZ29yaWFuIG1vbnRocy95ZWFyc1xuZnVuY3Rpb24gYXNSb3VnaFllYXJzKGR1cikge1xuICAgIHJldHVybiBhc1JvdWdoRGF5cyhkdXIpIC8gMzY1O1xufVxuZnVuY3Rpb24gYXNSb3VnaE1vbnRocyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaERheXMoZHVyKSAvIDMwO1xufVxuZnVuY3Rpb24gYXNSb3VnaERheXMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hNcyhkdXIpIC8gODY0ZTU7XG59XG5mdW5jdGlvbiBhc1JvdWdoTWludXRlcyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaE1zKGR1cikgLyAoMTAwMCAqIDYwKTtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hTZWNvbmRzKGR1cikge1xuICAgIHJldHVybiBhc1JvdWdoTXMoZHVyKSAvIDEwMDA7XG59XG5mdW5jdGlvbiBhc1JvdWdoTXMoZHVyKSB7XG4gICAgcmV0dXJuIGR1ci55ZWFycyAqICgzNjUgKiA4NjRlNSkgK1xuICAgICAgICBkdXIubW9udGhzICogKDMwICogODY0ZTUpICtcbiAgICAgICAgZHVyLmRheXMgKiA4NjRlNSArXG4gICAgICAgIGR1ci5taWxsaXNlY29uZHM7XG59XG4vLyBBZHZhbmNlZCBNYXRoXG5mdW5jdGlvbiB3aG9sZURpdmlkZUR1cmF0aW9ucyhudW1lcmF0b3IsIGRlbm9taW5hdG9yKSB7XG4gICAgbGV0IHJlcyA9IG51bGw7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBJTlRFUk5BTF9VTklUUy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBsZXQgdW5pdCA9IElOVEVSTkFMX1VOSVRTW2ldO1xuICAgICAgICBpZiAoZGVub21pbmF0b3JbdW5pdF0pIHtcbiAgICAgICAgICAgIGxldCBsb2NhbFJlcyA9IG51bWVyYXRvclt1bml0XSAvIGRlbm9taW5hdG9yW3VuaXRdO1xuICAgICAgICAgICAgaWYgKCFpc0ludChsb2NhbFJlcykgfHwgKHJlcyAhPT0gbnVsbCAmJiByZXMgIT09IGxvY2FsUmVzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzID0gbG9jYWxSZXM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobnVtZXJhdG9yW3VuaXRdKSB7XG4gICAgICAgICAgICAvLyBuZWVkcyB0byBkaXZpZGUgYnkgc29tZXRoaW5nIGJ1dCBjYW4ndCFcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZHVyKSB7XG4gICAgbGV0IG1zID0gZHVyLm1pbGxpc2Vjb25kcztcbiAgICBpZiAobXMpIHtcbiAgICAgICAgaWYgKG1zICUgMTAwMCAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IG1zIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zICUgKDEwMDAgKiA2MCkgIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdzZWNvbmQnLCB2YWx1ZTogbXMgLyAxMDAwIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zICUgKDEwMDAgKiA2MCAqIDYwKSAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbnV0ZScsIHZhbHVlOiBtcyAvICgxMDAwICogNjApIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnaG91cicsIHZhbHVlOiBtcyAvICgxMDAwICogNjAgKiA2MCkgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZHVyLmRheXMpIHtcbiAgICAgICAgaWYgKGR1ci5zcGVjaWZpZWRXZWVrcyAmJiBkdXIuZGF5cyAlIDcgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICd3ZWVrJywgdmFsdWU6IGR1ci5kYXlzIC8gNyB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHVuaXQ6ICdkYXknLCB2YWx1ZTogZHVyLmRheXMgfTtcbiAgICB9XG4gICAgaWYgKGR1ci5tb250aHMpIHtcbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21vbnRoJywgdmFsdWU6IGR1ci5tb250aHMgfTtcbiAgICB9XG4gICAgaWYgKGR1ci55ZWFycykge1xuICAgICAgICByZXR1cm4geyB1bml0OiAneWVhcicsIHZhbHVlOiBkdXIueWVhcnMgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IDAgfTtcbn1cblxuLy8gVE9ETzogbmV3IHV0aWwgYXJyYXlpZnk/XG5mdW5jdGlvbiByZW1vdmVFeGFjdChhcnJheSwgZXhhY3RWYWwpIHtcbiAgICBsZXQgcmVtb3ZlQ250ID0gMDtcbiAgICBsZXQgaSA9IDA7XG4gICAgd2hpbGUgKGkgPCBhcnJheS5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGFycmF5W2ldID09PSBleGFjdFZhbCkge1xuICAgICAgICAgICAgYXJyYXkuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgcmVtb3ZlQ250ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpICs9IDE7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlbW92ZUNudDtcbn1cbmZ1bmN0aW9uIGlzQXJyYXlzRXF1YWwoYTAsIGExLCBlcXVhbGl0eUZ1bmMpIHtcbiAgICBpZiAoYTAgPT09IGExKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBsZXQgbGVuID0gYTAubGVuZ3RoO1xuICAgIGxldCBpO1xuICAgIGlmIChsZW4gIT09IGExLmxlbmd0aCkgeyAvLyBub3QgYXJyYXk/IG9yIG5vdCBzYW1lIGxlbmd0aD9cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgaWYgKCEoZXF1YWxpdHlGdW5jID8gZXF1YWxpdHlGdW5jKGEwW2ldLCBhMVtpXSkgOiBhMFtpXSA9PT0gYTFbaV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmNvbnN0IERBWV9JRFMgPSBbJ3N1bicsICdtb24nLCAndHVlJywgJ3dlZCcsICd0aHUnLCAnZnJpJywgJ3NhdCddO1xuLy8gQWRkaW5nXG5mdW5jdGlvbiBhZGRXZWVrcyhtLCBuKSB7XG4gICAgbGV0IGEgPSBkYXRlVG9VdGNBcnJheShtKTtcbiAgICBhWzJdICs9IG4gKiA3O1xuICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShhKTtcbn1cbmZ1bmN0aW9uIGFkZERheXMobSwgbikge1xuICAgIGxldCBhID0gZGF0ZVRvVXRjQXJyYXkobSk7XG4gICAgYVsyXSArPSBuO1xuICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShhKTtcbn1cbmZ1bmN0aW9uIGFkZE1zKG0sIG4pIHtcbiAgICBsZXQgYSA9IGRhdGVUb1V0Y0FycmF5KG0pO1xuICAgIGFbNl0gKz0gbjtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoYSk7XG59XG4vLyBEaWZmaW5nIChhbGwgcmV0dXJuIGZsb2F0cylcbi8vIFRPRE86IHdoeSBub3QgdXNlIHJhbmdlcz9cbmZ1bmN0aW9uIGRpZmZXZWVrcyhtMCwgbTEpIHtcbiAgICByZXR1cm4gZGlmZkRheXMobTAsIG0xKSAvIDc7XG59XG5mdW5jdGlvbiBkaWZmRGF5cyhtMCwgbTEpIHtcbiAgICByZXR1cm4gKG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSkgLyAoMTAwMCAqIDYwICogNjAgKiAyNCk7XG59XG5mdW5jdGlvbiBkaWZmSG91cnMobTAsIG0xKSB7XG4gICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gKDEwMDAgKiA2MCAqIDYwKTtcbn1cbmZ1bmN0aW9uIGRpZmZNaW51dGVzKG0wLCBtMSkge1xuICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvICgxMDAwICogNjApO1xufVxuZnVuY3Rpb24gZGlmZlNlY29uZHMobTAsIG0xKSB7XG4gICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gMTAwMDtcbn1cbmZ1bmN0aW9uIGRpZmZEYXlBbmRUaW1lKG0wLCBtMSkge1xuICAgIGxldCBtMGRheSA9IHN0YXJ0T2ZEYXkobTApO1xuICAgIGxldCBtMWRheSA9IHN0YXJ0T2ZEYXkobTEpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHllYXJzOiAwLFxuICAgICAgICBtb250aHM6IDAsXG4gICAgICAgIGRheXM6IE1hdGgucm91bmQoZGlmZkRheXMobTBkYXksIG0xZGF5KSksXG4gICAgICAgIG1pbGxpc2Vjb25kczogKG0xLnZhbHVlT2YoKSAtIG0xZGF5LnZhbHVlT2YoKSkgLSAobTAudmFsdWVPZigpIC0gbTBkYXkudmFsdWVPZigpKSxcbiAgICB9O1xufVxuLy8gRGlmZmluZyBXaG9sZSBVbml0c1xuZnVuY3Rpb24gZGlmZldob2xlV2Vla3MobTAsIG0xKSB7XG4gICAgbGV0IGQgPSBkaWZmV2hvbGVEYXlzKG0wLCBtMSk7XG4gICAgaWYgKGQgIT09IG51bGwgJiYgZCAlIDcgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGQgLyA3O1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIGRpZmZXaG9sZURheXMobTAsIG0xKSB7XG4gICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKGRpZmZEYXlzKG0wLCBtMSkpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbi8vIFN0YXJ0LU9mXG5mdW5jdGlvbiBzdGFydE9mRGF5KG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgXSk7XG59XG5mdW5jdGlvbiBzdGFydE9mSG91cihtKSB7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKFtcbiAgICAgICAgbS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBtLmdldFVUQ01vbnRoKCksXG4gICAgICAgIG0uZ2V0VVRDRGF0ZSgpLFxuICAgICAgICBtLmdldFVUQ0hvdXJzKCksXG4gICAgXSk7XG59XG5mdW5jdGlvbiBzdGFydE9mTWludXRlKG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgICAgIG0uZ2V0VVRDSG91cnMoKSxcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCksXG4gICAgXSk7XG59XG5mdW5jdGlvbiBzdGFydE9mU2Vjb25kKG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgICAgIG0uZ2V0VVRDSG91cnMoKSxcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCksXG4gICAgICAgIG0uZ2V0VVRDU2Vjb25kcygpLFxuICAgIF0pO1xufVxuLy8gV2VlayBDb21wdXRhdGlvblxuZnVuY3Rpb24gd2Vla09mWWVhcihtYXJrZXIsIGRvdywgZG95KSB7XG4gICAgbGV0IHkgPSBtYXJrZXIuZ2V0VVRDRnVsbFllYXIoKTtcbiAgICBsZXQgdyA9IHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHksIGRvdywgZG95KTtcbiAgICBpZiAodyA8IDEpIHtcbiAgICAgICAgcmV0dXJuIHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHkgLSAxLCBkb3csIGRveSk7XG4gICAgfVxuICAgIGxldCBuZXh0VyA9IHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHkgKyAxLCBkb3csIGRveSk7XG4gICAgaWYgKG5leHRXID49IDEpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKHcsIG5leHRXKTtcbiAgICB9XG4gICAgcmV0dXJuIHc7XG59XG5mdW5jdGlvbiB3ZWVrT2ZHaXZlblllYXIobWFya2VyLCB5ZWFyLCBkb3csIGRveSkge1xuICAgIGxldCBmaXJzdFdlZWtTdGFydCA9IGFycmF5VG9VdGNEYXRlKFt5ZWFyLCAwLCAxICsgZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KV0pO1xuICAgIGxldCBkYXlTdGFydCA9IHN0YXJ0T2ZEYXkobWFya2VyKTtcbiAgICBsZXQgZGF5cyA9IE1hdGgucm91bmQoZGlmZkRheXMoZmlyc3RXZWVrU3RhcnQsIGRheVN0YXJ0KSk7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoZGF5cyAvIDcpICsgMTsgLy8gemVyby1pbmRleGVkXG59XG4vLyBzdGFydC1vZi1maXJzdC13ZWVrIC0gc3RhcnQtb2YteWVhclxuZnVuY3Rpb24gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSB7XG4gICAgLy8gZmlyc3Qtd2VlayBkYXkgLS0gd2hpY2ggamFudWFyeSBpcyBhbHdheXMgaW4gdGhlIGZpcnN0IHdlZWsgKDQgZm9yIGlzbywgMSBmb3Igb3RoZXIpXG4gICAgbGV0IGZ3ZCA9IDcgKyBkb3cgLSBkb3k7XG4gICAgLy8gZmlyc3Qtd2VlayBkYXkgbG9jYWwgd2Vla2RheSAtLSB3aGljaCBsb2NhbCB3ZWVrZGF5IGlzIGZ3ZFxuICAgIGxldCBmd2RsdyA9ICg3ICsgYXJyYXlUb1V0Y0RhdGUoW3llYXIsIDAsIGZ3ZF0pLmdldFVUQ0RheSgpIC0gZG93KSAlIDc7XG4gICAgcmV0dXJuIC1md2RsdyArIGZ3ZCAtIDE7XG59XG4vLyBBcnJheSBDb252ZXJzaW9uXG5mdW5jdGlvbiBkYXRlVG9Mb2NhbEFycmF5KGRhdGUpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgICAgIGRhdGUuZ2V0TW9udGgoKSxcbiAgICAgICAgZGF0ZS5nZXREYXRlKCksXG4gICAgICAgIGRhdGUuZ2V0SG91cnMoKSxcbiAgICAgICAgZGF0ZS5nZXRNaW51dGVzKCksXG4gICAgICAgIGRhdGUuZ2V0U2Vjb25kcygpLFxuICAgICAgICBkYXRlLmdldE1pbGxpc2Vjb25kcygpLFxuICAgIF07XG59XG5mdW5jdGlvbiBhcnJheVRvTG9jYWxEYXRlKGEpIHtcbiAgICByZXR1cm4gbmV3IERhdGUoYVswXSwgYVsxXSB8fCAwLCBhWzJdID09IG51bGwgPyAxIDogYVsyXSwgLy8gZGF5IG9mIG1vbnRoXG4gICAgYVszXSB8fCAwLCBhWzRdIHx8IDAsIGFbNV0gfHwgMCk7XG59XG5mdW5jdGlvbiBkYXRlVG9VdGNBcnJheShkYXRlKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgZGF0ZS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBkYXRlLmdldFVUQ01vbnRoKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDRGF0ZSgpLFxuICAgICAgICBkYXRlLmdldFVUQ0hvdXJzKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDTWludXRlcygpLFxuICAgICAgICBkYXRlLmdldFVUQ1NlY29uZHMoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENNaWxsaXNlY29uZHMoKSxcbiAgICBdO1xufVxuZnVuY3Rpb24gYXJyYXlUb1V0Y0RhdGUoYSkge1xuICAgIC8vIGFjY29yZGluZyB0byB3ZWIgc3RhbmRhcmRzIChhbmQgU2FmYXJpKSwgYSBtb250aCBpbmRleCBpcyByZXF1aXJlZC5cbiAgICAvLyBtYXNzYWdlIGlmIG9ubHkgZ2l2ZW4gYSB5ZWFyLlxuICAgIGlmIChhLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBhID0gYS5jb25jYXQoWzBdKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDKC4uLmEpKTtcbn1cbi8vIE90aGVyIFV0aWxzXG5mdW5jdGlvbiBpc1ZhbGlkRGF0ZShtKSB7XG4gICAgcmV0dXJuICFpc05hTihtLnZhbHVlT2YoKSk7XG59XG5mdW5jdGlvbiB0aW1lQXNNcyhtKSB7XG4gICAgcmV0dXJuIG0uZ2V0VVRDSG91cnMoKSAqIDEwMDAgKiA2MCAqIDYwICtcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCkgKiAxMDAwICogNjAgK1xuICAgICAgICBtLmdldFVUQ1NlY29uZHMoKSAqIDEwMDAgK1xuICAgICAgICBtLmdldFVUQ01pbGxpc2Vjb25kcygpO1xufVxuXG4vLyB0aW1lWm9uZU9mZnNldCBpcyBpbiBtaW51dGVzXG5mdW5jdGlvbiBidWlsZElzb1N0cmluZyhtYXJrZXIsIHRpbWVab25lT2Zmc2V0LCBzdHJpcFplcm9UaW1lID0gZmFsc2UpIHtcbiAgICBsZXQgcyA9IG1hcmtlci50b0lTT1N0cmluZygpO1xuICAgIHMgPSBzLnJlcGxhY2UoJy4wMDAnLCAnJyk7XG4gICAgaWYgKHN0cmlwWmVyb1RpbWUpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZSgnVDAwOjAwOjAwWicsICcnKTtcbiAgICB9XG4gICAgaWYgKHMubGVuZ3RoID4gMTApIHsgLy8gdGltZSBwYXJ0IHdhc24ndCBzdHJpcHBlZCwgY2FuIGFkZCB0aW1lem9uZSBpbmZvXG4gICAgICAgIGlmICh0aW1lWm9uZU9mZnNldCA9PSBudWxsKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCdaJywgJycpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRpbWVab25lT2Zmc2V0ICE9PSAwKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCdaJywgZm9ybWF0VGltZVpvbmVPZmZzZXQodGltZVpvbmVPZmZzZXQsIHRydWUpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UsIGl0cyBVVEMtMCBhbmQgd2Ugd2FudCB0byBrZWVwIHRoZSBaXG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuLy8gZm9ybWF0cyB0aGUgZGF0ZSwgYnV0IHdpdGggbm8gdGltZSBwYXJ0XG4vLyBUT0RPOiBzb21laG93IG1lcmdlIHdpdGggYnVpbGRJc29TdHJpbmcgYW5kIHN0cmlwWmVyb1RpbWVcbi8vIFRPRE86IHJlbmFtZS4gb21pdCBcInN0cmluZ1wiXG5mdW5jdGlvbiBmb3JtYXREYXlTdHJpbmcobWFya2VyKSB7XG4gICAgcmV0dXJuIG1hcmtlci50b0lTT1N0cmluZygpLnJlcGxhY2UoL1QuKiQvLCAnJyk7XG59XG5mdW5jdGlvbiBmb3JtYXRJc29Nb250aFN0cihtYXJrZXIpIHtcbiAgICByZXR1cm4gbWFya2VyLnRvSVNPU3RyaW5nKCkubWF0Y2goL15cXGR7NH0tXFxkezJ9LylbMF07XG59XG4vLyBUT0RPOiB1c2UgRGF0ZTo6dG9JU09TdHJpbmcgYW5kIHVzZSBldmVyeXRoaW5nIGFmdGVyIHRoZSBUP1xuZnVuY3Rpb24gZm9ybWF0SXNvVGltZVN0cmluZyhtYXJrZXIpIHtcbiAgICByZXR1cm4gcGFkU3RhcnQobWFya2VyLmdldFVUQ0hvdXJzKCksIDIpICsgJzonICtcbiAgICAgICAgcGFkU3RhcnQobWFya2VyLmdldFVUQ01pbnV0ZXMoKSwgMikgKyAnOicgK1xuICAgICAgICBwYWRTdGFydChtYXJrZXIuZ2V0VVRDU2Vjb25kcygpLCAyKTtcbn1cbmZ1bmN0aW9uIGZvcm1hdFRpbWVab25lT2Zmc2V0KG1pbnV0ZXMsIGRvSXNvID0gZmFsc2UpIHtcbiAgICBsZXQgc2lnbiA9IG1pbnV0ZXMgPCAwID8gJy0nIDogJysnO1xuICAgIGxldCBhYnMgPSBNYXRoLmFicyhtaW51dGVzKTtcbiAgICBsZXQgaG91cnMgPSBNYXRoLmZsb29yKGFicyAvIDYwKTtcbiAgICBsZXQgbWlucyA9IE1hdGgucm91bmQoYWJzICUgNjApO1xuICAgIGlmIChkb0lzbykge1xuICAgICAgICByZXR1cm4gYCR7c2lnbiArIHBhZFN0YXJ0KGhvdXJzLCAyKX06JHtwYWRTdGFydChtaW5zLCAyKX1gO1xuICAgIH1cbiAgICByZXR1cm4gYEdNVCR7c2lnbn0ke2hvdXJzfSR7bWlucyA/IGA6JHtwYWRTdGFydChtaW5zLCAyKX1gIDogJyd9YDtcbn1cblxuZnVuY3Rpb24gbWVtb2l6ZSh3b3JrZXJGdW5jLCByZXNFcXVhbGl0eSwgdGVhcmRvd25GdW5jKSB7XG4gICAgbGV0IGN1cnJlbnRBcmdzO1xuICAgIGxldCBjdXJyZW50UmVzO1xuICAgIHJldHVybiBmdW5jdGlvbiAoLi4ubmV3QXJncykge1xuICAgICAgICBpZiAoIWN1cnJlbnRBcmdzKSB7XG4gICAgICAgICAgICBjdXJyZW50UmVzID0gd29ya2VyRnVuYy5hcHBseSh0aGlzLCBuZXdBcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaXNBcnJheXNFcXVhbChjdXJyZW50QXJncywgbmV3QXJncykpIHtcbiAgICAgICAgICAgIGlmICh0ZWFyZG93bkZ1bmMpIHtcbiAgICAgICAgICAgICAgICB0ZWFyZG93bkZ1bmMoY3VycmVudFJlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzID0gd29ya2VyRnVuYy5hcHBseSh0aGlzLCBuZXdBcmdzKTtcbiAgICAgICAgICAgIGlmICghcmVzRXF1YWxpdHkgfHwgIXJlc0VxdWFsaXR5KHJlcywgY3VycmVudFJlcykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UmVzID0gcmVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRBcmdzID0gbmV3QXJncztcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRSZXM7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIG1lbW9pemVPYmpBcmcod29ya2VyRnVuYywgcmVzRXF1YWxpdHksIHRlYXJkb3duRnVuYykge1xuICAgIGxldCBjdXJyZW50QXJnO1xuICAgIGxldCBjdXJyZW50UmVzO1xuICAgIHJldHVybiAobmV3QXJnKSA9PiB7XG4gICAgICAgIGlmICghY3VycmVudEFyZykge1xuICAgICAgICAgICAgY3VycmVudFJlcyA9IHdvcmtlckZ1bmMuY2FsbCh0aGlzLCBuZXdBcmcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpc1Byb3BzRXF1YWwoY3VycmVudEFyZywgbmV3QXJnKSkge1xuICAgICAgICAgICAgaWYgKHRlYXJkb3duRnVuYykge1xuICAgICAgICAgICAgICAgIHRlYXJkb3duRnVuYyhjdXJyZW50UmVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXMgPSB3b3JrZXJGdW5jLmNhbGwodGhpcywgbmV3QXJnKTtcbiAgICAgICAgICAgIGlmICghcmVzRXF1YWxpdHkgfHwgIXJlc0VxdWFsaXR5KHJlcywgY3VycmVudFJlcykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UmVzID0gcmVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRBcmcgPSBuZXdBcmc7XG4gICAgICAgIHJldHVybiBjdXJyZW50UmVzO1xuICAgIH07XG59XG5mdW5jdGlvbiBtZW1vaXplQXJyYXlsaWtlKC8vIHVzZWQgYXQgYWxsP1xud29ya2VyRnVuYywgcmVzRXF1YWxpdHksIHRlYXJkb3duRnVuYykge1xuICAgIGxldCBjdXJyZW50QXJnU2V0cyA9IFtdO1xuICAgIGxldCBjdXJyZW50UmVzdWx0cyA9IFtdO1xuICAgIHJldHVybiAobmV3QXJnU2V0cykgPT4ge1xuICAgICAgICBsZXQgY3VycmVudExlbiA9IGN1cnJlbnRBcmdTZXRzLmxlbmd0aDtcbiAgICAgICAgbGV0IG5ld0xlbiA9IG5ld0FyZ1NldHMubGVuZ3RoO1xuICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgIGZvciAoOyBpIDwgY3VycmVudExlbjsgaSArPSAxKSB7XG4gICAgICAgICAgICBpZiAoIW5ld0FyZ1NldHNbaV0pIHsgLy8gb25lIG9mIHRoZSBvbGQgc2V0cyBubyBsb25nZXIgZXhpc3RzXG4gICAgICAgICAgICAgICAgaWYgKHRlYXJkb3duRnVuYykge1xuICAgICAgICAgICAgICAgICAgICB0ZWFyZG93bkZ1bmMoY3VycmVudFJlc3VsdHNbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFpc0FycmF5c0VxdWFsKGN1cnJlbnRBcmdTZXRzW2ldLCBuZXdBcmdTZXRzW2ldKSkge1xuICAgICAgICAgICAgICAgIGlmICh0ZWFyZG93bkZ1bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGVhcmRvd25GdW5jKGN1cnJlbnRSZXN1bHRzW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHJlcyA9IHdvcmtlckZ1bmMuYXBwbHkodGhpcywgbmV3QXJnU2V0c1tpXSk7XG4gICAgICAgICAgICAgICAgaWYgKCFyZXNFcXVhbGl0eSB8fCAhcmVzRXF1YWxpdHkocmVzLCBjdXJyZW50UmVzdWx0c1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFJlc3VsdHNbaV0gPSByZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAoOyBpIDwgbmV3TGVuOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGN1cnJlbnRSZXN1bHRzW2ldID0gd29ya2VyRnVuYy5hcHBseSh0aGlzLCBuZXdBcmdTZXRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50QXJnU2V0cyA9IG5ld0FyZ1NldHM7XG4gICAgICAgIGN1cnJlbnRSZXN1bHRzLnNwbGljZShuZXdMZW4pOyAvLyByZW1vdmUgZXhjZXNzXG4gICAgICAgIHJldHVybiBjdXJyZW50UmVzdWx0cztcbiAgICB9O1xufVxuZnVuY3Rpb24gbWVtb2l6ZUhhc2hsaWtlKHdvcmtlckZ1bmMsIHJlc0VxdWFsaXR5LCB0ZWFyZG93bkZ1bmMpIHtcbiAgICBsZXQgY3VycmVudEFyZ0hhc2ggPSB7fTtcbiAgICBsZXQgY3VycmVudFJlc0hhc2ggPSB7fTtcbiAgICByZXR1cm4gKG5ld0FyZ0hhc2gpID0+IHtcbiAgICAgICAgbGV0IG5ld1Jlc0hhc2ggPSB7fTtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIG5ld0FyZ0hhc2gpIHtcbiAgICAgICAgICAgIGlmICghY3VycmVudFJlc0hhc2hba2V5XSkge1xuICAgICAgICAgICAgICAgIG5ld1Jlc0hhc2hba2V5XSA9IHdvcmtlckZ1bmMuYXBwbHkodGhpcywgbmV3QXJnSGFzaFtrZXldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFpc0FycmF5c0VxdWFsKGN1cnJlbnRBcmdIYXNoW2tleV0sIG5ld0FyZ0hhc2hba2V5XSkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGVhcmRvd25GdW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlYXJkb3duRnVuYyhjdXJyZW50UmVzSGFzaFtrZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHJlcyA9IHdvcmtlckZ1bmMuYXBwbHkodGhpcywgbmV3QXJnSGFzaFtrZXldKTtcbiAgICAgICAgICAgICAgICBuZXdSZXNIYXNoW2tleV0gPSAocmVzRXF1YWxpdHkgJiYgcmVzRXF1YWxpdHkocmVzLCBjdXJyZW50UmVzSGFzaFtrZXldKSlcbiAgICAgICAgICAgICAgICAgICAgPyBjdXJyZW50UmVzSGFzaFtrZXldXG4gICAgICAgICAgICAgICAgICAgIDogcmVzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3UmVzSGFzaFtrZXldID0gY3VycmVudFJlc0hhc2hba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50QXJnSGFzaCA9IG5ld0FyZ0hhc2g7XG4gICAgICAgIGN1cnJlbnRSZXNIYXNoID0gbmV3UmVzSGFzaDtcbiAgICAgICAgcmV0dXJuIG5ld1Jlc0hhc2g7XG4gICAgfTtcbn1cblxuY29uc3QgRVhURU5ERURfU0VUVElOR1NfQU5EX1NFVkVSSVRJRVMgPSB7XG4gICAgd2VlazogMyxcbiAgICBzZXBhcmF0b3I6IDksXG4gICAgb21pdFplcm9NaW51dGU6IDksXG4gICAgbWVyaWRpZW06IDksXG4gICAgb21pdENvbW1hczogOSxcbn07XG5jb25zdCBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFUyA9IHtcbiAgICB0aW1lWm9uZU5hbWU6IDcsXG4gICAgZXJhOiA2LFxuICAgIHllYXI6IDUsXG4gICAgbW9udGg6IDQsXG4gICAgZGF5OiAyLFxuICAgIHdlZWtkYXk6IDIsXG4gICAgaG91cjogMSxcbiAgICBtaW51dGU6IDEsXG4gICAgc2Vjb25kOiAxLFxufTtcbmNvbnN0IE1FUklESUVNX1JFID0gL1xccyooW2FwXSlcXC4/bVxcLj8vaTsgLy8gZWF0cyB1cCBsZWFkaW5nIHNwYWNlcyB0b29cbmNvbnN0IENPTU1BX1JFID0gLywvZzsgLy8gd2UgbmVlZCByZSBmb3IgZ2xvYmFsbmVzc1xuY29uc3QgTVVMVElfU1BBQ0VfUkUgPSAvXFxzKy9nO1xuY29uc3QgTFRSX1JFID0gL1xcdTIwMGUvZzsgLy8gY29udHJvbCBjaGFyYWN0ZXJcbmNvbnN0IFVUQ19SRSA9IC9VVEN8R01ULztcbmNsYXNzIE5hdGl2ZUZvcm1hdHRlciB7XG4gICAgY29uc3RydWN0b3IoZm9ybWF0U2V0dGluZ3MpIHtcbiAgICAgICAgbGV0IHN0YW5kYXJkRGF0ZVByb3BzID0ge307XG4gICAgICAgIGxldCBleHRlbmRlZFNldHRpbmdzID0ge307XG4gICAgICAgIGxldCBzbWFsbGVzdFVuaXROdW0gPSA5OyAvLyB0aGUgc21hbGxlc3QgdW5pdCBpbiB0aGUgZm9ybWF0dGVyICg5IGlzIGEgc2VudGluZWwsIGJleW9uZCBtYXgpXG4gICAgICAgIGZvciAobGV0IG5hbWUgaW4gZm9ybWF0U2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGlmIChuYW1lIGluIEVYVEVOREVEX1NFVFRJTkdTX0FORF9TRVZFUklUSUVTKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5kZWRTZXR0aW5nc1tuYW1lXSA9IGZvcm1hdFNldHRpbmdzW25hbWVdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNldmVyaXR5ID0gRVhURU5ERURfU0VUVElOR1NfQU5EX1NFVkVSSVRJRVNbbmFtZV07XG4gICAgICAgICAgICAgICAgaWYgKHNldmVyaXR5IDwgOSkge1xuICAgICAgICAgICAgICAgICAgICBzbWFsbGVzdFVuaXROdW0gPSBNYXRoLm1pbihFWFRFTkRFRF9TRVRUSU5HU19BTkRfU0VWRVJJVElFU1tuYW1lXSwgc21hbGxlc3RVbml0TnVtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wc1tuYW1lXSA9IGZvcm1hdFNldHRpbmdzW25hbWVdO1xuICAgICAgICAgICAgICAgIGlmIChuYW1lIGluIFNUQU5EQVJEX0RBVEVfUFJPUF9TRVZFUklUSUVTKSB7IC8vIFRPRE86IHdoYXQgYWJvdXQgaG91cjEyPyBubyBzZXZlcml0eVxuICAgICAgICAgICAgICAgICAgICBzbWFsbGVzdFVuaXROdW0gPSBNYXRoLm1pbihTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFU1tuYW1lXSwgc21hbGxlc3RVbml0TnVtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGFuZGFyZERhdGVQcm9wcyA9IHN0YW5kYXJkRGF0ZVByb3BzO1xuICAgICAgICB0aGlzLmV4dGVuZGVkU2V0dGluZ3MgPSBleHRlbmRlZFNldHRpbmdzO1xuICAgICAgICB0aGlzLnNtYWxsZXN0VW5pdE51bSA9IHNtYWxsZXN0VW5pdE51bTtcbiAgICAgICAgdGhpcy5idWlsZEZvcm1hdHRpbmdGdW5jID0gbWVtb2l6ZShidWlsZEZvcm1hdHRpbmdGdW5jKTtcbiAgICB9XG4gICAgZm9ybWF0KGRhdGUsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRGb3JtYXR0aW5nRnVuYyh0aGlzLnN0YW5kYXJkRGF0ZVByb3BzLCB0aGlzLmV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpKGRhdGUpO1xuICAgIH1cbiAgICBmb3JtYXRSYW5nZShzdGFydCwgZW5kLCBjb250ZXh0LCBiZXR0ZXJEZWZhdWx0U2VwYXJhdG9yKSB7XG4gICAgICAgIGxldCB7IHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgZGlmZlNldmVyaXR5ID0gY29tcHV0ZU1hcmtlckRpZmZTZXZlcml0eShzdGFydC5tYXJrZXIsIGVuZC5tYXJrZXIsIGNvbnRleHQuY2FsZW5kYXJTeXN0ZW0pO1xuICAgICAgICBpZiAoIWRpZmZTZXZlcml0eSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0KHN0YXJ0LCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYmlnZ2VzdFVuaXRGb3JQYXJ0aWFsID0gZGlmZlNldmVyaXR5O1xuICAgICAgICBpZiAoYmlnZ2VzdFVuaXRGb3JQYXJ0aWFsID4gMSAmJiAvLyB0aGUgdHdvIGRhdGVzIGFyZSBkaWZmZXJlbnQgaW4gYSB3YXkgdGhhdCdzIGxhcmdlciBzY2FsZSB0aGFuIHRpbWVcbiAgICAgICAgICAgIChzdGFuZGFyZERhdGVQcm9wcy55ZWFyID09PSAnbnVtZXJpYycgfHwgc3RhbmRhcmREYXRlUHJvcHMueWVhciA9PT0gJzItZGlnaXQnKSAmJlxuICAgICAgICAgICAgKHN0YW5kYXJkRGF0ZVByb3BzLm1vbnRoID09PSAnbnVtZXJpYycgfHwgc3RhbmRhcmREYXRlUHJvcHMubW9udGggPT09ICcyLWRpZ2l0JykgJiZcbiAgICAgICAgICAgIChzdGFuZGFyZERhdGVQcm9wcy5kYXkgPT09ICdudW1lcmljJyB8fCBzdGFuZGFyZERhdGVQcm9wcy5kYXkgPT09ICcyLWRpZ2l0JykpIHtcbiAgICAgICAgICAgIGJpZ2dlc3RVbml0Rm9yUGFydGlhbCA9IDE7IC8vIG1ha2UgaXQgbG9vayBsaWtlIHRoZSBkYXRlcyBhcmUgb25seSBkaWZmZXJlbnQgaW4gdGVybXMgb2YgdGltZVxuICAgICAgICB9XG4gICAgICAgIGxldCBmdWxsMCA9IHRoaXMuZm9ybWF0KHN0YXJ0LCBjb250ZXh0KTtcbiAgICAgICAgbGV0IGZ1bGwxID0gdGhpcy5mb3JtYXQoZW5kLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKGZ1bGwwID09PSBmdWxsMSkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bGwwO1xuICAgICAgICB9XG4gICAgICAgIGxldCBwYXJ0aWFsRGF0ZVByb3BzID0gY29tcHV0ZVBhcnRpYWxGb3JtYXR0aW5nT3B0aW9ucyhzdGFuZGFyZERhdGVQcm9wcywgYmlnZ2VzdFVuaXRGb3JQYXJ0aWFsKTtcbiAgICAgICAgbGV0IHBhcnRpYWxGb3JtYXR0aW5nRnVuYyA9IGJ1aWxkRm9ybWF0dGluZ0Z1bmMocGFydGlhbERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG4gICAgICAgIGxldCBwYXJ0aWFsMCA9IHBhcnRpYWxGb3JtYXR0aW5nRnVuYyhzdGFydCk7XG4gICAgICAgIGxldCBwYXJ0aWFsMSA9IHBhcnRpYWxGb3JtYXR0aW5nRnVuYyhlbmQpO1xuICAgICAgICBsZXQgaW5zZXJ0aW9uID0gZmluZENvbW1vbkluc2VydGlvbihmdWxsMCwgcGFydGlhbDAsIGZ1bGwxLCBwYXJ0aWFsMSk7XG4gICAgICAgIGxldCBzZXBhcmF0b3IgPSBleHRlbmRlZFNldHRpbmdzLnNlcGFyYXRvciB8fCBiZXR0ZXJEZWZhdWx0U2VwYXJhdG9yIHx8IGNvbnRleHQuZGVmYXVsdFNlcGFyYXRvciB8fCAnJztcbiAgICAgICAgaWYgKGluc2VydGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIGluc2VydGlvbi5iZWZvcmUgKyBwYXJ0aWFsMCArIHNlcGFyYXRvciArIHBhcnRpYWwxICsgaW5zZXJ0aW9uLmFmdGVyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdWxsMCArIHNlcGFyYXRvciArIGZ1bGwxO1xuICAgIH1cbiAgICBnZXRTbWFsbGVzdFVuaXQoKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5zbWFsbGVzdFVuaXROdW0pIHtcbiAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3llYXInO1xuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIHJldHVybiAnbW9udGgnO1xuICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIHJldHVybiAnd2Vlayc7XG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkYXknO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3RpbWUnOyAvLyByZWFsbHk/XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBidWlsZEZvcm1hdHRpbmdGdW5jKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgbGV0IHN0YW5kYXJkRGF0ZVByb3BDbnQgPSBPYmplY3Qua2V5cyhzdGFuZGFyZERhdGVQcm9wcykubGVuZ3RoO1xuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wQ250ID09PSAxICYmIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9PT0gJ3Nob3J0Jykge1xuICAgICAgICByZXR1cm4gKGRhdGUpID0+IChmb3JtYXRUaW1lWm9uZU9mZnNldChkYXRlLnRpbWVab25lT2Zmc2V0KSk7XG4gICAgfVxuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wQ250ID09PSAwICYmIGV4dGVuZGVkU2V0dGluZ3Mud2Vlaykge1xuICAgICAgICByZXR1cm4gKGRhdGUpID0+IChmb3JtYXRXZWVrTnVtYmVyKGNvbnRleHQuY29tcHV0ZVdlZWtOdW1iZXIoZGF0ZS5tYXJrZXIpLCBjb250ZXh0LndlZWtUZXh0LCBjb250ZXh0LndlZWtUZXh0TG9uZywgY29udGV4dC5sb2NhbGUsIGV4dGVuZGVkU2V0dGluZ3Mud2VlaykpO1xuICAgIH1cbiAgICByZXR1cm4gYnVpbGROYXRpdmVGb3JtYXR0aW5nRnVuYyhzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG59XG5mdW5jdGlvbiBidWlsZE5hdGl2ZUZvcm1hdHRpbmdGdW5jKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgc3RhbmRhcmREYXRlUHJvcHMgPSBPYmplY3QuYXNzaWduKHt9LCBzdGFuZGFyZERhdGVQcm9wcyk7IC8vIGNvcHlcbiAgICBleHRlbmRlZFNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgZXh0ZW5kZWRTZXR0aW5ncyk7IC8vIGNvcHlcbiAgICBzYW5pdGl6ZVNldHRpbmdzKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzKTtcbiAgICBzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZSA9ICdVVEMnOyAvLyB3ZSBsZXZlcmFnZSB0aGUgb25seSBndWFyYW50ZWVkIHRpbWVab25lIGZvciBvdXIgVVRDIG1hcmtlcnNcbiAgICBsZXQgbm9ybWFsRm9ybWF0ID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoY29udGV4dC5sb2NhbGUuY29kZXMsIHN0YW5kYXJkRGF0ZVByb3BzKTtcbiAgICBsZXQgemVyb0Zvcm1hdDsgLy8gbmVlZGVkP1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlKSB7XG4gICAgICAgIGxldCB6ZXJvUHJvcHMgPSBPYmplY3QuYXNzaWduKHt9LCBzdGFuZGFyZERhdGVQcm9wcyk7XG4gICAgICAgIGRlbGV0ZSB6ZXJvUHJvcHMubWludXRlOyAvLyBzZWNvbmRzIGFuZCBtcyB3ZXJlIGFscmVhZHkgY29uc2lkZXJlZCBpbiBzYW5pdGl6ZVNldHRpbmdzXG4gICAgICAgIHplcm9Gb3JtYXQgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChjb250ZXh0LmxvY2FsZS5jb2RlcywgemVyb1Byb3BzKTtcbiAgICB9XG4gICAgcmV0dXJuIChkYXRlKSA9PiB7XG4gICAgICAgIGxldCB7IG1hcmtlciB9ID0gZGF0ZTtcbiAgICAgICAgbGV0IGZvcm1hdDtcbiAgICAgICAgaWYgKHplcm9Gb3JtYXQgJiYgIW1hcmtlci5nZXRVVENNaW51dGVzKCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IHplcm9Gb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBub3JtYWxGb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHMgPSBmb3JtYXQuZm9ybWF0KG1hcmtlcik7XG4gICAgICAgIHJldHVybiBwb3N0UHJvY2VzcyhzLCBkYXRlLCBzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHNhbml0aXplU2V0dGluZ3Moc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MpIHtcbiAgICAvLyBkZWFsIHdpdGggYSBicm93c2VyIGluY29uc2lzdGVuY3kgd2hlcmUgZm9ybWF0dGluZyB0aGUgdGltZXpvbmVcbiAgICAvLyByZXF1aXJlcyB0aGF0IHRoZSBob3VyL21pbnV0ZSBiZSBwcmVzZW50LlxuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZU5hbWUpIHtcbiAgICAgICAgaWYgKCFzdGFuZGFyZERhdGVQcm9wcy5ob3VyKSB7XG4gICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy5ob3VyID0gJzItZGlnaXQnO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3RhbmRhcmREYXRlUHJvcHMubWludXRlKSB7XG4gICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy5taW51dGUgPSAnMi1kaWdpdCc7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gb25seSBzdXBwb3J0IHNob3J0IHRpbWV6b25lIG5hbWVzXG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9PT0gJ2xvbmcnKSB7XG4gICAgICAgIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9ICdzaG9ydCc7XG4gICAgfVxuICAgIC8vIGlmIHJlcXVlc3RpbmcgdG8gZGlzcGxheSBzZWNvbmRzLCBNVVNUIGRpc3BsYXkgbWludXRlc1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlICYmIChzdGFuZGFyZERhdGVQcm9wcy5zZWNvbmQgfHwgc3RhbmRhcmREYXRlUHJvcHMubWlsbGlzZWNvbmQpKSB7XG4gICAgICAgIGRlbGV0ZSBleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHBvc3RQcm9jZXNzKHMsIGRhdGUsIHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgcyA9IHMucmVwbGFjZShMVFJfUkUsICcnKTsgLy8gcmVtb3ZlIGxlZnQtdG8tcmlnaHQgY29udHJvbCBjaGFycy4gZG8gZmlyc3QuIGdvb2QgZm9yIG90aGVyIHJlZ2V4ZXNcbiAgICBpZiAoc3RhbmRhcmREYXRlUHJvcHMudGltZVpvbmVOYW1lID09PSAnc2hvcnQnKSB7XG4gICAgICAgIHMgPSBpbmplY3RUem9TdHIocywgKGNvbnRleHQudGltZVpvbmUgPT09ICdVVEMnIHx8IGRhdGUudGltZVpvbmVPZmZzZXQgPT0gbnVsbCkgP1xuICAgICAgICAgICAgJ1VUQycgOiAvLyBpbXBvcnRhbnQgdG8gbm9ybWFsaXplIGZvciBJRSwgd2hpY2ggZG9lcyBcIkdNVFwiXG4gICAgICAgICAgICBmb3JtYXRUaW1lWm9uZU9mZnNldChkYXRlLnRpbWVab25lT2Zmc2V0KSk7XG4gICAgfVxuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRDb21tYXMpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZShDT01NQV9SRSwgJycpLnRyaW0oKTtcbiAgICB9XG4gICAgaWYgKGV4dGVuZGVkU2V0dGluZ3Mub21pdFplcm9NaW51dGUpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZSgnOjAwJywgJycpOyAvLyB6ZXJvRm9ybWF0IGRvZXNuJ3QgYWx3YXlzIGFjaGlldmUgdGhpc1xuICAgIH1cbiAgICAvLyBeIGRvIGFueXRoaW5nIHRoYXQgbWlnaHQgY3JlYXRlIGFkamFjZW50IHNwYWNlcyBiZWZvcmUgdGhpcyBwb2ludCxcbiAgICAvLyBiZWNhdXNlIE1FUklESUVNX1JFIGxpa2VzIHRvIGVhdCB1cCBsb2FkaW5nIHNwYWNlc1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSBmYWxzZSkge1xuICAgICAgICBzID0gcy5yZXBsYWNlKE1FUklESUVNX1JFLCAnJykudHJpbSgpO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSAnbmFycm93JykgeyAvLyBhL3BcbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgKG0wLCBtMSkgPT4gbTEudG9Mb2NhbGVMb3dlckNhc2UoKSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGV4dGVuZGVkU2V0dGluZ3MubWVyaWRpZW0gPT09ICdzaG9ydCcpIHsgLy8gYW0vcG1cbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgKG0wLCBtMSkgPT4gYCR7bTEudG9Mb2NhbGVMb3dlckNhc2UoKX1tYCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGV4dGVuZGVkU2V0dGluZ3MubWVyaWRpZW0gPT09ICdsb3dlcmNhc2UnKSB7IC8vIG90aGVyIG1lcmlkaWVtIHRyYW5zZm9ybWVycyBhbHJlYWR5IGNvbnZlcnRlZCB0byBsb3dlcmNhc2VcbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgKG0wKSA9PiBtMC50b0xvY2FsZUxvd2VyQ2FzZSgpKTtcbiAgICB9XG4gICAgcyA9IHMucmVwbGFjZShNVUxUSV9TUEFDRV9SRSwgJyAnKTtcbiAgICBzID0gcy50cmltKCk7XG4gICAgcmV0dXJuIHM7XG59XG5mdW5jdGlvbiBpbmplY3RUem9TdHIocywgdHpvU3RyKSB7XG4gICAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG4gICAgcyA9IHMucmVwbGFjZShVVENfUkUsICgpID0+IHtcbiAgICAgICAgcmVwbGFjZWQgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdHpvU3RyO1xuICAgIH0pO1xuICAgIC8vIElFMTEgZG9lc24ndCBpbmNsdWRlIFVUQy9HTVQgaW4gdGhlIG9yaWdpbmFsIHN0cmluZywgc28gYXBwZW5kIHRvIGVuZFxuICAgIGlmICghcmVwbGFjZWQpIHtcbiAgICAgICAgcyArPSBgICR7dHpvU3RyfWA7XG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuZnVuY3Rpb24gZm9ybWF0V2Vla051bWJlcihudW0sIHdlZWtUZXh0LCB3ZWVrVGV4dExvbmcsIGxvY2FsZSwgZGlzcGxheSkge1xuICAgIGxldCBwYXJ0cyA9IFtdO1xuICAgIGlmIChkaXNwbGF5ID09PSAnbG9uZycpIHtcbiAgICAgICAgcGFydHMucHVzaCh3ZWVrVGV4dExvbmcpO1xuICAgIH1cbiAgICBlbHNlIGlmIChkaXNwbGF5ID09PSAnc2hvcnQnIHx8IGRpc3BsYXkgPT09ICduYXJyb3cnKSB7XG4gICAgICAgIHBhcnRzLnB1c2god2Vla1RleHQpO1xuICAgIH1cbiAgICBpZiAoZGlzcGxheSA9PT0gJ2xvbmcnIHx8IGRpc3BsYXkgPT09ICdzaG9ydCcpIHtcbiAgICAgICAgcGFydHMucHVzaCgnICcpO1xuICAgIH1cbiAgICBwYXJ0cy5wdXNoKGxvY2FsZS5zaW1wbGVOdW1iZXJGb3JtYXQuZm9ybWF0KG51bSkpO1xuICAgIGlmIChsb2NhbGUub3B0aW9ucy5kaXJlY3Rpb24gPT09ICdydGwnKSB7IC8vIFRPRE86IHVzZSBjb250cm9sIGNoYXJhY3RlcnMgaW5zdGVhZD9cbiAgICAgICAgcGFydHMucmV2ZXJzZSgpO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHMuam9pbignJyk7XG59XG4vLyBSYW5nZSBGb3JtYXR0aW5nIFV0aWxzXG4vLyAwID0gZXhhY3RseSB0aGUgc2FtZVxuLy8gMSA9IGRpZmZlcmVudCBieSB0aW1lXG4vLyBhbmQgYmlnZ2VyXG5mdW5jdGlvbiBjb21wdXRlTWFya2VyRGlmZlNldmVyaXR5KGQwLCBkMSwgY2EpIHtcbiAgICBpZiAoY2EuZ2V0TWFya2VyWWVhcihkMCkgIT09IGNhLmdldE1hcmtlclllYXIoZDEpKSB7XG4gICAgICAgIHJldHVybiA1O1xuICAgIH1cbiAgICBpZiAoY2EuZ2V0TWFya2VyTW9udGgoZDApICE9PSBjYS5nZXRNYXJrZXJNb250aChkMSkpIHtcbiAgICAgICAgcmV0dXJuIDQ7XG4gICAgfVxuICAgIGlmIChjYS5nZXRNYXJrZXJEYXkoZDApICE9PSBjYS5nZXRNYXJrZXJEYXkoZDEpKSB7XG4gICAgICAgIHJldHVybiAyO1xuICAgIH1cbiAgICBpZiAodGltZUFzTXMoZDApICE9PSB0aW1lQXNNcyhkMSkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIHJldHVybiAwO1xufVxuZnVuY3Rpb24gY29tcHV0ZVBhcnRpYWxGb3JtYXR0aW5nT3B0aW9ucyhvcHRpb25zLCBiaWdnZXN0VW5pdCkge1xuICAgIGxldCBwYXJ0aWFsT3B0aW9ucyA9IHt9O1xuICAgIGZvciAobGV0IG5hbWUgaW4gb3B0aW9ucykge1xuICAgICAgICBpZiAoIShuYW1lIGluIFNUQU5EQVJEX0RBVEVfUFJPUF9TRVZFUklUSUVTKSB8fCAvLyBub3QgYSBkYXRlIHBhcnQgcHJvcCAobGlrZSB0aW1lWm9uZSlcbiAgICAgICAgICAgIFNUQU5EQVJEX0RBVEVfUFJPUF9TRVZFUklUSUVTW25hbWVdIDw9IGJpZ2dlc3RVbml0KSB7XG4gICAgICAgICAgICBwYXJ0aWFsT3B0aW9uc1tuYW1lXSA9IG9wdGlvbnNbbmFtZV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBhcnRpYWxPcHRpb25zO1xufVxuZnVuY3Rpb24gZmluZENvbW1vbkluc2VydGlvbihmdWxsMCwgcGFydGlhbDAsIGZ1bGwxLCBwYXJ0aWFsMSkge1xuICAgIGxldCBpMCA9IDA7XG4gICAgd2hpbGUgKGkwIDwgZnVsbDAubGVuZ3RoKSB7XG4gICAgICAgIGxldCBmb3VuZDAgPSBmdWxsMC5pbmRleE9mKHBhcnRpYWwwLCBpMCk7XG4gICAgICAgIGlmIChmb3VuZDAgPT09IC0xKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBsZXQgYmVmb3JlMCA9IGZ1bGwwLnN1YnN0cigwLCBmb3VuZDApO1xuICAgICAgICBpMCA9IGZvdW5kMCArIHBhcnRpYWwwLmxlbmd0aDtcbiAgICAgICAgbGV0IGFmdGVyMCA9IGZ1bGwwLnN1YnN0cihpMCk7XG4gICAgICAgIGxldCBpMSA9IDA7XG4gICAgICAgIHdoaWxlIChpMSA8IGZ1bGwxLmxlbmd0aCkge1xuICAgICAgICAgICAgbGV0IGZvdW5kMSA9IGZ1bGwxLmluZGV4T2YocGFydGlhbDEsIGkxKTtcbiAgICAgICAgICAgIGlmIChmb3VuZDEgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYmVmb3JlMSA9IGZ1bGwxLnN1YnN0cigwLCBmb3VuZDEpO1xuICAgICAgICAgICAgaTEgPSBmb3VuZDEgKyBwYXJ0aWFsMS5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgYWZ0ZXIxID0gZnVsbDEuc3Vic3RyKGkxKTtcbiAgICAgICAgICAgIGlmIChiZWZvcmUwID09PSBiZWZvcmUxICYmIGFmdGVyMCA9PT0gYWZ0ZXIxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYmVmb3JlOiBiZWZvcmUwLFxuICAgICAgICAgICAgICAgICAgICBhZnRlcjogYWZ0ZXIwLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZFpvbmVkTWFya2VyKGRhdGVJbmZvLCBjYWxlbmRhclN5c3RlbSkge1xuICAgIGxldCBhID0gY2FsZW5kYXJTeXN0ZW0ubWFya2VyVG9BcnJheShkYXRlSW5mby5tYXJrZXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIG1hcmtlcjogZGF0ZUluZm8ubWFya2VyLFxuICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZUluZm8udGltZVpvbmVPZmZzZXQsXG4gICAgICAgIGFycmF5OiBhLFxuICAgICAgICB5ZWFyOiBhWzBdLFxuICAgICAgICBtb250aDogYVsxXSxcbiAgICAgICAgZGF5OiBhWzJdLFxuICAgICAgICBob3VyOiBhWzNdLFxuICAgICAgICBtaW51dGU6IGFbNF0sXG4gICAgICAgIHNlY29uZDogYVs1XSxcbiAgICAgICAgbWlsbGlzZWNvbmQ6IGFbNl0sXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlVmVyYm9zZUZvcm1hdHRpbmdBcmcoc3RhcnQsIGVuZCwgY29udGV4dCwgYmV0dGVyRGVmYXVsdFNlcGFyYXRvcikge1xuICAgIGxldCBzdGFydEluZm8gPSBleHBhbmRab25lZE1hcmtlcihzdGFydCwgY29udGV4dC5jYWxlbmRhclN5c3RlbSk7XG4gICAgbGV0IGVuZEluZm8gPSBlbmQgPyBleHBhbmRab25lZE1hcmtlcihlbmQsIGNvbnRleHQuY2FsZW5kYXJTeXN0ZW0pIDogbnVsbDtcbiAgICByZXR1cm4ge1xuICAgICAgICBkYXRlOiBzdGFydEluZm8sXG4gICAgICAgIHN0YXJ0OiBzdGFydEluZm8sXG4gICAgICAgIGVuZDogZW5kSW5mbyxcbiAgICAgICAgdGltZVpvbmU6IGNvbnRleHQudGltZVpvbmUsXG4gICAgICAgIGxvY2FsZUNvZGVzOiBjb250ZXh0LmxvY2FsZS5jb2RlcyxcbiAgICAgICAgZGVmYXVsdFNlcGFyYXRvcjogYmV0dGVyRGVmYXVsdFNlcGFyYXRvciB8fCBjb250ZXh0LmRlZmF1bHRTZXBhcmF0b3IsXG4gICAgfTtcbn1cblxuLypcblRPRE86IGZpeCB0aGUgdGVybWlub2xvZ3kgb2YgXCJmb3JtYXR0ZXJcIiB2cyBcImZvcm1hdHRpbmcgZnVuY1wiXG4qL1xuLypcbkF0IHRoZSB0aW1lIG9mIGluc3RhbnRpYXRpb24sIHRoaXMgb2JqZWN0IGRvZXMgbm90IGtub3cgd2hpY2ggY21kLWZvcm1hdHRpbmcgc3lzdGVtIGl0IHdpbGwgdXNlLlxuSXQgcmVjZWl2ZXMgdGhpcyBhdCB0aGUgdGltZSBvZiBmb3JtYXR0aW5nLCBhcyBhIHNldHRpbmcuXG4qL1xuY2xhc3MgQ21kRm9ybWF0dGVyIHtcbiAgICBjb25zdHJ1Y3RvcihjbWRTdHIpIHtcbiAgICAgICAgdGhpcy5jbWRTdHIgPSBjbWRTdHI7XG4gICAgfVxuICAgIGZvcm1hdChkYXRlLCBjb250ZXh0LCBiZXR0ZXJEZWZhdWx0U2VwYXJhdG9yKSB7XG4gICAgICAgIHJldHVybiBjb250ZXh0LmNtZEZvcm1hdHRlcih0aGlzLmNtZFN0ciwgY3JlYXRlVmVyYm9zZUZvcm1hdHRpbmdBcmcoZGF0ZSwgbnVsbCwgY29udGV4dCwgYmV0dGVyRGVmYXVsdFNlcGFyYXRvcikpO1xuICAgIH1cbiAgICBmb3JtYXRSYW5nZShzdGFydCwgZW5kLCBjb250ZXh0LCBiZXR0ZXJEZWZhdWx0U2VwYXJhdG9yKSB7XG4gICAgICAgIHJldHVybiBjb250ZXh0LmNtZEZvcm1hdHRlcih0aGlzLmNtZFN0ciwgY3JlYXRlVmVyYm9zZUZvcm1hdHRpbmdBcmcoc3RhcnQsIGVuZCwgY29udGV4dCwgYmV0dGVyRGVmYXVsdFNlcGFyYXRvcikpO1xuICAgIH1cbn1cblxuY2xhc3MgRnVuY0Zvcm1hdHRlciB7XG4gICAgY29uc3RydWN0b3IoZnVuYykge1xuICAgICAgICB0aGlzLmZ1bmMgPSBmdW5jO1xuICAgIH1cbiAgICBmb3JtYXQoZGF0ZSwgY29udGV4dCwgYmV0dGVyRGVmYXVsdFNlcGFyYXRvcikge1xuICAgICAgICByZXR1cm4gdGhpcy5mdW5jKGNyZWF0ZVZlcmJvc2VGb3JtYXR0aW5nQXJnKGRhdGUsIG51bGwsIGNvbnRleHQsIGJldHRlckRlZmF1bHRTZXBhcmF0b3IpKTtcbiAgICB9XG4gICAgZm9ybWF0UmFuZ2Uoc3RhcnQsIGVuZCwgY29udGV4dCwgYmV0dGVyRGVmYXVsdFNlcGFyYXRvcikge1xuICAgICAgICByZXR1cm4gdGhpcy5mdW5jKGNyZWF0ZVZlcmJvc2VGb3JtYXR0aW5nQXJnKHN0YXJ0LCBlbmQsIGNvbnRleHQsIGJldHRlckRlZmF1bHRTZXBhcmF0b3IpKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUZvcm1hdHRlcihpbnB1dCkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZUZvcm1hdHRlcihpbnB1dCk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ21kRm9ybWF0dGVyKGlucHV0KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gbmV3IEZ1bmNGb3JtYXR0ZXIoaW5wdXQpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuLy8gYmFzZSBvcHRpb25zXG4vLyAtLS0tLS0tLS0tLS1cbmNvbnN0IEJBU0VfT1BUSU9OX1JFRklORVJTID0ge1xuICAgIG5hdkxpbmtEYXlDbGljazogaWRlbnRpdHksXG4gICAgbmF2TGlua1dlZWtDbGljazogaWRlbnRpdHksXG4gICAgZHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIGJvb3RzdHJhcEZvbnRBd2Vzb21lOiBpZGVudGl0eSxcbiAgICBidXR0b25JY29uczogaWRlbnRpdHksXG4gICAgY3VzdG9tQnV0dG9uczogaWRlbnRpdHksXG4gICAgZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIGRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIG5leHREYXlUaHJlc2hvbGQ6IGNyZWF0ZUR1cmF0aW9uLFxuICAgIHNjcm9sbFRpbWU6IGNyZWF0ZUR1cmF0aW9uLFxuICAgIHNjcm9sbFRpbWVSZXNldDogQm9vbGVhbixcbiAgICBzbG90TWluVGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgc2xvdE1heFRpbWU6IGNyZWF0ZUR1cmF0aW9uLFxuICAgIGRheVBvcG92ZXJGb3JtYXQ6IGNyZWF0ZUZvcm1hdHRlcixcbiAgICBzbG90RHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIHNuYXBEdXJhdGlvbjogY3JlYXRlRHVyYXRpb24sXG4gICAgaGVhZGVyVG9vbGJhcjogaWRlbnRpdHksXG4gICAgZm9vdGVyVG9vbGJhcjogaWRlbnRpdHksXG4gICAgZGVmYXVsdFJhbmdlU2VwYXJhdG9yOiBTdHJpbmcsXG4gICAgdGl0bGVSYW5nZVNlcGFyYXRvcjogU3RyaW5nLFxuICAgIGZvcmNlRXZlbnREdXJhdGlvbjogQm9vbGVhbixcbiAgICBkYXlIZWFkZXJzOiBCb29sZWFuLFxuICAgIGRheUhlYWRlckZvcm1hdDogY3JlYXRlRm9ybWF0dGVyLFxuICAgIGRheUhlYWRlckNsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIGRheUhlYWRlckNvbnRlbnQ6IGlkZW50aXR5LFxuICAgIGRheUhlYWRlckRpZE1vdW50OiBpZGVudGl0eSxcbiAgICBkYXlIZWFkZXJXaWxsVW5tb3VudDogaWRlbnRpdHksXG4gICAgZGF5Q2VsbENsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIGRheUNlbGxDb250ZW50OiBpZGVudGl0eSxcbiAgICBkYXlDZWxsRGlkTW91bnQ6IGlkZW50aXR5LFxuICAgIGRheUNlbGxXaWxsVW5tb3VudDogaWRlbnRpdHksXG4gICAgaW5pdGlhbFZpZXc6IFN0cmluZyxcbiAgICBhc3BlY3RSYXRpbzogTnVtYmVyLFxuICAgIHdlZWtlbmRzOiBCb29sZWFuLFxuICAgIHdlZWtOdW1iZXJDYWxjdWxhdGlvbjogaWRlbnRpdHksXG4gICAgd2Vla051bWJlcnM6IEJvb2xlYW4sXG4gICAgd2Vla051bWJlckNsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIHdlZWtOdW1iZXJDb250ZW50OiBpZGVudGl0eSxcbiAgICB3ZWVrTnVtYmVyRGlkTW91bnQ6IGlkZW50aXR5LFxuICAgIHdlZWtOdW1iZXJXaWxsVW5tb3VudDogaWRlbnRpdHksXG4gICAgZWRpdGFibGU6IEJvb2xlYW4sXG4gICAgdmlld0NsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIHZpZXdEaWRNb3VudDogaWRlbnRpdHksXG4gICAgdmlld1dpbGxVbm1vdW50OiBpZGVudGl0eSxcbiAgICBub3dJbmRpY2F0b3I6IEJvb2xlYW4sXG4gICAgbm93SW5kaWNhdG9yU25hcDogaWRlbnRpdHksXG4gICAgbm93SW5kaWNhdG9yQ2xhc3NOYW1lczogaWRlbnRpdHksXG4gICAgbm93SW5kaWNhdG9yQ29udGVudDogaWRlbnRpdHksXG4gICAgbm93SW5kaWNhdG9yRGlkTW91bnQ6IGlkZW50aXR5LFxuICAgIG5vd0luZGljYXRvcldpbGxVbm1vdW50OiBpZGVudGl0eSxcbiAgICBzaG93Tm9uQ3VycmVudERhdGVzOiBCb29sZWFuLFxuICAgIGxhenlGZXRjaGluZzogQm9vbGVhbixcbiAgICBzdGFydFBhcmFtOiBTdHJpbmcsXG4gICAgZW5kUGFyYW06IFN0cmluZyxcbiAgICB0aW1lWm9uZVBhcmFtOiBTdHJpbmcsXG4gICAgdGltZVpvbmU6IFN0cmluZyxcbiAgICBsb2NhbGVzOiBpZGVudGl0eSxcbiAgICBsb2NhbGU6IGlkZW50aXR5LFxuICAgIHRoZW1lU3lzdGVtOiBTdHJpbmcsXG4gICAgZHJhZ1JldmVydER1cmF0aW9uOiBOdW1iZXIsXG4gICAgZHJhZ1Njcm9sbDogQm9vbGVhbixcbiAgICBhbGxEYXlNYWludGFpbkR1cmF0aW9uOiBCb29sZWFuLFxuICAgIHVuc2VsZWN0QXV0bzogQm9vbGVhbixcbiAgICBkcm9wQWNjZXB0OiBpZGVudGl0eSxcbiAgICBldmVudE9yZGVyOiBwYXJzZUZpZWxkU3BlY3MsXG4gICAgZXZlbnRPcmRlclN0cmljdDogQm9vbGVhbixcbiAgICBoYW5kbGVXaW5kb3dSZXNpemU6IEJvb2xlYW4sXG4gICAgd2luZG93UmVzaXplRGVsYXk6IE51bWJlcixcbiAgICBsb25nUHJlc3NEZWxheTogTnVtYmVyLFxuICAgIGV2ZW50RHJhZ01pbkRpc3RhbmNlOiBOdW1iZXIsXG4gICAgZXhwYW5kUm93czogQm9vbGVhbixcbiAgICBoZWlnaHQ6IGlkZW50aXR5LFxuICAgIGNvbnRlbnRIZWlnaHQ6IGlkZW50aXR5LFxuICAgIGRpcmVjdGlvbjogU3RyaW5nLFxuICAgIHdlZWtOdW1iZXJGb3JtYXQ6IGNyZWF0ZUZvcm1hdHRlcixcbiAgICBldmVudFJlc2l6YWJsZUZyb21TdGFydDogQm9vbGVhbixcbiAgICBkaXNwbGF5RXZlbnRUaW1lOiBCb29sZWFuLFxuICAgIGRpc3BsYXlFdmVudEVuZDogQm9vbGVhbixcbiAgICB3ZWVrVGV4dDogU3RyaW5nLFxuICAgIHdlZWtUZXh0TG9uZzogU3RyaW5nLFxuICAgIHByb2dyZXNzaXZlRXZlbnRSZW5kZXJpbmc6IEJvb2xlYW4sXG4gICAgYnVzaW5lc3NIb3VyczogaWRlbnRpdHksXG4gICAgaW5pdGlhbERhdGU6IGlkZW50aXR5LFxuICAgIG5vdzogaWRlbnRpdHksXG4gICAgZXZlbnREYXRhVHJhbnNmb3JtOiBpZGVudGl0eSxcbiAgICBzdGlja3lIZWFkZXJEYXRlczogaWRlbnRpdHksXG4gICAgc3RpY2t5Rm9vdGVyU2Nyb2xsYmFyOiBpZGVudGl0eSxcbiAgICB2aWV3SGVpZ2h0OiBpZGVudGl0eSxcbiAgICBkZWZhdWx0QWxsRGF5OiBCb29sZWFuLFxuICAgIGV2ZW50U291cmNlRmFpbHVyZTogaWRlbnRpdHksXG4gICAgZXZlbnRTb3VyY2VTdWNjZXNzOiBpZGVudGl0eSxcbiAgICBldmVudERpc3BsYXk6IFN0cmluZyxcbiAgICBldmVudFN0YXJ0RWRpdGFibGU6IEJvb2xlYW4sXG4gICAgZXZlbnREdXJhdGlvbkVkaXRhYmxlOiBCb29sZWFuLFxuICAgIGV2ZW50T3ZlcmxhcDogaWRlbnRpdHksXG4gICAgZXZlbnRDb25zdHJhaW50OiBpZGVudGl0eSxcbiAgICBldmVudEFsbG93OiBpZGVudGl0eSxcbiAgICBldmVudEJhY2tncm91bmRDb2xvcjogU3RyaW5nLFxuICAgIGV2ZW50Qm9yZGVyQ29sb3I6IFN0cmluZyxcbiAgICBldmVudFRleHRDb2xvcjogU3RyaW5nLFxuICAgIGV2ZW50Q29sb3I6IFN0cmluZyxcbiAgICBldmVudENsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIGV2ZW50Q29udGVudDogaWRlbnRpdHksXG4gICAgZXZlbnREaWRNb3VudDogaWRlbnRpdHksXG4gICAgZXZlbnRXaWxsVW5tb3VudDogaWRlbnRpdHksXG4gICAgc2VsZWN0Q29uc3RyYWludDogaWRlbnRpdHksXG4gICAgc2VsZWN0T3ZlcmxhcDogaWRlbnRpdHksXG4gICAgc2VsZWN0QWxsb3c6IGlkZW50aXR5LFxuICAgIGRyb3BwYWJsZTogQm9vbGVhbixcbiAgICB1bnNlbGVjdENhbmNlbDogU3RyaW5nLFxuICAgIHNsb3RMYWJlbEZvcm1hdDogaWRlbnRpdHksXG4gICAgc2xvdExhbmVDbGFzc05hbWVzOiBpZGVudGl0eSxcbiAgICBzbG90TGFuZUNvbnRlbnQ6IGlkZW50aXR5LFxuICAgIHNsb3RMYW5lRGlkTW91bnQ6IGlkZW50aXR5LFxuICAgIHNsb3RMYW5lV2lsbFVubW91bnQ6IGlkZW50aXR5LFxuICAgIHNsb3RMYWJlbENsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIHNsb3RMYWJlbENvbnRlbnQ6IGlkZW50aXR5LFxuICAgIHNsb3RMYWJlbERpZE1vdW50OiBpZGVudGl0eSxcbiAgICBzbG90TGFiZWxXaWxsVW5tb3VudDogaWRlbnRpdHksXG4gICAgZGF5TWF4RXZlbnRzOiBpZGVudGl0eSxcbiAgICBkYXlNYXhFdmVudFJvd3M6IGlkZW50aXR5LFxuICAgIGRheU1pbldpZHRoOiBOdW1iZXIsXG4gICAgc2xvdExhYmVsSW50ZXJ2YWw6IGNyZWF0ZUR1cmF0aW9uLFxuICAgIGFsbERheVRleHQ6IFN0cmluZyxcbiAgICBhbGxEYXlDbGFzc05hbWVzOiBpZGVudGl0eSxcbiAgICBhbGxEYXlDb250ZW50OiBpZGVudGl0eSxcbiAgICBhbGxEYXlEaWRNb3VudDogaWRlbnRpdHksXG4gICAgYWxsRGF5V2lsbFVubW91bnQ6IGlkZW50aXR5LFxuICAgIHNsb3RNaW5XaWR0aDogTnVtYmVyLFxuICAgIG5hdkxpbmtzOiBCb29sZWFuLFxuICAgIGV2ZW50VGltZUZvcm1hdDogY3JlYXRlRm9ybWF0dGVyLFxuICAgIHJlcmVuZGVyRGVsYXk6IE51bWJlcixcbiAgICBtb3JlTGlua1RleHQ6IGlkZW50aXR5LFxuICAgIG1vcmVMaW5rSGludDogaWRlbnRpdHksXG4gICAgc2VsZWN0TWluRGlzdGFuY2U6IE51bWJlcixcbiAgICBzZWxlY3RhYmxlOiBCb29sZWFuLFxuICAgIHNlbGVjdExvbmdQcmVzc0RlbGF5OiBOdW1iZXIsXG4gICAgZXZlbnRMb25nUHJlc3NEZWxheTogTnVtYmVyLFxuICAgIHNlbGVjdE1pcnJvcjogQm9vbGVhbixcbiAgICBldmVudE1heFN0YWNrOiBOdW1iZXIsXG4gICAgZXZlbnRNaW5IZWlnaHQ6IE51bWJlcixcbiAgICBldmVudE1pbldpZHRoOiBOdW1iZXIsXG4gICAgZXZlbnRTaG9ydEhlaWdodDogTnVtYmVyLFxuICAgIHNsb3RFdmVudE92ZXJsYXA6IEJvb2xlYW4sXG4gICAgcGx1Z2luczogaWRlbnRpdHksXG4gICAgZmlyc3REYXk6IE51bWJlcixcbiAgICBkYXlDb3VudDogTnVtYmVyLFxuICAgIGRhdGVBbGlnbm1lbnQ6IFN0cmluZyxcbiAgICBkYXRlSW5jcmVtZW50OiBjcmVhdGVEdXJhdGlvbixcbiAgICBoaWRkZW5EYXlzOiBpZGVudGl0eSxcbiAgICBmaXhlZFdlZWtDb3VudDogQm9vbGVhbixcbiAgICB2YWxpZFJhbmdlOiBpZGVudGl0eSxcbiAgICB2aXNpYmxlUmFuZ2U6IGlkZW50aXR5LFxuICAgIHRpdGxlRm9ybWF0OiBpZGVudGl0eSxcbiAgICBldmVudEludGVyYWN0aXZlOiBCb29sZWFuLFxuICAgIC8vIG9ubHkgdXNlZCBieSBsaXN0LXZpZXcsIGJ1dCBsYW5ndWFnZXMgZGVmaW5lIHRoZSB2YWx1ZSwgc28gd2UgbmVlZCBpdCBpbiBiYXNlIG9wdGlvbnNcbiAgICBub0V2ZW50c1RleHQ6IFN0cmluZyxcbiAgICB2aWV3SGludDogaWRlbnRpdHksXG4gICAgbmF2TGlua0hpbnQ6IGlkZW50aXR5LFxuICAgIGNsb3NlSGludDogU3RyaW5nLFxuICAgIHRpbWVIaW50OiBTdHJpbmcsXG4gICAgZXZlbnRIaW50OiBTdHJpbmcsXG4gICAgbW9yZUxpbmtDbGljazogaWRlbnRpdHksXG4gICAgbW9yZUxpbmtDbGFzc05hbWVzOiBpZGVudGl0eSxcbiAgICBtb3JlTGlua0NvbnRlbnQ6IGlkZW50aXR5LFxuICAgIG1vcmVMaW5rRGlkTW91bnQ6IGlkZW50aXR5LFxuICAgIG1vcmVMaW5rV2lsbFVubW91bnQ6IGlkZW50aXR5LFxuICAgIG1vbnRoU3RhcnRGb3JtYXQ6IGNyZWF0ZUZvcm1hdHRlcixcbiAgICAvLyBmb3IgY29ubmVjdG9yc1xuICAgIC8vIChjYW4ndCBiZSBwYXJ0IG9mIHBsdWdpbiBzeXN0ZW0gYi9jIG11c3QgYmUgcHJvdmlkZWQgYXQgcnVudGltZSlcbiAgICBoYW5kbGVDdXN0b21SZW5kZXJpbmc6IGlkZW50aXR5LFxuICAgIGN1c3RvbVJlbmRlcmluZ01ldGFNYXA6IGlkZW50aXR5LFxuICAgIGN1c3RvbVJlbmRlcmluZ1JlcGxhY2VzOiBCb29sZWFuLFxufTtcbi8vIGRvIE5PVCBnaXZlIGEgdHlwZSBoZXJlLiBuZWVkIGB0eXBlb2YgQkFTRV9PUFRJT05fREVGQVVMVFNgIHRvIGdpdmUgcmVhbCByZXN1bHRzLlxuLy8gcmF3IHZhbHVlcy5cbmNvbnN0IEJBU0VfT1BUSU9OX0RFRkFVTFRTID0ge1xuICAgIGV2ZW50RGlzcGxheTogJ2F1dG8nLFxuICAgIGRlZmF1bHRSYW5nZVNlcGFyYXRvcjogJyAtICcsXG4gICAgdGl0bGVSYW5nZVNlcGFyYXRvcjogJyBcXHUyMDEzICcsXG4gICAgZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbjogJzAxOjAwOjAwJyxcbiAgICBkZWZhdWx0QWxsRGF5RXZlbnREdXJhdGlvbjogeyBkYXk6IDEgfSxcbiAgICBmb3JjZUV2ZW50RHVyYXRpb246IGZhbHNlLFxuICAgIG5leHREYXlUaHJlc2hvbGQ6ICcwMDowMDowMCcsXG4gICAgZGF5SGVhZGVyczogdHJ1ZSxcbiAgICBpbml0aWFsVmlldzogJycsXG4gICAgYXNwZWN0UmF0aW86IDEuMzUsXG4gICAgaGVhZGVyVG9vbGJhcjoge1xuICAgICAgICBzdGFydDogJ3RpdGxlJyxcbiAgICAgICAgY2VudGVyOiAnJyxcbiAgICAgICAgZW5kOiAndG9kYXkgcHJldixuZXh0JyxcbiAgICB9LFxuICAgIHdlZWtlbmRzOiB0cnVlLFxuICAgIHdlZWtOdW1iZXJzOiBmYWxzZSxcbiAgICB3ZWVrTnVtYmVyQ2FsY3VsYXRpb246ICdsb2NhbCcsXG4gICAgZWRpdGFibGU6IGZhbHNlLFxuICAgIG5vd0luZGljYXRvcjogZmFsc2UsXG4gICAgc2Nyb2xsVGltZTogJzA2OjAwOjAwJyxcbiAgICBzY3JvbGxUaW1lUmVzZXQ6IHRydWUsXG4gICAgc2xvdE1pblRpbWU6ICcwMDowMDowMCcsXG4gICAgc2xvdE1heFRpbWU6ICcyNDowMDowMCcsXG4gICAgc2hvd05vbkN1cnJlbnREYXRlczogdHJ1ZSxcbiAgICBsYXp5RmV0Y2hpbmc6IHRydWUsXG4gICAgc3RhcnRQYXJhbTogJ3N0YXJ0JyxcbiAgICBlbmRQYXJhbTogJ2VuZCcsXG4gICAgdGltZVpvbmVQYXJhbTogJ3RpbWVab25lJyxcbiAgICB0aW1lWm9uZTogJ2xvY2FsJyxcbiAgICBsb2NhbGVzOiBbXSxcbiAgICBsb2NhbGU6ICcnLFxuICAgIHRoZW1lU3lzdGVtOiAnc3RhbmRhcmQnLFxuICAgIGRyYWdSZXZlcnREdXJhdGlvbjogNTAwLFxuICAgIGRyYWdTY3JvbGw6IHRydWUsXG4gICAgYWxsRGF5TWFpbnRhaW5EdXJhdGlvbjogZmFsc2UsXG4gICAgdW5zZWxlY3RBdXRvOiB0cnVlLFxuICAgIGRyb3BBY2NlcHQ6ICcqJyxcbiAgICBldmVudE9yZGVyOiAnc3RhcnQsLWR1cmF0aW9uLGFsbERheSx0aXRsZScsXG4gICAgZGF5UG9wb3ZlckZvcm1hdDogeyBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJywgeWVhcjogJ251bWVyaWMnIH0sXG4gICAgaGFuZGxlV2luZG93UmVzaXplOiB0cnVlLFxuICAgIHdpbmRvd1Jlc2l6ZURlbGF5OiAxMDAsXG4gICAgbG9uZ1ByZXNzRGVsYXk6IDEwMDAsXG4gICAgZXZlbnREcmFnTWluRGlzdGFuY2U6IDUsXG4gICAgZXhwYW5kUm93czogZmFsc2UsXG4gICAgbmF2TGlua3M6IGZhbHNlLFxuICAgIHNlbGVjdGFibGU6IGZhbHNlLFxuICAgIGV2ZW50TWluSGVpZ2h0OiAxNSxcbiAgICBldmVudE1pbldpZHRoOiAzMCxcbiAgICBldmVudFNob3J0SGVpZ2h0OiAzMCxcbiAgICBtb250aFN0YXJ0Rm9ybWF0OiB7IG1vbnRoOiAnbG9uZycsIGRheTogJ251bWVyaWMnIH0sXG4gICAgbm93SW5kaWNhdG9yU25hcDogJ2F1dG8nLFxufTtcbi8vIGNhbGVuZGFyIGxpc3RlbmVyc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tXG5jb25zdCBDQUxFTkRBUl9MSVNURU5FUl9SRUZJTkVSUyA9IHtcbiAgICBkYXRlc1NldDogaWRlbnRpdHksXG4gICAgZXZlbnRzU2V0OiBpZGVudGl0eSxcbiAgICBldmVudEFkZDogaWRlbnRpdHksXG4gICAgZXZlbnRDaGFuZ2U6IGlkZW50aXR5LFxuICAgIGV2ZW50UmVtb3ZlOiBpZGVudGl0eSxcbiAgICB3aW5kb3dSZXNpemU6IGlkZW50aXR5LFxuICAgIGV2ZW50Q2xpY2s6IGlkZW50aXR5LFxuICAgIGV2ZW50TW91c2VFbnRlcjogaWRlbnRpdHksXG4gICAgZXZlbnRNb3VzZUxlYXZlOiBpZGVudGl0eSxcbiAgICBzZWxlY3Q6IGlkZW50aXR5LFxuICAgIHVuc2VsZWN0OiBpZGVudGl0eSxcbiAgICBsb2FkaW5nOiBpZGVudGl0eSxcbiAgICAvLyBpbnRlcm5hbFxuICAgIF91bm1vdW50OiBpZGVudGl0eSxcbiAgICBfYmVmb3JlcHJpbnQ6IGlkZW50aXR5LFxuICAgIF9hZnRlcnByaW50OiBpZGVudGl0eSxcbiAgICBfbm9FdmVudERyb3A6IGlkZW50aXR5LFxuICAgIF9ub0V2ZW50UmVzaXplOiBpZGVudGl0eSxcbiAgICBfcmVzaXplOiBpZGVudGl0eSxcbiAgICBfc2Nyb2xsUmVxdWVzdDogaWRlbnRpdHksXG59O1xuLy8gY2FsZW5kYXItc3BlY2lmaWMgb3B0aW9uc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuY29uc3QgQ0FMRU5EQVJfT1BUSU9OX1JFRklORVJTID0ge1xuICAgIGJ1dHRvblRleHQ6IGlkZW50aXR5LFxuICAgIGJ1dHRvbkhpbnRzOiBpZGVudGl0eSxcbiAgICB2aWV3czogaWRlbnRpdHksXG4gICAgcGx1Z2luczogaWRlbnRpdHksXG4gICAgaW5pdGlhbEV2ZW50czogaWRlbnRpdHksXG4gICAgZXZlbnRzOiBpZGVudGl0eSxcbiAgICBldmVudFNvdXJjZXM6IGlkZW50aXR5LFxufTtcbmNvbnN0IENPTVBMRVhfT1BUSU9OX0NPTVBBUkFUT1JTID0ge1xuICAgIGhlYWRlclRvb2xiYXI6IGlzTWF5YmVPYmplY3RzRXF1YWwsXG4gICAgZm9vdGVyVG9vbGJhcjogaXNNYXliZU9iamVjdHNFcXVhbCxcbiAgICBidXR0b25UZXh0OiBpc01heWJlT2JqZWN0c0VxdWFsLFxuICAgIGJ1dHRvbkhpbnRzOiBpc01heWJlT2JqZWN0c0VxdWFsLFxuICAgIGJ1dHRvbkljb25zOiBpc01heWJlT2JqZWN0c0VxdWFsLFxuICAgIGRhdGVJbmNyZW1lbnQ6IGlzTWF5YmVPYmplY3RzRXF1YWwsXG4gICAgcGx1Z2luczogaXNNYXliZUFycmF5c0VxdWFsLFxuICAgIGV2ZW50czogaXNNYXliZUFycmF5c0VxdWFsLFxuICAgIGV2ZW50U291cmNlczogaXNNYXliZUFycmF5c0VxdWFsLFxuICAgIFsncmVzb3VyY2VzJ106IGlzTWF5YmVBcnJheXNFcXVhbCxcbn07XG5mdW5jdGlvbiBpc01heWJlT2JqZWN0c0VxdWFsKGEsIGIpIHtcbiAgICBpZiAodHlwZW9mIGEgPT09ICdvYmplY3QnICYmIHR5cGVvZiBiID09PSAnb2JqZWN0JyAmJiBhICYmIGIpIHsgLy8gYm90aCBub24tbnVsbCBvYmplY3RzXG4gICAgICAgIHJldHVybiBpc1Byb3BzRXF1YWwoYSwgYik7XG4gICAgfVxuICAgIHJldHVybiBhID09PSBiO1xufVxuZnVuY3Rpb24gaXNNYXliZUFycmF5c0VxdWFsKGEsIGIpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhKSAmJiBBcnJheS5pc0FycmF5KGIpKSB7XG4gICAgICAgIHJldHVybiBpc0FycmF5c0VxdWFsKGEsIGIpO1xuICAgIH1cbiAgICByZXR1cm4gYSA9PT0gYjtcbn1cbi8vIHZpZXctc3BlY2lmaWMgb3B0aW9uc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5jb25zdCBWSUVXX09QVElPTl9SRUZJTkVSUyA9IHtcbiAgICB0eXBlOiBTdHJpbmcsXG4gICAgY29tcG9uZW50OiBpZGVudGl0eSxcbiAgICBidXR0b25UZXh0OiBTdHJpbmcsXG4gICAgYnV0dG9uVGV4dEtleTogU3RyaW5nLFxuICAgIGRhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3M6IGlkZW50aXR5LFxuICAgIHVzZXNNaW5NYXhUaW1lOiBCb29sZWFuLFxuICAgIGNsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIGNvbnRlbnQ6IGlkZW50aXR5LFxuICAgIGRpZE1vdW50OiBpZGVudGl0eSxcbiAgICB3aWxsVW5tb3VudDogaWRlbnRpdHksXG59O1xuLy8gdXRpbCBmdW5jc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gbWVyZ2VSYXdPcHRpb25zKG9wdGlvblNldHMpIHtcbiAgICByZXR1cm4gbWVyZ2VQcm9wcyhvcHRpb25TZXRzLCBDT01QTEVYX09QVElPTl9DT01QQVJBVE9SUyk7XG59XG5mdW5jdGlvbiByZWZpbmVQcm9wcyhpbnB1dCwgcmVmaW5lcnMpIHtcbiAgICBsZXQgcmVmaW5lZCA9IHt9O1xuICAgIGxldCBleHRyYSA9IHt9O1xuICAgIGZvciAobGV0IHByb3BOYW1lIGluIHJlZmluZXJzKSB7XG4gICAgICAgIGlmIChwcm9wTmFtZSBpbiBpbnB1dCkge1xuICAgICAgICAgICAgcmVmaW5lZFtwcm9wTmFtZV0gPSByZWZpbmVyc1twcm9wTmFtZV0oaW5wdXRbcHJvcE5hbWVdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGxldCBwcm9wTmFtZSBpbiBpbnB1dCkge1xuICAgICAgICBpZiAoIShwcm9wTmFtZSBpbiByZWZpbmVycykpIHtcbiAgICAgICAgICAgIGV4dHJhW3Byb3BOYW1lXSA9IGlucHV0W3Byb3BOYW1lXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyByZWZpbmVkLCBleHRyYSB9O1xufVxuZnVuY3Rpb24gaWRlbnRpdHkocmF3KSB7XG4gICAgcmV0dXJuIHJhdztcbn1cblxuY29uc3QgeyBoYXNPd25Qcm9wZXJ0eSB9ID0gT2JqZWN0LnByb3RvdHlwZTtcbi8vIE1lcmdlcyBhbiBhcnJheSBvZiBvYmplY3RzIGludG8gYSBzaW5nbGUgb2JqZWN0LlxuLy8gVGhlIHNlY29uZCBhcmd1bWVudCBhbGxvd3MgZm9yIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIHdobydzIG9iamVjdCB2YWx1ZXMgd2lsbCBiZSBtZXJnZWQgdG9nZXRoZXIuXG5mdW5jdGlvbiBtZXJnZVByb3BzKHByb3BPYmpzLCBjb21wbGV4UHJvcHNNYXApIHtcbiAgICBsZXQgZGVzdCA9IHt9O1xuICAgIGlmIChjb21wbGV4UHJvcHNNYXApIHtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBpbiBjb21wbGV4UHJvcHNNYXApIHtcbiAgICAgICAgICAgIGlmIChjb21wbGV4UHJvcHNNYXBbbmFtZV0gPT09IGlzTWF5YmVPYmplY3RzRXF1YWwpIHsgLy8gaW1wbGllcyB0aGF0IGl0J3Mgb2JqZWN0LW1lcmdlYWJsZVxuICAgICAgICAgICAgICAgIGxldCBjb21wbGV4T2JqcyA9IFtdO1xuICAgICAgICAgICAgICAgIC8vIGNvbGxlY3QgdGhlIHRyYWlsaW5nIG9iamVjdCB2YWx1ZXMsIHN0b3BwaW5nIHdoZW4gYSBub24tb2JqZWN0IGlzIGRpc2NvdmVyZWRcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gcHJvcE9ianMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHZhbCA9IHByb3BPYmpzW2ldW25hbWVdO1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsKSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxleE9ianMudW5zaGlmdCh2YWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0W25hbWVdID0gdmFsOyAvLyBpZiB0aGVyZSB3ZXJlIG5vIG9iamVjdHMsIHRoaXMgdmFsdWUgd2lsbCBiZSB1c2VkXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgdHJhaWxpbmcgdmFsdWVzIHdlcmUgb2JqZWN0cywgdXNlIHRoZSBtZXJnZWQgdmFsdWVcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxleE9ianMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3RbbmFtZV0gPSBtZXJnZVByb3BzKGNvbXBsZXhPYmpzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gY29weSB2YWx1ZXMgaW50byB0aGUgZGVzdGluYXRpb24sIGdvaW5nIGZyb20gbGFzdCB0byBmaXJzdFxuICAgIGZvciAobGV0IGkgPSBwcm9wT2Jqcy5sZW5ndGggLSAxOyBpID49IDA7IGkgLT0gMSkge1xuICAgICAgICBsZXQgcHJvcHMgPSBwcm9wT2Jqc1tpXTtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgaWYgKCEobmFtZSBpbiBkZXN0KSkgeyAvLyBpZiBhbHJlYWR5IGFzc2lnbmVkIGJ5IHByZXZpb3VzIHByb3BzIG9yIGNvbXBsZXggcHJvcHMsIGRvbid0IHJlYXNzaWduXG4gICAgICAgICAgICAgICAgZGVzdFtuYW1lXSA9IHByb3BzW25hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkZXN0O1xufVxuZnVuY3Rpb24gZmlsdGVySGFzaChoYXNoLCBmdW5jKSB7XG4gICAgbGV0IGZpbHRlcmVkID0ge307XG4gICAgZm9yIChsZXQga2V5IGluIGhhc2gpIHtcbiAgICAgICAgaWYgKGZ1bmMoaGFzaFtrZXldLCBrZXkpKSB7XG4gICAgICAgICAgICBmaWx0ZXJlZFtrZXldID0gaGFzaFtrZXldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmaWx0ZXJlZDtcbn1cbmZ1bmN0aW9uIG1hcEhhc2goaGFzaCwgZnVuYykge1xuICAgIGxldCBuZXdIYXNoID0ge307XG4gICAgZm9yIChsZXQga2V5IGluIGhhc2gpIHtcbiAgICAgICAgbmV3SGFzaFtrZXldID0gZnVuYyhoYXNoW2tleV0sIGtleSk7XG4gICAgfVxuICAgIHJldHVybiBuZXdIYXNoO1xufVxuZnVuY3Rpb24gYXJyYXlUb0hhc2goYSkge1xuICAgIGxldCBoYXNoID0ge307XG4gICAgZm9yIChsZXQgaXRlbSBvZiBhKSB7XG4gICAgICAgIGhhc2hbaXRlbV0gPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gaGFzaDtcbn1cbi8vIFRPRE86IHJlYXNzZXNzIGJyb3dzZXIgc3VwcG9ydFxuLy8gaHR0cHM6Ly9jYW5pdXNlLmNvbS8/c2VhcmNoPW9iamVjdC52YWx1ZXNcbmZ1bmN0aW9uIGhhc2hWYWx1ZXNUb0FycmF5KG9iaikge1xuICAgIGxldCBhID0gW107XG4gICAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgICAgICBhLnB1c2gob2JqW2tleV0pO1xuICAgIH1cbiAgICByZXR1cm4gYTtcbn1cbmZ1bmN0aW9uIGlzUHJvcHNFcXVhbChvYmowLCBvYmoxKSB7XG4gICAgaWYgKG9iajAgPT09IG9iajEpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGZvciAobGV0IGtleSBpbiBvYmowKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iajAsIGtleSkpIHtcbiAgICAgICAgICAgIGlmICghKGtleSBpbiBvYmoxKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGxldCBrZXkgaW4gb2JqMSkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmoxLCBrZXkpKSB7XG4gICAgICAgICAgICBpZiAob2JqMFtrZXldICE9PSBvYmoxW2tleV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5jb25zdCBIQU5ETEVSX1JFID0gL15vbltBLVpdLztcbmZ1bmN0aW9uIGlzTm9uSGFuZGxlclByb3BzRXF1YWwob2JqMCwgb2JqMSkge1xuICAgIGNvbnN0IGtleXMgPSBnZXRVbmVxdWFsUHJvcHMob2JqMCwgb2JqMSk7XG4gICAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICAgICAgaWYgKCFIQU5ETEVSX1JFLnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gZ2V0VW5lcXVhbFByb3BzKG9iajAsIG9iajEpIHtcbiAgICBsZXQga2V5cyA9IFtdO1xuICAgIGZvciAobGV0IGtleSBpbiBvYmowKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iajAsIGtleSkpIHtcbiAgICAgICAgICAgIGlmICghKGtleSBpbiBvYmoxKSkge1xuICAgICAgICAgICAgICAgIGtleXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAobGV0IGtleSBpbiBvYmoxKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iajEsIGtleSkpIHtcbiAgICAgICAgICAgIGlmIChvYmowW2tleV0gIT09IG9iajFba2V5XSkge1xuICAgICAgICAgICAgICAgIGtleXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBrZXlzO1xufVxuZnVuY3Rpb24gY29tcGFyZU9ianMob2xkUHJvcHMsIG5ld1Byb3BzLCBlcXVhbGl0eUZ1bmNzID0ge30pIHtcbiAgICBpZiAob2xkUHJvcHMgPT09IG5ld1Byb3BzKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBpZiAoZGVidWcpIHtcbiAgICAvLyAgIGZvciAobGV0IGtleSBpbiBuZXdQcm9wcykge1xuICAgIC8vICAgICBpZiAoa2V5IGluIG9sZFByb3BzICYmIGlzT2JqVmFsc0VxdWFsKG9sZFByb3BzW2tleV0sIG5ld1Byb3BzW2tleV0sIGVxdWFsaXR5RnVuY3Nba2V5XSkpIHtcbiAgICAvLyAgICAgICAvLyBlcXVhbFxuICAgIC8vICAgICB9IGVsc2Uge1xuICAgIC8vICAgICAgIGlmIChkZWJ1Zykge1xuICAgIC8vICAgICAgICAgY29uc29sZS5sb2coJ3Byb3AgZGlmZmVyZW5jZScsIGtleSwgb2xkUHJvcHNba2V5XSwgbmV3UHJvcHNba2V5XSlcbiAgICAvLyAgICAgICB9XG4gICAgLy8gICAgIH1cbiAgICAvLyAgIH1cbiAgICAvLyAgIC8vIGNoZWNrIGZvciBwcm9wcyB0aGF0IHdlcmUgb21pdHRlZCBpbiB0aGUgbmV3XG4gICAgLy8gICBmb3IgKGxldCBrZXkgaW4gb2xkUHJvcHMpIHtcbiAgICAvLyAgICAgaWYgKCEoa2V5IGluIG5ld1Byb3BzKSkge1xuICAgIC8vICAgICAgIGlmIChkZWJ1Zykge1xuICAgIC8vICAgICAgICAgY29uc29sZS5sb2coJ3Byb3AgYWJzZW50Jywga2V5KVxuICAgIC8vICAgICAgIH1cbiAgICAvLyAgICAgfVxuICAgIC8vICAgfVxuICAgIC8vIH1cbiAgICBmb3IgKGxldCBrZXkgaW4gbmV3UHJvcHMpIHtcbiAgICAgICAgaWYgKGtleSBpbiBvbGRQcm9wcyAmJiBpc09ialZhbHNFcXVhbChvbGRQcm9wc1trZXldLCBuZXdQcm9wc1trZXldLCBlcXVhbGl0eUZ1bmNzW2tleV0pKSA7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGNoZWNrIGZvciBwcm9wcyB0aGF0IHdlcmUgb21pdHRlZCBpbiB0aGUgbmV3XG4gICAgZm9yIChsZXQga2V5IGluIG9sZFByb3BzKSB7XG4gICAgICAgIGlmICghKGtleSBpbiBuZXdQcm9wcykpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8qXG5hc3N1bWVkIFwidHJ1ZVwiIGVxdWFsaXR5IGZvciBoYW5kbGVyIG5hbWVzIGxpa2UgXCJvblJlY2VpdmVTb21ldGhpbmdcIlxuKi9cbmZ1bmN0aW9uIGlzT2JqVmFsc0VxdWFsKHZhbDAsIHZhbDEsIGNvbXBhcmF0b3IpIHtcbiAgICBpZiAodmFsMCA9PT0gdmFsMSB8fCBjb21wYXJhdG9yID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoY29tcGFyYXRvcikge1xuICAgICAgICByZXR1cm4gY29tcGFyYXRvcih2YWwwLCB2YWwxKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gY29sbGVjdEZyb21IYXNoKGhhc2gsIHN0YXJ0SW5kZXggPSAwLCBlbmRJbmRleCwgc3RlcCA9IDEpIHtcbiAgICBsZXQgcmVzID0gW107XG4gICAgaWYgKGVuZEluZGV4ID09IG51bGwpIHtcbiAgICAgICAgZW5kSW5kZXggPSBPYmplY3Qua2V5cyhoYXNoKS5sZW5ndGg7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgZW5kSW5kZXg7IGkgKz0gc3RlcCkge1xuICAgICAgICBsZXQgdmFsID0gaGFzaFtpXTtcbiAgICAgICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7IC8vIHdpbGwgZGlzcmVnYXJkIHVuZGVmaW5lZCBmb3Igc3BhcnNlIGFycmF5c1xuICAgICAgICAgICAgcmVzLnB1c2godmFsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5sZXQgY2FsZW5kYXJTeXN0ZW1DbGFzc01hcCA9IHt9O1xuZnVuY3Rpb24gcmVnaXN0ZXJDYWxlbmRhclN5c3RlbShuYW1lLCB0aGVDbGFzcykge1xuICAgIGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXBbbmFtZV0gPSB0aGVDbGFzcztcbn1cbmZ1bmN0aW9uIGNyZWF0ZUNhbGVuZGFyU3lzdGVtKG5hbWUpIHtcbiAgICByZXR1cm4gbmV3IGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXBbbmFtZV0oKTtcbn1cbmNsYXNzIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtIHtcbiAgICBnZXRNYXJrZXJZZWFyKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZ2V0VVRDRnVsbFllYXIoKTtcbiAgICB9XG4gICAgZ2V0TWFya2VyTW9udGgoZCkge1xuICAgICAgICByZXR1cm4gZC5nZXRVVENNb250aCgpO1xuICAgIH1cbiAgICBnZXRNYXJrZXJEYXkoZCkge1xuICAgICAgICByZXR1cm4gZC5nZXRVVENEYXRlKCk7XG4gICAgfVxuICAgIGFycmF5VG9NYXJrZXIoYXJyKSB7XG4gICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShhcnIpO1xuICAgIH1cbiAgICBtYXJrZXJUb0FycmF5KG1hcmtlcikge1xuICAgICAgICByZXR1cm4gZGF0ZVRvVXRjQXJyYXkobWFya2VyKTtcbiAgICB9XG59XG5yZWdpc3RlckNhbGVuZGFyU3lzdGVtKCdncmVnb3J5JywgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0pO1xuXG5jb25zdCBJU09fUkUgPSAvXlxccyooXFxkezR9KSgtPyhcXGR7Mn0pKC0/KFxcZHsyfSkoW1QgXShcXGR7Mn0pOj8oXFxkezJ9KSg6PyhcXGR7Mn0pKFxcLihcXGQrKSk/KT8oWnwoKFstK10pKFxcZHsyfSkoOj8oXFxkezJ9KSk/KSk/KT8pPyk/JC87XG5mdW5jdGlvbiBwYXJzZShzdHIpIHtcbiAgICBsZXQgbSA9IElTT19SRS5leGVjKHN0cik7XG4gICAgaWYgKG0pIHtcbiAgICAgICAgbGV0IG1hcmtlciA9IG5ldyBEYXRlKERhdGUuVVRDKE51bWJlcihtWzFdKSwgbVszXSA/IE51bWJlcihtWzNdKSAtIDEgOiAwLCBOdW1iZXIobVs1XSB8fCAxKSwgTnVtYmVyKG1bN10gfHwgMCksIE51bWJlcihtWzhdIHx8IDApLCBOdW1iZXIobVsxMF0gfHwgMCksIG1bMTJdID8gTnVtYmVyKGAwLiR7bVsxMl19YCkgKiAxMDAwIDogMCkpO1xuICAgICAgICBpZiAoaXNWYWxpZERhdGUobWFya2VyKSkge1xuICAgICAgICAgICAgbGV0IHRpbWVab25lT2Zmc2V0ID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChtWzEzXSkge1xuICAgICAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0ID0gKG1bMTVdID09PSAnLScgPyAtMSA6IDEpICogKE51bWJlcihtWzE2XSB8fCAwKSAqIDYwICtcbiAgICAgICAgICAgICAgICAgICAgTnVtYmVyKG1bMThdIHx8IDApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbWFya2VyLFxuICAgICAgICAgICAgICAgIGlzVGltZVVuc3BlY2lmaWVkOiAhbVs2XSxcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmNsYXNzIERhdGVFbnYge1xuICAgIGNvbnN0cnVjdG9yKHNldHRpbmdzKSB7XG4gICAgICAgIGxldCB0aW1lWm9uZSA9IHRoaXMudGltZVpvbmUgPSBzZXR0aW5ncy50aW1lWm9uZTtcbiAgICAgICAgbGV0IGlzTmFtZWRUaW1lWm9uZSA9IHRpbWVab25lICE9PSAnbG9jYWwnICYmIHRpbWVab25lICE9PSAnVVRDJztcbiAgICAgICAgaWYgKHNldHRpbmdzLm5hbWVkVGltZVpvbmVJbXBsICYmIGlzTmFtZWRUaW1lWm9uZSkge1xuICAgICAgICAgICAgdGhpcy5uYW1lZFRpbWVab25lSW1wbCA9IG5ldyBzZXR0aW5ncy5uYW1lZFRpbWVab25lSW1wbCh0aW1lWm9uZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jYW5Db21wdXRlT2Zmc2V0ID0gQm9vbGVhbighaXNOYW1lZFRpbWVab25lIHx8IHRoaXMubmFtZWRUaW1lWm9uZUltcGwpO1xuICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtID0gY3JlYXRlQ2FsZW5kYXJTeXN0ZW0oc2V0dGluZ3MuY2FsZW5kYXJTeXN0ZW0pO1xuICAgICAgICB0aGlzLmxvY2FsZSA9IHNldHRpbmdzLmxvY2FsZTtcbiAgICAgICAgdGhpcy53ZWVrRG93ID0gc2V0dGluZ3MubG9jYWxlLndlZWsuZG93O1xuICAgICAgICB0aGlzLndlZWtEb3kgPSBzZXR0aW5ncy5sb2NhbGUud2Vlay5kb3k7XG4gICAgICAgIGlmIChzZXR0aW5ncy53ZWVrTnVtYmVyQ2FsY3VsYXRpb24gPT09ICdJU08nKSB7XG4gICAgICAgICAgICB0aGlzLndlZWtEb3cgPSAxO1xuICAgICAgICAgICAgdGhpcy53ZWVrRG95ID0gNDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzLmZpcnN0RGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgdGhpcy53ZWVrRG93ID0gc2V0dGluZ3MuZmlyc3REYXk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy53ZWVrTnVtYmVyQ2FsY3VsYXRpb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRoaXMud2Vla051bWJlckZ1bmMgPSBzZXR0aW5ncy53ZWVrTnVtYmVyQ2FsY3VsYXRpb247XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53ZWVrVGV4dCA9IHNldHRpbmdzLndlZWtUZXh0ICE9IG51bGwgPyBzZXR0aW5ncy53ZWVrVGV4dCA6IHNldHRpbmdzLmxvY2FsZS5vcHRpb25zLndlZWtUZXh0O1xuICAgICAgICB0aGlzLndlZWtUZXh0TG9uZyA9IChzZXR0aW5ncy53ZWVrVGV4dExvbmcgIT0gbnVsbCA/IHNldHRpbmdzLndlZWtUZXh0TG9uZyA6IHNldHRpbmdzLmxvY2FsZS5vcHRpb25zLndlZWtUZXh0TG9uZykgfHwgdGhpcy53ZWVrVGV4dDtcbiAgICAgICAgdGhpcy5jbWRGb3JtYXR0ZXIgPSBzZXR0aW5ncy5jbWRGb3JtYXR0ZXI7XG4gICAgICAgIHRoaXMuZGVmYXVsdFNlcGFyYXRvciA9IHNldHRpbmdzLmRlZmF1bHRTZXBhcmF0b3I7XG4gICAgfVxuICAgIC8vIENyZWF0aW5nIC8gUGFyc2luZ1xuICAgIGNyZWF0ZU1hcmtlcihpbnB1dCkge1xuICAgICAgICBsZXQgbWV0YSA9IHRoaXMuY3JlYXRlTWFya2VyTWV0YShpbnB1dCk7XG4gICAgICAgIGlmIChtZXRhID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWV0YS5tYXJrZXI7XG4gICAgfVxuICAgIGNyZWF0ZU5vd01hcmtlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuY2FuQ29tcHV0ZU9mZnNldCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGltZXN0YW1wVG9NYXJrZXIobmV3IERhdGUoKS52YWx1ZU9mKCkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlIGNhbid0IGNvbXB1dGUgdGhlIGN1cnJlbnQgZGF0ZSB2YWwgZm9yIGEgdGltZXpvbmUsXG4gICAgICAgIC8vIGJldHRlciB0byBnaXZlIHRoZSBjdXJyZW50IGxvY2FsIGRhdGUgdmFscyB0aGFuIFVUQ1xuICAgICAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoZGF0ZVRvTG9jYWxBcnJheShuZXcgRGF0ZSgpKSk7XG4gICAgfVxuICAgIGNyZWF0ZU1hcmtlck1ldGEoaW5wdXQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcnNlKGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbWFya2VyID0gbnVsbDtcbiAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIG1hcmtlciA9IHRoaXMudGltZXN0YW1wVG9NYXJrZXIoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlucHV0IGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICAgICAgaW5wdXQgPSBpbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgICAgICBpZiAoIWlzTmFOKGlucHV0KSkge1xuICAgICAgICAgICAgICAgIG1hcmtlciA9IHRoaXMudGltZXN0YW1wVG9NYXJrZXIoaW5wdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgICAgICBtYXJrZXIgPSBhcnJheVRvVXRjRGF0ZShpbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1hcmtlciA9PT0gbnVsbCB8fCAhaXNWYWxpZERhdGUobWFya2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgbWFya2VyLCBpc1RpbWVVbnNwZWNpZmllZDogZmFsc2UsIGZvcmNlZFR6bzogbnVsbCB9O1xuICAgIH1cbiAgICBwYXJzZShzKSB7XG4gICAgICAgIGxldCBwYXJ0cyA9IHBhcnNlKHMpO1xuICAgICAgICBpZiAocGFydHMgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGxldCB7IG1hcmtlciB9ID0gcGFydHM7XG4gICAgICAgIGxldCBmb3JjZWRUem8gPSBudWxsO1xuICAgICAgICBpZiAocGFydHMudGltZVpvbmVPZmZzZXQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNhbkNvbXB1dGVPZmZzZXQpIHtcbiAgICAgICAgICAgICAgICBtYXJrZXIgPSB0aGlzLnRpbWVzdGFtcFRvTWFya2VyKG1hcmtlci52YWx1ZU9mKCkgLSBwYXJ0cy50aW1lWm9uZU9mZnNldCAqIDYwICogMTAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3JjZWRUem8gPSBwYXJ0cy50aW1lWm9uZU9mZnNldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBtYXJrZXIsIGlzVGltZVVuc3BlY2lmaWVkOiBwYXJ0cy5pc1RpbWVVbnNwZWNpZmllZCwgZm9yY2VkVHpvIH07XG4gICAgfVxuICAgIC8vIEFjY2Vzc29yc1xuICAgIGdldFllYXIobWFya2VyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobWFya2VyKTtcbiAgICB9XG4gICAgZ2V0TW9udGgobWFya2VyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG1hcmtlcik7XG4gICAgfVxuICAgIGdldERheShtYXJrZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyRGF5KG1hcmtlcik7XG4gICAgfVxuICAgIC8vIEFkZGluZyAvIFN1YnRyYWN0aW5nXG4gICAgYWRkKG1hcmtlciwgZHVyKSB7XG4gICAgICAgIGxldCBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMF0gKz0gZHVyLnllYXJzO1xuICAgICAgICBhWzFdICs9IGR1ci5tb250aHM7XG4gICAgICAgIGFbMl0gKz0gZHVyLmRheXM7XG4gICAgICAgIGFbNl0gKz0gZHVyLm1pbGxpc2Vjb25kcztcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9XG4gICAgc3VidHJhY3QobWFya2VyLCBkdXIpIHtcbiAgICAgICAgbGV0IGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVswXSAtPSBkdXIueWVhcnM7XG4gICAgICAgIGFbMV0gLT0gZHVyLm1vbnRocztcbiAgICAgICAgYVsyXSAtPSBkdXIuZGF5cztcbiAgICAgICAgYVs2XSAtPSBkdXIubWlsbGlzZWNvbmRzO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH1cbiAgICBhZGRZZWFycyhtYXJrZXIsIG4pIHtcbiAgICAgICAgbGV0IGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVswXSArPSBuO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH1cbiAgICBhZGRNb250aHMobWFya2VyLCBuKSB7XG4gICAgICAgIGxldCBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMV0gKz0gbjtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9XG4gICAgLy8gRGlmZmluZyBXaG9sZSBVbml0c1xuICAgIGRpZmZXaG9sZVllYXJzKG0wLCBtMSkge1xuICAgICAgICBsZXQgeyBjYWxlbmRhclN5c3RlbSB9ID0gdGhpcztcbiAgICAgICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpICYmXG4gICAgICAgICAgICBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTApID09PSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTEpICYmXG4gICAgICAgICAgICBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtMCkgPT09IGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0xKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobTEpIC0gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtMCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRpZmZXaG9sZU1vbnRocyhtMCwgbTEpIHtcbiAgICAgICAgbGV0IHsgY2FsZW5kYXJTeXN0ZW0gfSA9IHRoaXM7XG4gICAgICAgIGlmICh0aW1lQXNNcyhtMCkgPT09IHRpbWVBc01zKG0xKSAmJlxuICAgICAgICAgICAgY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyRGF5KG0wKSA9PT0gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyRGF5KG0xKSkge1xuICAgICAgICAgICAgcmV0dXJuIChjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtMSkgLSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtMCkpICtcbiAgICAgICAgICAgICAgICAoY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtMSkgLSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0wKSkgKiAxMjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gUmFuZ2UgLyBEdXJhdGlvblxuICAgIGdyZWF0ZXN0V2hvbGVVbml0KG0wLCBtMSkge1xuICAgICAgICBsZXQgbiA9IHRoaXMuZGlmZldob2xlWWVhcnMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICd5ZWFyJywgdmFsdWU6IG4gfTtcbiAgICAgICAgfVxuICAgICAgICBuID0gdGhpcy5kaWZmV2hvbGVNb250aHMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdtb250aCcsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZXaG9sZVdlZWtzKG0wLCBtMSk7XG4gICAgICAgIGlmIChuICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnd2VlaycsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZXaG9sZURheXMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdkYXknLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmSG91cnMobTAsIG0xKTtcbiAgICAgICAgaWYgKGlzSW50KG4pKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnaG91cicsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZNaW51dGVzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbnV0ZScsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZTZWNvbmRzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3NlY29uZCcsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSB9O1xuICAgIH1cbiAgICBjb3VudER1cmF0aW9uc0JldHdlZW4obTAsIG0xLCBkKSB7XG4gICAgICAgIC8vIFRPRE86IGNhbiB1c2UgZ3JlYXRlc3RXaG9sZVVuaXRcbiAgICAgICAgbGV0IGRpZmY7XG4gICAgICAgIGlmIChkLnllYXJzKSB7XG4gICAgICAgICAgICBkaWZmID0gdGhpcy5kaWZmV2hvbGVZZWFycyhtMCwgbTEpO1xuICAgICAgICAgICAgaWYgKGRpZmYgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZiAvIGFzUm91Z2hZZWFycyhkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZC5tb250aHMpIHtcbiAgICAgICAgICAgIGRpZmYgPSB0aGlzLmRpZmZXaG9sZU1vbnRocyhtMCwgbTEpO1xuICAgICAgICAgICAgaWYgKGRpZmYgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZiAvIGFzUm91Z2hNb250aHMoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGQuZGF5cykge1xuICAgICAgICAgICAgZGlmZiA9IGRpZmZXaG9sZURheXMobTAsIG0xKTtcbiAgICAgICAgICAgIGlmIChkaWZmICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmYgLyBhc1JvdWdoRGF5cyhkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSkgLyBhc1JvdWdoTXMoZCk7XG4gICAgfVxuICAgIC8vIFN0YXJ0LU9mXG4gICAgLy8gdGhlc2UgRE9OJ1QgcmV0dXJuIHpvbmVkLWRhdGVzLiBvbmx5IFVUQyBzdGFydC1vZiBkYXRlc1xuICAgIHN0YXJ0T2YobSwgdW5pdCkge1xuICAgICAgICBpZiAodW5pdCA9PT0gJ3llYXInKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFydE9mWWVhcihtKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodW5pdCA9PT0gJ21vbnRoJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZk1vbnRoKG0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1bml0ID09PSAnd2VlaycpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2ZXZWVrKG0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1bml0ID09PSAnZGF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZEYXkobSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVuaXQgPT09ICdob3VyJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZIb3VyKG0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1bml0ID09PSAnbWludXRlJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZNaW51dGUobSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVuaXQgPT09ICdzZWNvbmQnKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RhcnRPZlNlY29uZChtKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgc3RhcnRPZlllYXIobSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKFtcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtKSxcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIHN0YXJ0T2ZNb250aChtKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmFycmF5VG9NYXJrZXIoW1xuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0pLFxuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtKSxcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIHN0YXJ0T2ZXZWVrKG0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihbXG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobSksXG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0pLFxuICAgICAgICAgICAgbS5nZXRVVENEYXRlKCkgLSAoKG0uZ2V0VVRDRGF5KCkgLSB0aGlzLndlZWtEb3cgKyA3KSAlIDcpLFxuICAgICAgICBdKTtcbiAgICB9XG4gICAgLy8gV2VlayBOdW1iZXJcbiAgICBjb21wdXRlV2Vla051bWJlcihtYXJrZXIpIHtcbiAgICAgICAgaWYgKHRoaXMud2Vla051bWJlckZ1bmMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndlZWtOdW1iZXJGdW5jKHRoaXMudG9EYXRlKG1hcmtlcikpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB3ZWVrT2ZZZWFyKG1hcmtlciwgdGhpcy53ZWVrRG93LCB0aGlzLndlZWtEb3kpO1xuICAgIH1cbiAgICAvLyBUT0RPOiBjaG9rZSBvbiB0aW1lWm9uZU5hbWU6IGxvbmdcbiAgICBmb3JtYXQobWFya2VyLCBmb3JtYXR0ZXIsIGRhdGVPcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXQoe1xuICAgICAgICAgICAgbWFya2VyLFxuICAgICAgICAgICAgdGltZVpvbmVPZmZzZXQ6IGRhdGVPcHRpb25zLmZvcmNlZFR6byAhPSBudWxsID9cbiAgICAgICAgICAgICAgICBkYXRlT3B0aW9ucy5mb3JjZWRUem8gOlxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0Rm9yTWFya2VyKG1hcmtlciksXG4gICAgICAgIH0sIHRoaXMpO1xuICAgIH1cbiAgICBmb3JtYXRSYW5nZShzdGFydCwgZW5kLCBmb3JtYXR0ZXIsIGRhdGVPcHRpb25zID0ge30pIHtcbiAgICAgICAgaWYgKGRhdGVPcHRpb25zLmlzRW5kRXhjbHVzaXZlKSB7XG4gICAgICAgICAgICBlbmQgPSBhZGRNcyhlbmQsIC0xKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm9ybWF0dGVyLmZvcm1hdFJhbmdlKHtcbiAgICAgICAgICAgIG1hcmtlcjogc3RhcnQsXG4gICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZU9wdGlvbnMuZm9yY2VkU3RhcnRUem8gIT0gbnVsbCA/XG4gICAgICAgICAgICAgICAgZGF0ZU9wdGlvbnMuZm9yY2VkU3RhcnRUem8gOlxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0Rm9yTWFya2VyKHN0YXJ0KSxcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgbWFya2VyOiBlbmQsXG4gICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZU9wdGlvbnMuZm9yY2VkRW5kVHpvICE9IG51bGwgP1xuICAgICAgICAgICAgICAgIGRhdGVPcHRpb25zLmZvcmNlZEVuZFR6byA6XG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXRGb3JNYXJrZXIoZW5kKSxcbiAgICAgICAgfSwgdGhpcywgZGF0ZU9wdGlvbnMuZGVmYXVsdFNlcGFyYXRvcik7XG4gICAgfVxuICAgIC8qXG4gICAgRFVNQjogdGhlIG9taXRUaW1lIGFyZyBpcyBkdW1iLiBpZiB3ZSBvbWl0IHRoZSB0aW1lLCB3ZSB3YW50IHRvIG9taXQgdGhlIHRpbWV6b25lIG9mZnNldC4gYW5kIGlmIHdlIGRvIHRoYXQsXG4gICAgbWlnaHQgYXMgd2VsbCB1c2UgYnVpbGRJc29TdHJpbmcgb3Igc29tZSBvdGhlciB1dGlsIGRpcmVjdGx5XG4gICAgKi9cbiAgICBmb3JtYXRJc28obWFya2VyLCBleHRyYU9wdGlvbnMgPSB7fSkge1xuICAgICAgICBsZXQgdGltZVpvbmVPZmZzZXQgPSBudWxsO1xuICAgICAgICBpZiAoIWV4dHJhT3B0aW9ucy5vbWl0VGltZVpvbmVPZmZzZXQpIHtcbiAgICAgICAgICAgIGlmIChleHRyYU9wdGlvbnMuZm9yY2VkVHpvICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCA9IGV4dHJhT3B0aW9ucy5mb3JjZWRUem87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCA9IHRoaXMub2Zmc2V0Rm9yTWFya2VyKG1hcmtlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJ1aWxkSXNvU3RyaW5nKG1hcmtlciwgdGltZVpvbmVPZmZzZXQsIGV4dHJhT3B0aW9ucy5vbWl0VGltZSk7XG4gICAgfVxuICAgIC8vIFRpbWVab25lXG4gICAgdGltZXN0YW1wVG9NYXJrZXIobXMpIHtcbiAgICAgICAgaWYgKHRoaXMudGltZVpvbmUgPT09ICdsb2NhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShkYXRlVG9Mb2NhbEFycmF5KG5ldyBEYXRlKG1zKSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnRpbWVab25lID09PSAnVVRDJyB8fCAhdGhpcy5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG1zKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUodGhpcy5uYW1lZFRpbWVab25lSW1wbC50aW1lc3RhbXBUb0FycmF5KG1zKSk7XG4gICAgfVxuICAgIG9mZnNldEZvck1hcmtlcihtKSB7XG4gICAgICAgIGlmICh0aGlzLnRpbWVab25lID09PSAnbG9jYWwnKSB7XG4gICAgICAgICAgICByZXR1cm4gLWFycmF5VG9Mb2NhbERhdGUoZGF0ZVRvVXRjQXJyYXkobSkpLmdldFRpbWV6b25lT2Zmc2V0KCk7IC8vIGNvbnZlcnQgXCJpbnZlcnNlXCIgb2Zmc2V0IHRvIFwibm9ybWFsXCIgb2Zmc2V0XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFtZWRUaW1lWm9uZUltcGwub2Zmc2V0Rm9yQXJyYXkoZGF0ZVRvVXRjQXJyYXkobSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICAvLyBDb252ZXJzaW9uXG4gICAgdG9EYXRlKG0sIGZvcmNlZFR6bykge1xuICAgICAgICBpZiAodGhpcy50aW1lWm9uZSA9PT0gJ2xvY2FsJykge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9Mb2NhbERhdGUoZGF0ZVRvVXRjQXJyYXkobSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnRpbWVab25lID09PSAnVVRDJykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG0udmFsdWVPZigpKTsgLy8gbWFrZSBzdXJlIGl0J3MgYSBjb3B5XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLm5hbWVkVGltZVpvbmVJbXBsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobS52YWx1ZU9mKCkgLSAoZm9yY2VkVHpvIHx8IDApKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IERhdGUobS52YWx1ZU9mKCkgLVxuICAgICAgICAgICAgdGhpcy5uYW1lZFRpbWVab25lSW1wbC5vZmZzZXRGb3JBcnJheShkYXRlVG9VdGNBcnJheShtKSkgKiAxMDAwICogNjApO1xuICAgIH1cbn1cblxuY2xhc3MgVGhlbWUge1xuICAgIGNvbnN0cnVjdG9yKGNhbGVuZGFyT3B0aW9ucykge1xuICAgICAgICBpZiAodGhpcy5pY29uT3ZlcnJpZGVPcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuc2V0SWNvbk92ZXJyaWRlKGNhbGVuZGFyT3B0aW9uc1t0aGlzLmljb25PdmVycmlkZU9wdGlvbl0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHNldEljb25PdmVycmlkZShpY29uT3ZlcnJpZGVIYXNoKSB7XG4gICAgICAgIGxldCBpY29uQ2xhc3Nlc0NvcHk7XG4gICAgICAgIGxldCBidXR0b25OYW1lO1xuICAgICAgICBpZiAodHlwZW9mIGljb25PdmVycmlkZUhhc2ggPT09ICdvYmplY3QnICYmIGljb25PdmVycmlkZUhhc2gpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgICAgICBpY29uQ2xhc3Nlc0NvcHkgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmljb25DbGFzc2VzKTtcbiAgICAgICAgICAgIGZvciAoYnV0dG9uTmFtZSBpbiBpY29uT3ZlcnJpZGVIYXNoKSB7XG4gICAgICAgICAgICAgICAgaWNvbkNsYXNzZXNDb3B5W2J1dHRvbk5hbWVdID0gdGhpcy5hcHBseUljb25PdmVycmlkZVByZWZpeChpY29uT3ZlcnJpZGVIYXNoW2J1dHRvbk5hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaWNvbkNsYXNzZXMgPSBpY29uQ2xhc3Nlc0NvcHk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaWNvbk92ZXJyaWRlSGFzaCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMuaWNvbkNsYXNzZXMgPSB7fTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhcHBseUljb25PdmVycmlkZVByZWZpeChjbGFzc05hbWUpIHtcbiAgICAgICAgbGV0IHByZWZpeCA9IHRoaXMuaWNvbk92ZXJyaWRlUHJlZml4O1xuICAgICAgICBpZiAocHJlZml4ICYmIGNsYXNzTmFtZS5pbmRleE9mKHByZWZpeCkgIT09IDApIHsgLy8gaWYgbm90IGFscmVhZHkgcHJlc2VudFxuICAgICAgICAgICAgY2xhc3NOYW1lID0gcHJlZml4ICsgY2xhc3NOYW1lO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbGFzc05hbWU7XG4gICAgfVxuICAgIGdldENsYXNzKGtleSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jbGFzc2VzW2tleV0gfHwgJyc7XG4gICAgfVxuICAgIGdldEljb25DbGFzcyhidXR0b25OYW1lLCBpc1J0bCkge1xuICAgICAgICBsZXQgY2xhc3NOYW1lO1xuICAgICAgICBpZiAoaXNSdGwgJiYgdGhpcy5ydGxJY29uQ2xhc3Nlcykge1xuICAgICAgICAgICAgY2xhc3NOYW1lID0gdGhpcy5ydGxJY29uQ2xhc3Nlc1tidXR0b25OYW1lXSB8fCB0aGlzLmljb25DbGFzc2VzW2J1dHRvbk5hbWVdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NOYW1lID0gdGhpcy5pY29uQ2xhc3Nlc1tidXR0b25OYW1lXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gYCR7dGhpcy5iYXNlSWNvbkNsYXNzfSAke2NsYXNzTmFtZX1gO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgZ2V0Q3VzdG9tQnV0dG9uSWNvbkNsYXNzKGN1c3RvbUJ1dHRvblByb3BzKSB7XG4gICAgICAgIGxldCBjbGFzc05hbWU7XG4gICAgICAgIGlmICh0aGlzLmljb25PdmVycmlkZUN1c3RvbUJ1dHRvbk9wdGlvbikge1xuICAgICAgICAgICAgY2xhc3NOYW1lID0gY3VzdG9tQnV0dG9uUHJvcHNbdGhpcy5pY29uT3ZlcnJpZGVDdXN0b21CdXR0b25PcHRpb25dO1xuICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBgJHt0aGlzLmJhc2VJY29uQ2xhc3N9ICR7dGhpcy5hcHBseUljb25PdmVycmlkZVByZWZpeChjbGFzc05hbWUpfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbn1cblRoZW1lLnByb3RvdHlwZS5jbGFzc2VzID0ge307XG5UaGVtZS5wcm90b3R5cGUuaWNvbkNsYXNzZXMgPSB7fTtcblRoZW1lLnByb3RvdHlwZS5iYXNlSWNvbkNsYXNzID0gJyc7XG5UaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlUHJlZml4ID0gJyc7XG5cbi8qXG5OT1RFOiB0aGlzIGNhbiBiZSBhIHB1YmxpYyBBUEksIGVzcGVjaWFsbHkgY3JlYXRlRWxlbWVudCBmb3IgaG9va3MuXG5TZWUgZXhhbXBsZXMvdHlwZXNjcmlwdC1zY2hlZHVsZXIvc3JjL2luZGV4LnRzXG4qL1xuZnVuY3Rpb24gZmx1c2hTeW5jKHJ1bkJlZm9yZUZsdXNoKSB7XG4gICAgcnVuQmVmb3JlRmx1c2goKTtcbiAgICBsZXQgb2xkRGVib3VuY2VSZW5kZXJpbmcgPSBwcmVhY3Qub3B0aW9ucy5kZWJvdW5jZVJlbmRlcmluZzsgLy8gb3JpZ1xuICAgIGxldCBjYWxsYmFja1EgPSBbXTtcbiAgICBmdW5jdGlvbiBleGVjQ2FsbGJhY2tTeW5jKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrUS5wdXNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgcHJlYWN0Lm9wdGlvbnMuZGVib3VuY2VSZW5kZXJpbmcgPSBleGVjQ2FsbGJhY2tTeW5jO1xuICAgIHByZWFjdC5yZW5kZXIocHJlYWN0LmNyZWF0ZUVsZW1lbnQoRmFrZUNvbXBvbmVudCwge30pLCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgd2hpbGUgKGNhbGxiYWNrUS5sZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2tRLnNoaWZ0KCkoKTtcbiAgICB9XG4gICAgcHJlYWN0Lm9wdGlvbnMuZGVib3VuY2VSZW5kZXJpbmcgPSBvbGREZWJvdW5jZVJlbmRlcmluZztcbn1cbmNsYXNzIEZha2VDb21wb25lbnQgZXh0ZW5kcyBwcmVhY3QuQ29tcG9uZW50IHtcbiAgICByZW5kZXIoKSB7IHJldHVybiBwcmVhY3QuY3JlYXRlRWxlbWVudCgnZGl2Jywge30pOyB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7IHRoaXMuc2V0U3RhdGUoe30pOyB9XG59XG4vLyBUT0RPOiB1c2UgcHJlYWN0L2NvbXBhdCBpbnN0ZWFkP1xuZnVuY3Rpb24gY3JlYXRlQ29udGV4dChkZWZhdWx0VmFsdWUpIHtcbiAgICBsZXQgQ29udGV4dFR5cGUgPSBwcmVhY3QuY3JlYXRlQ29udGV4dChkZWZhdWx0VmFsdWUpO1xuICAgIGxldCBvcmlnUHJvdmlkZXIgPSBDb250ZXh0VHlwZS5Qcm92aWRlcjtcbiAgICBDb250ZXh0VHlwZS5Qcm92aWRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IGlzTmV3ID0gIXRoaXMuZ2V0Q2hpbGRDb250ZXh0O1xuICAgICAgICBsZXQgY2hpbGRyZW4gPSBvcmlnUHJvdmlkZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBwcmVmZXItcmVzdC1wYXJhbXNcbiAgICAgICAgaWYgKGlzTmV3KSB7XG4gICAgICAgICAgICBsZXQgc3VicyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5zaG91bGRDb21wb25lbnRVcGRhdGUgPSAoX3Byb3BzKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucHJvcHMudmFsdWUgIT09IF9wcm9wcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBzdWJzLmZvckVhY2goKGMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY29udGV4dCA9IF9wcm9wcy52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZm9yY2VVcGRhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuc3ViID0gKGMpID0+IHtcbiAgICAgICAgICAgICAgICBzdWJzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgbGV0IG9sZCA9IGMuY29tcG9uZW50V2lsbFVubW91bnQ7XG4gICAgICAgICAgICAgICAgYy5jb21wb25lbnRXaWxsVW5tb3VudCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3Vicy5zcGxpY2Uoc3Vicy5pbmRleE9mKGMpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgb2xkICYmIG9sZC5jYWxsKGMpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaGlsZHJlbjtcbiAgICB9O1xuICAgIHJldHVybiBDb250ZXh0VHlwZTtcbn1cblxuY2xhc3MgU2Nyb2xsUmVzcG9uZGVyIHtcbiAgICBjb25zdHJ1Y3RvcihleGVjRnVuYywgZW1pdHRlciwgc2Nyb2xsVGltZSwgc2Nyb2xsVGltZVJlc2V0KSB7XG4gICAgICAgIHRoaXMuZXhlY0Z1bmMgPSBleGVjRnVuYztcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gZW1pdHRlcjtcbiAgICAgICAgdGhpcy5zY3JvbGxUaW1lID0gc2Nyb2xsVGltZTtcbiAgICAgICAgdGhpcy5zY3JvbGxUaW1lUmVzZXQgPSBzY3JvbGxUaW1lUmVzZXQ7XG4gICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsUmVxdWVzdCA9IChyZXF1ZXN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnF1ZXVlZFJlcXVlc3QgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLnF1ZXVlZFJlcXVlc3QgfHwge30sIHJlcXVlc3QpO1xuICAgICAgICAgICAgdGhpcy5kcmFpbigpO1xuICAgICAgICB9O1xuICAgICAgICBlbWl0dGVyLm9uKCdfc2Nyb2xsUmVxdWVzdCcsIHRoaXMuaGFuZGxlU2Nyb2xsUmVxdWVzdCk7XG4gICAgICAgIHRoaXMuZmlyZUluaXRpYWxTY3JvbGwoKTtcbiAgICB9XG4gICAgZGV0YWNoKCkge1xuICAgICAgICB0aGlzLmVtaXR0ZXIub2ZmKCdfc2Nyb2xsUmVxdWVzdCcsIHRoaXMuaGFuZGxlU2Nyb2xsUmVxdWVzdCk7XG4gICAgfVxuICAgIHVwZGF0ZShpc0RhdGVzTmV3KSB7XG4gICAgICAgIGlmIChpc0RhdGVzTmV3ICYmIHRoaXMuc2Nyb2xsVGltZVJlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLmZpcmVJbml0aWFsU2Nyb2xsKCk7IC8vIHdpbGwgZHJhaW5cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZHJhaW4oKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmaXJlSW5pdGlhbFNjcm9sbCgpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGxSZXF1ZXN0KHtcbiAgICAgICAgICAgIHRpbWU6IHRoaXMuc2Nyb2xsVGltZSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGRyYWluKCkge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZWRSZXF1ZXN0ICYmIHRoaXMuZXhlY0Z1bmModGhpcy5xdWV1ZWRSZXF1ZXN0KSkge1xuICAgICAgICAgICAgdGhpcy5xdWV1ZWRSZXF1ZXN0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuY29uc3QgVmlld0NvbnRleHRUeXBlID0gY3JlYXRlQ29udGV4dCh7fSk7IC8vIGZvciBDb21wb25lbnRzXG5mdW5jdGlvbiBidWlsZFZpZXdDb250ZXh0KHZpZXdTcGVjLCB2aWV3QXBpLCB2aWV3T3B0aW9ucywgZGF0ZVByb2ZpbGVHZW5lcmF0b3IsIGRhdGVFbnYsIG5vd01hbmFnZXIsIHRoZW1lLCBwbHVnaW5Ib29rcywgZGlzcGF0Y2gsIGdldEN1cnJlbnREYXRhLCBlbWl0dGVyLCBjYWxlbmRhckFwaSwgcmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCwgdW5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGF0ZUVudixcbiAgICAgICAgbm93TWFuYWdlcixcbiAgICAgICAgb3B0aW9uczogdmlld09wdGlvbnMsXG4gICAgICAgIHBsdWdpbkhvb2tzLFxuICAgICAgICBlbWl0dGVyLFxuICAgICAgICBkaXNwYXRjaCxcbiAgICAgICAgZ2V0Q3VycmVudERhdGEsXG4gICAgICAgIGNhbGVuZGFyQXBpLFxuICAgICAgICB2aWV3U3BlYyxcbiAgICAgICAgdmlld0FwaSxcbiAgICAgICAgZGF0ZVByb2ZpbGVHZW5lcmF0b3IsXG4gICAgICAgIHRoZW1lLFxuICAgICAgICBpc1J0bDogdmlld09wdGlvbnMuZGlyZWN0aW9uID09PSAncnRsJyxcbiAgICAgICAgYWRkUmVzaXplSGFuZGxlcihoYW5kbGVyKSB7XG4gICAgICAgICAgICBlbWl0dGVyLm9uKCdfcmVzaXplJywgaGFuZGxlcik7XG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZVJlc2l6ZUhhbmRsZXIoaGFuZGxlcikge1xuICAgICAgICAgICAgZW1pdHRlci5vZmYoJ19yZXNpemUnLCBoYW5kbGVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgY3JlYXRlU2Nyb2xsUmVzcG9uZGVyKGV4ZWNGdW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNjcm9sbFJlc3BvbmRlcihleGVjRnVuYywgZW1pdHRlciwgY3JlYXRlRHVyYXRpb24odmlld09wdGlvbnMuc2Nyb2xsVGltZSksIHZpZXdPcHRpb25zLnNjcm9sbFRpbWVSZXNldCk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQsXG4gICAgICAgIHVucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCxcbiAgICB9O1xufVxuXG4vKiBlc2xpbnQgbWF4LWNsYXNzZXMtcGVyLWZpbGU6IG9mZiAqL1xuY2xhc3MgUHVyZUNvbXBvbmVudCBleHRlbmRzIENvbXBvbmVudCB7XG4gICAgLy8gZGVidWc6IGJvb2xlYW5cbiAgICBzaG91bGRDb21wb25lbnRVcGRhdGUobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgICAgY29uc3Qgc2hvdWxkVXBkYXRlID0gIWNvbXBhcmVPYmpzKHRoaXMucHJvcHMsIG5leHRQcm9wcywgdGhpcy5wcm9wRXF1YWxpdHkgLyosIHRoaXMuZGVidWcgKi8pIHx8XG4gICAgICAgICAgICAhY29tcGFyZU9ianModGhpcy5zdGF0ZSwgbmV4dFN0YXRlLCB0aGlzLnN0YXRlRXF1YWxpdHkgLyosIHRoaXMuZGVidWcgKi8pO1xuICAgICAgICAvLyBpZiAodGhpcy5kZWJ1ZyAmJiBzaG91bGRVcGRhdGUpIHtcbiAgICAgICAgLy8gICBjb25zb2xlLmxvZygnc2hvdWxkVXBkYXRlIScpXG4gICAgICAgIC8vIH1cbiAgICAgICAgcmV0dXJuIHNob3VsZFVwZGF0ZTtcbiAgICB9XG4gICAgLy8gSEFDSyBmb3IgZnJlYWtpbicgUmVhY3QgU3RyaWN0TW9kZVxuICAgIHNhZmVTZXRTdGF0ZShuZXdTdGF0ZSkge1xuICAgICAgICBpZiAoIWNvbXBhcmVPYmpzKHRoaXMuc3RhdGUsIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZSksIG5ld1N0YXRlKSwgdGhpcy5zdGF0ZUVxdWFsaXR5KSkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShuZXdTdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5QdXJlQ29tcG9uZW50LmFkZFByb3BzRXF1YWxpdHkgPSBhZGRQcm9wc0VxdWFsaXR5O1xuUHVyZUNvbXBvbmVudC5hZGRTdGF0ZUVxdWFsaXR5ID0gYWRkU3RhdGVFcXVhbGl0eTtcblB1cmVDb21wb25lbnQuY29udGV4dFR5cGUgPSBWaWV3Q29udGV4dFR5cGU7XG5QdXJlQ29tcG9uZW50LnByb3RvdHlwZS5wcm9wRXF1YWxpdHkgPSB7fTtcblB1cmVDb21wb25lbnQucHJvdG90eXBlLnN0YXRlRXF1YWxpdHkgPSB7fTtcbmNsYXNzIEJhc2VDb21wb25lbnQgZXh0ZW5kcyBQdXJlQ29tcG9uZW50IHtcbn1cbkJhc2VDb21wb25lbnQuY29udGV4dFR5cGUgPSBWaWV3Q29udGV4dFR5cGU7XG5mdW5jdGlvbiBhZGRQcm9wc0VxdWFsaXR5KHByb3BFcXVhbGl0eSkge1xuICAgIGxldCBoYXNoID0gT2JqZWN0LmNyZWF0ZSh0aGlzLnByb3RvdHlwZS5wcm9wRXF1YWxpdHkpO1xuICAgIE9iamVjdC5hc3NpZ24oaGFzaCwgcHJvcEVxdWFsaXR5KTtcbiAgICB0aGlzLnByb3RvdHlwZS5wcm9wRXF1YWxpdHkgPSBoYXNoO1xufVxuZnVuY3Rpb24gYWRkU3RhdGVFcXVhbGl0eShzdGF0ZUVxdWFsaXR5KSB7XG4gICAgbGV0IGhhc2ggPSBPYmplY3QuY3JlYXRlKHRoaXMucHJvdG90eXBlLnN0YXRlRXF1YWxpdHkpO1xuICAgIE9iamVjdC5hc3NpZ24oaGFzaCwgc3RhdGVFcXVhbGl0eSk7XG4gICAgdGhpcy5wcm90b3R5cGUuc3RhdGVFcXVhbGl0eSA9IGhhc2g7XG59XG4vLyB1c2Ugb3RoZXIgb25lXG5mdW5jdGlvbiBzZXRSZWYocmVmLCBjdXJyZW50KSB7XG4gICAgaWYgKHR5cGVvZiByZWYgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmVmKGN1cnJlbnQpO1xuICAgIH1cbiAgICBlbHNlIGlmIChyZWYpIHtcbiAgICAgICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWFjdC9pc3N1ZXMvMTMwMjlcbiAgICAgICAgcmVmLmN1cnJlbnQgPSBjdXJyZW50O1xuICAgIH1cbn1cblxuY2xhc3MgQ29udGVudEluamVjdG9yIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuaWQgPSBndWlkKCk7XG4gICAgICAgIHRoaXMucXVldWVkRG9tTm9kZXMgPSBbXTtcbiAgICAgICAgdGhpcy5jdXJyZW50RG9tTm9kZXMgPSBbXTtcbiAgICAgICAgdGhpcy5oYW5kbGVFbCA9IChlbCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBvcHRpb25zIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgICAgICBjb25zdCB7IGdlbmVyYXRvck5hbWUgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMuY3VzdG9tUmVuZGVyaW5nUmVwbGFjZXMgfHwgIWhhc0N1c3RvbVJlbmRlcmluZ0hhbmRsZXIoZ2VuZXJhdG9yTmFtZSwgb3B0aW9ucykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVsUmVmKGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy51cGRhdGVFbFJlZiA9IChlbCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucHJvcHMuZWxSZWYpIHtcbiAgICAgICAgICAgICAgICBzZXRSZWYodGhpcy5wcm9wcy5lbFJlZiwgZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGNvbnN0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHsgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICAgICAgY29uc3QgeyBjdXN0b21HZW5lcmF0b3IsIGRlZmF1bHRHZW5lcmF0b3IsIHJlbmRlclByb3BzIH0gPSBwcm9wcztcbiAgICAgICAgY29uc3QgYXR0cnMgPSBidWlsZEVsQXR0cnMocHJvcHMsIFtdLCB0aGlzLmhhbmRsZUVsKTtcbiAgICAgICAgbGV0IHVzZURlZmF1bHQgPSBmYWxzZTtcbiAgICAgICAgbGV0IGlubmVyQ29udGVudDtcbiAgICAgICAgbGV0IHF1ZXVlZERvbU5vZGVzID0gW107XG4gICAgICAgIGxldCBjdXJyZW50R2VuZXJhdG9yTWV0YTtcbiAgICAgICAgaWYgKGN1c3RvbUdlbmVyYXRvciAhPSBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBjdXN0b21HZW5lcmF0b3JSZXMgPSB0eXBlb2YgY3VzdG9tR2VuZXJhdG9yID09PSAnZnVuY3Rpb24nID9cbiAgICAgICAgICAgICAgICBjdXN0b21HZW5lcmF0b3IocmVuZGVyUHJvcHMsIGNyZWF0ZUVsZW1lbnQpIDpcbiAgICAgICAgICAgICAgICBjdXN0b21HZW5lcmF0b3I7XG4gICAgICAgICAgICBpZiAoY3VzdG9tR2VuZXJhdG9yUmVzID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgdXNlRGVmYXVsdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc09iamVjdCA9IGN1c3RvbUdlbmVyYXRvclJlcyAmJiB0eXBlb2YgY3VzdG9tR2VuZXJhdG9yUmVzID09PSAnb2JqZWN0JzsgLy8gbm9uLW51bGxcbiAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QgJiYgKCdodG1sJyBpbiBjdXN0b21HZW5lcmF0b3JSZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJzLmRhbmdlcm91c2x5U2V0SW5uZXJIVE1MID0geyBfX2h0bWw6IGN1c3RvbUdlbmVyYXRvclJlcy5odG1sIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGlzT2JqZWN0ICYmICgnZG9tTm9kZXMnIGluIGN1c3RvbUdlbmVyYXRvclJlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcXVldWVkRG9tTm9kZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChjdXN0b21HZW5lcmF0b3JSZXMuZG9tTm9kZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChpc09iamVjdFxuICAgICAgICAgICAgICAgICAgICA/IGlzVmFsaWRFbGVtZW50KGN1c3RvbUdlbmVyYXRvclJlcykgLy8gdmRvbSBub2RlXG4gICAgICAgICAgICAgICAgICAgIDogdHlwZW9mIGN1c3RvbUdlbmVyYXRvclJlcyAhPT0gJ2Z1bmN0aW9uJyAvLyBwcmltaXRpdmUgdmFsdWUgKGxpa2Ugc3RyaW5nIG9yIG51bWJlcilcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdXNlIGluIHZkb21cbiAgICAgICAgICAgICAgICAgICAgaW5uZXJDb250ZW50ID0gY3VzdG9tR2VuZXJhdG9yUmVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYW4gZXhvdGljIG9iamVjdCBmb3IgaGFuZGxlQ3VzdG9tUmVuZGVyaW5nXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRHZW5lcmF0b3JNZXRhID0gY3VzdG9tR2VuZXJhdG9yUmVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHVzZURlZmF1bHQgPSAhaGFzQ3VzdG9tUmVuZGVyaW5nSGFuZGxlcihwcm9wcy5nZW5lcmF0b3JOYW1lLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXNlRGVmYXVsdCAmJiBkZWZhdWx0R2VuZXJhdG9yKSB7XG4gICAgICAgICAgICBpbm5lckNvbnRlbnQgPSBkZWZhdWx0R2VuZXJhdG9yKHJlbmRlclByb3BzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnF1ZXVlZERvbU5vZGVzID0gcXVldWVkRG9tTm9kZXM7XG4gICAgICAgIHRoaXMuY3VycmVudEdlbmVyYXRvck1ldGEgPSBjdXJyZW50R2VuZXJhdG9yTWV0YTtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUVsZW1lbnQocHJvcHMuZWxUYWcsIGF0dHJzLCBpbm5lckNvbnRlbnQpO1xuICAgIH1cbiAgICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgICAgdGhpcy5hcHBseVF1ZXVldWREb21Ob2RlcygpO1xuICAgICAgICB0aGlzLnRyaWdnZXJDdXN0b21SZW5kZXJpbmcodHJ1ZSk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZFVwZGF0ZSgpIHtcbiAgICAgICAgdGhpcy5hcHBseVF1ZXVldWREb21Ob2RlcygpO1xuICAgICAgICB0aGlzLnRyaWdnZXJDdXN0b21SZW5kZXJpbmcodHJ1ZSk7XG4gICAgfVxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICB0aGlzLnRyaWdnZXJDdXN0b21SZW5kZXJpbmcoZmFsc2UpOyAvLyBUT0RPOiBkaWZmZXJlbnQgQVBJIGZvciByZW1vdmFsP1xuICAgIH1cbiAgICB0cmlnZ2VyQ3VzdG9tUmVuZGVyaW5nKGlzQWN0aXZlKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgY29uc3QgeyBwcm9wcywgY29udGV4dCB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgeyBoYW5kbGVDdXN0b21SZW5kZXJpbmcsIGN1c3RvbVJlbmRlcmluZ01ldGFNYXAgfSA9IGNvbnRleHQub3B0aW9ucztcbiAgICAgICAgaWYgKGhhbmRsZUN1c3RvbVJlbmRlcmluZykge1xuICAgICAgICAgICAgY29uc3QgZ2VuZXJhdG9yTWV0YSA9IChfYSA9IHRoaXMuY3VycmVudEdlbmVyYXRvck1ldGEpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGN1c3RvbVJlbmRlcmluZ01ldGFNYXAgPT09IG51bGwgfHwgY3VzdG9tUmVuZGVyaW5nTWV0YU1hcCA9PT0gdm9pZCAwID8gdm9pZCAwIDogY3VzdG9tUmVuZGVyaW5nTWV0YU1hcFtwcm9wcy5nZW5lcmF0b3JOYW1lXTtcbiAgICAgICAgICAgIGlmIChnZW5lcmF0b3JNZXRhKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlQ3VzdG9tUmVuZGVyaW5nKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7IGlkOiB0aGlzLmlkLCBpc0FjdGl2ZSwgY29udGFpbmVyRWw6IHRoaXMuYmFzZSwgcmVwb3J0TmV3Q29udGFpbmVyRWw6IHRoaXMudXBkYXRlRWxSZWYsIC8vIGZyb250LWVuZCBmcmFtZXdvcmsgdGVsbHMgdXMgYWJvdXQgbmV3IGNvbnRhaW5lciBlbHNcbiAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdG9yTWV0YSB9LCBwcm9wcyksIHsgZWxDbGFzc2VzOiAocHJvcHMuZWxDbGFzc2VzIHx8IFtdKS5maWx0ZXIoaXNUcnV0aHkpIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBhcHBseVF1ZXVldWREb21Ob2RlcygpIHtcbiAgICAgICAgY29uc3QgeyBxdWV1ZWREb21Ob2RlcywgY3VycmVudERvbU5vZGVzIH0gPSB0aGlzO1xuICAgICAgICBjb25zdCBlbCA9IHRoaXMuYmFzZTtcbiAgICAgICAgaWYgKCFpc0FycmF5c0VxdWFsKHF1ZXVlZERvbU5vZGVzLCBjdXJyZW50RG9tTm9kZXMpKSB7XG4gICAgICAgICAgICBjdXJyZW50RG9tTm9kZXMuZm9yRWFjaChyZW1vdmVFbGVtZW50KTtcbiAgICAgICAgICAgIGZvciAobGV0IG5ld05vZGUgb2YgcXVldWVkRG9tTm9kZXMpIHtcbiAgICAgICAgICAgICAgICBlbC5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY3VycmVudERvbU5vZGVzID0gcXVldWVkRG9tTm9kZXM7XG4gICAgICAgIH1cbiAgICB9XG59XG5Db250ZW50SW5qZWN0b3IuYWRkUHJvcHNFcXVhbGl0eSh7XG4gICAgZWxDbGFzc2VzOiBpc0FycmF5c0VxdWFsLFxuICAgIGVsU3R5bGU6IGlzUHJvcHNFcXVhbCxcbiAgICBlbEF0dHJzOiBpc05vbkhhbmRsZXJQcm9wc0VxdWFsLFxuICAgIHJlbmRlclByb3BzOiBpc1Byb3BzRXF1YWwsXG59KTtcbi8vIFV0aWxcbi8qXG5Eb2VzIFVJLWZyYW1ld29yayBwcm92aWRlIGN1c3RvbSB3YXkgb2YgcmVuZGVyaW5nIHRoYXQgZG9lcyBub3QgdXNlIFByZWFjdCBWRE9NXG5BTkQgZG9lcyB0aGUgY2FsZW5kYXIncyBvcHRpb25zIGRlZmluZSBjdXN0b20gcmVuZGVyaW5nP1xuQUtBLiBTaG91bGQgd2UgTk9UIHJlbmRlciB0aGUgZGVmYXVsdCBjb250ZW50P1xuKi9cbmZ1bmN0aW9uIGhhc0N1c3RvbVJlbmRlcmluZ0hhbmRsZXIoZ2VuZXJhdG9yTmFtZSwgb3B0aW9ucykge1xuICAgIHZhciBfYTtcbiAgICByZXR1cm4gQm9vbGVhbihvcHRpb25zLmhhbmRsZUN1c3RvbVJlbmRlcmluZyAmJlxuICAgICAgICBnZW5lcmF0b3JOYW1lICYmXG4gICAgICAgICgoX2EgPSBvcHRpb25zLmN1c3RvbVJlbmRlcmluZ01ldGFNYXApID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYVtnZW5lcmF0b3JOYW1lXSkpO1xufVxuZnVuY3Rpb24gYnVpbGRFbEF0dHJzKHByb3BzLCBleHRyYUNsYXNzTmFtZXMsIGVsUmVmKSB7XG4gICAgY29uc3QgYXR0cnMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByb3BzLmVsQXR0cnMpLCB7IHJlZjogZWxSZWYgfSk7XG4gICAgaWYgKHByb3BzLmVsQ2xhc3NlcyB8fCBleHRyYUNsYXNzTmFtZXMpIHtcbiAgICAgICAgYXR0cnMuY2xhc3NOYW1lID0gKHByb3BzLmVsQ2xhc3NlcyB8fCBbXSlcbiAgICAgICAgICAgIC5jb25jYXQoZXh0cmFDbGFzc05hbWVzIHx8IFtdKVxuICAgICAgICAgICAgLmNvbmNhdChhdHRycy5jbGFzc05hbWUgfHwgW10pXG4gICAgICAgICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAgICAgICAuam9pbignICcpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuZWxTdHlsZSkge1xuICAgICAgICBhdHRycy5zdHlsZSA9IHByb3BzLmVsU3R5bGU7XG4gICAgfVxuICAgIHJldHVybiBhdHRycztcbn1cbmZ1bmN0aW9uIGlzVHJ1dGh5KHZhbCkge1xuICAgIHJldHVybiBCb29sZWFuKHZhbCk7XG59XG5cbmNvbnN0IFJlbmRlcklkID0gY3JlYXRlQ29udGV4dCgwKTtcblxuY2xhc3MgQ29udGVudENvbnRhaW5lciBleHRlbmRzIENvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuSW5uZXJDb250ZW50ID0gSW5uZXJDb250ZW50SW5qZWN0b3IuYmluZCh1bmRlZmluZWQsIHRoaXMpO1xuICAgICAgICB0aGlzLmhhbmRsZUVsID0gKGVsKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgICAgICAgICBpZiAodGhpcy5wcm9wcy5lbFJlZikge1xuICAgICAgICAgICAgICAgIHNldFJlZih0aGlzLnByb3BzLmVsUmVmLCBlbCk7XG4gICAgICAgICAgICAgICAgaWYgKGVsICYmIHRoaXMuZGlkTW91bnRNaXNmaXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcG9uZW50RGlkTW91bnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgZ2VuZXJhdGVkQ2xhc3NOYW1lcyA9IGdlbmVyYXRlQ2xhc3NOYW1lcyhwcm9wcy5jbGFzc05hbWVHZW5lcmF0b3IsIHByb3BzLnJlbmRlclByb3BzKTtcbiAgICAgICAgaWYgKHByb3BzLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICBjb25zdCBlbEF0dHJzID0gYnVpbGRFbEF0dHJzKHByb3BzLCBnZW5lcmF0ZWRDbGFzc05hbWVzLCB0aGlzLmhhbmRsZUVsKTtcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkcmVuID0gcHJvcHMuY2hpbGRyZW4odGhpcy5Jbm5lckNvbnRlbnQsIHByb3BzLnJlbmRlclByb3BzLCBlbEF0dHJzKTtcbiAgICAgICAgICAgIGlmIChwcm9wcy5lbFRhZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVFbGVtZW50KHByb3BzLmVsVGFnLCBlbEF0dHJzLCBjaGlsZHJlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGRyZW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRWxlbWVudCgoQ29udGVudEluamVjdG9yKSwgT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcm9wcyksIHsgZWxSZWY6IHRoaXMuaGFuZGxlRWwsIGVsVGFnOiBwcm9wcy5lbFRhZyB8fCAnZGl2JywgZWxDbGFzc2VzOiAocHJvcHMuZWxDbGFzc2VzIHx8IFtdKS5jb25jYXQoZ2VuZXJhdGVkQ2xhc3NOYW1lcyksIHJlbmRlcklkOiB0aGlzLmNvbnRleHQgfSkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICBpZiAodGhpcy5lbCkge1xuICAgICAgICAgICAgKF9iID0gKF9hID0gdGhpcy5wcm9wcykuZGlkTW91bnQpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMucHJvcHMucmVuZGVyUHJvcHMpLCB7IGVsOiB0aGlzLmVsIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGlkTW91bnRNaXNmaXJlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgKF9iID0gKF9hID0gdGhpcy5wcm9wcykud2lsbFVubW91bnQpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMucHJvcHMucmVuZGVyUHJvcHMpLCB7IGVsOiB0aGlzLmVsIH0pKTtcbiAgICB9XG59XG5Db250ZW50Q29udGFpbmVyLmNvbnRleHRUeXBlID0gUmVuZGVySWQ7XG5mdW5jdGlvbiBJbm5lckNvbnRlbnRJbmplY3Rvcihjb250YWluZXJDb21wb25lbnQsIHByb3BzKSB7XG4gICAgY29uc3QgcGFyZW50UHJvcHMgPSBjb250YWluZXJDb21wb25lbnQucHJvcHM7XG4gICAgcmV0dXJuIGNyZWF0ZUVsZW1lbnQoKENvbnRlbnRJbmplY3RvciksIE9iamVjdC5hc3NpZ24oeyByZW5kZXJQcm9wczogcGFyZW50UHJvcHMucmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IHBhcmVudFByb3BzLmdlbmVyYXRvck5hbWUsIGN1c3RvbUdlbmVyYXRvcjogcGFyZW50UHJvcHMuY3VzdG9tR2VuZXJhdG9yLCBkZWZhdWx0R2VuZXJhdG9yOiBwYXJlbnRQcm9wcy5kZWZhdWx0R2VuZXJhdG9yLCByZW5kZXJJZDogY29udGFpbmVyQ29tcG9uZW50LmNvbnRleHQgfSwgcHJvcHMpKTtcbn1cbi8vIFV0aWxzXG5mdW5jdGlvbiBnZW5lcmF0ZUNsYXNzTmFtZXMoY2xhc3NOYW1lR2VuZXJhdG9yLCByZW5kZXJQcm9wcykge1xuICAgIGNvbnN0IGNsYXNzTmFtZXMgPSB0eXBlb2YgY2xhc3NOYW1lR2VuZXJhdG9yID09PSAnZnVuY3Rpb24nID9cbiAgICAgICAgY2xhc3NOYW1lR2VuZXJhdG9yKHJlbmRlclByb3BzKSA6XG4gICAgICAgIGNsYXNzTmFtZUdlbmVyYXRvciB8fCBbXTtcbiAgICByZXR1cm4gdHlwZW9mIGNsYXNzTmFtZXMgPT09ICdzdHJpbmcnID8gW2NsYXNzTmFtZXNdIDogY2xhc3NOYW1lcztcbn1cblxuY2xhc3MgVmlld0NvbnRhaW5lciBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgICAgIGxldCByZW5kZXJQcm9wcyA9IHsgdmlldzogY29udGV4dC52aWV3QXBpIH07XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChDb250ZW50Q29udGFpbmVyLCB7IGVsUmVmOiBwcm9wcy5lbFJlZiwgZWxUYWc6IHByb3BzLmVsVGFnIHx8ICdkaXYnLCBlbEF0dHJzOiBwcm9wcy5lbEF0dHJzLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAuLi5idWlsZFZpZXdDbGFzc05hbWVzKHByb3BzLnZpZXdTcGVjKSxcbiAgICAgICAgICAgICAgICAuLi4ocHJvcHMuZWxDbGFzc2VzIHx8IFtdKSxcbiAgICAgICAgICAgIF0sIGVsU3R5bGU6IHByb3BzLmVsU3R5bGUsIHJlbmRlclByb3BzOiByZW5kZXJQcm9wcywgY2xhc3NOYW1lR2VuZXJhdG9yOiBvcHRpb25zLnZpZXdDbGFzc05hbWVzLCBnZW5lcmF0b3JOYW1lOiB1bmRlZmluZWQsIGRpZE1vdW50OiBvcHRpb25zLnZpZXdEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMudmlld1dpbGxVbm1vdW50IH0sICgpID0+IHByb3BzLmNoaWxkcmVuKSk7XG4gICAgfVxufVxuZnVuY3Rpb24gYnVpbGRWaWV3Q2xhc3NOYW1lcyh2aWV3U3BlYykge1xuICAgIHJldHVybiBbXG4gICAgICAgIGBmYy0ke3ZpZXdTcGVjLnR5cGV9LXZpZXdgLFxuICAgICAgICAnZmMtdmlldycsXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gcGFyc2VSYW5nZShpbnB1dCwgZGF0ZUVudikge1xuICAgIGxldCBzdGFydCA9IG51bGw7XG4gICAgbGV0IGVuZCA9IG51bGw7XG4gICAgaWYgKGlucHV0LnN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoaW5wdXQuc3RhcnQpO1xuICAgIH1cbiAgICBpZiAoaW5wdXQuZW5kKSB7XG4gICAgICAgIGVuZCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKGlucHV0LmVuZCk7XG4gICAgfVxuICAgIGlmICghc3RhcnQgJiYgIWVuZCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHN0YXJ0ICYmIGVuZCAmJiBlbmQgPCBzdGFydCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHsgc3RhcnQsIGVuZCB9O1xufVxuLy8gU0lERS1FRkZFQ1Q6IHdpbGwgbXV0YXRlIHJhbmdlcy5cbi8vIFdpbGwgcmV0dXJuIGEgbmV3IGFycmF5IHJlc3VsdC5cbmZ1bmN0aW9uIGludmVydFJhbmdlcyhyYW5nZXMsIGNvbnN0cmFpbnRSYW5nZSkge1xuICAgIGxldCBpbnZlcnRlZFJhbmdlcyA9IFtdO1xuICAgIGxldCB7IHN0YXJ0IH0gPSBjb25zdHJhaW50UmFuZ2U7IC8vIHRoZSBlbmQgb2YgdGhlIHByZXZpb3VzIHJhbmdlLiB0aGUgc3RhcnQgb2YgdGhlIG5ldyByYW5nZVxuICAgIGxldCBpO1xuICAgIGxldCBkYXRlUmFuZ2U7XG4gICAgLy8gcmFuZ2VzIG5lZWQgdG8gYmUgaW4gb3JkZXIuIHJlcXVpcmVkIGZvciBvdXIgZGF0ZS13YWxraW5nIGFsZ29yaXRobVxuICAgIHJhbmdlcy5zb3J0KGNvbXBhcmVSYW5nZXMpO1xuICAgIGZvciAoaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgZGF0ZVJhbmdlID0gcmFuZ2VzW2ldO1xuICAgICAgICAvLyBhZGQgdGhlIHNwYW4gb2YgdGltZSBiZWZvcmUgdGhlIGV2ZW50IChpZiB0aGVyZSBpcyBhbnkpXG4gICAgICAgIGlmIChkYXRlUmFuZ2Uuc3RhcnQgPiBzdGFydCkgeyAvLyBjb21wYXJlIG1pbGxpc2Vjb25kIHRpbWUgKHNraXAgYW55IGFtYmlnIGxvZ2ljKVxuICAgICAgICAgICAgaW52ZXJ0ZWRSYW5nZXMucHVzaCh7IHN0YXJ0LCBlbmQ6IGRhdGVSYW5nZS5zdGFydCB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZVJhbmdlLmVuZCA+IHN0YXJ0KSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVSYW5nZS5lbmQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gYWRkIHRoZSBzcGFuIG9mIHRpbWUgYWZ0ZXIgdGhlIGxhc3QgZXZlbnQgKGlmIHRoZXJlIGlzIGFueSlcbiAgICBpZiAoc3RhcnQgPCBjb25zdHJhaW50UmFuZ2UuZW5kKSB7IC8vIGNvbXBhcmUgbWlsbGlzZWNvbmQgdGltZSAoc2tpcCBhbnkgYW1iaWcgbG9naWMpXG4gICAgICAgIGludmVydGVkUmFuZ2VzLnB1c2goeyBzdGFydCwgZW5kOiBjb25zdHJhaW50UmFuZ2UuZW5kIH0pO1xuICAgIH1cbiAgICByZXR1cm4gaW52ZXJ0ZWRSYW5nZXM7XG59XG5mdW5jdGlvbiBjb21wYXJlUmFuZ2VzKHJhbmdlMCwgcmFuZ2UxKSB7XG4gICAgcmV0dXJuIHJhbmdlMC5zdGFydC52YWx1ZU9mKCkgLSByYW5nZTEuc3RhcnQudmFsdWVPZigpOyAvLyBlYXJsaWVyIHJhbmdlcyBnbyBmaXJzdFxufVxuZnVuY3Rpb24gaW50ZXJzZWN0UmFuZ2VzKHJhbmdlMCwgcmFuZ2UxKSB7XG4gICAgbGV0IHsgc3RhcnQsIGVuZCB9ID0gcmFuZ2UwO1xuICAgIGxldCBuZXdSYW5nZSA9IG51bGw7XG4gICAgaWYgKHJhbmdlMS5zdGFydCAhPT0gbnVsbCkge1xuICAgICAgICBpZiAoc3RhcnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gcmFuZ2UxLnN0YXJ0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3RhcnQgPSBuZXcgRGF0ZShNYXRoLm1heChzdGFydC52YWx1ZU9mKCksIHJhbmdlMS5zdGFydC52YWx1ZU9mKCkpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAocmFuZ2UxLmVuZCAhPSBudWxsKSB7XG4gICAgICAgIGlmIChlbmQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGVuZCA9IHJhbmdlMS5lbmQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlbmQgPSBuZXcgRGF0ZShNYXRoLm1pbihlbmQudmFsdWVPZigpLCByYW5nZTEuZW5kLnZhbHVlT2YoKSkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChzdGFydCA9PT0gbnVsbCB8fCBlbmQgPT09IG51bGwgfHwgc3RhcnQgPCBlbmQpIHtcbiAgICAgICAgbmV3UmFuZ2UgPSB7IHN0YXJ0LCBlbmQgfTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld1JhbmdlO1xufVxuZnVuY3Rpb24gcmFuZ2VzRXF1YWwocmFuZ2UwLCByYW5nZTEpIHtcbiAgICByZXR1cm4gKHJhbmdlMC5zdGFydCA9PT0gbnVsbCA/IG51bGwgOiByYW5nZTAuc3RhcnQudmFsdWVPZigpKSA9PT0gKHJhbmdlMS5zdGFydCA9PT0gbnVsbCA/IG51bGwgOiByYW5nZTEuc3RhcnQudmFsdWVPZigpKSAmJlxuICAgICAgICAocmFuZ2UwLmVuZCA9PT0gbnVsbCA/IG51bGwgOiByYW5nZTAuZW5kLnZhbHVlT2YoKSkgPT09IChyYW5nZTEuZW5kID09PSBudWxsID8gbnVsbCA6IHJhbmdlMS5lbmQudmFsdWVPZigpKTtcbn1cbmZ1bmN0aW9uIHJhbmdlc0ludGVyc2VjdChyYW5nZTAsIHJhbmdlMSkge1xuICAgIHJldHVybiAocmFuZ2UwLmVuZCA9PT0gbnVsbCB8fCByYW5nZTEuc3RhcnQgPT09IG51bGwgfHwgcmFuZ2UwLmVuZCA+IHJhbmdlMS5zdGFydCkgJiZcbiAgICAgICAgKHJhbmdlMC5zdGFydCA9PT0gbnVsbCB8fCByYW5nZTEuZW5kID09PSBudWxsIHx8IHJhbmdlMC5zdGFydCA8IHJhbmdlMS5lbmQpO1xufVxuZnVuY3Rpb24gcmFuZ2VDb250YWluc1JhbmdlKG91dGVyUmFuZ2UsIGlubmVyUmFuZ2UpIHtcbiAgICByZXR1cm4gKG91dGVyUmFuZ2Uuc3RhcnQgPT09IG51bGwgfHwgKGlubmVyUmFuZ2Uuc3RhcnQgIT09IG51bGwgJiYgaW5uZXJSYW5nZS5zdGFydCA+PSBvdXRlclJhbmdlLnN0YXJ0KSkgJiZcbiAgICAgICAgKG91dGVyUmFuZ2UuZW5kID09PSBudWxsIHx8IChpbm5lclJhbmdlLmVuZCAhPT0gbnVsbCAmJiBpbm5lclJhbmdlLmVuZCA8PSBvdXRlclJhbmdlLmVuZCkpO1xufVxuZnVuY3Rpb24gcmFuZ2VDb250YWluc01hcmtlcihyYW5nZSwgZGF0ZSkge1xuICAgIHJldHVybiAocmFuZ2Uuc3RhcnQgPT09IG51bGwgfHwgZGF0ZSA+PSByYW5nZS5zdGFydCkgJiZcbiAgICAgICAgKHJhbmdlLmVuZCA9PT0gbnVsbCB8fCBkYXRlIDwgcmFuZ2UuZW5kKTtcbn1cbi8vIElmIHRoZSBnaXZlbiBkYXRlIGlzIG5vdCB3aXRoaW4gdGhlIGdpdmVuIHJhbmdlLCBtb3ZlIGl0IGluc2lkZS5cbi8vIChJZiBpdCdzIHBhc3QgdGhlIGVuZCwgbWFrZSBpdCBvbmUgbWlsbGlzZWNvbmQgYmVmb3JlIHRoZSBlbmQpLlxuZnVuY3Rpb24gY29uc3RyYWluTWFya2VyVG9SYW5nZShkYXRlLCByYW5nZSkge1xuICAgIGlmIChyYW5nZS5zdGFydCAhPSBudWxsICYmIGRhdGUgPCByYW5nZS5zdGFydCkge1xuICAgICAgICByZXR1cm4gcmFuZ2Uuc3RhcnQ7XG4gICAgfVxuICAgIGlmIChyYW5nZS5lbmQgIT0gbnVsbCAmJiBkYXRlID49IHJhbmdlLmVuZCkge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUocmFuZ2UuZW5kLnZhbHVlT2YoKSAtIDEpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZTtcbn1cblxuLyogRGF0ZSBzdHVmZiB0aGF0IGRvZXNuJ3QgYmVsb25nIGluIGRhdGVsaWIgY29yZVxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4vLyBnaXZlbiBhIHRpbWVkIHJhbmdlLCBjb21wdXRlcyBhbiBhbGwtZGF5IHJhbmdlIHRoYXQgaGFzIHRoZSBzYW1lIGV4YWN0IGR1cmF0aW9uLFxuLy8gYnV0IHdob3NlIHN0YXJ0IHRpbWUgaXMgYWxpZ25lZCB3aXRoIHRoZSBzdGFydCBvZiB0aGUgZGF5LlxuZnVuY3Rpb24gY29tcHV0ZUFsaWduZWREYXlSYW5nZSh0aW1lZFJhbmdlKSB7XG4gICAgbGV0IGRheUNudCA9IE1hdGguZmxvb3IoZGlmZkRheXModGltZWRSYW5nZS5zdGFydCwgdGltZWRSYW5nZS5lbmQpKSB8fCAxO1xuICAgIGxldCBzdGFydCA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5zdGFydCk7XG4gICAgbGV0IGVuZCA9IGFkZERheXMoc3RhcnQsIGRheUNudCk7XG4gICAgcmV0dXJuIHsgc3RhcnQsIGVuZCB9O1xufVxuLy8gZ2l2ZW4gYSB0aW1lZCByYW5nZSwgY29tcHV0ZXMgYW4gYWxsLWRheSByYW5nZSBiYXNlZCBvbiBob3cgZm9yIHRoZSBlbmQgZGF0ZSBibGVlZHMgaW50byB0aGUgbmV4dCBkYXlcbi8vIFRPRE86IGdpdmUgbmV4dERheVRocmVzaG9sZCBhIGRlZmF1bHQgYXJnXG5mdW5jdGlvbiBjb21wdXRlVmlzaWJsZURheVJhbmdlKHRpbWVkUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQgPSBjcmVhdGVEdXJhdGlvbigwKSkge1xuICAgIGxldCBzdGFydERheSA9IG51bGw7XG4gICAgbGV0IGVuZERheSA9IG51bGw7XG4gICAgaWYgKHRpbWVkUmFuZ2UuZW5kKSB7XG4gICAgICAgIGVuZERheSA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5lbmQpO1xuICAgICAgICBsZXQgZW5kVGltZU1TID0gdGltZWRSYW5nZS5lbmQudmFsdWVPZigpIC0gZW5kRGF5LnZhbHVlT2YoKTsgLy8gIyBvZiBtaWxsaXNlY29uZHMgaW50byBgZW5kRGF5YFxuICAgICAgICAvLyBJZiB0aGUgZW5kIHRpbWUgaXMgYWN0dWFsbHkgaW5jbHVzaXZlbHkgcGFydCBvZiB0aGUgbmV4dCBkYXkgYW5kIGlzIGVxdWFsIHRvIG9yXG4gICAgICAgIC8vIGJleW9uZCB0aGUgbmV4dCBkYXkgdGhyZXNob2xkLCBhZGp1c3QgdGhlIGVuZCB0byBiZSB0aGUgZXhjbHVzaXZlIGVuZCBvZiBgZW5kRGF5YC5cbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBsZWF2aW5nIGl0IGFzIGluY2x1c2l2ZSB3aWxsIGNhdXNlIGl0IHRvIGV4Y2x1ZGUgYGVuZERheWAuXG4gICAgICAgIGlmIChlbmRUaW1lTVMgJiYgZW5kVGltZU1TID49IGFzUm91Z2hNcyhuZXh0RGF5VGhyZXNob2xkKSkge1xuICAgICAgICAgICAgZW5kRGF5ID0gYWRkRGF5cyhlbmREYXksIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0aW1lZFJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0RGF5ID0gc3RhcnRPZkRheSh0aW1lZFJhbmdlLnN0YXJ0KTsgLy8gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF5IHRoZSByYW5nZSBzdGFydHNcbiAgICAgICAgLy8gSWYgZW5kIGlzIHdpdGhpbiBgc3RhcnREYXlgIGJ1dCBub3QgcGFzdCBuZXh0RGF5VGhyZXNob2xkLCBhc3NpZ24gdGhlIGRlZmF1bHQgZHVyYXRpb24gb2Ygb25lIGRheS5cbiAgICAgICAgaWYgKGVuZERheSAmJiBlbmREYXkgPD0gc3RhcnREYXkpIHtcbiAgICAgICAgICAgIGVuZERheSA9IGFkZERheXMoc3RhcnREYXksIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydERheSwgZW5kOiBlbmREYXkgfTtcbn1cbi8vIHNwYW5zIGZyb20gb25lIGRheSBpbnRvIGFub3RoZXI/XG5mdW5jdGlvbiBpc011bHRpRGF5UmFuZ2UocmFuZ2UpIHtcbiAgICBsZXQgdmlzaWJsZVJhbmdlID0gY29tcHV0ZVZpc2libGVEYXlSYW5nZShyYW5nZSk7XG4gICAgcmV0dXJuIGRpZmZEYXlzKHZpc2libGVSYW5nZS5zdGFydCwgdmlzaWJsZVJhbmdlLmVuZCkgPiAxO1xufVxuZnVuY3Rpb24gZGlmZkRhdGVzKGRhdGUwLCBkYXRlMSwgZGF0ZUVudiwgbGFyZ2VVbml0KSB7XG4gICAgaWYgKGxhcmdlVW5pdCA9PT0gJ3llYXInKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbihkYXRlRW52LmRpZmZXaG9sZVllYXJzKGRhdGUwLCBkYXRlMSksICd5ZWFyJyk7XG4gICAgfVxuICAgIGlmIChsYXJnZVVuaXQgPT09ICdtb250aCcpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKGRhdGVFbnYuZGlmZldob2xlTW9udGhzKGRhdGUwLCBkYXRlMSksICdtb250aCcpO1xuICAgIH1cbiAgICByZXR1cm4gZGlmZkRheUFuZFRpbWUoZGF0ZTAsIGRhdGUxKTsgLy8gcmV0dXJucyBhIGR1cmF0aW9uXG59XG5cbmNsYXNzIERhdGVQcm9maWxlR2VuZXJhdG9yIHtcbiAgICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgICAgICB0aGlzLnByb3BzID0gcHJvcHM7XG4gICAgICAgIHRoaXMuaW5pdEhpZGRlbkRheXMoKTtcbiAgICB9XG4gICAgLyogRGF0ZSBSYW5nZSBDb21wdXRhdGlvblxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgLy8gQnVpbGRzIGEgc3RydWN0dXJlIHdpdGggaW5mbyBhYm91dCB3aGF0IHRoZSBkYXRlcy9yYW5nZXMgd2lsbCBiZSBmb3IgdGhlIFwicHJldlwiIHZpZXcuXG4gICAgYnVpbGRQcmV2KGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUsIGZvcmNlVG9WYWxpZCkge1xuICAgICAgICBsZXQgeyBkYXRlRW52IH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBsZXQgcHJldkRhdGUgPSBkYXRlRW52LnN1YnRyYWN0KGRhdGVFbnYuc3RhcnRPZihjdXJyZW50RGF0ZSwgY3VycmVudERhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpLCAvLyBpbXBvcnRhbnQgZm9yIHN0YXJ0LW9mLW1vbnRoXG4gICAgICAgIGN1cnJlbnREYXRlUHJvZmlsZS5kYXRlSW5jcmVtZW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGQocHJldkRhdGUsIC0xLCBmb3JjZVRvVmFsaWQpO1xuICAgIH1cbiAgICAvLyBCdWlsZHMgYSBzdHJ1Y3R1cmUgd2l0aCBpbmZvIGFib3V0IHdoYXQgdGhlIGRhdGVzL3JhbmdlcyB3aWxsIGJlIGZvciB0aGUgXCJuZXh0XCIgdmlldy5cbiAgICBidWlsZE5leHQoY3VycmVudERhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSwgZm9yY2VUb1ZhbGlkKSB7XG4gICAgICAgIGxldCB7IGRhdGVFbnYgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgIGxldCBuZXh0RGF0ZSA9IGRhdGVFbnYuYWRkKGRhdGVFbnYuc3RhcnRPZihjdXJyZW50RGF0ZSwgY3VycmVudERhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpLCAvLyBpbXBvcnRhbnQgZm9yIHN0YXJ0LW9mLW1vbnRoXG4gICAgICAgIGN1cnJlbnREYXRlUHJvZmlsZS5kYXRlSW5jcmVtZW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGQobmV4dERhdGUsIDEsIGZvcmNlVG9WYWxpZCk7XG4gICAgfVxuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSBob2xkaW5nIGRhdGVzL3JhbmdlcyBmb3IgcmVuZGVyaW5nIGFyb3VuZCB0aGUgZ2l2ZW4gZGF0ZS5cbiAgICAvLyBPcHRpb25hbCBkaXJlY3Rpb24gcGFyYW0gaW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGUgaXMgYmVpbmcgaW5jcmVtZW50ZWQvZGVjcmVtZW50ZWRcbiAgICAvLyBmcm9tIGl0cyBwcmV2aW91cyB2YWx1ZS4gZGVjcmVtZW50ZWQgPSAtMSwgaW5jcmVtZW50ZWQgPSAxIChkZWZhdWx0KS5cbiAgICBidWlsZChjdXJyZW50RGF0ZSwgZGlyZWN0aW9uLCBmb3JjZVRvVmFsaWQgPSB0cnVlKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgdmFsaWRSYW5nZTtcbiAgICAgICAgbGV0IGN1cnJlbnRJbmZvO1xuICAgICAgICBsZXQgaXNSYW5nZUFsbERheTtcbiAgICAgICAgbGV0IHJlbmRlclJhbmdlO1xuICAgICAgICBsZXQgYWN0aXZlUmFuZ2U7XG4gICAgICAgIGxldCBpc1ZhbGlkO1xuICAgICAgICB2YWxpZFJhbmdlID0gdGhpcy5idWlsZFZhbGlkUmFuZ2UoKTtcbiAgICAgICAgdmFsaWRSYW5nZSA9IHRoaXMudHJpbUhpZGRlbkRheXModmFsaWRSYW5nZSk7XG4gICAgICAgIGlmIChmb3JjZVRvVmFsaWQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gY29uc3RyYWluTWFya2VyVG9SYW5nZShjdXJyZW50RGF0ZSwgdmFsaWRSYW5nZSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudEluZm8gPSB0aGlzLmJ1aWxkQ3VycmVudFJhbmdlSW5mbyhjdXJyZW50RGF0ZSwgZGlyZWN0aW9uKTtcbiAgICAgICAgaXNSYW5nZUFsbERheSA9IC9eKHllYXJ8bW9udGh8d2Vla3xkYXkpJC8udGVzdChjdXJyZW50SW5mby51bml0KTtcbiAgICAgICAgcmVuZGVyUmFuZ2UgPSB0aGlzLmJ1aWxkUmVuZGVyUmFuZ2UodGhpcy50cmltSGlkZGVuRGF5cyhjdXJyZW50SW5mby5yYW5nZSksIGN1cnJlbnRJbmZvLnVuaXQsIGlzUmFuZ2VBbGxEYXkpO1xuICAgICAgICByZW5kZXJSYW5nZSA9IHRoaXMudHJpbUhpZGRlbkRheXMocmVuZGVyUmFuZ2UpO1xuICAgICAgICBhY3RpdmVSYW5nZSA9IHJlbmRlclJhbmdlO1xuICAgICAgICBpZiAoIXByb3BzLnNob3dOb25DdXJyZW50RGF0ZXMpIHtcbiAgICAgICAgICAgIGFjdGl2ZVJhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKGFjdGl2ZVJhbmdlLCBjdXJyZW50SW5mby5yYW5nZSk7XG4gICAgICAgIH1cbiAgICAgICAgYWN0aXZlUmFuZ2UgPSB0aGlzLmFkanVzdEFjdGl2ZVJhbmdlKGFjdGl2ZVJhbmdlKTtcbiAgICAgICAgYWN0aXZlUmFuZ2UgPSBpbnRlcnNlY3RSYW5nZXMoYWN0aXZlUmFuZ2UsIHZhbGlkUmFuZ2UpOyAvLyBtaWdodCByZXR1cm4gbnVsbFxuICAgICAgICAvLyBpdCdzIGludmFsaWQgaWYgdGhlIG9yaWdpbmFsbHkgcmVxdWVzdGVkIGRhdGUgaXMgbm90IGNvbnRhaW5lZCxcbiAgICAgICAgLy8gb3IgaWYgdGhlIHJhbmdlIGlzIGNvbXBsZXRlbHkgb3V0c2lkZSBvZiB0aGUgdmFsaWQgcmFuZ2UuXG4gICAgICAgIGlzVmFsaWQgPSByYW5nZXNJbnRlcnNlY3QoY3VycmVudEluZm8ucmFuZ2UsIHZhbGlkUmFuZ2UpO1xuICAgICAgICAvLyBIQUNLOiBjb25zdHJhaW4gdG8gcmVuZGVyLXJhbmdlIHNvIGBjdXJyZW50RGF0ZWAgaXMgbW9yZSB1c2VmdWwgdG8gdmlldyByZW5kZXJpbmdcbiAgICAgICAgaWYgKCFyYW5nZUNvbnRhaW5zTWFya2VyKHJlbmRlclJhbmdlLCBjdXJyZW50RGF0ZSkpIHtcbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gcmVuZGVyUmFuZ2Uuc3RhcnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGN1cnJlbnREYXRlLFxuICAgICAgICAgICAgLy8gY29uc3RyYWludCBmb3Igd2hlcmUgcHJldi9uZXh0IG9wZXJhdGlvbnMgY2FuIGdvIGFuZCB3aGVyZSBldmVudHMgY2FuIGJlIGRyYWdnZWQvcmVzaXplZCB0by5cbiAgICAgICAgICAgIC8vIGFuIG9iamVjdCB3aXRoIG9wdGlvbmFsIHN0YXJ0IGFuZCBlbmQgcHJvcGVydGllcy5cbiAgICAgICAgICAgIHZhbGlkUmFuZ2UsXG4gICAgICAgICAgICAvLyByYW5nZSB0aGUgdmlldyBpcyBmb3JtYWxseSByZXNwb25zaWJsZSBmb3IuXG4gICAgICAgICAgICAvLyBmb3IgZXhhbXBsZSwgYSBtb250aCB2aWV3IG1pZ2h0IGhhdmUgMXN0LTMxc3QsIGV4Y2x1ZGluZyBwYWRkZWQgZGF0ZXNcbiAgICAgICAgICAgIGN1cnJlbnRSYW5nZTogY3VycmVudEluZm8ucmFuZ2UsXG4gICAgICAgICAgICAvLyBuYW1lIG9mIGxhcmdlc3QgdW5pdCBiZWluZyBkaXNwbGF5ZWQsIGxpa2UgXCJtb250aFwiIG9yIFwid2Vla1wiXG4gICAgICAgICAgICBjdXJyZW50UmFuZ2VVbml0OiBjdXJyZW50SW5mby51bml0LFxuICAgICAgICAgICAgaXNSYW5nZUFsbERheSxcbiAgICAgICAgICAgIC8vIGRhdGVzIHRoYXQgZGlzcGxheSBldmVudHMgYW5kIGFjY2VwdCBkcmFnLW4tZHJvcFxuICAgICAgICAgICAgLy8gd2lsbCBiZSBgbnVsbGAgaWYgbm8gZGF0ZXMgYWNjZXB0IGV2ZW50c1xuICAgICAgICAgICAgYWN0aXZlUmFuZ2UsXG4gICAgICAgICAgICAvLyBkYXRlIHJhbmdlIHdpdGggYSByZW5kZXJlZCBza2VsZXRvblxuICAgICAgICAgICAgLy8gaW5jbHVkZXMgbm90LWFjdGl2ZSBkYXlzIHRoYXQgbmVlZCBzb21lIHNvcnQgb2YgRE9NXG4gICAgICAgICAgICByZW5kZXJSYW5nZSxcbiAgICAgICAgICAgIC8vIER1cmF0aW9uIG9iamVjdCB0aGF0IGRlbm90ZXMgdGhlIGZpcnN0IHZpc2libGUgdGltZSBvZiBhbnkgZ2l2ZW4gZGF5XG4gICAgICAgICAgICBzbG90TWluVGltZTogcHJvcHMuc2xvdE1pblRpbWUsXG4gICAgICAgICAgICAvLyBEdXJhdGlvbiBvYmplY3QgdGhhdCBkZW5vdGVzIHRoZSBleGNsdXNpdmUgdmlzaWJsZSBlbmQgdGltZSBvZiBhbnkgZ2l2ZW4gZGF5XG4gICAgICAgICAgICBzbG90TWF4VGltZTogcHJvcHMuc2xvdE1heFRpbWUsXG4gICAgICAgICAgICBpc1ZhbGlkLFxuICAgICAgICAgICAgLy8gaG93IGZhciB0aGUgY3VycmVudCBkYXRlIHdpbGwgbW92ZSBmb3IgYSBwcmV2L25leHQgb3BlcmF0aW9uXG4gICAgICAgICAgICBkYXRlSW5jcmVtZW50OiB0aGlzLmJ1aWxkRGF0ZUluY3JlbWVudChjdXJyZW50SW5mby5kdXJhdGlvbiksXG4gICAgICAgICAgICAvLyBwYXNzIGEgZmFsbGJhY2sgKG1pZ2h0IGJlIG51bGwpIF5cbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gQnVpbGRzIGFuIG9iamVjdCB3aXRoIG9wdGlvbmFsIHN0YXJ0L2VuZCBwcm9wZXJ0aWVzLlxuICAgIC8vIEluZGljYXRlcyB0aGUgbWluaW11bS9tYXhpbXVtIGRhdGVzIHRvIGRpc3BsYXkuXG4gICAgLy8gbm90IHJlc3BvbnNpYmxlIGZvciB0cmltbWluZyBoaWRkZW4gZGF5cy5cbiAgICBidWlsZFZhbGlkUmFuZ2UoKSB7XG4gICAgICAgIGxldCBpbnB1dCA9IHRoaXMucHJvcHMudmFsaWRSYW5nZUlucHV0O1xuICAgICAgICBsZXQgc2ltcGxlSW5wdXQgPSB0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbidcbiAgICAgICAgICAgID8gaW5wdXQuY2FsbCh0aGlzLnByb3BzLmNhbGVuZGFyQXBpLCB0aGlzLnByb3BzLmRhdGVFbnYudG9EYXRlKHRoaXMucHJvcHMubm93TWFuYWdlci5nZXREYXRlTWFya2VyKCkpKVxuICAgICAgICAgICAgOiBpbnB1dDtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVmaW5lUmFuZ2Uoc2ltcGxlSW5wdXQpIHx8XG4gICAgICAgICAgICB7IHN0YXJ0OiBudWxsLCBlbmQ6IG51bGwgfTsgLy8gY29tcGxldGVseSBvcGVuLWVuZGVkXG4gICAgfVxuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSB3aXRoIGluZm8gYWJvdXQgdGhlIFwiY3VycmVudFwiIHJhbmdlLCB0aGUgcmFuZ2UgdGhhdCBpc1xuICAgIC8vIGhpZ2hsaWdodGVkIGFzIGJlaW5nIHRoZSBjdXJyZW50IG1vbnRoIGZvciBleGFtcGxlLlxuICAgIC8vIFNlZSBidWlsZCgpIGZvciBhIGRlc2NyaXB0aW9uIG9mIGBkaXJlY3Rpb25gLlxuICAgIC8vIEd1YXJhbnRlZWQgdG8gaGF2ZSBgcmFuZ2VgIGFuZCBgdW5pdGAgcHJvcGVydGllcy4gYGR1cmF0aW9uYCBpcyBvcHRpb25hbC5cbiAgICBidWlsZEN1cnJlbnRSYW5nZUluZm8oZGF0ZSwgZGlyZWN0aW9uKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgZHVyYXRpb24gPSBudWxsO1xuICAgICAgICBsZXQgdW5pdCA9IG51bGw7XG4gICAgICAgIGxldCByYW5nZSA9IG51bGw7XG4gICAgICAgIGxldCBkYXlDb3VudDtcbiAgICAgICAgaWYgKHByb3BzLmR1cmF0aW9uKSB7XG4gICAgICAgICAgICBkdXJhdGlvbiA9IHByb3BzLmR1cmF0aW9uO1xuICAgICAgICAgICAgdW5pdCA9IHByb3BzLmR1cmF0aW9uVW5pdDtcbiAgICAgICAgICAgIHJhbmdlID0gdGhpcy5idWlsZFJhbmdlRnJvbUR1cmF0aW9uKGRhdGUsIGRpcmVjdGlvbiwgZHVyYXRpb24sIHVuaXQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKChkYXlDb3VudCA9IHRoaXMucHJvcHMuZGF5Q291bnQpKSB7XG4gICAgICAgICAgICB1bml0ID0gJ2RheSc7XG4gICAgICAgICAgICByYW5nZSA9IHRoaXMuYnVpbGRSYW5nZUZyb21EYXlDb3VudChkYXRlLCBkaXJlY3Rpb24sIGRheUNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgocmFuZ2UgPSB0aGlzLmJ1aWxkQ3VzdG9tVmlzaWJsZVJhbmdlKGRhdGUpKSkge1xuICAgICAgICAgICAgdW5pdCA9IHByb3BzLmRhdGVFbnYuZ3JlYXRlc3RXaG9sZVVuaXQocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCkudW5pdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGR1cmF0aW9uID0gdGhpcy5nZXRGYWxsYmFja0R1cmF0aW9uKCk7XG4gICAgICAgICAgICB1bml0ID0gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGR1cmF0aW9uKS51bml0O1xuICAgICAgICAgICAgcmFuZ2UgPSB0aGlzLmJ1aWxkUmFuZ2VGcm9tRHVyYXRpb24oZGF0ZSwgZGlyZWN0aW9uLCBkdXJhdGlvbiwgdW5pdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZHVyYXRpb24sIHVuaXQsIHJhbmdlIH07XG4gICAgfVxuICAgIGdldEZhbGxiYWNrRHVyYXRpb24oKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbih7IGRheTogMSB9KTtcbiAgICB9XG4gICAgLy8gUmV0dXJucyBhIG5ldyBhY3RpdmVSYW5nZSB0byBoYXZlIHRpbWUgdmFsdWVzICh1bi1hbWJpZ3VhdGUpXG4gICAgLy8gc2xvdE1pblRpbWUgb3Igc2xvdE1heFRpbWUgY2F1c2VzIHRoZSByYW5nZSB0byBleHBhbmQuXG4gICAgYWRqdXN0QWN0aXZlUmFuZ2UocmFuZ2UpIHtcbiAgICAgICAgbGV0IHsgZGF0ZUVudiwgdXNlc01pbk1heFRpbWUsIHNsb3RNaW5UaW1lLCBzbG90TWF4VGltZSB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IHsgc3RhcnQsIGVuZCB9ID0gcmFuZ2U7XG4gICAgICAgIGlmICh1c2VzTWluTWF4VGltZSkge1xuICAgICAgICAgICAgLy8gZXhwYW5kIGFjdGl2ZSByYW5nZSBpZiBzbG90TWluVGltZSBpcyBuZWdhdGl2ZSAod2h5IG5vdCB3aGVuIHBvc2l0aXZlPylcbiAgICAgICAgICAgIGlmIChhc1JvdWdoRGF5cyhzbG90TWluVGltZSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5hZGQoc3RhcnQsIHNsb3RNaW5UaW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGV4cGFuZCBhY3RpdmUgcmFuZ2UgaWYgc2xvdE1heFRpbWUgaXMgYmV5b25kIG9uZSBkYXkgKHdoeSBub3Qgd2hlbiBuZWdhdGl2ZT8pXG4gICAgICAgICAgICBpZiAoYXNSb3VnaERheXMoc2xvdE1heFRpbWUpID4gMSkge1xuICAgICAgICAgICAgICAgIGVuZCA9IHN0YXJ0T2ZEYXkoZW5kKTsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgIGVuZCA9IGFkZERheXMoZW5kLCAtMSk7XG4gICAgICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoZW5kLCBzbG90TWF4VGltZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhcnQsIGVuZCB9O1xuICAgIH1cbiAgICAvLyBCdWlsZHMgdGhlIFwiY3VycmVudFwiIHJhbmdlIHdoZW4gaXQgaXMgc3BlY2lmaWVkIGFzIGFuIGV4cGxpY2l0IGR1cmF0aW9uLlxuICAgIC8vIGB1bml0YCBpcyB0aGUgYWxyZWFkeS1jb21wdXRlZCBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IgdW5pdCBvZiBkdXJhdGlvbi5cbiAgICBidWlsZFJhbmdlRnJvbUR1cmF0aW9uKGRhdGUsIGRpcmVjdGlvbiwgZHVyYXRpb24sIHVuaXQpIHtcbiAgICAgICAgbGV0IHsgZGF0ZUVudiwgZGF0ZUFsaWdubWVudCB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IHN0YXJ0O1xuICAgICAgICBsZXQgZW5kO1xuICAgICAgICBsZXQgcmVzO1xuICAgICAgICAvLyBjb21wdXRlIHdoYXQgdGhlIGFsaWdubWVudCBzaG91bGQgYmVcbiAgICAgICAgaWYgKCFkYXRlQWxpZ25tZW50KSB7XG4gICAgICAgICAgICBsZXQgeyBkYXRlSW5jcmVtZW50IH0gPSB0aGlzLnByb3BzO1xuICAgICAgICAgICAgaWYgKGRhdGVJbmNyZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyB1c2UgdGhlIHNtYWxsZXIgb2YgdGhlIHR3byB1bml0c1xuICAgICAgICAgICAgICAgIGlmIChhc1JvdWdoTXMoZGF0ZUluY3JlbWVudCkgPCBhc1JvdWdoTXMoZHVyYXRpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGVBbGlnbm1lbnQgPSBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZGF0ZUluY3JlbWVudCkudW5pdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGVBbGlnbm1lbnQgPSB1bml0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRhdGVBbGlnbm1lbnQgPSB1bml0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHRoZSB2aWV3IGRpc3BsYXlzIGEgc2luZ2xlIGRheSBvciBzbWFsbGVyXG4gICAgICAgIGlmIChhc1JvdWdoRGF5cyhkdXJhdGlvbikgPD0gMSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNIaWRkZW5EYXkoc3RhcnQpKSB7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSB0aGlzLnNraXBIaWRkZW5EYXlzKHN0YXJ0LCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gc3RhcnRPZkRheShzdGFydCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY29tcHV0ZVJlcygpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5zdGFydE9mKGRhdGUsIGRhdGVBbGlnbm1lbnQpO1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoc3RhcnQsIGR1cmF0aW9uKTtcbiAgICAgICAgICAgIHJlcyA9IHsgc3RhcnQsIGVuZCB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbXB1dGVSZXMoKTtcbiAgICAgICAgLy8gaWYgcmFuZ2UgaXMgY29tcGxldGVseSBlbnZlbG9wZWQgYnkgaGlkZGVuIGRheXMsIGdvIHBhc3QgdGhlIGhpZGRlbiBkYXlzXG4gICAgICAgIGlmICghdGhpcy50cmltSGlkZGVuRGF5cyhyZXMpKSB7XG4gICAgICAgICAgICBkYXRlID0gdGhpcy5za2lwSGlkZGVuRGF5cyhkYXRlLCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgY29tcHV0ZVJlcygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICAgIC8vIEJ1aWxkcyB0aGUgXCJjdXJyZW50XCIgcmFuZ2Ugd2hlbiBhIGRheUNvdW50IGlzIHNwZWNpZmllZC5cbiAgICBidWlsZFJhbmdlRnJvbURheUNvdW50KGRhdGUsIGRpcmVjdGlvbiwgZGF5Q291bnQpIHtcbiAgICAgICAgbGV0IHsgZGF0ZUVudiwgZGF0ZUFsaWdubWVudCB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IHJ1bm5pbmdDb3VudCA9IDA7XG4gICAgICAgIGxldCBzdGFydCA9IGRhdGU7XG4gICAgICAgIGxldCBlbmQ7XG4gICAgICAgIGlmIChkYXRlQWxpZ25tZW50KSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVFbnYuc3RhcnRPZihzdGFydCwgZGF0ZUFsaWdubWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTtcbiAgICAgICAgc3RhcnQgPSB0aGlzLnNraXBIaWRkZW5EYXlzKHN0YXJ0LCBkaXJlY3Rpb24pO1xuICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgZW5kID0gYWRkRGF5cyhlbmQsIDEpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzSGlkZGVuRGF5KGVuZCkpIHtcbiAgICAgICAgICAgICAgICBydW5uaW5nQ291bnQgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSB3aGlsZSAocnVubmluZ0NvdW50IDwgZGF5Q291bnQpO1xuICAgICAgICByZXR1cm4geyBzdGFydCwgZW5kIH07XG4gICAgfVxuICAgIC8vIEJ1aWxkcyBhIG5vcm1hbGl6ZWQgcmFuZ2Ugb2JqZWN0IGZvciB0aGUgXCJ2aXNpYmxlXCIgcmFuZ2UsXG4gICAgLy8gd2hpY2ggaXMgYSB3YXkgdG8gZGVmaW5lIHRoZSBjdXJyZW50UmFuZ2UgYW5kIGFjdGl2ZVJhbmdlIGF0IHRoZSBzYW1lIHRpbWUuXG4gICAgYnVpbGRDdXN0b21WaXNpYmxlUmFuZ2UoZGF0ZSkge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IGlucHV0ID0gcHJvcHMudmlzaWJsZVJhbmdlSW5wdXQ7XG4gICAgICAgIGxldCBzaW1wbGVJbnB1dCA9IHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICAgICAgPyBpbnB1dC5jYWxsKHByb3BzLmNhbGVuZGFyQXBpLCBwcm9wcy5kYXRlRW52LnRvRGF0ZShkYXRlKSlcbiAgICAgICAgICAgIDogaW5wdXQ7XG4gICAgICAgIGxldCByYW5nZSA9IHRoaXMucmVmaW5lUmFuZ2Uoc2ltcGxlSW5wdXQpO1xuICAgICAgICBpZiAocmFuZ2UgJiYgKHJhbmdlLnN0YXJ0ID09IG51bGwgfHwgcmFuZ2UuZW5kID09IG51bGwpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuICAgIC8vIENvbXB1dGVzIHRoZSByYW5nZSB0aGF0IHdpbGwgcmVwcmVzZW50IHRoZSBlbGVtZW50L2NlbGxzIGZvciAqcmVuZGVyaW5nKixcbiAgICAvLyBidXQgd2hpY2ggbWF5IGhhdmUgdm9pZGVkIGRheXMvdGltZXMuXG4gICAgLy8gbm90IHJlc3BvbnNpYmxlIGZvciB0cmltbWluZyBoaWRkZW4gZGF5cy5cbiAgICBidWlsZFJlbmRlclJhbmdlKGN1cnJlbnRSYW5nZSwgY3VycmVudFJhbmdlVW5pdCwgaXNSYW5nZUFsbERheSkge1xuICAgICAgICByZXR1cm4gY3VycmVudFJhbmdlO1xuICAgIH1cbiAgICAvLyBDb21wdXRlIHRoZSBkdXJhdGlvbiB2YWx1ZSB0aGF0IHNob3VsZCBiZSBhZGRlZC9zdWJzdHJhY3RlZCB0byB0aGUgY3VycmVudCBkYXRlXG4gICAgLy8gd2hlbiBhIHByZXYvbmV4dCBvcGVyYXRpb24gaGFwcGVucy5cbiAgICBidWlsZERhdGVJbmNyZW1lbnQoZmFsbGJhY2spIHtcbiAgICAgICAgbGV0IHsgZGF0ZUluY3JlbWVudCB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IGN1c3RvbUFsaWdubWVudDtcbiAgICAgICAgaWYgKGRhdGVJbmNyZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRlSW5jcmVtZW50O1xuICAgICAgICB9XG4gICAgICAgIGlmICgoY3VzdG9tQWxpZ25tZW50ID0gdGhpcy5wcm9wcy5kYXRlQWxpZ25tZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKDEsIGN1c3RvbUFsaWdubWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsbGJhY2s7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHsgZGF5czogMSB9KTtcbiAgICB9XG4gICAgcmVmaW5lUmFuZ2UocmFuZ2VJbnB1dCkge1xuICAgICAgICBpZiAocmFuZ2VJbnB1dCkge1xuICAgICAgICAgICAgbGV0IHJhbmdlID0gcGFyc2VSYW5nZShyYW5nZUlucHV0LCB0aGlzLnByb3BzLmRhdGVFbnYpO1xuICAgICAgICAgICAgaWYgKHJhbmdlKSB7XG4gICAgICAgICAgICAgICAgcmFuZ2UgPSBjb21wdXRlVmlzaWJsZURheVJhbmdlKHJhbmdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByYW5nZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLyogSGlkZGVuIERheXNcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIC8vIEluaXRpYWxpemVzIGludGVybmFsIHZhcmlhYmxlcyByZWxhdGVkIHRvIGNhbGN1bGF0aW5nIGhpZGRlbiBkYXlzLW9mLXdlZWtcbiAgICBpbml0SGlkZGVuRGF5cygpIHtcbiAgICAgICAgbGV0IGhpZGRlbkRheXMgPSB0aGlzLnByb3BzLmhpZGRlbkRheXMgfHwgW107IC8vIGFycmF5IG9mIGRheS1vZi13ZWVrIGluZGljZXMgdGhhdCBhcmUgaGlkZGVuXG4gICAgICAgIGxldCBpc0hpZGRlbkRheUhhc2ggPSBbXTsgLy8gaXMgdGhlIGRheS1vZi13ZWVrIGhpZGRlbj8gKGhhc2ggd2l0aCBkYXktb2Ytd2Vlay1pbmRleCAtPiBib29sKVxuICAgICAgICBsZXQgZGF5Q250ID0gMDtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLndlZWtlbmRzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgaGlkZGVuRGF5cy5wdXNoKDAsIDYpOyAvLyAwPXN1bmRheSwgNj1zYXR1cmRheVxuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmICghKGlzSGlkZGVuRGF5SGFzaFtpXSA9IGhpZGRlbkRheXMuaW5kZXhPZihpKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAgICAgZGF5Q250ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXlDbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBoaWRkZW5EYXlzJyk7IC8vIGFsbCBkYXlzIHdlcmUgaGlkZGVuPyBiYWQuXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc0hpZGRlbkRheUhhc2ggPSBpc0hpZGRlbkRheUhhc2g7XG4gICAgfVxuICAgIC8vIFJlbW92ZSBkYXlzIGZyb20gdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIHRoZSByYW5nZSB0aGF0IGFyZSBjb21wdXRlZCBhcyBoaWRkZW4uXG4gICAgLy8gSWYgdGhlIHdob2xlIHJhbmdlIGlzIHRyaW1tZWQgb2ZmLCByZXR1cm5zIG51bGxcbiAgICB0cmltSGlkZGVuRGF5cyhyYW5nZSkge1xuICAgICAgICBsZXQgeyBzdGFydCwgZW5kIH0gPSByYW5nZTtcbiAgICAgICAgaWYgKHN0YXJ0KSB7XG4gICAgICAgICAgICBzdGFydCA9IHRoaXMuc2tpcEhpZGRlbkRheXMoc3RhcnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbmQpIHtcbiAgICAgICAgICAgIGVuZCA9IHRoaXMuc2tpcEhpZGRlbkRheXMoZW5kLCAtMSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXJ0ID09IG51bGwgfHwgZW5kID09IG51bGwgfHwgc3RhcnQgPCBlbmQpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN0YXJ0LCBlbmQgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gSXMgdGhlIGN1cnJlbnQgZGF5IGhpZGRlbj9cbiAgICAvLyBgZGF5YCBpcyBhIGRheS1vZi13ZWVrIGluZGV4ICgwLTYpLCBvciBhIERhdGUgKHVzZWQgZm9yIFVUQylcbiAgICBpc0hpZGRlbkRheShkYXkpIHtcbiAgICAgICAgaWYgKGRheSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICAgIGRheSA9IGRheS5nZXRVVENEYXkoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5pc0hpZGRlbkRheUhhc2hbZGF5XTtcbiAgICB9XG4gICAgLy8gSW5jcmVtZW50aW5nIHRoZSBjdXJyZW50IGRheSB1bnRpbCBpdCBpcyBubyBsb25nZXIgYSBoaWRkZW4gZGF5LCByZXR1cm5pbmcgYSBjb3B5LlxuICAgIC8vIERPRVMgTk9UIENPTlNJREVSIHZhbGlkUmFuZ2UhXG4gICAgLy8gSWYgdGhlIGluaXRpYWwgdmFsdWUgb2YgYGRhdGVgIGlzIG5vdCBhIGhpZGRlbiBkYXksIGRvbid0IGRvIGFueXRoaW5nLlxuICAgIC8vIFBhc3MgYGlzRXhjbHVzaXZlYCBhcyBgdHJ1ZWAgaWYgeW91IGFyZSBkZWFsaW5nIHdpdGggYW4gZW5kIGRhdGUuXG4gICAgLy8gYGluY2AgZGVmYXVsdHMgdG8gYDFgIChpbmNyZW1lbnQgb25lIGRheSBmb3J3YXJkIGVhY2ggdGltZSlcbiAgICBza2lwSGlkZGVuRGF5cyhkYXRlLCBpbmMgPSAxLCBpc0V4Y2x1c2l2ZSA9IGZhbHNlKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLmlzSGlkZGVuRGF5SGFzaFsoZGF0ZS5nZXRVVENEYXkoKSArIChpc0V4Y2x1c2l2ZSA/IGluYyA6IDApICsgNykgJSA3XSkge1xuICAgICAgICAgICAgZGF0ZSA9IGFkZERheXMoZGF0ZSwgaW5jKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUV2ZW50SW5zdGFuY2UoZGVmSWQsIHJhbmdlLCBmb3JjZWRTdGFydFR6bywgZm9yY2VkRW5kVHpvKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgaW5zdGFuY2VJZDogZ3VpZCgpLFxuICAgICAgICBkZWZJZCxcbiAgICAgICAgcmFuZ2UsXG4gICAgICAgIGZvcmNlZFN0YXJ0VHpvOiBmb3JjZWRTdGFydFR6byA9PSBudWxsID8gbnVsbCA6IGZvcmNlZFN0YXJ0VHpvLFxuICAgICAgICBmb3JjZWRFbmRUem86IGZvcmNlZEVuZFR6byA9PSBudWxsID8gbnVsbCA6IGZvcmNlZEVuZFR6byxcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBwYXJzZVJlY3VycmluZyhyZWZpbmVkLCBkZWZhdWx0QWxsRGF5LCBkYXRlRW52LCByZWN1cnJpbmdUeXBlcykge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVjdXJyaW5nVHlwZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgbGV0IHBhcnNlZCA9IHJlY3VycmluZ1R5cGVzW2ldLnBhcnNlKHJlZmluZWQsIGRhdGVFbnYpO1xuICAgICAgICBpZiAocGFyc2VkKSB7XG4gICAgICAgICAgICBsZXQgeyBhbGxEYXkgfSA9IHJlZmluZWQ7XG4gICAgICAgICAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhbGxEYXkgPSBkZWZhdWx0QWxsRGF5O1xuICAgICAgICAgICAgICAgIGlmIChhbGxEYXkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhbGxEYXkgPSBwYXJzZWQuYWxsRGF5R3Vlc3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhbGxEYXkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsRGF5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFsbERheSxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogcGFyc2VkLmR1cmF0aW9uLFxuICAgICAgICAgICAgICAgIHR5cGVEYXRhOiBwYXJzZWQudHlwZURhdGEsXG4gICAgICAgICAgICAgICAgdHlwZUlkOiBpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIGV4cGFuZFJlY3VycmluZyhldmVudFN0b3JlLCBmcmFtaW5nUmFuZ2UsIGNvbnRleHQpIHtcbiAgICBsZXQgeyBkYXRlRW52LCBwbHVnaW5Ib29rcywgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICBsZXQgeyBkZWZzLCBpbnN0YW5jZXMgfSA9IGV2ZW50U3RvcmU7XG4gICAgLy8gcmVtb3ZlIGV4aXN0aW5nIHJlY3VycmluZyBpbnN0YW5jZXNcbiAgICAvLyBUT0RPOiBiYWQuIGFsd2F5cyBleHBhbmQgZXZlbnRzIGFzIGEgc2Vjb25kIHN0ZXBcbiAgICBpbnN0YW5jZXMgPSBmaWx0ZXJIYXNoKGluc3RhbmNlcywgKGluc3RhbmNlKSA9PiAhZGVmc1tpbnN0YW5jZS5kZWZJZF0ucmVjdXJyaW5nRGVmKTtcbiAgICBmb3IgKGxldCBkZWZJZCBpbiBkZWZzKSB7XG4gICAgICAgIGxldCBkZWYgPSBkZWZzW2RlZklkXTtcbiAgICAgICAgaWYgKGRlZi5yZWN1cnJpbmdEZWYpIHtcbiAgICAgICAgICAgIGxldCB7IGR1cmF0aW9uIH0gPSBkZWYucmVjdXJyaW5nRGVmO1xuICAgICAgICAgICAgaWYgKCFkdXJhdGlvbikge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gZGVmLmFsbERheSA/XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb24gOlxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3RhcnRzID0gZXhwYW5kUmVjdXJyaW5nUmFuZ2VzKGRlZiwgZHVyYXRpb24sIGZyYW1pbmdSYW5nZSwgZGF0ZUVudiwgcGx1Z2luSG9va3MucmVjdXJyaW5nVHlwZXMpO1xuICAgICAgICAgICAgZm9yIChsZXQgc3RhcnQgb2Ygc3RhcnRzKSB7XG4gICAgICAgICAgICAgICAgbGV0IGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWZJZCwge1xuICAgICAgICAgICAgICAgICAgICBzdGFydCxcbiAgICAgICAgICAgICAgICAgICAgZW5kOiBkYXRlRW52LmFkZChzdGFydCwgZHVyYXRpb24pLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGluc3RhbmNlc1tpbnN0YW5jZS5pbnN0YW5jZUlkXSA9IGluc3RhbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGRlZnMsIGluc3RhbmNlcyB9O1xufVxuLypcbkV2ZW50IE1VU1QgaGF2ZSBhIHJlY3VycmluZ0RlZlxuKi9cbmZ1bmN0aW9uIGV4cGFuZFJlY3VycmluZ1JhbmdlcyhldmVudERlZiwgZHVyYXRpb24sIGZyYW1pbmdSYW5nZSwgZGF0ZUVudiwgcmVjdXJyaW5nVHlwZXMpIHtcbiAgICBsZXQgdHlwZURlZiA9IHJlY3VycmluZ1R5cGVzW2V2ZW50RGVmLnJlY3VycmluZ0RlZi50eXBlSWRdO1xuICAgIGxldCBtYXJrZXJzID0gdHlwZURlZi5leHBhbmQoZXZlbnREZWYucmVjdXJyaW5nRGVmLnR5cGVEYXRhLCB7XG4gICAgICAgIHN0YXJ0OiBkYXRlRW52LnN1YnRyYWN0KGZyYW1pbmdSYW5nZS5zdGFydCwgZHVyYXRpb24pLFxuICAgICAgICBlbmQ6IGZyYW1pbmdSYW5nZS5lbmQsXG4gICAgfSwgZGF0ZUVudik7XG4gICAgLy8gdGhlIHJlY3VycmVuY2UgcGx1Z2lucyBkb24ndCBndWFyYW50ZWUgdGhhdCBhbGwtZGF5IGV2ZW50cyBhcmUgc3RhcnQtb2YtZGF5LCBzbyB3ZSBoYXZlIHRvXG4gICAgaWYgKGV2ZW50RGVmLmFsbERheSkge1xuICAgICAgICBtYXJrZXJzID0gbWFya2Vycy5tYXAoc3RhcnRPZkRheSk7XG4gICAgfVxuICAgIHJldHVybiBtYXJrZXJzO1xufVxuXG5jb25zdCBFVkVOVF9OT05fREFURV9SRUZJTkVSUyA9IHtcbiAgICBpZDogU3RyaW5nLFxuICAgIGdyb3VwSWQ6IFN0cmluZyxcbiAgICB0aXRsZTogU3RyaW5nLFxuICAgIHVybDogU3RyaW5nLFxuICAgIGludGVyYWN0aXZlOiBCb29sZWFuLFxufTtcbmNvbnN0IEVWRU5UX0RBVEVfUkVGSU5FUlMgPSB7XG4gICAgc3RhcnQ6IGlkZW50aXR5LFxuICAgIGVuZDogaWRlbnRpdHksXG4gICAgZGF0ZTogaWRlbnRpdHksXG4gICAgYWxsRGF5OiBCb29sZWFuLFxufTtcbmNvbnN0IEVWRU5UX1JFRklORVJTID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIEVWRU5UX05PTl9EQVRFX1JFRklORVJTKSwgRVZFTlRfREFURV9SRUZJTkVSUyksIHsgZXh0ZW5kZWRQcm9wczogaWRlbnRpdHkgfSk7XG5mdW5jdGlvbiBwYXJzZUV2ZW50KHJhdywgZXZlbnRTb3VyY2UsIGNvbnRleHQsIGFsbG93T3BlblJhbmdlLCByZWZpbmVycyA9IGJ1aWxkRXZlbnRSZWZpbmVycyhjb250ZXh0KSwgZGVmSWRNYXAsIGluc3RhbmNlSWRNYXApIHtcbiAgICBsZXQgeyByZWZpbmVkLCBleHRyYSB9ID0gcmVmaW5lRXZlbnREZWYocmF3LCBjb250ZXh0LCByZWZpbmVycyk7XG4gICAgbGV0IGRlZmF1bHRBbGxEYXkgPSBjb21wdXRlSXNEZWZhdWx0QWxsRGF5KGV2ZW50U291cmNlLCBjb250ZXh0KTtcbiAgICBsZXQgcmVjdXJyaW5nUmVzID0gcGFyc2VSZWN1cnJpbmcocmVmaW5lZCwgZGVmYXVsdEFsbERheSwgY29udGV4dC5kYXRlRW52LCBjb250ZXh0LnBsdWdpbkhvb2tzLnJlY3VycmluZ1R5cGVzKTtcbiAgICBpZiAocmVjdXJyaW5nUmVzKSB7XG4gICAgICAgIGxldCBkZWYgPSBwYXJzZUV2ZW50RGVmKHJlZmluZWQsIGV4dHJhLCBldmVudFNvdXJjZSA/IGV2ZW50U291cmNlLnNvdXJjZUlkIDogJycsIHJlY3VycmluZ1Jlcy5hbGxEYXksIEJvb2xlYW4ocmVjdXJyaW5nUmVzLmR1cmF0aW9uKSwgY29udGV4dCwgZGVmSWRNYXApO1xuICAgICAgICBkZWYucmVjdXJyaW5nRGVmID0ge1xuICAgICAgICAgICAgdHlwZUlkOiByZWN1cnJpbmdSZXMudHlwZUlkLFxuICAgICAgICAgICAgdHlwZURhdGE6IHJlY3VycmluZ1Jlcy50eXBlRGF0YSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiByZWN1cnJpbmdSZXMuZHVyYXRpb24sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB7IGRlZiwgaW5zdGFuY2U6IG51bGwgfTtcbiAgICB9XG4gICAgbGV0IHNpbmdsZVJlcyA9IHBhcnNlU2luZ2xlKHJlZmluZWQsIGRlZmF1bHRBbGxEYXksIGNvbnRleHQsIGFsbG93T3BlblJhbmdlKTtcbiAgICBpZiAoc2luZ2xlUmVzKSB7XG4gICAgICAgIGxldCBkZWYgPSBwYXJzZUV2ZW50RGVmKHJlZmluZWQsIGV4dHJhLCBldmVudFNvdXJjZSA/IGV2ZW50U291cmNlLnNvdXJjZUlkIDogJycsIHNpbmdsZVJlcy5hbGxEYXksIHNpbmdsZVJlcy5oYXNFbmQsIGNvbnRleHQsIGRlZklkTWFwKTtcbiAgICAgICAgbGV0IGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIHNpbmdsZVJlcy5yYW5nZSwgc2luZ2xlUmVzLmZvcmNlZFN0YXJ0VHpvLCBzaW5nbGVSZXMuZm9yY2VkRW5kVHpvKTtcbiAgICAgICAgaWYgKGluc3RhbmNlSWRNYXAgJiYgZGVmLnB1YmxpY0lkICYmIGluc3RhbmNlSWRNYXBbZGVmLnB1YmxpY0lkXSkge1xuICAgICAgICAgICAgaW5zdGFuY2UuaW5zdGFuY2VJZCA9IGluc3RhbmNlSWRNYXBbZGVmLnB1YmxpY0lkXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBkZWYsIGluc3RhbmNlIH07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gcmVmaW5lRXZlbnREZWYocmF3LCBjb250ZXh0LCByZWZpbmVycyA9IGJ1aWxkRXZlbnRSZWZpbmVycyhjb250ZXh0KSkge1xuICAgIHJldHVybiByZWZpbmVQcm9wcyhyYXcsIHJlZmluZXJzKTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRXZlbnRSZWZpbmVycyhjb250ZXh0KSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBFVkVOVF9VSV9SRUZJTkVSUyksIEVWRU5UX1JFRklORVJTKSwgY29udGV4dC5wbHVnaW5Ib29rcy5ldmVudFJlZmluZXJzKTtcbn1cbi8qXG5XaWxsIE5PVCBwb3B1bGF0ZSBleHRlbmRlZFByb3BzIHdpdGggdGhlIGxlZnRvdmVyIHByb3BlcnRpZXMuXG5XaWxsIE5PVCBwb3B1bGF0ZSBkYXRlLXJlbGF0ZWQgcHJvcHMuXG4qL1xuZnVuY3Rpb24gcGFyc2VFdmVudERlZihyZWZpbmVkLCBleHRyYSwgc291cmNlSWQsIGFsbERheSwgaGFzRW5kLCBjb250ZXh0LCBkZWZJZE1hcCkge1xuICAgIGxldCBkZWYgPSB7XG4gICAgICAgIHRpdGxlOiByZWZpbmVkLnRpdGxlIHx8ICcnLFxuICAgICAgICBncm91cElkOiByZWZpbmVkLmdyb3VwSWQgfHwgJycsXG4gICAgICAgIHB1YmxpY0lkOiByZWZpbmVkLmlkIHx8ICcnLFxuICAgICAgICB1cmw6IHJlZmluZWQudXJsIHx8ICcnLFxuICAgICAgICByZWN1cnJpbmdEZWY6IG51bGwsXG4gICAgICAgIGRlZklkOiAoKGRlZklkTWFwICYmIHJlZmluZWQuaWQpID8gZGVmSWRNYXBbcmVmaW5lZC5pZF0gOiAnJykgfHwgZ3VpZCgpLFxuICAgICAgICBzb3VyY2VJZCxcbiAgICAgICAgYWxsRGF5LFxuICAgICAgICBoYXNFbmQsXG4gICAgICAgIGludGVyYWN0aXZlOiByZWZpbmVkLmludGVyYWN0aXZlLFxuICAgICAgICB1aTogY3JlYXRlRXZlbnRVaShyZWZpbmVkLCBjb250ZXh0KSxcbiAgICAgICAgZXh0ZW5kZWRQcm9wczogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCAocmVmaW5lZC5leHRlbmRlZFByb3BzIHx8IHt9KSksIGV4dHJhKSxcbiAgICB9O1xuICAgIGZvciAobGV0IG1lbWJlckFkZGVyIG9mIGNvbnRleHQucGx1Z2luSG9va3MuZXZlbnREZWZNZW1iZXJBZGRlcnMpIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihkZWYsIG1lbWJlckFkZGVyKHJlZmluZWQpKTtcbiAgICB9XG4gICAgLy8gaGVscCBvdXQgRXZlbnRJbXBsIGZyb20gaGF2aW5nIHVzZXIgbW9kaWZ5IHByb3BzXG4gICAgT2JqZWN0LmZyZWV6ZShkZWYudWkuY2xhc3NOYW1lcyk7XG4gICAgT2JqZWN0LmZyZWV6ZShkZWYuZXh0ZW5kZWRQcm9wcyk7XG4gICAgcmV0dXJuIGRlZjtcbn1cbmZ1bmN0aW9uIHBhcnNlU2luZ2xlKHJlZmluZWQsIGRlZmF1bHRBbGxEYXksIGNvbnRleHQsIGFsbG93T3BlblJhbmdlKSB7XG4gICAgbGV0IHsgYWxsRGF5IH0gPSByZWZpbmVkO1xuICAgIGxldCBzdGFydE1ldGE7XG4gICAgbGV0IHN0YXJ0TWFya2VyID0gbnVsbDtcbiAgICBsZXQgaGFzRW5kID0gZmFsc2U7XG4gICAgbGV0IGVuZE1ldGE7XG4gICAgbGV0IGVuZE1hcmtlciA9IG51bGw7XG4gICAgbGV0IHN0YXJ0SW5wdXQgPSByZWZpbmVkLnN0YXJ0ICE9IG51bGwgPyByZWZpbmVkLnN0YXJ0IDogcmVmaW5lZC5kYXRlO1xuICAgIHN0YXJ0TWV0YSA9IGNvbnRleHQuZGF0ZUVudi5jcmVhdGVNYXJrZXJNZXRhKHN0YXJ0SW5wdXQpO1xuICAgIGlmIChzdGFydE1ldGEpIHtcbiAgICAgICAgc3RhcnRNYXJrZXIgPSBzdGFydE1ldGEubWFya2VyO1xuICAgIH1cbiAgICBlbHNlIGlmICghYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChyZWZpbmVkLmVuZCAhPSBudWxsKSB7XG4gICAgICAgIGVuZE1ldGEgPSBjb250ZXh0LmRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShyZWZpbmVkLmVuZCk7XG4gICAgfVxuICAgIGlmIChhbGxEYXkgPT0gbnVsbCkge1xuICAgICAgICBpZiAoZGVmYXVsdEFsbERheSAhPSBudWxsKSB7XG4gICAgICAgICAgICBhbGxEYXkgPSBkZWZhdWx0QWxsRGF5O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gZmFsbCBiYWNrIHRvIHRoZSBkYXRlIHByb3BzIExBU1RcbiAgICAgICAgICAgIGFsbERheSA9ICghc3RhcnRNZXRhIHx8IHN0YXJ0TWV0YS5pc1RpbWVVbnNwZWNpZmllZCkgJiZcbiAgICAgICAgICAgICAgICAoIWVuZE1ldGEgfHwgZW5kTWV0YS5pc1RpbWVVbnNwZWNpZmllZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGFsbERheSAmJiBzdGFydE1hcmtlcikge1xuICAgICAgICBzdGFydE1hcmtlciA9IHN0YXJ0T2ZEYXkoc3RhcnRNYXJrZXIpO1xuICAgIH1cbiAgICBpZiAoZW5kTWV0YSkge1xuICAgICAgICBlbmRNYXJrZXIgPSBlbmRNZXRhLm1hcmtlcjtcbiAgICAgICAgaWYgKGFsbERheSkge1xuICAgICAgICAgICAgZW5kTWFya2VyID0gc3RhcnRPZkRheShlbmRNYXJrZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGFydE1hcmtlciAmJiBlbmRNYXJrZXIgPD0gc3RhcnRNYXJrZXIpIHtcbiAgICAgICAgICAgIGVuZE1hcmtlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGVuZE1hcmtlcikge1xuICAgICAgICBoYXNFbmQgPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIGlmICghYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICAgICAgaGFzRW5kID0gY29udGV4dC5vcHRpb25zLmZvcmNlRXZlbnREdXJhdGlvbiB8fCBmYWxzZTtcbiAgICAgICAgZW5kTWFya2VyID0gY29udGV4dC5kYXRlRW52LmFkZChzdGFydE1hcmtlciwgYWxsRGF5ID9cbiAgICAgICAgICAgIGNvbnRleHQub3B0aW9ucy5kZWZhdWx0QWxsRGF5RXZlbnREdXJhdGlvbiA6XG4gICAgICAgICAgICBjb250ZXh0Lm9wdGlvbnMuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbik7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGFsbERheSxcbiAgICAgICAgaGFzRW5kLFxuICAgICAgICByYW5nZTogeyBzdGFydDogc3RhcnRNYXJrZXIsIGVuZDogZW5kTWFya2VyIH0sXG4gICAgICAgIGZvcmNlZFN0YXJ0VHpvOiBzdGFydE1ldGEgPyBzdGFydE1ldGEuZm9yY2VkVHpvIDogbnVsbCxcbiAgICAgICAgZm9yY2VkRW5kVHpvOiBlbmRNZXRhID8gZW5kTWV0YS5mb3JjZWRUem8gOiBudWxsLFxuICAgIH07XG59XG5mdW5jdGlvbiBjb21wdXRlSXNEZWZhdWx0QWxsRGF5KGV2ZW50U291cmNlLCBjb250ZXh0KSB7XG4gICAgbGV0IHJlcyA9IG51bGw7XG4gICAgaWYgKGV2ZW50U291cmNlKSB7XG4gICAgICAgIHJlcyA9IGV2ZW50U291cmNlLmRlZmF1bHRBbGxEYXk7XG4gICAgfVxuICAgIGlmIChyZXMgPT0gbnVsbCkge1xuICAgICAgICByZXMgPSBjb250ZXh0Lm9wdGlvbnMuZGVmYXVsdEFsbERheTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gcGFyc2VFdmVudHMocmF3RXZlbnRzLCBldmVudFNvdXJjZSwgY29udGV4dCwgYWxsb3dPcGVuUmFuZ2UsIGRlZklkTWFwLCBpbnN0YW5jZUlkTWFwKSB7XG4gICAgbGV0IGV2ZW50U3RvcmUgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICBsZXQgZXZlbnRSZWZpbmVycyA9IGJ1aWxkRXZlbnRSZWZpbmVycyhjb250ZXh0KTtcbiAgICBmb3IgKGxldCByYXdFdmVudCBvZiByYXdFdmVudHMpIHtcbiAgICAgICAgbGV0IHR1cGxlID0gcGFyc2VFdmVudChyYXdFdmVudCwgZXZlbnRTb3VyY2UsIGNvbnRleHQsIGFsbG93T3BlblJhbmdlLCBldmVudFJlZmluZXJzLCBkZWZJZE1hcCwgaW5zdGFuY2VJZE1hcCk7XG4gICAgICAgIGlmICh0dXBsZSkge1xuICAgICAgICAgICAgZXZlbnRUdXBsZVRvU3RvcmUodHVwbGUsIGV2ZW50U3RvcmUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBldmVudFN0b3JlO1xufVxuZnVuY3Rpb24gZXZlbnRUdXBsZVRvU3RvcmUodHVwbGUsIGV2ZW50U3RvcmUgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKSkge1xuICAgIGV2ZW50U3RvcmUuZGVmc1t0dXBsZS5kZWYuZGVmSWRdID0gdHVwbGUuZGVmO1xuICAgIGlmICh0dXBsZS5pbnN0YW5jZSkge1xuICAgICAgICBldmVudFN0b3JlLmluc3RhbmNlc1t0dXBsZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSA9IHR1cGxlLmluc3RhbmNlO1xuICAgIH1cbiAgICByZXR1cm4gZXZlbnRTdG9yZTtcbn1cbi8vIHJldHJpZXZlcyBldmVudHMgdGhhdCBoYXZlIHRoZSBzYW1lIGdyb3VwSWQgYXMgdGhlIGluc3RhbmNlIHNwZWNpZmllZCBieSBgaW5zdGFuY2VJZGBcbi8vIG9yIHRoZXkgYXJlIHRoZSBzYW1lIGFzIHRoZSBpbnN0YW5jZS5cbi8vIHdoeSBtaWdodCBpbnN0YW5jZUlkIG5vdCBiZSBpbiB0aGUgc3RvcmU/IGFuIGV2ZW50IGZyb20gYW5vdGhlciBjYWxlbmRhcj9cbmZ1bmN0aW9uIGdldFJlbGV2YW50RXZlbnRzKGV2ZW50U3RvcmUsIGluc3RhbmNlSWQpIHtcbiAgICBsZXQgaW5zdGFuY2UgPSBldmVudFN0b3JlLmluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICBpZiAoaW5zdGFuY2UpIHtcbiAgICAgICAgbGV0IGRlZiA9IGV2ZW50U3RvcmUuZGVmc1tpbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIC8vIGdldCBldmVudHMvaW5zdGFuY2VzIHdpdGggc2FtZSBncm91cFxuICAgICAgICBsZXQgbmV3U3RvcmUgPSBmaWx0ZXJFdmVudFN0b3JlRGVmcyhldmVudFN0b3JlLCAobG9va0RlZikgPT4gaXNFdmVudERlZnNHcm91cGVkKGRlZiwgbG9va0RlZikpO1xuICAgICAgICAvLyBhZGQgdGhlIG9yaWdpbmFsXG4gICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgdXNlIGV2ZW50VHVwbGVUb1N0b3JlIG9yIHNvbWV0aGluZyBsaWtlIGl0XG4gICAgICAgIG5ld1N0b3JlLmRlZnNbZGVmLmRlZklkXSA9IGRlZjtcbiAgICAgICAgbmV3U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlLmluc3RhbmNlSWRdID0gaW5zdGFuY2U7XG4gICAgICAgIHJldHVybiBuZXdTdG9yZTtcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xufVxuZnVuY3Rpb24gaXNFdmVudERlZnNHcm91cGVkKGRlZjAsIGRlZjEpIHtcbiAgICByZXR1cm4gQm9vbGVhbihkZWYwLmdyb3VwSWQgJiYgZGVmMC5ncm91cElkID09PSBkZWYxLmdyb3VwSWQpO1xufVxuZnVuY3Rpb24gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCkge1xuICAgIHJldHVybiB7IGRlZnM6IHt9LCBpbnN0YW5jZXM6IHt9IH07XG59XG5mdW5jdGlvbiBtZXJnZUV2ZW50U3RvcmVzKHN0b3JlMCwgc3RvcmUxKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGVmczogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzdG9yZTAuZGVmcyksIHN0b3JlMS5kZWZzKSxcbiAgICAgICAgaW5zdGFuY2VzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHN0b3JlMC5pbnN0YW5jZXMpLCBzdG9yZTEuaW5zdGFuY2VzKSxcbiAgICB9O1xufVxuZnVuY3Rpb24gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZmlsdGVyRnVuYykge1xuICAgIGxldCBkZWZzID0gZmlsdGVySGFzaChldmVudFN0b3JlLmRlZnMsIGZpbHRlckZ1bmMpO1xuICAgIGxldCBpbnN0YW5jZXMgPSBmaWx0ZXJIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCAoaW5zdGFuY2UpID0+IChkZWZzW2luc3RhbmNlLmRlZklkXSAvLyBzdGlsbCBleGlzdHM/XG4gICAgKSk7XG4gICAgcmV0dXJuIHsgZGVmcywgaW5zdGFuY2VzIH07XG59XG5mdW5jdGlvbiBleGNsdWRlU3ViRXZlbnRTdG9yZShtYXN0ZXIsIHN1Yikge1xuICAgIGxldCB7IGRlZnMsIGluc3RhbmNlcyB9ID0gbWFzdGVyO1xuICAgIGxldCBmaWx0ZXJlZERlZnMgPSB7fTtcbiAgICBsZXQgZmlsdGVyZWRJbnN0YW5jZXMgPSB7fTtcbiAgICBmb3IgKGxldCBkZWZJZCBpbiBkZWZzKSB7XG4gICAgICAgIGlmICghc3ViLmRlZnNbZGVmSWRdKSB7IC8vIG5vdCBleHBsaWNpdGx5IGV4Y2x1ZGVkXG4gICAgICAgICAgICBmaWx0ZXJlZERlZnNbZGVmSWRdID0gZGVmc1tkZWZJZF07XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChsZXQgaW5zdGFuY2VJZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgaWYgKCFzdWIuaW5zdGFuY2VzW2luc3RhbmNlSWRdICYmIC8vIG5vdCBleHBsaWNpdGx5IGV4Y2x1ZGVkXG4gICAgICAgICAgICBmaWx0ZXJlZERlZnNbaW5zdGFuY2VzW2luc3RhbmNlSWRdLmRlZklkXSAvLyBkZWYgd2Fzbid0IGZpbHRlcmVkIGF3YXlcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBmaWx0ZXJlZEluc3RhbmNlc1tpbnN0YW5jZUlkXSA9IGluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBkZWZzOiBmaWx0ZXJlZERlZnMsXG4gICAgICAgIGluc3RhbmNlczogZmlsdGVyZWRJbnN0YW5jZXMsXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplQ29uc3RyYWludChpbnB1dCwgY29udGV4dCkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICByZXR1cm4gcGFyc2VFdmVudHMoaW5wdXQsIG51bGwsIGNvbnRleHQsIHRydWUpOyAvLyBhbGxvd09wZW5SYW5nZT10cnVlXG4gICAgfVxuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gcGFyc2VFdmVudHMoW2lucHV0XSwgbnVsbCwgY29udGV4dCwgdHJ1ZSk7IC8vIGFsbG93T3BlblJhbmdlPXRydWVcbiAgICB9XG4gICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyhpbnB1dCk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNsYXNzTmFtZXMocmF3KSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocmF3KSkge1xuICAgICAgICByZXR1cm4gcmF3O1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHJhdyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHJhdy5zcGxpdCgvXFxzKy8pO1xuICAgIH1cbiAgICByZXR1cm4gW107XG59XG5cbi8vIFRPRE86IGJldHRlciBjYWxsZWQgXCJFdmVudFNldHRpbmdzXCIgb3IgXCJFdmVudENvbmZpZ1wiXG4vLyBUT0RPOiBtb3ZlIHRoaXMgZmlsZSBpbnRvIHN0cnVjdHNcbi8vIFRPRE86IHNlcGFyYXRlIGNvbnN0cmFpbnQvb3ZlcmxhcC9hbGxvdywgYmVjYXVzZSBzZWxlY3Rpb24gdXNlcyBvbmx5IHRoYXQsIG5vdCBvdGhlciBwcm9wc1xuY29uc3QgRVZFTlRfVUlfUkVGSU5FUlMgPSB7XG4gICAgZGlzcGxheTogU3RyaW5nLFxuICAgIGVkaXRhYmxlOiBCb29sZWFuLFxuICAgIHN0YXJ0RWRpdGFibGU6IEJvb2xlYW4sXG4gICAgZHVyYXRpb25FZGl0YWJsZTogQm9vbGVhbixcbiAgICBjb25zdHJhaW50OiBpZGVudGl0eSxcbiAgICBvdmVybGFwOiBpZGVudGl0eSxcbiAgICBhbGxvdzogaWRlbnRpdHksXG4gICAgY2xhc3NOYW1lOiBwYXJzZUNsYXNzTmFtZXMsXG4gICAgY2xhc3NOYW1lczogcGFyc2VDbGFzc05hbWVzLFxuICAgIGNvbG9yOiBTdHJpbmcsXG4gICAgYmFja2dyb3VuZENvbG9yOiBTdHJpbmcsXG4gICAgYm9yZGVyQ29sb3I6IFN0cmluZyxcbiAgICB0ZXh0Q29sb3I6IFN0cmluZyxcbn07XG5jb25zdCBFTVBUWV9FVkVOVF9VSSA9IHtcbiAgICBkaXNwbGF5OiBudWxsLFxuICAgIHN0YXJ0RWRpdGFibGU6IG51bGwsXG4gICAgZHVyYXRpb25FZGl0YWJsZTogbnVsbCxcbiAgICBjb25zdHJhaW50czogW10sXG4gICAgb3ZlcmxhcDogbnVsbCxcbiAgICBhbGxvd3M6IFtdLFxuICAgIGJhY2tncm91bmRDb2xvcjogJycsXG4gICAgYm9yZGVyQ29sb3I6ICcnLFxuICAgIHRleHRDb2xvcjogJycsXG4gICAgY2xhc3NOYW1lczogW10sXG59O1xuZnVuY3Rpb24gY3JlYXRlRXZlbnRVaShyZWZpbmVkLCBjb250ZXh0KSB7XG4gICAgbGV0IGNvbnN0cmFpbnQgPSBub3JtYWxpemVDb25zdHJhaW50KHJlZmluZWQuY29uc3RyYWludCwgY29udGV4dCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGlzcGxheTogcmVmaW5lZC5kaXNwbGF5IHx8IG51bGwsXG4gICAgICAgIHN0YXJ0RWRpdGFibGU6IHJlZmluZWQuc3RhcnRFZGl0YWJsZSAhPSBudWxsID8gcmVmaW5lZC5zdGFydEVkaXRhYmxlIDogcmVmaW5lZC5lZGl0YWJsZSxcbiAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogcmVmaW5lZC5kdXJhdGlvbkVkaXRhYmxlICE9IG51bGwgPyByZWZpbmVkLmR1cmF0aW9uRWRpdGFibGUgOiByZWZpbmVkLmVkaXRhYmxlLFxuICAgICAgICBjb25zdHJhaW50czogY29uc3RyYWludCAhPSBudWxsID8gW2NvbnN0cmFpbnRdIDogW10sXG4gICAgICAgIG92ZXJsYXA6IHJlZmluZWQub3ZlcmxhcCAhPSBudWxsID8gcmVmaW5lZC5vdmVybGFwIDogbnVsbCxcbiAgICAgICAgYWxsb3dzOiByZWZpbmVkLmFsbG93ICE9IG51bGwgPyBbcmVmaW5lZC5hbGxvd10gOiBbXSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiByZWZpbmVkLmJhY2tncm91bmRDb2xvciB8fCByZWZpbmVkLmNvbG9yIHx8ICcnLFxuICAgICAgICBib3JkZXJDb2xvcjogcmVmaW5lZC5ib3JkZXJDb2xvciB8fCByZWZpbmVkLmNvbG9yIHx8ICcnLFxuICAgICAgICB0ZXh0Q29sb3I6IHJlZmluZWQudGV4dENvbG9yIHx8ICcnLFxuICAgICAgICBjbGFzc05hbWVzOiAocmVmaW5lZC5jbGFzc05hbWUgfHwgW10pLmNvbmNhdChyZWZpbmVkLmNsYXNzTmFtZXMgfHwgW10pLCAvLyBqb2luIHNpbmd1bGFyIGFuZCBwbHVyYWxcbiAgICB9O1xufVxuLy8gVE9ETzogcHJldmVudCBhZ2FpbnN0IHByb2JsZW1zIHdpdGggPDIgYXJncyFcbmZ1bmN0aW9uIGNvbWJpbmVFdmVudFVpcyh1aXMpIHtcbiAgICByZXR1cm4gdWlzLnJlZHVjZShjb21iaW5lVHdvRXZlbnRVaXMsIEVNUFRZX0VWRU5UX1VJKTtcbn1cbmZ1bmN0aW9uIGNvbWJpbmVUd29FdmVudFVpcyhpdGVtMCwgaXRlbTEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkaXNwbGF5OiBpdGVtMS5kaXNwbGF5ICE9IG51bGwgPyBpdGVtMS5kaXNwbGF5IDogaXRlbTAuZGlzcGxheSxcbiAgICAgICAgc3RhcnRFZGl0YWJsZTogaXRlbTEuc3RhcnRFZGl0YWJsZSAhPSBudWxsID8gaXRlbTEuc3RhcnRFZGl0YWJsZSA6IGl0ZW0wLnN0YXJ0RWRpdGFibGUsXG4gICAgICAgIGR1cmF0aW9uRWRpdGFibGU6IGl0ZW0xLmR1cmF0aW9uRWRpdGFibGUgIT0gbnVsbCA/IGl0ZW0xLmR1cmF0aW9uRWRpdGFibGUgOiBpdGVtMC5kdXJhdGlvbkVkaXRhYmxlLFxuICAgICAgICBjb25zdHJhaW50czogaXRlbTAuY29uc3RyYWludHMuY29uY2F0KGl0ZW0xLmNvbnN0cmFpbnRzKSxcbiAgICAgICAgb3ZlcmxhcDogdHlwZW9mIGl0ZW0xLm92ZXJsYXAgPT09ICdib29sZWFuJyA/IGl0ZW0xLm92ZXJsYXAgOiBpdGVtMC5vdmVybGFwLFxuICAgICAgICBhbGxvd3M6IGl0ZW0wLmFsbG93cy5jb25jYXQoaXRlbTEuYWxsb3dzKSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBpdGVtMS5iYWNrZ3JvdW5kQ29sb3IgfHwgaXRlbTAuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICBib3JkZXJDb2xvcjogaXRlbTEuYm9yZGVyQ29sb3IgfHwgaXRlbTAuYm9yZGVyQ29sb3IsXG4gICAgICAgIHRleHRDb2xvcjogaXRlbTEudGV4dENvbG9yIHx8IGl0ZW0wLnRleHRDb2xvcixcbiAgICAgICAgY2xhc3NOYW1lczogaXRlbTAuY2xhc3NOYW1lcy5jb25jYXQoaXRlbTEuY2xhc3NOYW1lcyksXG4gICAgfTtcbn1cblxuY29uc3QgRVZFTlRfU09VUkNFX1JFRklORVJTID0ge1xuICAgIGlkOiBTdHJpbmcsXG4gICAgZGVmYXVsdEFsbERheTogQm9vbGVhbixcbiAgICB1cmw6IFN0cmluZyxcbiAgICBmb3JtYXQ6IFN0cmluZyxcbiAgICBldmVudHM6IGlkZW50aXR5LFxuICAgIGV2ZW50RGF0YVRyYW5zZm9ybTogaWRlbnRpdHksXG4gICAgLy8gZm9yIGFueSBuZXR3b3JrLXJlbGF0ZWQgc291cmNlc1xuICAgIHN1Y2Nlc3M6IGlkZW50aXR5LFxuICAgIGZhaWx1cmU6IGlkZW50aXR5LFxufTtcbmZ1bmN0aW9uIHBhcnNlRXZlbnRTb3VyY2UocmF3LCBjb250ZXh0LCByZWZpbmVycyA9IGJ1aWxkRXZlbnRTb3VyY2VSZWZpbmVycyhjb250ZXh0KSkge1xuICAgIGxldCByYXdPYmo7XG4gICAgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJhd09iaiA9IHsgdXJsOiByYXcgfTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHJhdyA9PT0gJ2Z1bmN0aW9uJyB8fCBBcnJheS5pc0FycmF5KHJhdykpIHtcbiAgICAgICAgcmF3T2JqID0geyBldmVudHM6IHJhdyB9O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgcmF3ID09PSAnb2JqZWN0JyAmJiByYXcpIHsgLy8gbm90IG51bGxcbiAgICAgICAgcmF3T2JqID0gcmF3O1xuICAgIH1cbiAgICBpZiAocmF3T2JqKSB7XG4gICAgICAgIGxldCB7IHJlZmluZWQsIGV4dHJhIH0gPSByZWZpbmVQcm9wcyhyYXdPYmosIHJlZmluZXJzKTtcbiAgICAgICAgbGV0IG1ldGFSZXMgPSBidWlsZEV2ZW50U291cmNlTWV0YShyZWZpbmVkLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKG1ldGFSZXMpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgX3JhdzogcmF3LFxuICAgICAgICAgICAgICAgIGlzRmV0Y2hpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGxhdGVzdEZldGNoSWQ6ICcnLFxuICAgICAgICAgICAgICAgIGZldGNoUmFuZ2U6IG51bGwsXG4gICAgICAgICAgICAgICAgZGVmYXVsdEFsbERheTogcmVmaW5lZC5kZWZhdWx0QWxsRGF5LFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YVRyYW5zZm9ybTogcmVmaW5lZC5ldmVudERhdGFUcmFuc2Zvcm0sXG4gICAgICAgICAgICAgICAgc3VjY2VzczogcmVmaW5lZC5zdWNjZXNzLFxuICAgICAgICAgICAgICAgIGZhaWx1cmU6IHJlZmluZWQuZmFpbHVyZSxcbiAgICAgICAgICAgICAgICBwdWJsaWNJZDogcmVmaW5lZC5pZCB8fCAnJyxcbiAgICAgICAgICAgICAgICBzb3VyY2VJZDogZ3VpZCgpLFxuICAgICAgICAgICAgICAgIHNvdXJjZURlZklkOiBtZXRhUmVzLnNvdXJjZURlZklkLFxuICAgICAgICAgICAgICAgIG1ldGE6IG1ldGFSZXMubWV0YSxcbiAgICAgICAgICAgICAgICB1aTogY3JlYXRlRXZlbnRVaShyZWZpbmVkLCBjb250ZXh0KSxcbiAgICAgICAgICAgICAgICBleHRlbmRlZFByb3BzOiBleHRyYSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50U291cmNlUmVmaW5lcnMoY29udGV4dCkge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgRVZFTlRfVUlfUkVGSU5FUlMpLCBFVkVOVF9TT1VSQ0VfUkVGSU5FUlMpLCBjb250ZXh0LnBsdWdpbkhvb2tzLmV2ZW50U291cmNlUmVmaW5lcnMpO1xufVxuZnVuY3Rpb24gYnVpbGRFdmVudFNvdXJjZU1ldGEocmF3LCBjb250ZXh0KSB7XG4gICAgbGV0IGRlZnMgPSBjb250ZXh0LnBsdWdpbkhvb2tzLmV2ZW50U291cmNlRGVmcztcbiAgICBmb3IgKGxldCBpID0gZGVmcy5sZW5ndGggLSAxOyBpID49IDA7IGkgLT0gMSkgeyAvLyBsYXRlci1hZGRlZCBwbHVnaW5zIHRha2UgcHJlY2VkZW5jZVxuICAgICAgICBsZXQgZGVmID0gZGVmc1tpXTtcbiAgICAgICAgbGV0IG1ldGEgPSBkZWYucGFyc2VNZXRhKHJhdyk7XG4gICAgICAgIGlmIChtZXRhKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzb3VyY2VEZWZJZDogaSwgbWV0YSB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiByZWR1Y2VFdmVudFN0b3JlKGV2ZW50U3RvcmUsIGFjdGlvbiwgZXZlbnRTb3VyY2VzLCBkYXRlUHJvZmlsZSwgY29udGV4dCkge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnUkVDRUlWRV9FVkVOVFMnOiAvLyByYXdcbiAgICAgICAgICAgIHJldHVybiByZWNlaXZlUmF3RXZlbnRzKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlc1thY3Rpb24uc291cmNlSWRdLCBhY3Rpb24uZmV0Y2hJZCwgYWN0aW9uLmZldGNoUmFuZ2UsIGFjdGlvbi5yYXdFdmVudHMsIGNvbnRleHQpO1xuICAgICAgICBjYXNlICdSRVNFVF9SQVdfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiByZXNldFJhd0V2ZW50cyhldmVudFN0b3JlLCBldmVudFNvdXJjZXNbYWN0aW9uLnNvdXJjZUlkXSwgYWN0aW9uLnJhd0V2ZW50cywgZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGNvbnRleHQpO1xuICAgICAgICBjYXNlICdBRERfRVZFTlRTJzogLy8gYWxyZWFkeSBwYXJzZWQsIGJ1dCBub3QgZXhwYW5kZWRcbiAgICAgICAgICAgIHJldHVybiBhZGRFdmVudChldmVudFN0b3JlLCBhY3Rpb24uZXZlbnRTdG9yZSwgLy8gbmV3IG9uZXNcbiAgICAgICAgICAgIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjb250ZXh0KTtcbiAgICAgICAgY2FzZSAnUkVTRVRfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiBhY3Rpb24uZXZlbnRTdG9yZTtcbiAgICAgICAgY2FzZSAnTUVSR0VfRVZFTlRTJzogLy8gYWxyZWFkeSBwYXJzZWQgYW5kIGV4cGFuZGVkXG4gICAgICAgICAgICByZXR1cm4gbWVyZ2VFdmVudFN0b3JlcyhldmVudFN0b3JlLCBhY3Rpb24uZXZlbnRTdG9yZSk7XG4gICAgICAgIGNhc2UgJ1BSRVYnOiAvLyBUT0RPOiBob3cgZG8gd2UgdHJhY2sgYWxsIGFjdGlvbnMgdGhhdCBhZmZlY3QgZGF0ZVByb2ZpbGUgOihcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9EQVRFJzpcbiAgICAgICAgY2FzZSAnQ0hBTkdFX1ZJRVdfVFlQRSc6XG4gICAgICAgICAgICBpZiAoZGF0ZVByb2ZpbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXhwYW5kUmVjdXJyaW5nKGV2ZW50U3RvcmUsIGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBjb250ZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBldmVudFN0b3JlO1xuICAgICAgICBjYXNlICdSRU1PVkVfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiBleGNsdWRlU3ViRXZlbnRTdG9yZShldmVudFN0b3JlLCBhY3Rpb24uZXZlbnRTdG9yZSk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9TT1VSQ0UnOlxuICAgICAgICAgICAgcmV0dXJuIGV4Y2x1ZGVFdmVudHNCeVNvdXJjZUlkKGV2ZW50U3RvcmUsIGFjdGlvbi5zb3VyY2VJZCk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9BTExfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgKGV2ZW50RGVmKSA9PiAoIWV2ZW50RGVmLnNvdXJjZUlkIC8vIG9ubHkga2VlcCBldmVudHMgd2l0aCBubyBzb3VyY2UgaWRcbiAgICAgICAgICAgICkpO1xuICAgICAgICBjYXNlICdSRU1PVkVfQUxMX0VWRU5UUyc6XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZXZlbnRTdG9yZTtcbiAgICB9XG59XG5mdW5jdGlvbiByZWNlaXZlUmF3RXZlbnRzKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlLCBmZXRjaElkLCBmZXRjaFJhbmdlLCByYXdFdmVudHMsIGNvbnRleHQpIHtcbiAgICBpZiAoZXZlbnRTb3VyY2UgJiYgLy8gbm90IGFscmVhZHkgcmVtb3ZlZFxuICAgICAgICBmZXRjaElkID09PSBldmVudFNvdXJjZS5sYXRlc3RGZXRjaElkIC8vIFRPRE86IHdpc2ggdGhpcyBsb2dpYyB3YXMgYWx3YXlzIGluIGV2ZW50LXNvdXJjZXNcbiAgICApIHtcbiAgICAgICAgbGV0IHN1YnNldCA9IHBhcnNlRXZlbnRzKHRyYW5zZm9ybVJhd0V2ZW50cyhyYXdFdmVudHMsIGV2ZW50U291cmNlLCBjb250ZXh0KSwgZXZlbnRTb3VyY2UsIGNvbnRleHQpO1xuICAgICAgICBpZiAoZmV0Y2hSYW5nZSkge1xuICAgICAgICAgICAgc3Vic2V0ID0gZXhwYW5kUmVjdXJyaW5nKHN1YnNldCwgZmV0Y2hSYW5nZSwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1lcmdlRXZlbnRTdG9yZXMoZXhjbHVkZUV2ZW50c0J5U291cmNlSWQoZXZlbnRTdG9yZSwgZXZlbnRTb3VyY2Uuc291cmNlSWQpLCBzdWJzZXQpO1xuICAgIH1cbiAgICByZXR1cm4gZXZlbnRTdG9yZTtcbn1cbmZ1bmN0aW9uIHJlc2V0UmF3RXZlbnRzKGV4aXN0aW5nRXZlbnRTdG9yZSwgZXZlbnRTb3VyY2UsIHJhd0V2ZW50cywgYWN0aXZlUmFuZ2UsIGNvbnRleHQpIHtcbiAgICBjb25zdCB7IGRlZklkTWFwLCBpbnN0YW5jZUlkTWFwIH0gPSBidWlsZFB1YmxpY0lkTWFwcyhleGlzdGluZ0V2ZW50U3RvcmUpO1xuICAgIGxldCBuZXdFdmVudFN0b3JlID0gcGFyc2VFdmVudHModHJhbnNmb3JtUmF3RXZlbnRzKHJhd0V2ZW50cywgZXZlbnRTb3VyY2UsIGNvbnRleHQpLCBldmVudFNvdXJjZSwgY29udGV4dCwgZmFsc2UsIGRlZklkTWFwLCBpbnN0YW5jZUlkTWFwKTtcbiAgICByZXR1cm4gZXhwYW5kUmVjdXJyaW5nKG5ld0V2ZW50U3RvcmUsIGFjdGl2ZVJhbmdlLCBjb250ZXh0KTtcbn1cbmZ1bmN0aW9uIHRyYW5zZm9ybVJhd0V2ZW50cyhyYXdFdmVudHMsIGV2ZW50U291cmNlLCBjb250ZXh0KSB7XG4gICAgbGV0IGNhbEVhY2hUcmFuc2Zvcm0gPSBjb250ZXh0Lm9wdGlvbnMuZXZlbnREYXRhVHJhbnNmb3JtO1xuICAgIGxldCBzb3VyY2VFYWNoVHJhbnNmb3JtID0gZXZlbnRTb3VyY2UgPyBldmVudFNvdXJjZS5ldmVudERhdGFUcmFuc2Zvcm0gOiBudWxsO1xuICAgIGlmIChzb3VyY2VFYWNoVHJhbnNmb3JtKSB7XG4gICAgICAgIHJhd0V2ZW50cyA9IHRyYW5zZm9ybUVhY2hSYXdFdmVudChyYXdFdmVudHMsIHNvdXJjZUVhY2hUcmFuc2Zvcm0pO1xuICAgIH1cbiAgICBpZiAoY2FsRWFjaFRyYW5zZm9ybSkge1xuICAgICAgICByYXdFdmVudHMgPSB0cmFuc2Zvcm1FYWNoUmF3RXZlbnQocmF3RXZlbnRzLCBjYWxFYWNoVHJhbnNmb3JtKTtcbiAgICB9XG4gICAgcmV0dXJuIHJhd0V2ZW50cztcbn1cbmZ1bmN0aW9uIHRyYW5zZm9ybUVhY2hSYXdFdmVudChyYXdFdmVudHMsIGZ1bmMpIHtcbiAgICBsZXQgcmVmaW5lZEV2ZW50cztcbiAgICBpZiAoIWZ1bmMpIHtcbiAgICAgICAgcmVmaW5lZEV2ZW50cyA9IHJhd0V2ZW50cztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJlZmluZWRFdmVudHMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgcmF3RXZlbnQgb2YgcmF3RXZlbnRzKSB7XG4gICAgICAgICAgICBsZXQgcmVmaW5lZEV2ZW50ID0gZnVuYyhyYXdFdmVudCk7XG4gICAgICAgICAgICBpZiAocmVmaW5lZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZEV2ZW50cy5wdXNoKHJlZmluZWRFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChyZWZpbmVkRXZlbnQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlZmluZWRFdmVudHMucHVzaChyYXdFdmVudCk7XG4gICAgICAgICAgICB9IC8vIGlmIGEgZGlmZmVyZW50IGZhbHN5IHZhbHVlLCBkbyBub3RoaW5nXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlZmluZWRFdmVudHM7XG59XG5mdW5jdGlvbiBhZGRFdmVudChldmVudFN0b3JlLCBzdWJzZXQsIGV4cGFuZFJhbmdlLCBjb250ZXh0KSB7XG4gICAgaWYgKGV4cGFuZFJhbmdlKSB7XG4gICAgICAgIHN1YnNldCA9IGV4cGFuZFJlY3VycmluZyhzdWJzZXQsIGV4cGFuZFJhbmdlLCBjb250ZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIG1lcmdlRXZlbnRTdG9yZXMoZXZlbnRTdG9yZSwgc3Vic2V0KTtcbn1cbmZ1bmN0aW9uIHJlem9uZUV2ZW50U3RvcmVEYXRlcyhldmVudFN0b3JlLCBvbGREYXRlRW52LCBuZXdEYXRlRW52KSB7XG4gICAgbGV0IHsgZGVmcyB9ID0gZXZlbnRTdG9yZTtcbiAgICBsZXQgaW5zdGFuY2VzID0gbWFwSGFzaChldmVudFN0b3JlLmluc3RhbmNlcywgKGluc3RhbmNlKSA9PiB7XG4gICAgICAgIGxldCBkZWYgPSBkZWZzW2luc3RhbmNlLmRlZklkXTtcbiAgICAgICAgaWYgKGRlZi5hbGxEYXkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnN0YW5jZTsgLy8gaXNuJ3QgZGVwZW5kZW50IG9uIHRpbWV6b25lXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgaW5zdGFuY2UpLCB7IHJhbmdlOiB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IG5ld0RhdGVFbnYuY3JlYXRlTWFya2VyKG9sZERhdGVFbnYudG9EYXRlKGluc3RhbmNlLnJhbmdlLnN0YXJ0LCBpbnN0YW5jZS5mb3JjZWRTdGFydFR6bykpLFxuICAgICAgICAgICAgICAgIGVuZDogbmV3RGF0ZUVudi5jcmVhdGVNYXJrZXIob2xkRGF0ZUVudi50b0RhdGUoaW5zdGFuY2UucmFuZ2UuZW5kLCBpbnN0YW5jZS5mb3JjZWRFbmRUem8pKSxcbiAgICAgICAgICAgIH0sIGZvcmNlZFN0YXJ0VHpvOiBuZXdEYXRlRW52LmNhbkNvbXB1dGVPZmZzZXQgPyBudWxsIDogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sIGZvcmNlZEVuZFR6bzogbmV3RGF0ZUVudi5jYW5Db21wdXRlT2Zmc2V0ID8gbnVsbCA6IGluc3RhbmNlLmZvcmNlZEVuZFR6byB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4geyBkZWZzLCBpbnN0YW5jZXMgfTtcbn1cbmZ1bmN0aW9uIGV4Y2x1ZGVFdmVudHNCeVNvdXJjZUlkKGV2ZW50U3RvcmUsIHNvdXJjZUlkKSB7XG4gICAgcmV0dXJuIGZpbHRlckV2ZW50U3RvcmVEZWZzKGV2ZW50U3RvcmUsIChldmVudERlZikgPT4gZXZlbnREZWYuc291cmNlSWQgIT09IHNvdXJjZUlkKTtcbn1cbi8vIFFVRVNUSU9OOiB3aHkgbm90IGp1c3QgcmV0dXJuIGluc3RhbmNlcz8gZG8gYSBnZW5lcmFsIG9iamVjdC1wcm9wZXJ0eS1leGNsdXNpb24gdXRpbFxuZnVuY3Rpb24gZXhjbHVkZUluc3RhbmNlcyhldmVudFN0b3JlLCByZW1vdmFscykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGRlZnM6IGV2ZW50U3RvcmUuZGVmcyxcbiAgICAgICAgaW5zdGFuY2VzOiBmaWx0ZXJIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCAoaW5zdGFuY2UpID0+ICFyZW1vdmFsc1tpbnN0YW5jZS5pbnN0YW5jZUlkXSksXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGJ1aWxkUHVibGljSWRNYXBzKGV2ZW50U3RvcmUpIHtcbiAgICBjb25zdCB7IGRlZnMsIGluc3RhbmNlcyB9ID0gZXZlbnRTdG9yZTtcbiAgICBjb25zdCBkZWZJZE1hcCA9IHt9O1xuICAgIGNvbnN0IGluc3RhbmNlSWRNYXAgPSB7fTtcbiAgICBmb3IgKGxldCBkZWZJZCBpbiBkZWZzKSB7XG4gICAgICAgIGNvbnN0IGRlZiA9IGRlZnNbZGVmSWRdO1xuICAgICAgICBjb25zdCB7IHB1YmxpY0lkIH0gPSBkZWY7XG4gICAgICAgIGlmIChwdWJsaWNJZCkge1xuICAgICAgICAgICAgZGVmSWRNYXBbcHVibGljSWRdID0gZGVmSWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChsZXQgaW5zdGFuY2VJZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgIGNvbnN0IGRlZiA9IGRlZnNbaW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICBjb25zdCB7IHB1YmxpY0lkIH0gPSBkZWY7XG4gICAgICAgIGlmIChwdWJsaWNJZCkge1xuICAgICAgICAgICAgaW5zdGFuY2VJZE1hcFtwdWJsaWNJZF0gPSBpbnN0YW5jZUlkO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGRlZklkTWFwLCBpbnN0YW5jZUlkTWFwIH07XG59XG5cbmNsYXNzIEVtaXR0ZXIge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmhhbmRsZXJzID0ge307XG4gICAgICAgIHRoaXMudGhpc0NvbnRleHQgPSBudWxsO1xuICAgIH1cbiAgICBzZXRUaGlzQ29udGV4dCh0aGlzQ29udGV4dCkge1xuICAgICAgICB0aGlzLnRoaXNDb250ZXh0ID0gdGhpc0NvbnRleHQ7XG4gICAgfVxuICAgIHNldE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH1cbiAgICBvbih0eXBlLCBoYW5kbGVyKSB7XG4gICAgICAgIGFkZFRvSGFzaCh0aGlzLmhhbmRsZXJzLCB0eXBlLCBoYW5kbGVyKTtcbiAgICB9XG4gICAgb2ZmKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgcmVtb3ZlRnJvbUhhc2godGhpcy5oYW5kbGVycywgdHlwZSwgaGFuZGxlcik7XG4gICAgfVxuICAgIHRyaWdnZXIodHlwZSwgLi4uYXJncykge1xuICAgICAgICBsZXQgYXR0YWNoZWRIYW5kbGVycyA9IHRoaXMuaGFuZGxlcnNbdHlwZV0gfHwgW107XG4gICAgICAgIGxldCBvcHRpb25IYW5kbGVyID0gdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9uc1t0eXBlXTtcbiAgICAgICAgbGV0IGhhbmRsZXJzID0gW10uY29uY2F0KG9wdGlvbkhhbmRsZXIgfHwgW10sIGF0dGFjaGVkSGFuZGxlcnMpO1xuICAgICAgICBmb3IgKGxldCBoYW5kbGVyIG9mIGhhbmRsZXJzKSB7XG4gICAgICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMudGhpc0NvbnRleHQsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhhc0hhbmRsZXJzKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oKHRoaXMuaGFuZGxlcnNbdHlwZV0gJiYgdGhpcy5oYW5kbGVyc1t0eXBlXS5sZW5ndGgpIHx8XG4gICAgICAgICAgICAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9uc1t0eXBlXSkpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFkZFRvSGFzaChoYXNoLCB0eXBlLCBoYW5kbGVyKSB7XG4gICAgKGhhc2hbdHlwZV0gfHwgKGhhc2hbdHlwZV0gPSBbXSkpXG4gICAgICAgIC5wdXNoKGhhbmRsZXIpO1xufVxuZnVuY3Rpb24gcmVtb3ZlRnJvbUhhc2goaGFzaCwgdHlwZSwgaGFuZGxlcikge1xuICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgIGlmIChoYXNoW3R5cGVdKSB7XG4gICAgICAgICAgICBoYXNoW3R5cGVdID0gaGFzaFt0eXBlXS5maWx0ZXIoKGZ1bmMpID0+IGZ1bmMgIT09IGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBkZWxldGUgaGFzaFt0eXBlXTsgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyIGZ1bmNzIGZvciB0aGlzIHR5cGVcbiAgICB9XG59XG5cbmNvbnN0IERFRl9ERUZBVUxUUyA9IHtcbiAgICBzdGFydFRpbWU6ICcwOTowMCcsXG4gICAgZW5kVGltZTogJzE3OjAwJyxcbiAgICBkYXlzT2ZXZWVrOiBbMSwgMiwgMywgNCwgNV0sXG4gICAgZGlzcGxheTogJ2ludmVyc2UtYmFja2dyb3VuZCcsXG4gICAgY2xhc3NOYW1lczogJ2ZjLW5vbi1idXNpbmVzcycsXG4gICAgZ3JvdXBJZDogJ19idXNpbmVzc0hvdXJzJywgLy8gc28gbXVsdGlwbGUgZGVmcyBnZXQgZ3JvdXBlZFxufTtcbi8qXG5UT0RPOiBwYXNzIGFyb3VuZCBhcyBFdmVudERlZkhhc2ghISFcbiovXG5mdW5jdGlvbiBwYXJzZUJ1c2luZXNzSG91cnMoaW5wdXQsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gcGFyc2VFdmVudHMocmVmaW5lSW5wdXRzKGlucHV0KSwgbnVsbCwgY29udGV4dCk7XG59XG5mdW5jdGlvbiByZWZpbmVJbnB1dHMoaW5wdXQpIHtcbiAgICBsZXQgcmF3RGVmcztcbiAgICBpZiAoaW5wdXQgPT09IHRydWUpIHtcbiAgICAgICAgcmF3RGVmcyA9IFt7fV07IC8vIHdpbGwgZ2V0IERFRl9ERUZBVUxUUyB2ZXJiYXRpbVxuICAgIH1cbiAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICAvLyBpZiBzcGVjaWZ5aW5nIGFuIGFycmF5LCBldmVyeSBzdWItZGVmaW5pdGlvbiBORUVEUyBhIGRheS1vZi13ZWVrXG4gICAgICAgIHJhd0RlZnMgPSBpbnB1dC5maWx0ZXIoKHJhd0RlZikgPT4gcmF3RGVmLmRheXNPZldlZWspO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByYXdEZWZzID0gW2lucHV0XTtcbiAgICB9XG4gICAgZWxzZSB7IC8vIGlzIHByb2JhYmx5IGZhbHNlXG4gICAgICAgIHJhd0RlZnMgPSBbXTtcbiAgICB9XG4gICAgcmF3RGVmcyA9IHJhd0RlZnMubWFwKChyYXdEZWYpID0+IChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIERFRl9ERUZBVUxUUyksIHJhd0RlZikpKTtcbiAgICByZXR1cm4gcmF3RGVmcztcbn1cblxuZnVuY3Rpb24gdHJpZ2dlckRhdGVTZWxlY3Qoc2VsZWN0aW9uLCBwZXYsIGNvbnRleHQpIHtcbiAgICBjb250ZXh0LmVtaXR0ZXIudHJpZ2dlcignc2VsZWN0JywgT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBidWlsZERhdGVTcGFuQXBpV2l0aENvbnRleHQoc2VsZWN0aW9uLCBjb250ZXh0KSksIHsganNFdmVudDogcGV2ID8gcGV2Lm9yaWdFdmVudCA6IG51bGwsIHZpZXc6IGNvbnRleHQudmlld0FwaSB8fCBjb250ZXh0LmNhbGVuZGFyQXBpLnZpZXcgfSkpO1xufVxuZnVuY3Rpb24gdHJpZ2dlckRhdGVVbnNlbGVjdChwZXYsIGNvbnRleHQpIHtcbiAgICBjb250ZXh0LmVtaXR0ZXIudHJpZ2dlcigndW5zZWxlY3QnLCB7XG4gICAgICAgIGpzRXZlbnQ6IHBldiA/IHBldi5vcmlnRXZlbnQgOiBudWxsLFxuICAgICAgICB2aWV3OiBjb250ZXh0LnZpZXdBcGkgfHwgY29udGV4dC5jYWxlbmRhckFwaS52aWV3LFxuICAgIH0pO1xufVxuZnVuY3Rpb24gYnVpbGREYXRlU3BhbkFwaVdpdGhDb250ZXh0KGRhdGVTcGFuLCBjb250ZXh0KSB7XG4gICAgbGV0IHByb3BzID0ge307XG4gICAgZm9yIChsZXQgdHJhbnNmb3JtIG9mIGNvbnRleHQucGx1Z2luSG9va3MuZGF0ZVNwYW5UcmFuc2Zvcm1zKSB7XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocHJvcHMsIHRyYW5zZm9ybShkYXRlU3BhbiwgY29udGV4dCkpO1xuICAgIH1cbiAgICBPYmplY3QuYXNzaWduKHByb3BzLCBidWlsZERhdGVTcGFuQXBpKGRhdGVTcGFuLCBjb250ZXh0LmRhdGVFbnYpKTtcbiAgICByZXR1cm4gcHJvcHM7XG59XG4vLyBHaXZlbiBhbiBldmVudCdzIGFsbERheSBzdGF0dXMgYW5kIHN0YXJ0IGRhdGUsIHJldHVybiB3aGF0IGl0cyBmYWxsYmFjayBlbmQgZGF0ZSBzaG91bGQgYmUuXG4vLyBUT0RPOiByZW5hbWUgdG8gY29tcHV0ZURlZmF1bHRFdmVudEVuZFxuZnVuY3Rpb24gZ2V0RGVmYXVsdEV2ZW50RW5kKGFsbERheSwgbWFya2VyLCBjb250ZXh0KSB7XG4gICAgbGV0IHsgZGF0ZUVudiwgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICBsZXQgZW5kID0gbWFya2VyO1xuICAgIGlmIChhbGxEYXkpIHtcbiAgICAgICAgZW5kID0gc3RhcnRPZkRheShlbmQpO1xuICAgICAgICBlbmQgPSBkYXRlRW52LmFkZChlbmQsIG9wdGlvbnMuZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb24pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoZW5kLCBvcHRpb25zLmRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gZW5kO1xufVxuXG4vLyBhcHBsaWVzIHRoZSBtdXRhdGlvbiB0byBBTEwgZGVmcy9pbnN0YW5jZXMgd2l0aGluIHRoZSBldmVudCBzdG9yZVxuZnVuY3Rpb24gYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudENvbmZpZ0Jhc2UsIG11dGF0aW9uLCBjb250ZXh0KSB7XG4gICAgbGV0IGV2ZW50Q29uZmlncyA9IGNvbXBpbGVFdmVudFVpcyhldmVudFN0b3JlLmRlZnMsIGV2ZW50Q29uZmlnQmFzZSk7XG4gICAgbGV0IGRlc3QgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICBmb3IgKGxldCBkZWZJZCBpbiBldmVudFN0b3JlLmRlZnMpIHtcbiAgICAgICAgbGV0IGRlZiA9IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF07XG4gICAgICAgIGRlc3QuZGVmc1tkZWZJZF0gPSBhcHBseU11dGF0aW9uVG9FdmVudERlZihkZWYsIGV2ZW50Q29uZmlnc1tkZWZJZF0sIG11dGF0aW9uLCBjb250ZXh0KTtcbiAgICB9XG4gICAgZm9yIChsZXQgaW5zdGFuY2VJZCBpbiBldmVudFN0b3JlLmluc3RhbmNlcykge1xuICAgICAgICBsZXQgaW5zdGFuY2UgPSBldmVudFN0b3JlLmluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICAgICAgbGV0IGRlZiA9IGRlc3QuZGVmc1tpbnN0YW5jZS5kZWZJZF07IC8vIGltcG9ydGFudCB0byBncmFiIHRoZSBuZXdseSBtb2RpZmllZCBkZWZcbiAgICAgICAgZGVzdC5pbnN0YW5jZXNbaW5zdGFuY2VJZF0gPSBhcHBseU11dGF0aW9uVG9FdmVudEluc3RhbmNlKGluc3RhbmNlLCBkZWYsIGV2ZW50Q29uZmlnc1tpbnN0YW5jZS5kZWZJZF0sIG11dGF0aW9uLCBjb250ZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIGRlc3Q7XG59XG5mdW5jdGlvbiBhcHBseU11dGF0aW9uVG9FdmVudERlZihldmVudERlZiwgZXZlbnRDb25maWcsIG11dGF0aW9uLCBjb250ZXh0KSB7XG4gICAgbGV0IHN0YW5kYXJkUHJvcHMgPSBtdXRhdGlvbi5zdGFuZGFyZFByb3BzIHx8IHt9O1xuICAgIC8vIGlmIGhhc0VuZCBoYXMgbm90IGJlZW4gc3BlY2lmaWVkLCBndWVzcyBhIGdvb2QgdmFsdWUgYmFzZWQgb24gZGVsdGFzLlxuICAgIC8vIGlmIGR1cmF0aW9uIHdpbGwgY2hhbmdlLCB0aGVyZSdzIG5vIHdheSB0aGUgZGVmYXVsdCBkdXJhdGlvbiB3aWxsIHBlcnNpc3QsXG4gICAgLy8gYW5kIHRodXMsIHdlIG5lZWQgdG8gbWFyayB0aGUgZXZlbnQgYXMgaGF2aW5nIGEgcmVhbCBlbmRcbiAgICBpZiAoc3RhbmRhcmRQcm9wcy5oYXNFbmQgPT0gbnVsbCAmJlxuICAgICAgICBldmVudENvbmZpZy5kdXJhdGlvbkVkaXRhYmxlICYmXG4gICAgICAgIChtdXRhdGlvbi5zdGFydERlbHRhIHx8IG11dGF0aW9uLmVuZERlbHRhKSkge1xuICAgICAgICBzdGFuZGFyZFByb3BzLmhhc0VuZCA9IHRydWU7IC8vIFRPRE86IGlzIHRoaXMgbXV0YXRpb24gb2theT9cbiAgICB9XG4gICAgbGV0IGNvcHkgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnREZWYpLCBzdGFuZGFyZFByb3BzKSwgeyB1aTogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBldmVudERlZi51aSksIHN0YW5kYXJkUHJvcHMudWkpIH0pO1xuICAgIGlmIChtdXRhdGlvbi5leHRlbmRlZFByb3BzKSB7XG4gICAgICAgIGNvcHkuZXh0ZW5kZWRQcm9wcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgY29weS5leHRlbmRlZFByb3BzKSwgbXV0YXRpb24uZXh0ZW5kZWRQcm9wcyk7XG4gICAgfVxuICAgIGZvciAobGV0IGFwcGxpZXIgb2YgY29udGV4dC5wbHVnaW5Ib29rcy5ldmVudERlZk11dGF0aW9uQXBwbGllcnMpIHtcbiAgICAgICAgYXBwbGllcihjb3B5LCBtdXRhdGlvbiwgY29udGV4dCk7XG4gICAgfVxuICAgIGlmICghY29weS5oYXNFbmQgJiYgY29udGV4dC5vcHRpb25zLmZvcmNlRXZlbnREdXJhdGlvbikge1xuICAgICAgICBjb3B5Lmhhc0VuZCA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xufVxuZnVuY3Rpb24gYXBwbHlNdXRhdGlvblRvRXZlbnRJbnN0YW5jZShldmVudEluc3RhbmNlLCBldmVudERlZiwgLy8gbXVzdCBmaXJzdCBiZSBtb2RpZmllZCBieSBhcHBseU11dGF0aW9uVG9FdmVudERlZlxuZXZlbnRDb25maWcsIG11dGF0aW9uLCBjb250ZXh0KSB7XG4gICAgbGV0IHsgZGF0ZUVudiB9ID0gY29udGV4dDtcbiAgICBsZXQgZm9yY2VBbGxEYXkgPSBtdXRhdGlvbi5zdGFuZGFyZFByb3BzICYmIG11dGF0aW9uLnN0YW5kYXJkUHJvcHMuYWxsRGF5ID09PSB0cnVlO1xuICAgIGxldCBjbGVhckVuZCA9IG11dGF0aW9uLnN0YW5kYXJkUHJvcHMgJiYgbXV0YXRpb24uc3RhbmRhcmRQcm9wcy5oYXNFbmQgPT09IGZhbHNlO1xuICAgIGxldCBjb3B5ID0gT2JqZWN0LmFzc2lnbih7fSwgZXZlbnRJbnN0YW5jZSk7XG4gICAgaWYgKGZvcmNlQWxsRGF5KSB7XG4gICAgICAgIGNvcHkucmFuZ2UgPSBjb21wdXRlQWxpZ25lZERheVJhbmdlKGNvcHkucmFuZ2UpO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24uZGF0ZXNEZWx0YSAmJiBldmVudENvbmZpZy5zdGFydEVkaXRhYmxlKSB7XG4gICAgICAgIGNvcHkucmFuZ2UgPSB7XG4gICAgICAgICAgICBzdGFydDogZGF0ZUVudi5hZGQoY29weS5yYW5nZS5zdGFydCwgbXV0YXRpb24uZGF0ZXNEZWx0YSksXG4gICAgICAgICAgICBlbmQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2UuZW5kLCBtdXRhdGlvbi5kYXRlc0RlbHRhKSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLnN0YXJ0RGVsdGEgJiYgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2Uuc3RhcnQsIG11dGF0aW9uLnN0YXJ0RGVsdGEpLFxuICAgICAgICAgICAgZW5kOiBjb3B5LnJhbmdlLmVuZCxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLmVuZERlbHRhICYmIGV2ZW50Q29uZmlnLmR1cmF0aW9uRWRpdGFibGUpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBjb3B5LnJhbmdlLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBkYXRlRW52LmFkZChjb3B5LnJhbmdlLmVuZCwgbXV0YXRpb24uZW5kRGVsdGEpLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoY2xlYXJFbmQpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBjb3B5LnJhbmdlLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBnZXREZWZhdWx0RXZlbnRFbmQoZXZlbnREZWYuYWxsRGF5LCBjb3B5LnJhbmdlLnN0YXJ0LCBjb250ZXh0KSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gaW4gY2FzZSBldmVudCB3YXMgYWxsLWRheSBidXQgdGhlIHN1cHBsaWVkIGRlbHRhcyB3ZXJlIG5vdFxuICAgIC8vIGJldHRlciB1dGlsIGZvciB0aGlzP1xuICAgIGlmIChldmVudERlZi5hbGxEYXkpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBzdGFydE9mRGF5KGNvcHkucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kOiBzdGFydE9mRGF5KGNvcHkucmFuZ2UuZW5kKSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gaGFuZGxlIGludmFsaWQgZHVyYXRpb25zXG4gICAgaWYgKGNvcHkucmFuZ2UuZW5kIDwgY29weS5yYW5nZS5zdGFydCkge1xuICAgICAgICBjb3B5LnJhbmdlLmVuZCA9IGdldERlZmF1bHRFdmVudEVuZChldmVudERlZi5hbGxEYXksIGNvcHkucmFuZ2Uuc3RhcnQsIGNvbnRleHQpO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbn1cblxuY2xhc3MgRXZlbnRTb3VyY2VJbXBsIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBpbnRlcm5hbEV2ZW50U291cmNlKSB7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZSA9IGludGVybmFsRXZlbnRTb3VyY2U7XG4gICAgfVxuICAgIHJlbW92ZSgpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRfU09VUkNFJyxcbiAgICAgICAgICAgIHNvdXJjZUlkOiB0aGlzLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWQsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZWZldGNoKCkge1xuICAgICAgICB0aGlzLmNvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ0ZFVENIX0VWRU5UX1NPVVJDRVMnLFxuICAgICAgICAgICAgc291cmNlSWRzOiBbdGhpcy5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkXSxcbiAgICAgICAgICAgIGlzUmVmZXRjaDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGdldCBpZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5wdWJsaWNJZDtcbiAgICB9XG4gICAgZ2V0IHVybCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5tZXRhLnVybDtcbiAgICB9XG4gICAgZ2V0IGZvcm1hdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5tZXRhLmZvcm1hdDsgLy8gVE9ETzogYmFkLiBub3QgZ3VhcmFudGVlZFxuICAgIH1cbn1cblxuY2xhc3MgRXZlbnRJbXBsIHtcbiAgICAvLyBpbnN0YW5jZSB3aWxsIGJlIG51bGwgaWYgZXhwcmVzc2luZyBhIHJlY3VycmluZyBldmVudCB0aGF0IGhhcyBubyBjdXJyZW50IGluc3RhbmNlcyxcbiAgICAvLyBPUiBpZiB0cnlpbmcgdG8gdmFsaWRhdGUgYW4gaW5jb21pbmcgZXh0ZXJuYWwgZXZlbnQgdGhhdCBoYXMgbm8gZGF0ZXMgYXNzaWduZWRcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBkZWYsIGluc3RhbmNlKSB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB0aGlzLl9kZWYgPSBkZWY7XG4gICAgICAgIHRoaXMuX2luc3RhbmNlID0gaW5zdGFuY2UgfHwgbnVsbDtcbiAgICB9XG4gICAgLypcbiAgICBUT0RPOiBtYWtlIGV2ZW50IHN0cnVjdCBtb3JlIHJlc3BvbnNpYmxlIGZvciB0aGlzXG4gICAgKi9cbiAgICBzZXRQcm9wKG5hbWUsIHZhbCkge1xuICAgICAgICBpZiAobmFtZSBpbiBFVkVOVF9EQVRFX1JFRklORVJTKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0NvdWxkIG5vdCBzZXQgZGF0ZS1yZWxhdGVkIHByb3AgXFwnbmFtZVxcJy4gVXNlIG9uZSBvZiB0aGUgZGF0ZS1yZWxhdGVkIG1ldGhvZHMgaW5zdGVhZC4nKTtcbiAgICAgICAgICAgIC8vIFRPRE86IG1ha2UgcHJvcGVyIGFsaWFzaW5nIHN5c3RlbT9cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuYW1lID09PSAnaWQnKSB7XG4gICAgICAgICAgICB2YWwgPSBFVkVOVF9OT05fREFURV9SRUZJTkVSU1tuYW1lXSh2YWwpO1xuICAgICAgICAgICAgdGhpcy5tdXRhdGUoe1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHM6IHsgcHVibGljSWQ6IHZhbCB9LCAvLyBoYXJkY29kZWQgaW50ZXJuYWwgbmFtZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobmFtZSBpbiBFVkVOVF9OT05fREFURV9SRUZJTkVSUykge1xuICAgICAgICAgICAgdmFsID0gRVZFTlRfTk9OX0RBVEVfUkVGSU5FUlNbbmFtZV0odmFsKTtcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFByb3BzOiB7IFtuYW1lXTogdmFsIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuYW1lIGluIEVWRU5UX1VJX1JFRklORVJTKSB7XG4gICAgICAgICAgICBsZXQgdWkgPSBFVkVOVF9VSV9SRUZJTkVSU1tuYW1lXSh2YWwpO1xuICAgICAgICAgICAgaWYgKG5hbWUgPT09ICdjb2xvcicpIHtcbiAgICAgICAgICAgICAgICB1aSA9IHsgYmFja2dyb3VuZENvbG9yOiB2YWwsIGJvcmRlckNvbG9yOiB2YWwgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG5hbWUgPT09ICdlZGl0YWJsZScpIHtcbiAgICAgICAgICAgICAgICB1aSA9IHsgc3RhcnRFZGl0YWJsZTogdmFsLCBkdXJhdGlvbkVkaXRhYmxlOiB2YWwgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHVpID0geyBbbmFtZV06IHZhbCB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tdXRhdGUoe1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHM6IHsgdWkgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBDb3VsZCBub3Qgc2V0IHByb3AgJyR7bmFtZX0nLiBVc2Ugc2V0RXh0ZW5kZWRQcm9wIGluc3RlYWQuYCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0RXh0ZW5kZWRQcm9wKG5hbWUsIHZhbCkge1xuICAgICAgICB0aGlzLm11dGF0ZSh7XG4gICAgICAgICAgICBleHRlbmRlZFByb3BzOiB7IFtuYW1lXTogdmFsIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzZXRTdGFydChzdGFydElucHV0LCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgbGV0IHsgZGF0ZUVudiB9ID0gdGhpcy5fY29udGV4dDtcbiAgICAgICAgbGV0IHN0YXJ0ID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoc3RhcnRJbnB1dCk7XG4gICAgICAgIGlmIChzdGFydCAmJiB0aGlzLl9pbnN0YW5jZSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIGxldCBpbnN0YW5jZVJhbmdlID0gdGhpcy5faW5zdGFuY2UucmFuZ2U7XG4gICAgICAgICAgICBsZXQgc3RhcnREZWx0YSA9IGRpZmZEYXRlcyhpbnN0YW5jZVJhbmdlLnN0YXJ0LCBzdGFydCwgZGF0ZUVudiwgb3B0aW9ucy5ncmFudWxhcml0eSk7IC8vIHdoYXQgaWYgcGFyc2VkIGJhZCE/XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tYWludGFpbkR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBkYXRlc0RlbHRhOiBzdGFydERlbHRhIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFydERlbHRhIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHNldEVuZChlbmRJbnB1dCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGxldCB7IGRhdGVFbnYgfSA9IHRoaXMuX2NvbnRleHQ7XG4gICAgICAgIGxldCBlbmQ7XG4gICAgICAgIGlmIChlbmRJbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICBlbmQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihlbmRJbnB1dCk7XG4gICAgICAgICAgICBpZiAoIWVuZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2luc3RhbmNlKSB7XG4gICAgICAgICAgICBpZiAoZW5kKSB7XG4gICAgICAgICAgICAgICAgbGV0IGVuZERlbHRhID0gZGlmZkRhdGVzKHRoaXMuX2luc3RhbmNlLnJhbmdlLmVuZCwgZW5kLCBkYXRlRW52LCBvcHRpb25zLmdyYW51bGFyaXR5KTtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGVuZERlbHRhIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFuZGFyZFByb3BzOiB7IGhhc0VuZDogZmFsc2UgfSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBzZXREYXRlcyhzdGFydElucHV0LCBlbmRJbnB1dCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGxldCB7IGRhdGVFbnYgfSA9IHRoaXMuX2NvbnRleHQ7XG4gICAgICAgIGxldCBzdGFuZGFyZFByb3BzID0geyBhbGxEYXk6IG9wdGlvbnMuYWxsRGF5IH07XG4gICAgICAgIGxldCBzdGFydCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKHN0YXJ0SW5wdXQpO1xuICAgICAgICBsZXQgZW5kO1xuICAgICAgICBpZiAoIXN0YXJ0KSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICB9XG4gICAgICAgIGlmIChlbmRJbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICBlbmQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihlbmRJbnB1dCk7XG4gICAgICAgICAgICBpZiAoIWVuZCkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2luc3RhbmNlKSB7XG4gICAgICAgICAgICBsZXQgaW5zdGFuY2VSYW5nZSA9IHRoaXMuX2luc3RhbmNlLnJhbmdlO1xuICAgICAgICAgICAgLy8gd2hlbiBjb21wdXRpbmcgdGhlIGRpZmYgZm9yIGFuIGV2ZW50IGJlaW5nIGNvbnZlcnRlZCB0byBhbGwtZGF5LFxuICAgICAgICAgICAgLy8gY29tcHV0ZSBkaWZmIG9mZiBvZiB0aGUgYWxsLWRheSB2YWx1ZXMgdGhlIHdheSBldmVudC1tdXRhdGlvbiBkb2VzLlxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYWxsRGF5ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgaW5zdGFuY2VSYW5nZSA9IGNvbXB1dGVBbGlnbmVkRGF5UmFuZ2UoaW5zdGFuY2VSYW5nZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3RhcnREZWx0YSA9IGRpZmZEYXRlcyhpbnN0YW5jZVJhbmdlLnN0YXJ0LCBzdGFydCwgZGF0ZUVudiwgb3B0aW9ucy5ncmFudWxhcml0eSk7XG4gICAgICAgICAgICBpZiAoZW5kKSB7XG4gICAgICAgICAgICAgICAgbGV0IGVuZERlbHRhID0gZGlmZkRhdGVzKGluc3RhbmNlUmFuZ2UuZW5kLCBlbmQsIGRhdGVFbnYsIG9wdGlvbnMuZ3JhbnVsYXJpdHkpO1xuICAgICAgICAgICAgICAgIGlmIChkdXJhdGlvbnNFcXVhbChzdGFydERlbHRhLCBlbmREZWx0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBkYXRlc0RlbHRhOiBzdGFydERlbHRhLCBzdGFuZGFyZFByb3BzIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFydERlbHRhLCBlbmREZWx0YSwgc3RhbmRhcmRQcm9wcyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8gbWVhbnMgXCJjbGVhciB0aGUgZW5kXCJcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFByb3BzLmhhc0VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZGF0ZXNEZWx0YTogc3RhcnREZWx0YSwgc3RhbmRhcmRQcm9wcyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBtb3ZlU3RhcnQoZGVsdGFJbnB1dCkge1xuICAgICAgICBsZXQgZGVsdGEgPSBjcmVhdGVEdXJhdGlvbihkZWx0YUlucHV0KTtcbiAgICAgICAgaWYgKGRlbHRhKSB7IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFydERlbHRhOiBkZWx0YSB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBtb3ZlRW5kKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgbGV0IGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZW5kRGVsdGE6IGRlbHRhIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIG1vdmVEYXRlcyhkZWx0YUlucHV0KSB7XG4gICAgICAgIGxldCBkZWx0YSA9IGNyZWF0ZUR1cmF0aW9uKGRlbHRhSW5wdXQpO1xuICAgICAgICBpZiAoZGVsdGEpIHsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGRhdGVzRGVsdGE6IGRlbHRhIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHNldEFsbERheShhbGxEYXksIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBsZXQgc3RhbmRhcmRQcm9wcyA9IHsgYWxsRGF5IH07XG4gICAgICAgIGxldCB7IG1haW50YWluRHVyYXRpb24gfSA9IG9wdGlvbnM7XG4gICAgICAgIGlmIChtYWludGFpbkR1cmF0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgIG1haW50YWluRHVyYXRpb24gPSB0aGlzLl9jb250ZXh0Lm9wdGlvbnMuYWxsRGF5TWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fZGVmLmFsbERheSAhPT0gYWxsRGF5KSB7XG4gICAgICAgICAgICBzdGFuZGFyZFByb3BzLmhhc0VuZCA9IG1haW50YWluRHVyYXRpb247XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFuZGFyZFByb3BzIH0pO1xuICAgIH1cbiAgICBmb3JtYXRSYW5nZShmb3JtYXRJbnB1dCkge1xuICAgICAgICBsZXQgeyBkYXRlRW52IH0gPSB0aGlzLl9jb250ZXh0O1xuICAgICAgICBsZXQgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgbGV0IGZvcm1hdHRlciA9IGNyZWF0ZUZvcm1hdHRlcihmb3JtYXRJbnB1dCk7XG4gICAgICAgIGlmICh0aGlzLl9kZWYuaGFzRW5kKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXRSYW5nZShpbnN0YW5jZS5yYW5nZS5zdGFydCwgaW5zdGFuY2UucmFuZ2UuZW5kLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICBmb3JjZWRTdGFydFR6bzogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICAgICAgZm9yY2VkRW5kVHpvOiBpbnN0YW5jZS5mb3JjZWRFbmRUem8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoaW5zdGFuY2UucmFuZ2Uuc3RhcnQsIGZvcm1hdHRlciwge1xuICAgICAgICAgICAgZm9yY2VkVHpvOiBpbnN0YW5jZS5mb3JjZWRTdGFydFR6byxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIG11dGF0ZShtdXRhdGlvbikge1xuICAgICAgICBsZXQgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgICBsZXQgZGVmID0gdGhpcy5fZGVmO1xuICAgICAgICAgICAgbGV0IGNvbnRleHQgPSB0aGlzLl9jb250ZXh0O1xuICAgICAgICAgICAgbGV0IHsgZXZlbnRTdG9yZSB9ID0gY29udGV4dC5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICAgICAgbGV0IHJlbGV2YW50RXZlbnRzID0gZ2V0UmVsZXZhbnRFdmVudHMoZXZlbnRTdG9yZSwgaW5zdGFuY2UuaW5zdGFuY2VJZCk7XG4gICAgICAgICAgICBsZXQgZXZlbnRDb25maWdCYXNlID0ge1xuICAgICAgICAgICAgICAgICcnOiB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICcnLFxuICAgICAgICAgICAgICAgICAgICBzdGFydEVkaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbkVkaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50czogW10sXG4gICAgICAgICAgICAgICAgICAgIG92ZXJsYXA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGFsbG93czogW10sXG4gICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJycsXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgdGV4dENvbG9yOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lczogW10sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZWxldmFudEV2ZW50cyA9IGFwcGx5TXV0YXRpb25Ub0V2ZW50U3RvcmUocmVsZXZhbnRFdmVudHMsIGV2ZW50Q29uZmlnQmFzZSwgbXV0YXRpb24sIGNvbnRleHQpO1xuICAgICAgICAgICAgbGV0IG9sZEV2ZW50ID0gbmV3IEV2ZW50SW1wbChjb250ZXh0LCBkZWYsIGluc3RhbmNlKTsgLy8gc25hcHNob3RcbiAgICAgICAgICAgIHRoaXMuX2RlZiA9IHJlbGV2YW50RXZlbnRzLmRlZnNbZGVmLmRlZklkXTtcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbmNlID0gcmVsZXZhbnRFdmVudHMuaW5zdGFuY2VzW2luc3RhbmNlLmluc3RhbmNlSWRdO1xuICAgICAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogcmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudENoYW5nZScsIHtcbiAgICAgICAgICAgICAgICBvbGRFdmVudCxcbiAgICAgICAgICAgICAgICBldmVudDogdGhpcyxcbiAgICAgICAgICAgICAgICByZWxhdGVkRXZlbnRzOiBidWlsZEV2ZW50QXBpcyhyZWxldmFudEV2ZW50cywgY29udGV4dCwgaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgIHJldmVydCgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnUkVTRVRfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50U3RvcmUsIC8vIHRoZSBPUklHSU5BTCBzdG9yZVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVtb3ZlKCkge1xuICAgICAgICBsZXQgY29udGV4dCA9IHRoaXMuX2NvbnRleHQ7XG4gICAgICAgIGxldCBhc1N0b3JlID0gZXZlbnRBcGlUb1N0b3JlKHRoaXMpO1xuICAgICAgICBjb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRTJyxcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IGFzU3RvcmUsXG4gICAgICAgIH0pO1xuICAgICAgICBjb250ZXh0LmVtaXR0ZXIudHJpZ2dlcignZXZlbnRSZW1vdmUnLCB7XG4gICAgICAgICAgICBldmVudDogdGhpcyxcbiAgICAgICAgICAgIHJlbGF0ZWRFdmVudHM6IFtdLFxuICAgICAgICAgICAgcmV2ZXJ0KCkge1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogYXNTdG9yZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBnZXQgc291cmNlKCkge1xuICAgICAgICBsZXQgeyBzb3VyY2VJZCB9ID0gdGhpcy5fZGVmO1xuICAgICAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRXZlbnRTb3VyY2VJbXBsKHRoaXMuX2NvbnRleHQsIHRoaXMuX2NvbnRleHQuZ2V0Q3VycmVudERhdGEoKS5ldmVudFNvdXJjZXNbc291cmNlSWRdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZ2V0IHN0YXJ0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faW5zdGFuY2UgP1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dC5kYXRlRW52LnRvRGF0ZSh0aGlzLl9pbnN0YW5jZS5yYW5nZS5zdGFydCkgOlxuICAgICAgICAgICAgbnVsbDtcbiAgICB9XG4gICAgZ2V0IGVuZCgpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9pbnN0YW5jZSAmJiB0aGlzLl9kZWYuaGFzRW5kKSA/XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0LmRhdGVFbnYudG9EYXRlKHRoaXMuX2luc3RhbmNlLnJhbmdlLmVuZCkgOlxuICAgICAgICAgICAgbnVsbDtcbiAgICB9XG4gICAgZ2V0IHN0YXJ0U3RyKCkge1xuICAgICAgICBsZXQgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fY29udGV4dC5kYXRlRW52LmZvcm1hdElzbyhpbnN0YW5jZS5yYW5nZS5zdGFydCwge1xuICAgICAgICAgICAgICAgIG9taXRUaW1lOiB0aGlzLl9kZWYuYWxsRGF5LFxuICAgICAgICAgICAgICAgIGZvcmNlZFR6bzogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIGdldCBlbmRTdHIoKSB7XG4gICAgICAgIGxldCBpbnN0YW5jZSA9IHRoaXMuX2luc3RhbmNlO1xuICAgICAgICBpZiAoaW5zdGFuY2UgJiYgdGhpcy5fZGVmLmhhc0VuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHQuZGF0ZUVudi5mb3JtYXRJc28oaW5zdGFuY2UucmFuZ2UuZW5kLCB7XG4gICAgICAgICAgICAgICAgb21pdFRpbWU6IHRoaXMuX2RlZi5hbGxEYXksXG4gICAgICAgICAgICAgICAgZm9yY2VkVHpvOiBpbnN0YW5jZS5mb3JjZWRFbmRUem8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIC8vIGNvbXB1dGFibGUgcHJvcHMgdGhhdCBhbGwgYWNjZXNzIHRoZSBkZWZcbiAgICAvLyBUT0RPOiBmaW5kIGEgVHlwZVNjcmlwdC1jb21wYXRpYmxlIHdheSB0byBkbyB0aGlzIGF0IHNjYWxlXG4gICAgZ2V0IGlkKCkgeyByZXR1cm4gdGhpcy5fZGVmLnB1YmxpY0lkOyB9XG4gICAgZ2V0IGdyb3VwSWQoKSB7IHJldHVybiB0aGlzLl9kZWYuZ3JvdXBJZDsgfVxuICAgIGdldCBhbGxEYXkoKSB7IHJldHVybiB0aGlzLl9kZWYuYWxsRGF5OyB9XG4gICAgZ2V0IHRpdGxlKCkgeyByZXR1cm4gdGhpcy5fZGVmLnRpdGxlOyB9XG4gICAgZ2V0IHVybCgpIHsgcmV0dXJuIHRoaXMuX2RlZi51cmw7IH1cbiAgICBnZXQgZGlzcGxheSgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5kaXNwbGF5IHx8ICdhdXRvJzsgfSAvLyBiYWQuIGp1c3Qgbm9ybWFsaXplIHRoZSB0eXBlIGVhcmxpZXJcbiAgICBnZXQgc3RhcnRFZGl0YWJsZSgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5zdGFydEVkaXRhYmxlOyB9XG4gICAgZ2V0IGR1cmF0aW9uRWRpdGFibGUoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuZHVyYXRpb25FZGl0YWJsZTsgfVxuICAgIGdldCBjb25zdHJhaW50KCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLmNvbnN0cmFpbnRzWzBdIHx8IG51bGw7IH1cbiAgICBnZXQgb3ZlcmxhcCgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5vdmVybGFwOyB9XG4gICAgZ2V0IGFsbG93KCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLmFsbG93c1swXSB8fCBudWxsOyB9XG4gICAgZ2V0IGJhY2tncm91bmRDb2xvcigpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5iYWNrZ3JvdW5kQ29sb3I7IH1cbiAgICBnZXQgYm9yZGVyQ29sb3IoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYm9yZGVyQ29sb3I7IH1cbiAgICBnZXQgdGV4dENvbG9yKCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLnRleHRDb2xvcjsgfVxuICAgIC8vIE5PVEU6IHVzZXIgY2FuJ3QgbW9kaWZ5IHRoZXNlIGJlY2F1c2UgT2JqZWN0LmZyZWV6ZSB3YXMgY2FsbGVkIGluIGV2ZW50LWRlZiBwYXJzaW5nXG4gICAgZ2V0IGNsYXNzTmFtZXMoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuY2xhc3NOYW1lczsgfVxuICAgIGdldCBleHRlbmRlZFByb3BzKCkgeyByZXR1cm4gdGhpcy5fZGVmLmV4dGVuZGVkUHJvcHM7IH1cbiAgICB0b1BsYWluT2JqZWN0KHNldHRpbmdzID0ge30pIHtcbiAgICAgICAgbGV0IGRlZiA9IHRoaXMuX2RlZjtcbiAgICAgICAgbGV0IHsgdWkgfSA9IGRlZjtcbiAgICAgICAgbGV0IHsgc3RhcnRTdHIsIGVuZFN0ciB9ID0gdGhpcztcbiAgICAgICAgbGV0IHJlcyA9IHtcbiAgICAgICAgICAgIGFsbERheTogZGVmLmFsbERheSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGRlZi50aXRsZSkge1xuICAgICAgICAgICAgcmVzLnRpdGxlID0gZGVmLnRpdGxlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGFydFN0cikge1xuICAgICAgICAgICAgcmVzLnN0YXJ0ID0gc3RhcnRTdHI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVuZFN0cikge1xuICAgICAgICAgICAgcmVzLmVuZCA9IGVuZFN0cjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGVmLnB1YmxpY0lkKSB7XG4gICAgICAgICAgICByZXMuaWQgPSBkZWYucHVibGljSWQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlZi5ncm91cElkKSB7XG4gICAgICAgICAgICByZXMuZ3JvdXBJZCA9IGRlZi5ncm91cElkO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZWYudXJsKSB7XG4gICAgICAgICAgICByZXMudXJsID0gZGVmLnVybDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodWkuZGlzcGxheSAmJiB1aS5kaXNwbGF5ICE9PSAnYXV0bycpIHtcbiAgICAgICAgICAgIHJlcy5kaXNwbGF5ID0gdWkuZGlzcGxheTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUT0RPOiB3aGF0IGFib3V0IHJlY3VycmluZy1ldmVudCBwcm9wZXJ0aWVzPz8/XG4gICAgICAgIC8vIFRPRE86IGluY2x1ZGUgc3RhcnRFZGl0YWJsZS9kdXJhdGlvbkVkaXRhYmxlL2NvbnN0cmFpbnQvb3ZlcmxhcC9hbGxvd1xuICAgICAgICBpZiAoc2V0dGluZ3MuY29sbGFwc2VDb2xvciAmJiB1aS5iYWNrZ3JvdW5kQ29sb3IgJiYgdWkuYmFja2dyb3VuZENvbG9yID09PSB1aS5ib3JkZXJDb2xvcikge1xuICAgICAgICAgICAgcmVzLmNvbG9yID0gdWkuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKHVpLmJhY2tncm91bmRDb2xvcikge1xuICAgICAgICAgICAgICAgIHJlcy5iYWNrZ3JvdW5kQ29sb3IgPSB1aS5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodWkuYm9yZGVyQ29sb3IpIHtcbiAgICAgICAgICAgICAgICByZXMuYm9yZGVyQ29sb3IgPSB1aS5ib3JkZXJDb2xvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodWkudGV4dENvbG9yKSB7XG4gICAgICAgICAgICByZXMudGV4dENvbG9yID0gdWkudGV4dENvbG9yO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1aS5jbGFzc05hbWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVzLmNsYXNzTmFtZXMgPSB1aS5jbGFzc05hbWVzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhkZWYuZXh0ZW5kZWRQcm9wcykubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MuY29sbGFwc2VFeHRlbmRlZFByb3BzKSB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihyZXMsIGRlZi5leHRlbmRlZFByb3BzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlcy5leHRlbmRlZFByb3BzID0gZGVmLmV4dGVuZGVkUHJvcHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgdG9KU09OKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b1BsYWluT2JqZWN0KCk7XG4gICAgfVxufVxuZnVuY3Rpb24gZXZlbnRBcGlUb1N0b3JlKGV2ZW50QXBpKSB7XG4gICAgbGV0IGRlZiA9IGV2ZW50QXBpLl9kZWY7XG4gICAgbGV0IGluc3RhbmNlID0gZXZlbnRBcGkuX2luc3RhbmNlO1xuICAgIHJldHVybiB7XG4gICAgICAgIGRlZnM6IHsgW2RlZi5kZWZJZF06IGRlZiB9LFxuICAgICAgICBpbnN0YW5jZXM6IGluc3RhbmNlXG4gICAgICAgICAgICA/IHsgW2luc3RhbmNlLmluc3RhbmNlSWRdOiBpbnN0YW5jZSB9XG4gICAgICAgICAgICA6IHt9LFxuICAgIH07XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50QXBpcyhldmVudFN0b3JlLCBjb250ZXh0LCBleGNsdWRlSW5zdGFuY2UpIHtcbiAgICBsZXQgeyBkZWZzLCBpbnN0YW5jZXMgfSA9IGV2ZW50U3RvcmU7XG4gICAgbGV0IGV2ZW50QXBpcyA9IFtdO1xuICAgIGxldCBleGNsdWRlSW5zdGFuY2VJZCA9IGV4Y2x1ZGVJbnN0YW5jZSA/IGV4Y2x1ZGVJbnN0YW5jZS5pbnN0YW5jZUlkIDogJyc7XG4gICAgZm9yIChsZXQgaWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgIGxldCBpbnN0YW5jZSA9IGluc3RhbmNlc1tpZF07XG4gICAgICAgIGxldCBkZWYgPSBkZWZzW2luc3RhbmNlLmRlZklkXTtcbiAgICAgICAgaWYgKGluc3RhbmNlLmluc3RhbmNlSWQgIT09IGV4Y2x1ZGVJbnN0YW5jZUlkKSB7XG4gICAgICAgICAgICBldmVudEFwaXMucHVzaChuZXcgRXZlbnRJbXBsKGNvbnRleHQsIGRlZiwgaW5zdGFuY2UpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXZlbnRBcGlzO1xufVxuXG4vKlxuU3BlY2lmeWluZyBuZXh0RGF5VGhyZXNob2xkIHNpZ25hbHMgdGhhdCBhbGwtZGF5IHJhbmdlcyBzaG91bGQgYmUgc2xpY2VkLlxuKi9cbmZ1bmN0aW9uIHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGZyYW1pbmdSYW5nZSwgbmV4dERheVRocmVzaG9sZCkge1xuICAgIGxldCBpbnZlcnNlQmdCeUdyb3VwSWQgPSB7fTtcbiAgICBsZXQgaW52ZXJzZUJnQnlEZWZJZCA9IHt9O1xuICAgIGxldCBkZWZCeUdyb3VwSWQgPSB7fTtcbiAgICBsZXQgYmdSYW5nZXMgPSBbXTtcbiAgICBsZXQgZmdSYW5nZXMgPSBbXTtcbiAgICBsZXQgZXZlbnRVaXMgPSBjb21waWxlRXZlbnRVaXMoZXZlbnRTdG9yZS5kZWZzLCBldmVudFVpQmFzZXMpO1xuICAgIGZvciAobGV0IGRlZklkIGluIGV2ZW50U3RvcmUuZGVmcykge1xuICAgICAgICBsZXQgZGVmID0gZXZlbnRTdG9yZS5kZWZzW2RlZklkXTtcbiAgICAgICAgbGV0IHVpID0gZXZlbnRVaXNbZGVmLmRlZklkXTtcbiAgICAgICAgaWYgKHVpLmRpc3BsYXkgPT09ICdpbnZlcnNlLWJhY2tncm91bmQnKSB7XG4gICAgICAgICAgICBpZiAoZGVmLmdyb3VwSWQpIHtcbiAgICAgICAgICAgICAgICBpbnZlcnNlQmdCeUdyb3VwSWRbZGVmLmdyb3VwSWRdID0gW107XG4gICAgICAgICAgICAgICAgaWYgKCFkZWZCeUdyb3VwSWRbZGVmLmdyb3VwSWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlZkJ5R3JvdXBJZFtkZWYuZ3JvdXBJZF0gPSBkZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlEZWZJZFtkZWZJZF0gPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGxldCBpbnN0YW5jZUlkIGluIGV2ZW50U3RvcmUuaW5zdGFuY2VzKSB7XG4gICAgICAgIGxldCBpbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlSWRdO1xuICAgICAgICBsZXQgZGVmID0gZXZlbnRTdG9yZS5kZWZzW2luc3RhbmNlLmRlZklkXTtcbiAgICAgICAgbGV0IHVpID0gZXZlbnRVaXNbZGVmLmRlZklkXTtcbiAgICAgICAgbGV0IG9yaWdSYW5nZSA9IGluc3RhbmNlLnJhbmdlO1xuICAgICAgICBsZXQgbm9ybWFsUmFuZ2UgPSAoIWRlZi5hbGxEYXkgJiYgbmV4dERheVRocmVzaG9sZCkgP1xuICAgICAgICAgICAgY29tcHV0ZVZpc2libGVEYXlSYW5nZShvcmlnUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQpIDpcbiAgICAgICAgICAgIG9yaWdSYW5nZTtcbiAgICAgICAgbGV0IHNsaWNlZFJhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKG5vcm1hbFJhbmdlLCBmcmFtaW5nUmFuZ2UpO1xuICAgICAgICBpZiAoc2xpY2VkUmFuZ2UpIHtcbiAgICAgICAgICAgIGlmICh1aS5kaXNwbGF5ID09PSAnaW52ZXJzZS1iYWNrZ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIGlmIChkZWYuZ3JvdXBJZCkge1xuICAgICAgICAgICAgICAgICAgICBpbnZlcnNlQmdCeUdyb3VwSWRbZGVmLmdyb3VwSWRdLnB1c2goc2xpY2VkUmFuZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlEZWZJZFtpbnN0YW5jZS5kZWZJZF0ucHVzaChzbGljZWRSYW5nZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodWkuZGlzcGxheSAhPT0gJ25vbmUnKSB7XG4gICAgICAgICAgICAgICAgKHVpLmRpc3BsYXkgPT09ICdiYWNrZ3JvdW5kJyA/IGJnUmFuZ2VzIDogZmdSYW5nZXMpLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBkZWYsXG4gICAgICAgICAgICAgICAgICAgIHVpLFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZSxcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IHNsaWNlZFJhbmdlLFxuICAgICAgICAgICAgICAgICAgICBpc1N0YXJ0OiBub3JtYWxSYW5nZS5zdGFydCAmJiBub3JtYWxSYW5nZS5zdGFydC52YWx1ZU9mKCkgPT09IHNsaWNlZFJhbmdlLnN0YXJ0LnZhbHVlT2YoKSxcbiAgICAgICAgICAgICAgICAgICAgaXNFbmQ6IG5vcm1hbFJhbmdlLmVuZCAmJiBub3JtYWxSYW5nZS5lbmQudmFsdWVPZigpID09PSBzbGljZWRSYW5nZS5lbmQudmFsdWVPZigpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAobGV0IGdyb3VwSWQgaW4gaW52ZXJzZUJnQnlHcm91cElkKSB7IC8vIEJZIEdST1VQXG4gICAgICAgIGxldCByYW5nZXMgPSBpbnZlcnNlQmdCeUdyb3VwSWRbZ3JvdXBJZF07XG4gICAgICAgIGxldCBpbnZlcnRlZFJhbmdlcyA9IGludmVydFJhbmdlcyhyYW5nZXMsIGZyYW1pbmdSYW5nZSk7XG4gICAgICAgIGZvciAobGV0IGludmVydGVkUmFuZ2Ugb2YgaW52ZXJ0ZWRSYW5nZXMpIHtcbiAgICAgICAgICAgIGxldCBkZWYgPSBkZWZCeUdyb3VwSWRbZ3JvdXBJZF07XG4gICAgICAgICAgICBsZXQgdWkgPSBldmVudFVpc1tkZWYuZGVmSWRdO1xuICAgICAgICAgICAgYmdSYW5nZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZGVmLFxuICAgICAgICAgICAgICAgIHVpLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlOiBudWxsLFxuICAgICAgICAgICAgICAgIHJhbmdlOiBpbnZlcnRlZFJhbmdlLFxuICAgICAgICAgICAgICAgIGlzU3RhcnQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGlzRW5kOiBmYWxzZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAobGV0IGRlZklkIGluIGludmVyc2VCZ0J5RGVmSWQpIHtcbiAgICAgICAgbGV0IHJhbmdlcyA9IGludmVyc2VCZ0J5RGVmSWRbZGVmSWRdO1xuICAgICAgICBsZXQgaW52ZXJ0ZWRSYW5nZXMgPSBpbnZlcnRSYW5nZXMocmFuZ2VzLCBmcmFtaW5nUmFuZ2UpO1xuICAgICAgICBmb3IgKGxldCBpbnZlcnRlZFJhbmdlIG9mIGludmVydGVkUmFuZ2VzKSB7XG4gICAgICAgICAgICBiZ1Jhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBkZWY6IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF0sXG4gICAgICAgICAgICAgICAgdWk6IGV2ZW50VWlzW2RlZklkXSxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZTogbnVsbCxcbiAgICAgICAgICAgICAgICByYW5nZTogaW52ZXJ0ZWRSYW5nZSxcbiAgICAgICAgICAgICAgICBpc1N0YXJ0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc0VuZDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBiZzogYmdSYW5nZXMsIGZnOiBmZ1JhbmdlcyB9O1xufVxuZnVuY3Rpb24gaGFzQmdSZW5kZXJpbmcoZGVmKSB7XG4gICAgcmV0dXJuIGRlZi51aS5kaXNwbGF5ID09PSAnYmFja2dyb3VuZCcgfHwgZGVmLnVpLmRpc3BsYXkgPT09ICdpbnZlcnNlLWJhY2tncm91bmQnO1xufVxuZnVuY3Rpb24gc2V0RWxTZWcoZWwsIHNlZykge1xuICAgIGVsLmZjU2VnID0gc2VnO1xufVxuZnVuY3Rpb24gZ2V0RWxTZWcoZWwpIHtcbiAgICByZXR1cm4gZWwuZmNTZWcgfHxcbiAgICAgICAgZWwucGFyZW50Tm9kZS5mY1NlZyB8fCAvLyBmb3IgdGhlIGhhcm5lc3NcbiAgICAgICAgbnVsbDtcbn1cbi8vIGV2ZW50IHVpIGNvbXB1dGF0aW9uXG5mdW5jdGlvbiBjb21waWxlRXZlbnRVaXMoZXZlbnREZWZzLCBldmVudFVpQmFzZXMpIHtcbiAgICByZXR1cm4gbWFwSGFzaChldmVudERlZnMsIChldmVudERlZikgPT4gY29tcGlsZUV2ZW50VWkoZXZlbnREZWYsIGV2ZW50VWlCYXNlcykpO1xufVxuZnVuY3Rpb24gY29tcGlsZUV2ZW50VWkoZXZlbnREZWYsIGV2ZW50VWlCYXNlcykge1xuICAgIGxldCB1aXMgPSBbXTtcbiAgICBpZiAoZXZlbnRVaUJhc2VzWycnXSkge1xuICAgICAgICB1aXMucHVzaChldmVudFVpQmFzZXNbJyddKTtcbiAgICB9XG4gICAgaWYgKGV2ZW50VWlCYXNlc1tldmVudERlZi5kZWZJZF0pIHtcbiAgICAgICAgdWlzLnB1c2goZXZlbnRVaUJhc2VzW2V2ZW50RGVmLmRlZklkXSk7XG4gICAgfVxuICAgIHVpcy5wdXNoKGV2ZW50RGVmLnVpKTtcbiAgICByZXR1cm4gY29tYmluZUV2ZW50VWlzKHVpcyk7XG59XG5mdW5jdGlvbiBzb3J0RXZlbnRTZWdzKHNlZ3MsIGV2ZW50T3JkZXJTcGVjcykge1xuICAgIGxldCBvYmpzID0gc2Vncy5tYXAoYnVpbGRTZWdDb21wYXJlT2JqKTtcbiAgICBvYmpzLnNvcnQoKG9iajAsIG9iajEpID0+IGNvbXBhcmVCeUZpZWxkU3BlY3Mob2JqMCwgb2JqMSwgZXZlbnRPcmRlclNwZWNzKSk7XG4gICAgcmV0dXJuIG9ianMubWFwKChjKSA9PiBjLl9zZWcpO1xufVxuLy8gcmV0dXJucyBhIG9iamVjdCB3aXRoIGFsbCBwcmltaXRpdmUgcHJvcHMgdGhhdCBjYW4gYmUgY29tcGFyZWRcbmZ1bmN0aW9uIGJ1aWxkU2VnQ29tcGFyZU9iaihzZWcpIHtcbiAgICBsZXQgeyBldmVudFJhbmdlIH0gPSBzZWc7XG4gICAgbGV0IGV2ZW50RGVmID0gZXZlbnRSYW5nZS5kZWY7XG4gICAgbGV0IHJhbmdlID0gZXZlbnRSYW5nZS5pbnN0YW5jZSA/IGV2ZW50UmFuZ2UuaW5zdGFuY2UucmFuZ2UgOiBldmVudFJhbmdlLnJhbmdlO1xuICAgIGxldCBzdGFydCA9IHJhbmdlLnN0YXJ0ID8gcmFuZ2Uuc3RhcnQudmFsdWVPZigpIDogMDsgLy8gVE9ETzogYmV0dGVyIHN1cHBvcnQgZm9yIG9wZW4tcmFuZ2UgZXZlbnRzXG4gICAgbGV0IGVuZCA9IHJhbmdlLmVuZCA/IHJhbmdlLmVuZC52YWx1ZU9mKCkgOiAwOyAvLyBcIlxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnREZWYuZXh0ZW5kZWRQcm9wcyksIGV2ZW50RGVmKSwgeyBpZDogZXZlbnREZWYucHVibGljSWQsIHN0YXJ0LFxuICAgICAgICBlbmQsIGR1cmF0aW9uOiBlbmQgLSBzdGFydCwgYWxsRGF5OiBOdW1iZXIoZXZlbnREZWYuYWxsRGF5KSwgX3NlZzogc2VnIH0pO1xufVxuZnVuY3Rpb24gY29tcHV0ZVNlZ0RyYWdnYWJsZShzZWcsIGNvbnRleHQpIHtcbiAgICBsZXQgeyBwbHVnaW5Ib29rcyB9ID0gY29udGV4dDtcbiAgICBsZXQgdHJhbnNmb3JtZXJzID0gcGx1Z2luSG9va3MuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnM7XG4gICAgbGV0IHsgZGVmLCB1aSB9ID0gc2VnLmV2ZW50UmFuZ2U7XG4gICAgbGV0IHZhbCA9IHVpLnN0YXJ0RWRpdGFibGU7XG4gICAgZm9yIChsZXQgdHJhbnNmb3JtZXIgb2YgdHJhbnNmb3JtZXJzKSB7XG4gICAgICAgIHZhbCA9IHRyYW5zZm9ybWVyKHZhbCwgZGVmLCB1aSwgY29udGV4dCk7XG4gICAgfVxuICAgIHJldHVybiB2YWw7XG59XG5mdW5jdGlvbiBjb21wdXRlU2VnU3RhcnRSZXNpemFibGUoc2VnLCBjb250ZXh0KSB7XG4gICAgcmV0dXJuIHNlZy5pc1N0YXJ0ICYmIHNlZy5ldmVudFJhbmdlLnVpLmR1cmF0aW9uRWRpdGFibGUgJiYgY29udGV4dC5vcHRpb25zLmV2ZW50UmVzaXphYmxlRnJvbVN0YXJ0O1xufVxuZnVuY3Rpb24gY29tcHV0ZVNlZ0VuZFJlc2l6YWJsZShzZWcsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gc2VnLmlzRW5kICYmIHNlZy5ldmVudFJhbmdlLnVpLmR1cmF0aW9uRWRpdGFibGU7XG59XG5mdW5jdGlvbiBidWlsZFNlZ1RpbWVUZXh0KHNlZywgdGltZUZvcm1hdCwgY29udGV4dCwgZGVmYXVsdERpc3BsYXlFdmVudFRpbWUsIC8vIGRlZmF1bHRzIHRvIHRydWVcbmRlZmF1bHREaXNwbGF5RXZlbnRFbmQsIC8vIGRlZmF1bHRzIHRvIHRydWVcbnN0YXJ0T3ZlcnJpZGUsIGVuZE92ZXJyaWRlKSB7XG4gICAgbGV0IHsgZGF0ZUVudiwgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICBsZXQgeyBkaXNwbGF5RXZlbnRUaW1lLCBkaXNwbGF5RXZlbnRFbmQgfSA9IG9wdGlvbnM7XG4gICAgbGV0IGV2ZW50RGVmID0gc2VnLmV2ZW50UmFuZ2UuZGVmO1xuICAgIGxldCBldmVudEluc3RhbmNlID0gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgaWYgKGRpc3BsYXlFdmVudFRpbWUgPT0gbnVsbCkge1xuICAgICAgICBkaXNwbGF5RXZlbnRUaW1lID0gZGVmYXVsdERpc3BsYXlFdmVudFRpbWUgIT09IGZhbHNlO1xuICAgIH1cbiAgICBpZiAoZGlzcGxheUV2ZW50RW5kID09IG51bGwpIHtcbiAgICAgICAgZGlzcGxheUV2ZW50RW5kID0gZGVmYXVsdERpc3BsYXlFdmVudEVuZCAhPT0gZmFsc2U7XG4gICAgfVxuICAgIGxldCB3aG9sZUV2ZW50U3RhcnQgPSBldmVudEluc3RhbmNlLnJhbmdlLnN0YXJ0O1xuICAgIGxldCB3aG9sZUV2ZW50RW5kID0gZXZlbnRJbnN0YW5jZS5yYW5nZS5lbmQ7XG4gICAgbGV0IHNlZ1N0YXJ0ID0gc3RhcnRPdmVycmlkZSB8fCBzZWcuc3RhcnQgfHwgc2VnLmV2ZW50UmFuZ2UucmFuZ2Uuc3RhcnQ7XG4gICAgbGV0IHNlZ0VuZCA9IGVuZE92ZXJyaWRlIHx8IHNlZy5lbmQgfHwgc2VnLmV2ZW50UmFuZ2UucmFuZ2UuZW5kO1xuICAgIGxldCBpc1N0YXJ0RGF5ID0gc3RhcnRPZkRheSh3aG9sZUV2ZW50U3RhcnQpLnZhbHVlT2YoKSA9PT0gc3RhcnRPZkRheShzZWdTdGFydCkudmFsdWVPZigpO1xuICAgIGxldCBpc0VuZERheSA9IHN0YXJ0T2ZEYXkoYWRkTXMod2hvbGVFdmVudEVuZCwgLTEpKS52YWx1ZU9mKCkgPT09IHN0YXJ0T2ZEYXkoYWRkTXMoc2VnRW5kLCAtMSkpLnZhbHVlT2YoKTtcbiAgICBpZiAoZGlzcGxheUV2ZW50VGltZSAmJiAhZXZlbnREZWYuYWxsRGF5ICYmIChpc1N0YXJ0RGF5IHx8IGlzRW5kRGF5KSkge1xuICAgICAgICBzZWdTdGFydCA9IGlzU3RhcnREYXkgPyB3aG9sZUV2ZW50U3RhcnQgOiBzZWdTdGFydDtcbiAgICAgICAgc2VnRW5kID0gaXNFbmREYXkgPyB3aG9sZUV2ZW50RW5kIDogc2VnRW5kO1xuICAgICAgICBpZiAoZGlzcGxheUV2ZW50RW5kICYmIGV2ZW50RGVmLmhhc0VuZCkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2Uoc2VnU3RhcnQsIHNlZ0VuZCwgdGltZUZvcm1hdCwge1xuICAgICAgICAgICAgICAgIGZvcmNlZFN0YXJ0VHpvOiBzdGFydE92ZXJyaWRlID8gbnVsbCA6IGV2ZW50SW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICAgICAgZm9yY2VkRW5kVHpvOiBlbmRPdmVycmlkZSA/IG51bGwgOiBldmVudEluc3RhbmNlLmZvcmNlZEVuZFR6byxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdChzZWdTdGFydCwgdGltZUZvcm1hdCwge1xuICAgICAgICAgICAgZm9yY2VkVHpvOiBzdGFydE92ZXJyaWRlID8gbnVsbCA6IGV2ZW50SW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sIC8vIG5vb29vbywgc2FtZVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xufVxuZnVuY3Rpb24gZ2V0U2VnTWV0YShzZWcsIHRvZGF5UmFuZ2UsIG5vd0RhdGUpIHtcbiAgICBsZXQgc2VnUmFuZ2UgPSBzZWcuZXZlbnRSYW5nZS5yYW5nZTtcbiAgICByZXR1cm4ge1xuICAgICAgICBpc1Bhc3Q6IHNlZ1JhbmdlLmVuZCA8PSAobm93RGF0ZSB8fCB0b2RheVJhbmdlLnN0YXJ0KSxcbiAgICAgICAgaXNGdXR1cmU6IHNlZ1JhbmdlLnN0YXJ0ID49IChub3dEYXRlIHx8IHRvZGF5UmFuZ2UuZW5kKSxcbiAgICAgICAgaXNUb2RheTogdG9kYXlSYW5nZSAmJiByYW5nZUNvbnRhaW5zTWFya2VyKHRvZGF5UmFuZ2UsIHNlZ1JhbmdlLnN0YXJ0KSxcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0RXZlbnRDbGFzc05hbWVzKHByb3BzKSB7XG4gICAgbGV0IGNsYXNzTmFtZXMgPSBbJ2ZjLWV2ZW50J107XG4gICAgaWYgKHByb3BzLmlzTWlycm9yKSB7XG4gICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtZXZlbnQtbWlycm9yJyk7XG4gICAgfVxuICAgIGlmIChwcm9wcy5pc0RyYWdnYWJsZSkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LWRyYWdnYWJsZScpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuaXNTdGFydFJlc2l6YWJsZSB8fCBwcm9wcy5pc0VuZFJlc2l6YWJsZSkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LXJlc2l6YWJsZScpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuaXNEcmFnZ2luZykge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LWRyYWdnaW5nJyk7XG4gICAgfVxuICAgIGlmIChwcm9wcy5pc1Jlc2l6aW5nKSB7XG4gICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtZXZlbnQtcmVzaXppbmcnKTtcbiAgICB9XG4gICAgaWYgKHByb3BzLmlzU2VsZWN0ZWQpIHtcbiAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy1ldmVudC1zZWxlY3RlZCcpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuaXNTdGFydCkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LXN0YXJ0Jyk7XG4gICAgfVxuICAgIGlmIChwcm9wcy5pc0VuZCkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LWVuZCcpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuaXNQYXN0KSB7XG4gICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtZXZlbnQtcGFzdCcpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuaXNUb2RheSkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LXRvZGF5Jyk7XG4gICAgfVxuICAgIGlmIChwcm9wcy5pc0Z1dHVyZSkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWV2ZW50LWZ1dHVyZScpO1xuICAgIH1cbiAgICByZXR1cm4gY2xhc3NOYW1lcztcbn1cbmZ1bmN0aW9uIGJ1aWxkRXZlbnRSYW5nZUtleShldmVudFJhbmdlKSB7XG4gICAgcmV0dXJuIGV2ZW50UmFuZ2UuaW5zdGFuY2VcbiAgICAgICAgPyBldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWRcbiAgICAgICAgOiBgJHtldmVudFJhbmdlLmRlZi5kZWZJZH06JHtldmVudFJhbmdlLnJhbmdlLnN0YXJ0LnRvSVNPU3RyaW5nKCl9YDtcbiAgICAvLyBpbnZlcnNlLWJhY2tncm91bmQgZXZlbnRzIGRvbid0IGhhdmUgc3BlY2lmaWMgaW5zdGFuY2VzLiBUT0RPOiBiZXR0ZXIgc29sdXRpb25cbn1cbmZ1bmN0aW9uIGdldFNlZ0FuY2hvckF0dHJzKHNlZywgY29udGV4dCkge1xuICAgIGxldCB7IGRlZiwgaW5zdGFuY2UgfSA9IHNlZy5ldmVudFJhbmdlO1xuICAgIGxldCB7IHVybCB9ID0gZGVmO1xuICAgIGlmICh1cmwpIHtcbiAgICAgICAgcmV0dXJuIHsgaHJlZjogdXJsIH07XG4gICAgfVxuICAgIGxldCB7IGVtaXR0ZXIsIG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgbGV0IHsgZXZlbnRJbnRlcmFjdGl2ZSB9ID0gb3B0aW9ucztcbiAgICBpZiAoZXZlbnRJbnRlcmFjdGl2ZSA9PSBudWxsKSB7XG4gICAgICAgIGV2ZW50SW50ZXJhY3RpdmUgPSBkZWYuaW50ZXJhY3RpdmU7XG4gICAgICAgIGlmIChldmVudEludGVyYWN0aXZlID09IG51bGwpIHtcbiAgICAgICAgICAgIGV2ZW50SW50ZXJhY3RpdmUgPSBCb29sZWFuKGVtaXR0ZXIuaGFzSGFuZGxlcnMoJ2V2ZW50Q2xpY2snKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gbW9jayB3aGF0IGhhcHBlbnMgaW4gRXZlbnRDbGlja2luZ1xuICAgIGlmIChldmVudEludGVyYWN0aXZlKSB7XG4gICAgICAgIC8vIG9ubHkgYXR0YWNoIGtleWJvYXJkLXJlbGF0ZWQgaGFuZGxlcnMgYmVjYXVzZSBjbGljayBoYW5kbGVyIGlzIGFscmVhZHkgZG9uZSBpbiBFdmVudENsaWNraW5nXG4gICAgICAgIHJldHVybiBjcmVhdGVBcmlhS2V5Ym9hcmRBdHRycygoZXYpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIudHJpZ2dlcignZXZlbnRDbGljaycsIHtcbiAgICAgICAgICAgICAgICBlbDogZXYudGFyZ2V0LFxuICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRJbXBsKGNvbnRleHQsIGRlZiwgaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2LFxuICAgICAgICAgICAgICAgIHZpZXc6IGNvbnRleHQudmlld0FwaSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHt9O1xufVxuXG5jb25zdCBTVEFOREFSRF9QUk9QUyA9IHtcbiAgICBzdGFydDogaWRlbnRpdHksXG4gICAgZW5kOiBpZGVudGl0eSxcbiAgICBhbGxEYXk6IEJvb2xlYW4sXG59O1xuZnVuY3Rpb24gcGFyc2VEYXRlU3BhbihyYXcsIGRhdGVFbnYsIGRlZmF1bHREdXJhdGlvbikge1xuICAgIGxldCBzcGFuID0gcGFyc2VPcGVuRGF0ZVNwYW4ocmF3LCBkYXRlRW52KTtcbiAgICBsZXQgeyByYW5nZSB9ID0gc3BhbjtcbiAgICBpZiAoIXJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoIXJhbmdlLmVuZCkge1xuICAgICAgICBpZiAoZGVmYXVsdER1cmF0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJhbmdlLmVuZCA9IGRhdGVFbnYuYWRkKHJhbmdlLnN0YXJ0LCBkZWZhdWx0RHVyYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gc3Bhbjtcbn1cbi8qXG5UT0RPOiBzb21laG93IGNvbWJpbmUgd2l0aCBwYXJzZVJhbmdlP1xuV2lsbCByZXR1cm4gbnVsbCBpZiB0aGUgc3RhcnQvZW5kIHByb3BzIHdlcmUgcHJlc2VudCBidXQgcGFyc2VkIGludmFsaWRseS5cbiovXG5mdW5jdGlvbiBwYXJzZU9wZW5EYXRlU3BhbihyYXcsIGRhdGVFbnYpIHtcbiAgICBsZXQgeyByZWZpbmVkOiBzdGFuZGFyZFByb3BzLCBleHRyYSB9ID0gcmVmaW5lUHJvcHMocmF3LCBTVEFOREFSRF9QUk9QUyk7XG4gICAgbGV0IHN0YXJ0TWV0YSA9IHN0YW5kYXJkUHJvcHMuc3RhcnQgPyBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoc3RhbmRhcmRQcm9wcy5zdGFydCkgOiBudWxsO1xuICAgIGxldCBlbmRNZXRhID0gc3RhbmRhcmRQcm9wcy5lbmQgPyBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoc3RhbmRhcmRQcm9wcy5lbmQpIDogbnVsbDtcbiAgICBsZXQgeyBhbGxEYXkgfSA9IHN0YW5kYXJkUHJvcHM7XG4gICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgIGFsbERheSA9IChzdGFydE1ldGEgJiYgc3RhcnRNZXRhLmlzVGltZVVuc3BlY2lmaWVkKSAmJlxuICAgICAgICAgICAgKCFlbmRNZXRhIHx8IGVuZE1ldGEuaXNUaW1lVW5zcGVjaWZpZWQpO1xuICAgIH1cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7IHJhbmdlOiB7XG4gICAgICAgICAgICBzdGFydDogc3RhcnRNZXRhID8gc3RhcnRNZXRhLm1hcmtlciA6IG51bGwsXG4gICAgICAgICAgICBlbmQ6IGVuZE1ldGEgPyBlbmRNZXRhLm1hcmtlciA6IG51bGwsXG4gICAgICAgIH0sIGFsbERheSB9LCBleHRyYSk7XG59XG5mdW5jdGlvbiBpc0RhdGVTcGFuc0VxdWFsKHNwYW4wLCBzcGFuMSkge1xuICAgIHJldHVybiByYW5nZXNFcXVhbChzcGFuMC5yYW5nZSwgc3BhbjEucmFuZ2UpICYmXG4gICAgICAgIHNwYW4wLmFsbERheSA9PT0gc3BhbjEuYWxsRGF5ICYmXG4gICAgICAgIGlzU3BhblByb3BzRXF1YWwoc3BhbjAsIHNwYW4xKTtcbn1cbi8vIHRoZSBOT04tREFURS1SRUxBVEVEIHByb3BzXG5mdW5jdGlvbiBpc1NwYW5Qcm9wc0VxdWFsKHNwYW4wLCBzcGFuMSkge1xuICAgIGZvciAobGV0IHByb3BOYW1lIGluIHNwYW4xKSB7XG4gICAgICAgIGlmIChwcm9wTmFtZSAhPT0gJ3JhbmdlJyAmJiBwcm9wTmFtZSAhPT0gJ2FsbERheScpIHtcbiAgICAgICAgICAgIGlmIChzcGFuMFtwcm9wTmFtZV0gIT09IHNwYW4xW3Byb3BOYW1lXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBhcmUgdGhlcmUgYW55IHByb3BzIHRoYXQgc3BhbjAgaGFzIHRoYXQgc3BhbjEgRE9FU04nVCBoYXZlP1xuICAgIC8vIGJvdGggaGF2ZSByYW5nZS9hbGxEYXksIHNvIG5vIG5lZWQgdG8gc3BlY2lhbC1jYXNlLlxuICAgIGZvciAobGV0IHByb3BOYW1lIGluIHNwYW4wKSB7XG4gICAgICAgIGlmICghKHByb3BOYW1lIGluIHNwYW4xKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gYnVpbGREYXRlU3BhbkFwaShzcGFuLCBkYXRlRW52KSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgYnVpbGRSYW5nZUFwaShzcGFuLnJhbmdlLCBkYXRlRW52LCBzcGFuLmFsbERheSkpLCB7IGFsbERheTogc3Bhbi5hbGxEYXkgfSk7XG59XG5mdW5jdGlvbiBidWlsZFJhbmdlQXBpV2l0aFRpbWVab25lKHJhbmdlLCBkYXRlRW52LCBvbWl0VGltZSkge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJ1aWxkUmFuZ2VBcGkocmFuZ2UsIGRhdGVFbnYsIG9taXRUaW1lKSksIHsgdGltZVpvbmU6IGRhdGVFbnYudGltZVpvbmUgfSk7XG59XG5mdW5jdGlvbiBidWlsZFJhbmdlQXBpKHJhbmdlLCBkYXRlRW52LCBvbWl0VGltZSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiBkYXRlRW52LnRvRGF0ZShyYW5nZS5zdGFydCksXG4gICAgICAgIGVuZDogZGF0ZUVudi50b0RhdGUocmFuZ2UuZW5kKSxcbiAgICAgICAgc3RhcnRTdHI6IGRhdGVFbnYuZm9ybWF0SXNvKHJhbmdlLnN0YXJ0LCB7IG9taXRUaW1lIH0pLFxuICAgICAgICBlbmRTdHI6IGRhdGVFbnYuZm9ybWF0SXNvKHJhbmdlLmVuZCwgeyBvbWl0VGltZSB9KSxcbiAgICB9O1xufVxuZnVuY3Rpb24gZmFicmljYXRlRXZlbnRSYW5nZShkYXRlU3BhbiwgZXZlbnRVaUJhc2VzLCBjb250ZXh0KSB7XG4gICAgbGV0IHJlcyA9IHJlZmluZUV2ZW50RGVmKHsgZWRpdGFibGU6IGZhbHNlIH0sIGNvbnRleHQpO1xuICAgIGxldCBkZWYgPSBwYXJzZUV2ZW50RGVmKHJlcy5yZWZpbmVkLCByZXMuZXh0cmEsICcnLCAvLyBzb3VyY2VJZFxuICAgIGRhdGVTcGFuLmFsbERheSwgdHJ1ZSwgLy8gaGFzRW5kXG4gICAgY29udGV4dCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGVmLFxuICAgICAgICB1aTogY29tcGlsZUV2ZW50VWkoZGVmLCBldmVudFVpQmFzZXMpLFxuICAgICAgICBpbnN0YW5jZTogY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIGRhdGVTcGFuLnJhbmdlKSxcbiAgICAgICAgcmFuZ2U6IGRhdGVTcGFuLnJhbmdlLFxuICAgICAgICBpc1N0YXJ0OiB0cnVlLFxuICAgICAgICBpc0VuZDogdHJ1ZSxcbiAgICB9O1xufVxuXG4vKlxuZ2l2ZW4gYSBmdW5jdGlvbiB0aGF0IHJlc29sdmVzIGEgcmVzdWx0IGFzeW5jaHJvbm91c2x5LlxudGhlIGZ1bmN0aW9uIGNhbiBlaXRoZXIgY2FsbCBwYXNzZWQtaW4gc3VjY2VzcyBhbmQgZmFpbHVyZSBjYWxsYmFja3MsXG5vciBpdCBjYW4gcmV0dXJuIGEgcHJvbWlzZS5cbmlmIHlvdSBuZWVkIHRvIHBhc3MgYWRkaXRpb25hbCBwYXJhbXMgdG8gZnVuYywgYmluZCB0aGVtIGZpcnN0LlxuKi9cbmZ1bmN0aW9uIHVucHJvbWlzaWZ5KGZ1bmMsIG5vcm1hbGl6ZWRTdWNjZXNzQ2FsbGJhY2ssIG5vcm1hbGl6ZWRGYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAvLyBndWFyZCBhZ2FpbnN0IHN1Y2Nlc3MvZmFpbHVyZSBjYWxsYmFja3MgYmVpbmcgY2FsbGVkIG1vcmUgdGhhbiBvbmNlXG4gICAgLy8gYW5kIGd1YXJkIGFnYWluc3QgYSBwcm9taXNlIEFORCBjYWxsYmFjayBiZWluZyB1c2VkIHRvZ2V0aGVyLlxuICAgIGxldCBpc1Jlc29sdmVkID0gZmFsc2U7XG4gICAgbGV0IHdyYXBwZWRTdWNjZXNzID0gZnVuY3Rpb24gKHJlcykge1xuICAgICAgICBpZiAoIWlzUmVzb2x2ZWQpIHtcbiAgICAgICAgICAgIGlzUmVzb2x2ZWQgPSB0cnVlO1xuICAgICAgICAgICAgbm9ybWFsaXplZFN1Y2Nlc3NDYWxsYmFjayhyZXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBsZXQgd3JhcHBlZEZhaWx1cmUgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgaWYgKCFpc1Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpc1Jlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRGYWlsdXJlQ2FsbGJhY2soZXJyb3IpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBsZXQgcmVzID0gZnVuYyh3cmFwcGVkU3VjY2Vzcywgd3JhcHBlZEZhaWx1cmUpO1xuICAgIGlmIChyZXMgJiYgdHlwZW9mIHJlcy50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJlcy50aGVuKHdyYXBwZWRTdWNjZXNzLCB3cmFwcGVkRmFpbHVyZSk7XG4gICAgfVxufVxuXG5jbGFzcyBKc29uUmVxdWVzdEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHJlc3BvbnNlKSB7XG4gICAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgICAgICB0aGlzLnJlc3BvbnNlID0gcmVzcG9uc2U7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVxdWVzdEpzb24obWV0aG9kLCB1cmwsIHBhcmFtcykge1xuICAgIG1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpO1xuICAgIGNvbnN0IGZldGNoT3B0aW9ucyA9IHtcbiAgICAgICAgbWV0aG9kLFxuICAgIH07XG4gICAgaWYgKG1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICAgICAgdXJsICs9ICh1cmwuaW5kZXhPZignPycpID09PSAtMSA/ICc/JyA6ICcmJykgK1xuICAgICAgICAgICAgbmV3IFVSTFNlYXJjaFBhcmFtcyhwYXJhbXMpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZmV0Y2hPcHRpb25zLmJvZHkgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHBhcmFtcyk7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzID0ge1xuICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gZmV0Y2godXJsLCBmZXRjaE9wdGlvbnMpLnRoZW4oKGZldGNoUmVzKSA9PiB7XG4gICAgICAgIGlmIChmZXRjaFJlcy5vaykge1xuICAgICAgICAgICAgcmV0dXJuIGZldGNoUmVzLmpzb24oKS50aGVuKChwYXJzZWRSZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBbcGFyc2VkUmVzcG9uc2UsIGZldGNoUmVzXTtcbiAgICAgICAgICAgIH0sICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSnNvblJlcXVlc3RFcnJvcignRmFpbHVyZSBwYXJzaW5nIEpTT04nLCBmZXRjaFJlcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBKc29uUmVxdWVzdEVycm9yKCdSZXF1ZXN0IGZhaWxlZCcsIGZldGNoUmVzKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5sZXQgY2FuVkdyb3dXaXRoaW5DZWxsO1xuZnVuY3Rpb24gZ2V0Q2FuVkdyb3dXaXRoaW5DZWxsKCkge1xuICAgIGlmIChjYW5WR3Jvd1dpdGhpbkNlbGwgPT0gbnVsbCkge1xuICAgICAgICBjYW5WR3Jvd1dpdGhpbkNlbGwgPSBjb21wdXRlQ2FuVkdyb3dXaXRoaW5DZWxsKCk7XG4gICAgfVxuICAgIHJldHVybiBjYW5WR3Jvd1dpdGhpbkNlbGw7XG59XG5mdW5jdGlvbiBjb21wdXRlQ2FuVkdyb3dXaXRoaW5DZWxsKCkge1xuICAgIC8vIGZvciBTU1IsIGJlY2F1c2UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsIGltbWVkaWF0ZWx5IGF0IHRvcC1sZXZlbFxuICAgIC8vIFRPRE86IGp1c3QgbWFrZSB0aGlzIGxvZ2ljIGV4ZWN1dGUgdG9wLWxldmVsLCBpbW1lZGlhdGVseSwgaW5zdGVhZCBvZiBkb2luZyBsYXppbHlcbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgbGV0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZWwuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIGVsLnN0eWxlLnRvcCA9ICcwcHgnO1xuICAgIGVsLnN0eWxlLmxlZnQgPSAnMHB4JztcbiAgICBlbC5pbm5lckhUTUwgPSAnPHRhYmxlPjx0cj48dGQ+PGRpdj48L2Rpdj48L3RkPjwvdHI+PC90YWJsZT4nO1xuICAgIGVsLnF1ZXJ5U2VsZWN0b3IoJ3RhYmxlJykuc3R5bGUuaGVpZ2h0ID0gJzEwMHB4JztcbiAgICBlbC5xdWVyeVNlbGVjdG9yKCdkaXYnKS5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChlbCk7XG4gICAgbGV0IGRpdiA9IGVsLnF1ZXJ5U2VsZWN0b3IoJ2RpdicpO1xuICAgIGxldCBwb3NzaWJsZSA9IGRpdi5vZmZzZXRIZWlnaHQgPiAwO1xuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZWwpO1xuICAgIHJldHVybiBwb3NzaWJsZTtcbn1cblxuY2xhc3MgQ2FsZW5kYXJSb290IGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBmb3JQcmludDogZmFsc2UsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlQmVmb3JlUHJpbnQgPSAoKSA9PiB7XG4gICAgICAgICAgICBmbHVzaFN5bmMoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBmb3JQcmludDogdHJ1ZSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZUFmdGVyUHJpbnQgPSAoKSA9PiB7XG4gICAgICAgICAgICBmbHVzaFN5bmMoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBmb3JQcmludDogZmFsc2UgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgb3B0aW9ucyB9ID0gcHJvcHM7XG4gICAgICAgIGxldCB7IGZvclByaW50IH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICBsZXQgaXNIZWlnaHRBdXRvID0gZm9yUHJpbnQgfHwgb3B0aW9ucy5oZWlnaHQgPT09ICdhdXRvJyB8fCBvcHRpb25zLmNvbnRlbnRIZWlnaHQgPT09ICdhdXRvJztcbiAgICAgICAgbGV0IGhlaWdodCA9ICghaXNIZWlnaHRBdXRvICYmIG9wdGlvbnMuaGVpZ2h0ICE9IG51bGwpID8gb3B0aW9ucy5oZWlnaHQgOiAnJztcbiAgICAgICAgbGV0IGNsYXNzTmFtZXMgPSBbXG4gICAgICAgICAgICAnZmMnLFxuICAgICAgICAgICAgZm9yUHJpbnQgPyAnZmMtbWVkaWEtcHJpbnQnIDogJ2ZjLW1lZGlhLXNjcmVlbicsXG4gICAgICAgICAgICBgZmMtZGlyZWN0aW9uLSR7b3B0aW9ucy5kaXJlY3Rpb259YCxcbiAgICAgICAgICAgIHByb3BzLnRoZW1lLmdldENsYXNzKCdyb290JyksXG4gICAgICAgIF07XG4gICAgICAgIGlmICghZ2V0Q2FuVkdyb3dXaXRoaW5DZWxsKCkpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtbGlxdWlkLWhhY2snKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvcHMuY2hpbGRyZW4oY2xhc3NOYW1lcywgaGVpZ2h0LCBpc0hlaWdodEF1dG8sIGZvclByaW50KTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIGxldCB7IGVtaXR0ZXIgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgIGVtaXR0ZXIub24oJ19iZWZvcmVwcmludCcsIHRoaXMuaGFuZGxlQmVmb3JlUHJpbnQpO1xuICAgICAgICBlbWl0dGVyLm9uKCdfYWZ0ZXJwcmludCcsIHRoaXMuaGFuZGxlQWZ0ZXJQcmludCk7XG4gICAgfVxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICBsZXQgeyBlbWl0dGVyIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBlbWl0dGVyLm9mZignX2JlZm9yZXByaW50JywgdGhpcy5oYW5kbGVCZWZvcmVQcmludCk7XG4gICAgICAgIGVtaXR0ZXIub2ZmKCdfYWZ0ZXJwcmludCcsIHRoaXMuaGFuZGxlQWZ0ZXJQcmludCk7XG4gICAgfVxufVxuXG5jbGFzcyBJbnRlcmFjdGlvbiB7XG4gICAgY29uc3RydWN0b3Ioc2V0dGluZ3MpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnQgPSBzZXR0aW5ncy5jb21wb25lbnQ7XG4gICAgICAgIHRoaXMuaXNIaXRDb21ib0FsbG93ZWQgPSBzZXR0aW5ncy5pc0hpdENvbWJvQWxsb3dlZCB8fCBudWxsO1xuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgIH1cbn1cbmZ1bmN0aW9uIHBhcnNlSW50ZXJhY3Rpb25TZXR0aW5ncyhjb21wb25lbnQsIGlucHV0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29tcG9uZW50LFxuICAgICAgICBlbDogaW5wdXQuZWwsXG4gICAgICAgIHVzZUV2ZW50Q2VudGVyOiBpbnB1dC51c2VFdmVudENlbnRlciAhPSBudWxsID8gaW5wdXQudXNlRXZlbnRDZW50ZXIgOiB0cnVlLFxuICAgICAgICBpc0hpdENvbWJvQWxsb3dlZDogaW5wdXQuaXNIaXRDb21ib0FsbG93ZWQgfHwgbnVsbCxcbiAgICB9O1xufVxuZnVuY3Rpb24gaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBbc2V0dGluZ3MuY29tcG9uZW50LnVpZF06IHNldHRpbmdzLFxuICAgIH07XG59XG4vLyBnbG9iYWwgc3RhdGVcbmNvbnN0IGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZSA9IHt9O1xuXG5jbGFzcyBOb3dUaW1lciBleHRlbmRzIENvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgc3VwZXIocHJvcHMsIGNvbnRleHQpO1xuICAgICAgICB0aGlzLmhhbmRsZVJlZnJlc2ggPSAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgdGltaW5nID0gdGhpcy5jb21wdXRlVGltaW5nKCk7XG4gICAgICAgICAgICBpZiAodGltaW5nLnN0YXRlLm5vd0RhdGUudmFsdWVPZigpICE9PSB0aGlzLnN0YXRlLm5vd0RhdGUudmFsdWVPZigpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh0aW1pbmcuc3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgICAgICAgICAgIHRoaXMuc2V0VGltZW91dCh0aW1pbmcud2FpdE1zKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVWaXNpYmlsaXR5Q2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFkb2N1bWVudC5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVJlZnJlc2goKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHRoaXMuY29tcHV0ZVRpbWluZygpLnN0YXRlO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBzdGF0ZSB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIHByb3BzLmNoaWxkcmVuKHN0YXRlLm5vd0RhdGUsIHN0YXRlLnRvZGF5UmFuZ2UpO1xuICAgIH1cbiAgICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgICAgdGhpcy5zZXRUaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuY29udGV4dC5ub3dNYW5hZ2VyLmFkZFJlc2V0TGlzdGVuZXIodGhpcy5oYW5kbGVSZWZyZXNoKTtcbiAgICAgICAgLy8gZmlyZWQgdGFiIGJlY29tZXMgdmlzaWJsZSBhZnRlciBiZWluZyBoaWRkZW5cbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndmlzaWJpbGl0eWNoYW5nZScsIHRoaXMuaGFuZGxlVmlzaWJpbGl0eUNoYW5nZSk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHMpIHtcbiAgICAgICAgaWYgKHByZXZQcm9wcy51bml0ICE9PSB0aGlzLnByb3BzLnVuaXQpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJUaW1lb3V0KCk7XG4gICAgICAgICAgICB0aGlzLnNldFRpbWVvdXQoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgICAgICAgdGhpcy5jb250ZXh0Lm5vd01hbmFnZXIucmVtb3ZlUmVzZXRMaXN0ZW5lcih0aGlzLmhhbmRsZVJlZnJlc2gpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgdGhpcy5oYW5kbGVWaXNpYmlsaXR5Q2hhbmdlKTtcbiAgICB9XG4gICAgY29tcHV0ZVRpbWluZygpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB1bnJvdW5kZWROb3cgPSBjb250ZXh0Lm5vd01hbmFnZXIuZ2V0RGF0ZU1hcmtlcigpO1xuICAgICAgICBsZXQgeyBub3dJbmRpY2F0b3JTbmFwIH0gPSBjb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIGlmIChub3dJbmRpY2F0b3JTbmFwID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIG5vd0luZGljYXRvclNuYXAgPVxuICAgICAgICAgICAgICAgIC8vIGxhcmdlIHVuaXQ/XG4gICAgICAgICAgICAgICAgL3llYXJ8bW9udGh8d2Vla3xkYXkvLnRlc3QocHJvcHMudW5pdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgc2xvdER1cmF0aW9uIDMwIG1pbnMgZm9yIGV4YW1wbGUsIHdvdWxkIE5PVCBhcHBlYXIgdG8gc25hcCAobGVnYWN5IGJlaGF2aW9yKVxuICAgICAgICAgICAgICAgICAgICAocHJvcHMudW5pdFZhbHVlIHx8IDEpID09PSAxO1xuICAgICAgICB9XG4gICAgICAgIGxldCBub3dEYXRlO1xuICAgICAgICBsZXQgd2FpdE1zO1xuICAgICAgICBpZiAobm93SW5kaWNhdG9yU25hcCkge1xuICAgICAgICAgICAgbm93RGF0ZSA9IGNvbnRleHQuZGF0ZUVudi5zdGFydE9mKHVucm91bmRlZE5vdywgcHJvcHMudW5pdCk7IC8vIGFrYSBjdXJyZW50VW5pdFN0YXJ0XG4gICAgICAgICAgICBsZXQgbmV4dFVuaXRTdGFydCA9IGNvbnRleHQuZGF0ZUVudi5hZGQobm93RGF0ZSwgY3JlYXRlRHVyYXRpb24oMSwgcHJvcHMudW5pdCkpO1xuICAgICAgICAgICAgd2FpdE1zID0gbmV4dFVuaXRTdGFydC52YWx1ZU9mKCkgLSB1bnJvdW5kZWROb3cudmFsdWVPZigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbm93RGF0ZSA9IHVucm91bmRlZE5vdztcbiAgICAgICAgICAgIHdhaXRNcyA9IDEwMDAgKiA2MDsgLy8gMSBtaW51dGVcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGVyZSBpcyBhIG1heCBzZXRUaW1lb3V0IG1zIHZhbHVlIChodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzQ2ODY1MC85NjM0MilcbiAgICAgICAgLy8gZW5zdXJlIG5vIGxvbmdlciB0aGFuIGEgZGF5XG4gICAgICAgIHdhaXRNcyA9IE1hdGgubWluKDEwMDAgKiA2MCAqIDYwICogMjQsIHdhaXRNcyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGF0ZTogeyBub3dEYXRlLCB0b2RheVJhbmdlOiBidWlsZERheVJhbmdlKG5vd0RhdGUpIH0sXG4gICAgICAgICAgICB3YWl0TXMsXG4gICAgICAgIH07XG4gICAgfVxuICAgIHNldFRpbWVvdXQod2FpdE1zID0gdGhpcy5jb21wdXRlVGltaW5nKCkud2FpdE1zKSB7XG4gICAgICAgIC8vIE5PVEU6IHRpbWVvdXQgY291bGQgdGFrZSBsb25nZXIgdGhhbiBleHBlY3RlZCBpZiB0YWIgc2xlZXBzLFxuICAgICAgICAvLyB3aGljaCBpcyB3aHkgd2UgbGlzdGVuIHRvICd2aXNpYmlsaXR5Y2hhbmdlJ1xuICAgICAgICB0aGlzLnRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgLy8gTk9URTogdGltZW91dCBjb3VsZCBhbHNvIHJldHVybiAqZWFybGllciogdGhhbiBleHBlY3RlZCwgYW5kIHdlIG5lZWQgdG8gd2FpdCAyIG1zIG1vcmVcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgd2h5IHVzZSB1c2Ugc2FtZSB3YWl0TXMgZnJvbSBjb21wdXRlVGltaW5nLCBzbyB3ZSBkb24ndCBza2lwIGFuIGludGVydmFsIHdoaWxlXG4gICAgICAgICAgICAvLyAuc2V0U3RhdGUoKSBpcyBleGVjdXRpbmdcbiAgICAgICAgICAgIGNvbnN0IHRpbWluZyA9IHRoaXMuY29tcHV0ZVRpbWluZygpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh0aW1pbmcuc3RhdGUsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFRpbWVvdXQodGltaW5nLndhaXRNcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgd2FpdE1zKTtcbiAgICB9XG4gICAgY2xlYXJUaW1lb3V0KCkge1xuICAgICAgICBpZiAodGhpcy50aW1lb3V0SWQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5Ob3dUaW1lci5jb250ZXh0VHlwZSA9IFZpZXdDb250ZXh0VHlwZTtcbmZ1bmN0aW9uIGJ1aWxkRGF5UmFuZ2UoZGF0ZSkge1xuICAgIGxldCBzdGFydCA9IHN0YXJ0T2ZEYXkoZGF0ZSk7XG4gICAgbGV0IGVuZCA9IGFkZERheXMoc3RhcnQsIDEpO1xuICAgIHJldHVybiB7IHN0YXJ0LCBlbmQgfTtcbn1cblxuY2xhc3MgQ2FsZW5kYXJJbXBsIHtcbiAgICBnZXRDdXJyZW50RGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudERhdGFNYW5hZ2VyLmdldEN1cnJlbnREYXRhKCk7XG4gICAgfVxuICAgIGRpc3BhdGNoKGFjdGlvbikge1xuICAgICAgICB0aGlzLmN1cnJlbnREYXRhTWFuYWdlci5kaXNwYXRjaChhY3Rpb24pO1xuICAgIH1cbiAgICBnZXQgdmlldygpIHsgcmV0dXJuIHRoaXMuZ2V0Q3VycmVudERhdGEoKS52aWV3QXBpOyB9XG4gICAgYmF0Y2hSZW5kZXJpbmcoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG4gICAgdXBkYXRlU2l6ZSgpIHtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCdfcmVzaXplJywgdHJ1ZSk7XG4gICAgfVxuICAgIC8vIE9wdGlvbnNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHNldE9wdGlvbihuYW1lLCB2YWwpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnU0VUX09QVElPTicsXG4gICAgICAgICAgICBvcHRpb25OYW1lOiBuYW1lLFxuICAgICAgICAgICAgcmF3T3B0aW9uVmFsdWU6IHZhbCxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGdldE9wdGlvbihuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnREYXRhTWFuYWdlci5jdXJyZW50Q2FsZW5kYXJPcHRpb25zSW5wdXRbbmFtZV07XG4gICAgfVxuICAgIGdldEF2YWlsYWJsZUxvY2FsZUNvZGVzKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5nZXRDdXJyZW50RGF0YSgpLmF2YWlsYWJsZVJhd0xvY2FsZXMpO1xuICAgIH1cbiAgICAvLyBUcmlnZ2VyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBvbihoYW5kbGVyTmFtZSwgaGFuZGxlcikge1xuICAgICAgICBsZXQgeyBjdXJyZW50RGF0YU1hbmFnZXIgfSA9IHRoaXM7XG4gICAgICAgIGlmIChjdXJyZW50RGF0YU1hbmFnZXIuY3VycmVudENhbGVuZGFyT3B0aW9uc1JlZmluZXJzW2hhbmRsZXJOYW1lXSkge1xuICAgICAgICAgICAgY3VycmVudERhdGFNYW5hZ2VyLmVtaXR0ZXIub24oaGFuZGxlck5hbWUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBVbmtub3duIGxpc3RlbmVyIG5hbWUgJyR7aGFuZGxlck5hbWV9J2ApO1xuICAgICAgICB9XG4gICAgfVxuICAgIG9mZihoYW5kbGVyTmFtZSwgaGFuZGxlcikge1xuICAgICAgICB0aGlzLmN1cnJlbnREYXRhTWFuYWdlci5lbWl0dGVyLm9mZihoYW5kbGVyTmFtZSwgaGFuZGxlcik7XG4gICAgfVxuICAgIC8vIG5vdCBtZWFudCBmb3IgcHVibGljIHVzZVxuICAgIHRyaWdnZXIoaGFuZGxlck5hbWUsIC4uLmFyZ3MpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50RGF0YU1hbmFnZXIuZW1pdHRlci50cmlnZ2VyKGhhbmRsZXJOYW1lLCAuLi5hcmdzKTtcbiAgICB9XG4gICAgLy8gVmlld1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY2hhbmdlVmlldyh2aWV3VHlwZSwgZGF0ZU9yUmFuZ2UpIHtcbiAgICAgICAgdGhpcy5iYXRjaFJlbmRlcmluZygoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgICAgICBpZiAoZGF0ZU9yUmFuZ2UpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZU9yUmFuZ2Uuc3RhcnQgJiYgZGF0ZU9yUmFuZ2UuZW5kKSB7IC8vIGEgcmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnQ0hBTkdFX1ZJRVdfVFlQRScsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3VHlwZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9PUFRJT04nLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uTmFtZTogJ3Zpc2libGVSYW5nZScsXG4gICAgICAgICAgICAgICAgICAgICAgICByYXdPcHRpb25WYWx1ZTogZGF0ZU9yUmFuZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHsgZGF0ZUVudiB9ID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfVklFV19UWVBFJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdUeXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZU1hcmtlcjogZGF0ZUVudi5jcmVhdGVNYXJrZXIoZGF0ZU9yUmFuZ2UpLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ0NIQU5HRV9WSUVXX1RZUEUnLFxuICAgICAgICAgICAgICAgICAgICB2aWV3VHlwZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8vIEZvcmNlcyBuYXZpZ2F0aW9uIHRvIGEgdmlldyBmb3IgdGhlIGdpdmVuIGRhdGUuXG4gICAgLy8gYHZpZXdUeXBlYCBjYW4gYmUgYSBzcGVjaWZpYyB2aWV3IG5hbWUgb3IgYSBnZW5lcmljIG9uZSBsaWtlIFwid2Vla1wiIG9yIFwiZGF5XCIuXG4gICAgLy8gbmVlZHMgdG8gY2hhbmdlXG4gICAgem9vbVRvKGRhdGVNYXJrZXIsIHZpZXdUeXBlKSB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgbGV0IHNwZWM7XG4gICAgICAgIHZpZXdUeXBlID0gdmlld1R5cGUgfHwgJ2RheSc7IC8vIGRheSBpcyBkZWZhdWx0IHpvb21cbiAgICAgICAgc3BlYyA9IHN0YXRlLnZpZXdTcGVjc1t2aWV3VHlwZV0gfHwgdGhpcy5nZXRVbml0Vmlld1NwZWModmlld1R5cGUpO1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIGlmIChzcGVjKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnQ0hBTkdFX1ZJRVdfVFlQRScsXG4gICAgICAgICAgICAgICAgdmlld1R5cGU6IHNwZWMudHlwZSxcbiAgICAgICAgICAgICAgICBkYXRlTWFya2VyLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnQ0hBTkdFX0RBVEUnLFxuICAgICAgICAgICAgICAgIGRhdGVNYXJrZXIsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBHaXZlbiBhIGR1cmF0aW9uIHNpbmd1bGFyIHVuaXQsIGxpa2UgXCJ3ZWVrXCIgb3IgXCJkYXlcIiwgZmluZHMgYSBtYXRjaGluZyB2aWV3IHNwZWMuXG4gICAgLy8gUHJlZmVyZW5jZSBpcyBnaXZlbiB0byB2aWV3cyB0aGF0IGhhdmUgY29ycmVzcG9uZGluZyBidXR0b25zLlxuICAgIGdldFVuaXRWaWV3U3BlYyh1bml0KSB7XG4gICAgICAgIGxldCB7IHZpZXdTcGVjcywgdG9vbGJhckNvbmZpZyB9ID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICBsZXQgdmlld1R5cGVzID0gW10uY29uY2F0KHRvb2xiYXJDb25maWcuaGVhZGVyID8gdG9vbGJhckNvbmZpZy5oZWFkZXIudmlld3NXaXRoQnV0dG9ucyA6IFtdLCB0b29sYmFyQ29uZmlnLmZvb3RlciA/IHRvb2xiYXJDb25maWcuZm9vdGVyLnZpZXdzV2l0aEJ1dHRvbnMgOiBbXSk7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBsZXQgc3BlYztcbiAgICAgICAgZm9yIChsZXQgdmlld1R5cGUgaW4gdmlld1NwZWNzKSB7XG4gICAgICAgICAgICB2aWV3VHlwZXMucHVzaCh2aWV3VHlwZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHZpZXdUeXBlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgc3BlYyA9IHZpZXdTcGVjc1t2aWV3VHlwZXNbaV1dO1xuICAgICAgICAgICAgaWYgKHNwZWMpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3BlYy5zaW5nbGVVbml0ID09PSB1bml0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzcGVjO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gQ3VycmVudCBEYXRlXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBwcmV2KCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUFJFVicgfSk7XG4gICAgfVxuICAgIG5leHQoKSB7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdORVhUJyB9KTtcbiAgICB9XG4gICAgcHJldlllYXIoKSB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiBzdGF0ZS5kYXRlRW52LmFkZFllYXJzKHN0YXRlLmN1cnJlbnREYXRlLCAtMSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBuZXh0WWVhcigpIHtcbiAgICAgICAgbGV0IHN0YXRlID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ0NIQU5HRV9EQVRFJyxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IHN0YXRlLmRhdGVFbnYuYWRkWWVhcnMoc3RhdGUuY3VycmVudERhdGUsIDEpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgdG9kYXkoKSB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiBzdGF0ZS5ub3dNYW5hZ2VyLmdldERhdGVNYXJrZXIoKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGdvdG9EYXRlKHpvbmVkRGF0ZUlucHV0KSB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiBzdGF0ZS5kYXRlRW52LmNyZWF0ZU1hcmtlcih6b25lZERhdGVJbnB1dCksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpbmNyZW1lbnREYXRlKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgbGV0IHN0YXRlID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICBsZXQgZGVsdGEgPSBjcmVhdGVEdXJhdGlvbihkZWx0YUlucHV0KTtcbiAgICAgICAgaWYgKGRlbHRhKSB7IC8vIGVsc2UsIHdhcm4gYWJvdXQgaW52YWxpZCBpbnB1dD9cbiAgICAgICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfREFURScsXG4gICAgICAgICAgICAgICAgZGF0ZU1hcmtlcjogc3RhdGUuZGF0ZUVudi5hZGQoc3RhdGUuY3VycmVudERhdGUsIGRlbHRhKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldERhdGUoKSB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgcmV0dXJuIHN0YXRlLmRhdGVFbnYudG9EYXRlKHN0YXRlLmN1cnJlbnREYXRlKTtcbiAgICB9XG4gICAgLy8gRGF0ZSBGb3JtYXR0aW5nIFV0aWxzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBmb3JtYXREYXRlKGQsIGZvcm1hdHRlcikge1xuICAgICAgICBsZXQgeyBkYXRlRW52IH0gPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdChkYXRlRW52LmNyZWF0ZU1hcmtlcihkKSwgY3JlYXRlRm9ybWF0dGVyKGZvcm1hdHRlcikpO1xuICAgIH1cbiAgICAvLyBgc2V0dGluZ3NgIGlzIGZvciBmb3JtYXR0ZXIgQU5EIGlzRW5kRXhjbHVzaXZlXG4gICAgZm9ybWF0UmFuZ2UoZDAsIGQxLCBzZXR0aW5ncykge1xuICAgICAgICBsZXQgeyBkYXRlRW52IH0gPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdFJhbmdlKGRhdGVFbnYuY3JlYXRlTWFya2VyKGQwKSwgZGF0ZUVudi5jcmVhdGVNYXJrZXIoZDEpLCBjcmVhdGVGb3JtYXR0ZXIoc2V0dGluZ3MpLCBzZXR0aW5ncyk7XG4gICAgfVxuICAgIGZvcm1hdElzbyhkLCBvbWl0VGltZSkge1xuICAgICAgICBsZXQgeyBkYXRlRW52IH0gPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdElzbyhkYXRlRW52LmNyZWF0ZU1hcmtlcihkKSwgeyBvbWl0VGltZSB9KTtcbiAgICB9XG4gICAgLy8gRGF0ZSBTZWxlY3Rpb24gLyBFdmVudCBTZWxlY3Rpb24gLyBEYXlDbGlja1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgc2VsZWN0KGRhdGVPck9iaiwgZW5kRGF0ZSkge1xuICAgICAgICBsZXQgc2VsZWN0aW9uSW5wdXQ7XG4gICAgICAgIGlmIChlbmREYXRlID09IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChkYXRlT3JPYmouc3RhcnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbklucHV0ID0gZGF0ZU9yT2JqO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uSW5wdXQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBkYXRlT3JPYmosXG4gICAgICAgICAgICAgICAgICAgIGVuZDogbnVsbCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2VsZWN0aW9uSW5wdXQgPSB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IGRhdGVPck9iaixcbiAgICAgICAgICAgICAgICBlbmQ6IGVuZERhdGUsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgbGV0IHNlbGVjdGlvbiA9IHBhcnNlRGF0ZVNwYW4oc2VsZWN0aW9uSW5wdXQsIHN0YXRlLmRhdGVFbnYsIGNyZWF0ZUR1cmF0aW9uKHsgZGF5czogMSB9KSk7XG4gICAgICAgIGlmIChzZWxlY3Rpb24pIHsgLy8gdGhyb3cgcGFyc2UgZXJyb3Igb3RoZXJ3aXNlP1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdTRUxFQ1RfREFURVMnLCBzZWxlY3Rpb24gfSk7XG4gICAgICAgICAgICB0cmlnZ2VyRGF0ZVNlbGVjdChzZWxlY3Rpb24sIG51bGwsIHN0YXRlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB1bnNlbGVjdChwZXYpIHtcbiAgICAgICAgbGV0IHN0YXRlID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICBpZiAoc3RhdGUuZGF0ZVNlbGVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9EQVRFUycgfSk7XG4gICAgICAgICAgICB0cmlnZ2VyRGF0ZVVuc2VsZWN0KHBldiwgc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIFB1YmxpYyBFdmVudHMgQVBJXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBhZGRFdmVudChldmVudElucHV0LCBzb3VyY2VJbnB1dCkge1xuICAgICAgICBpZiAoZXZlbnRJbnB1dCBpbnN0YW5jZW9mIEV2ZW50SW1wbCkge1xuICAgICAgICAgICAgbGV0IGRlZiA9IGV2ZW50SW5wdXQuX2RlZjtcbiAgICAgICAgICAgIGxldCBpbnN0YW5jZSA9IGV2ZW50SW5wdXQuX2luc3RhbmNlO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnREYXRhID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICAgICAgLy8gbm90IGFscmVhZHkgcHJlc2VudD8gZG9uJ3Qgd2FudCB0byBhZGQgYW4gb2xkIHNuYXBzaG90XG4gICAgICAgICAgICBpZiAoIWN1cnJlbnREYXRhLmV2ZW50U3RvcmUuZGVmc1tkZWYuZGVmSWRdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdBRERfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogZXZlbnRUdXBsZVRvU3RvcmUoeyBkZWYsIGluc3RhbmNlIH0pLCAvLyBUT0RPOiBiZXR0ZXIgdXRpbCBmb3IgdHdvIGFyZ3M/XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnRBZGQoZXZlbnRJbnB1dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZXZlbnRJbnB1dDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc3RhdGUgPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIGxldCBldmVudFNvdXJjZTtcbiAgICAgICAgaWYgKHNvdXJjZUlucHV0IGluc3RhbmNlb2YgRXZlbnRTb3VyY2VJbXBsKSB7XG4gICAgICAgICAgICBldmVudFNvdXJjZSA9IHNvdXJjZUlucHV0LmludGVybmFsRXZlbnRTb3VyY2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHNvdXJjZUlucHV0ID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIGlmIChzb3VyY2VJbnB1dCkgeyAvLyB0cnVlLiBwYXJ0IG9mIHRoZSBmaXJzdCBldmVudCBzb3VyY2VcbiAgICAgICAgICAgICAgICBbZXZlbnRTb3VyY2VdID0gaGFzaFZhbHVlc1RvQXJyYXkoc3RhdGUuZXZlbnRTb3VyY2VzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChzb3VyY2VJbnB1dCAhPSBudWxsKSB7IC8vIGFuIElELiBhY2NlcHRzIGEgbnVtYmVyIHRvb1xuICAgICAgICAgICAgbGV0IHNvdXJjZUFwaSA9IHRoaXMuZ2V0RXZlbnRTb3VyY2VCeUlkKHNvdXJjZUlucHV0KTsgLy8gVE9ETzogdXNlIGFuIGludGVybmFsIGZ1bmN0aW9uXG4gICAgICAgICAgICBpZiAoIXNvdXJjZUFwaSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgQ291bGQgbm90IGZpbmQgYW4gZXZlbnQgc291cmNlIHdpdGggSUQgXCIke3NvdXJjZUlucHV0fVwiYCk7IC8vIFRPRE86IHRlc3RcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV2ZW50U291cmNlID0gc291cmNlQXBpLmludGVybmFsRXZlbnRTb3VyY2U7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHR1cGxlID0gcGFyc2VFdmVudChldmVudElucHV0LCBldmVudFNvdXJjZSwgc3RhdGUsIGZhbHNlKTtcbiAgICAgICAgaWYgKHR1cGxlKSB7XG4gICAgICAgICAgICBsZXQgbmV3RXZlbnRBcGkgPSBuZXcgRXZlbnRJbXBsKHN0YXRlLCB0dXBsZS5kZWYsIHR1cGxlLmRlZi5yZWN1cnJpbmdEZWYgPyBudWxsIDogdHVwbGUuaW5zdGFuY2UpO1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ0FERF9FVkVOVFMnLFxuICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50VHVwbGVUb1N0b3JlKHR1cGxlKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnRBZGQobmV3RXZlbnRBcGkpO1xuICAgICAgICAgICAgcmV0dXJuIG5ld0V2ZW50QXBpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB0cmlnZ2VyRXZlbnRBZGQoZXZlbnRBcGkpIHtcbiAgICAgICAgbGV0IHsgZW1pdHRlciB9ID0gdGhpcy5nZXRDdXJyZW50RGF0YSgpO1xuICAgICAgICBlbWl0dGVyLnRyaWdnZXIoJ2V2ZW50QWRkJywge1xuICAgICAgICAgICAgZXZlbnQ6IGV2ZW50QXBpLFxuICAgICAgICAgICAgcmVsYXRlZEV2ZW50czogW10sXG4gICAgICAgICAgICByZXZlcnQ6ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1JFTU9WRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudEFwaVRvU3RvcmUoZXZlbnRBcGkpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IG9wdGltaXplXG4gICAgZ2V0RXZlbnRCeUlkKGlkKSB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHRoaXMuZ2V0Q3VycmVudERhdGEoKTtcbiAgICAgICAgbGV0IHsgZGVmcywgaW5zdGFuY2VzIH0gPSBzdGF0ZS5ldmVudFN0b3JlO1xuICAgICAgICBpZCA9IFN0cmluZyhpZCk7XG4gICAgICAgIGZvciAobGV0IGRlZklkIGluIGRlZnMpIHtcbiAgICAgICAgICAgIGxldCBkZWYgPSBkZWZzW2RlZklkXTtcbiAgICAgICAgICAgIGlmIChkZWYucHVibGljSWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRlZi5yZWN1cnJpbmdEZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudEltcGwoc3RhdGUsIGRlZiwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpbnN0YW5jZSA9IGluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluc3RhbmNlLmRlZklkID09PSBkZWYuZGVmSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZlbnRJbXBsKHN0YXRlLCBkZWYsIGluc3RhbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZ2V0RXZlbnRzKCkge1xuICAgICAgICBsZXQgY3VycmVudERhdGEgPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIHJldHVybiBidWlsZEV2ZW50QXBpcyhjdXJyZW50RGF0YS5ldmVudFN0b3JlLCBjdXJyZW50RGF0YSk7XG4gICAgfVxuICAgIHJlbW92ZUFsbEV2ZW50cygpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdSRU1PVkVfQUxMX0VWRU5UUycgfSk7XG4gICAgfVxuICAgIC8vIFB1YmxpYyBFdmVudCBTb3VyY2VzIEFQSVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgZ2V0RXZlbnRTb3VyY2VzKCkge1xuICAgICAgICBsZXQgc3RhdGUgPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIGxldCBzb3VyY2VIYXNoID0gc3RhdGUuZXZlbnRTb3VyY2VzO1xuICAgICAgICBsZXQgc291cmNlQXBpcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpbnRlcm5hbElkIGluIHNvdXJjZUhhc2gpIHtcbiAgICAgICAgICAgIHNvdXJjZUFwaXMucHVzaChuZXcgRXZlbnRTb3VyY2VJbXBsKHN0YXRlLCBzb3VyY2VIYXNoW2ludGVybmFsSWRdKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvdXJjZUFwaXM7XG4gICAgfVxuICAgIGdldEV2ZW50U291cmNlQnlJZChpZCkge1xuICAgICAgICBsZXQgc3RhdGUgPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIGxldCBzb3VyY2VIYXNoID0gc3RhdGUuZXZlbnRTb3VyY2VzO1xuICAgICAgICBpZCA9IFN0cmluZyhpZCk7XG4gICAgICAgIGZvciAobGV0IHNvdXJjZUlkIGluIHNvdXJjZUhhc2gpIHtcbiAgICAgICAgICAgIGlmIChzb3VyY2VIYXNoW3NvdXJjZUlkXS5wdWJsaWNJZCA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlSW1wbChzdGF0ZSwgc291cmNlSGFzaFtzb3VyY2VJZF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBhZGRFdmVudFNvdXJjZShzb3VyY2VJbnB1dCkge1xuICAgICAgICBsZXQgc3RhdGUgPSB0aGlzLmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgIGlmIChzb3VyY2VJbnB1dCBpbnN0YW5jZW9mIEV2ZW50U291cmNlSW1wbCkge1xuICAgICAgICAgICAgLy8gbm90IGFscmVhZHkgcHJlc2VudD8gZG9uJ3Qgd2FudCB0byBhZGQgYW4gb2xkIHNuYXBzaG90XG4gICAgICAgICAgICBpZiAoIXN0YXRlLmV2ZW50U291cmNlc1tzb3VyY2VJbnB1dC5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnQUREX0VWRU5UX1NPVVJDRVMnLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VzOiBbc291cmNlSW5wdXQuaW50ZXJuYWxFdmVudFNvdXJjZV0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc291cmNlSW5wdXQ7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGV2ZW50U291cmNlID0gcGFyc2VFdmVudFNvdXJjZShzb3VyY2VJbnB1dCwgc3RhdGUpO1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2UpIHsgLy8gVE9ETzogZXJyb3Igb3RoZXJ3aXNlP1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdBRERfRVZFTlRfU09VUkNFUycsIHNvdXJjZXM6IFtldmVudFNvdXJjZV0gfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlSW1wbChzdGF0ZSwgZXZlbnRTb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZW1vdmVBbGxFdmVudFNvdXJjZXMoKSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUkVNT1ZFX0FMTF9FVkVOVF9TT1VSQ0VTJyB9KTtcbiAgICB9XG4gICAgcmVmZXRjaEV2ZW50cygpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdGRVRDSF9FVkVOVF9TT1VSQ0VTJywgaXNSZWZldGNoOiB0cnVlIH0pO1xuICAgIH1cbiAgICAvLyBTY3JvbGxcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHNjcm9sbFRvVGltZSh0aW1lSW5wdXQpIHtcbiAgICAgICAgbGV0IHRpbWUgPSBjcmVhdGVEdXJhdGlvbih0aW1lSW5wdXQpO1xuICAgICAgICBpZiAodGltZSkge1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyKCdfc2Nyb2xsUmVxdWVzdCcsIHsgdGltZSB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gcG9pbnRJbnNpZGVSZWN0KHBvaW50LCByZWN0KSB7XG4gICAgcmV0dXJuIHBvaW50LmxlZnQgPj0gcmVjdC5sZWZ0ICYmXG4gICAgICAgIHBvaW50LmxlZnQgPCByZWN0LnJpZ2h0ICYmXG4gICAgICAgIHBvaW50LnRvcCA+PSByZWN0LnRvcCAmJlxuICAgICAgICBwb2ludC50b3AgPCByZWN0LmJvdHRvbTtcbn1cbi8vIFJldHVybnMgYSBuZXcgcmVjdGFuZ2xlIHRoYXQgaXMgdGhlIGludGVyc2VjdGlvbiBvZiB0aGUgdHdvIHJlY3RhbmdsZXMuIElmIHRoZXkgZG9uJ3QgaW50ZXJzZWN0LCByZXR1cm5zIGZhbHNlXG5mdW5jdGlvbiBpbnRlcnNlY3RSZWN0cyhyZWN0MSwgcmVjdDIpIHtcbiAgICBsZXQgcmVzID0ge1xuICAgICAgICBsZWZ0OiBNYXRoLm1heChyZWN0MS5sZWZ0LCByZWN0Mi5sZWZ0KSxcbiAgICAgICAgcmlnaHQ6IE1hdGgubWluKHJlY3QxLnJpZ2h0LCByZWN0Mi5yaWdodCksXG4gICAgICAgIHRvcDogTWF0aC5tYXgocmVjdDEudG9wLCByZWN0Mi50b3ApLFxuICAgICAgICBib3R0b206IE1hdGgubWluKHJlY3QxLmJvdHRvbSwgcmVjdDIuYm90dG9tKSxcbiAgICB9O1xuICAgIGlmIChyZXMubGVmdCA8IHJlcy5yaWdodCAmJiByZXMudG9wIDwgcmVzLmJvdHRvbSkge1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiB0cmFuc2xhdGVSZWN0KHJlY3QsIGRlbHRhWCwgZGVsdGFZKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogcmVjdC5sZWZ0ICsgZGVsdGFYLFxuICAgICAgICByaWdodDogcmVjdC5yaWdodCArIGRlbHRhWCxcbiAgICAgICAgdG9wOiByZWN0LnRvcCArIGRlbHRhWSxcbiAgICAgICAgYm90dG9tOiByZWN0LmJvdHRvbSArIGRlbHRhWSxcbiAgICB9O1xufVxuLy8gUmV0dXJucyBhIG5ldyBwb2ludCB0aGF0IHdpbGwgaGF2ZSBiZWVuIG1vdmVkIHRvIHJlc2lkZSB3aXRoaW4gdGhlIGdpdmVuIHJlY3RhbmdsZVxuZnVuY3Rpb24gY29uc3RyYWluUG9pbnQocG9pbnQsIHJlY3QpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiBNYXRoLm1pbihNYXRoLm1heChwb2ludC5sZWZ0LCByZWN0LmxlZnQpLCByZWN0LnJpZ2h0KSxcbiAgICAgICAgdG9wOiBNYXRoLm1pbihNYXRoLm1heChwb2ludC50b3AsIHJlY3QudG9wKSwgcmVjdC5ib3R0b20pLFxuICAgIH07XG59XG4vLyBSZXR1cm5zIGEgcG9pbnQgdGhhdCBpcyB0aGUgY2VudGVyIG9mIHRoZSBnaXZlbiByZWN0YW5nbGVcbmZ1bmN0aW9uIGdldFJlY3RDZW50ZXIocmVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IChyZWN0LmxlZnQgKyByZWN0LnJpZ2h0KSAvIDIsXG4gICAgICAgIHRvcDogKHJlY3QudG9wICsgcmVjdC5ib3R0b20pIC8gMixcbiAgICB9O1xufVxuLy8gU3VidHJhY3RzIHBvaW50MidzIGNvb3JkaW5hdGVzIGZyb20gcG9pbnQxJ3MgY29vcmRpbmF0ZXMsIHJldHVybmluZyBhIGRlbHRhXG5mdW5jdGlvbiBkaWZmUG9pbnRzKHBvaW50MSwgcG9pbnQyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogcG9pbnQxLmxlZnQgLSBwb2ludDIubGVmdCxcbiAgICAgICAgdG9wOiBwb2ludDEudG9wIC0gcG9pbnQyLnRvcCxcbiAgICB9O1xufVxuXG5jb25zdCBFTVBUWV9FVkVOVF9TVE9SRSA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpOyAvLyBmb3IgcHVyZWNvbXBvbmVudHMuIFRPRE86IGtlZXAgZWxzZXdoZXJlXG5jbGFzcyBTcGxpdHRlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZ2V0S2V5c0ZvckV2ZW50RGVmcyA9IG1lbW9pemUodGhpcy5fZ2V0S2V5c0ZvckV2ZW50RGVmcyk7XG4gICAgICAgIHRoaXMuc3BsaXREYXRlU2VsZWN0aW9uID0gbWVtb2l6ZSh0aGlzLl9zcGxpdERhdGVTcGFuKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50U3RvcmUgPSBtZW1vaXplKHRoaXMuX3NwbGl0RXZlbnRTdG9yZSk7XG4gICAgICAgIHRoaXMuc3BsaXRJbmRpdmlkdWFsVWkgPSBtZW1vaXplKHRoaXMuX3NwbGl0SW5kaXZpZHVhbFVpKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50RHJhZyA9IG1lbW9pemUodGhpcy5fc3BsaXRJbnRlcmFjdGlvbik7XG4gICAgICAgIHRoaXMuc3BsaXRFdmVudFJlc2l6ZSA9IG1lbW9pemUodGhpcy5fc3BsaXRJbnRlcmFjdGlvbik7XG4gICAgICAgIHRoaXMuZXZlbnRVaUJ1aWxkZXJzID0ge307IC8vIFRPRE86IHR5cGVzY3JpcHQgcHJvdGVjdGlvblxuICAgIH1cbiAgICBzcGxpdFByb3BzKHByb3BzKSB7XG4gICAgICAgIGxldCBrZXlJbmZvcyA9IHRoaXMuZ2V0S2V5SW5mbyhwcm9wcyk7XG4gICAgICAgIGxldCBkZWZLZXlzID0gdGhpcy5nZXRLZXlzRm9yRXZlbnREZWZzKHByb3BzLmV2ZW50U3RvcmUpO1xuICAgICAgICBsZXQgZGF0ZVNlbGVjdGlvbnMgPSB0aGlzLnNwbGl0RGF0ZVNlbGVjdGlvbihwcm9wcy5kYXRlU2VsZWN0aW9uKTtcbiAgICAgICAgbGV0IGluZGl2aWR1YWxVaSA9IHRoaXMuc3BsaXRJbmRpdmlkdWFsVWkocHJvcHMuZXZlbnRVaUJhc2VzLCBkZWZLZXlzKTsgLy8gdGhlIGluZGl2aWR1YWwgKmJhc2VzKlxuICAgICAgICBsZXQgZXZlbnRTdG9yZXMgPSB0aGlzLnNwbGl0RXZlbnRTdG9yZShwcm9wcy5ldmVudFN0b3JlLCBkZWZLZXlzKTtcbiAgICAgICAgbGV0IGV2ZW50RHJhZ3MgPSB0aGlzLnNwbGl0RXZlbnREcmFnKHByb3BzLmV2ZW50RHJhZyk7XG4gICAgICAgIGxldCBldmVudFJlc2l6ZXMgPSB0aGlzLnNwbGl0RXZlbnRSZXNpemUocHJvcHMuZXZlbnRSZXNpemUpO1xuICAgICAgICBsZXQgc3BsaXRQcm9wcyA9IHt9O1xuICAgICAgICB0aGlzLmV2ZW50VWlCdWlsZGVycyA9IG1hcEhhc2goa2V5SW5mb3MsIChpbmZvLCBrZXkpID0+IHRoaXMuZXZlbnRVaUJ1aWxkZXJzW2tleV0gfHwgbWVtb2l6ZShidWlsZEV2ZW50VWlGb3JLZXkpKTtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIGtleUluZm9zKSB7XG4gICAgICAgICAgICBsZXQga2V5SW5mbyA9IGtleUluZm9zW2tleV07XG4gICAgICAgICAgICBsZXQgZXZlbnRTdG9yZSA9IGV2ZW50U3RvcmVzW2tleV0gfHwgRU1QVFlfRVZFTlRfU1RPUkU7XG4gICAgICAgICAgICBsZXQgYnVpbGRFdmVudFVpID0gdGhpcy5ldmVudFVpQnVpbGRlcnNba2V5XTtcbiAgICAgICAgICAgIHNwbGl0UHJvcHNba2V5XSA9IHtcbiAgICAgICAgICAgICAgICBidXNpbmVzc0hvdXJzOiBrZXlJbmZvLmJ1c2luZXNzSG91cnMgfHwgcHJvcHMuYnVzaW5lc3NIb3VycyxcbiAgICAgICAgICAgICAgICBkYXRlU2VsZWN0aW9uOiBkYXRlU2VsZWN0aW9uc1trZXldIHx8IG51bGwsXG4gICAgICAgICAgICAgICAgZXZlbnRTdG9yZSxcbiAgICAgICAgICAgICAgICBldmVudFVpQmFzZXM6IGJ1aWxkRXZlbnRVaShwcm9wcy5ldmVudFVpQmFzZXNbJyddLCBrZXlJbmZvLnVpLCBpbmRpdmlkdWFsVWlba2V5XSksXG4gICAgICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246IGV2ZW50U3RvcmUuaW5zdGFuY2VzW3Byb3BzLmV2ZW50U2VsZWN0aW9uXSA/IHByb3BzLmV2ZW50U2VsZWN0aW9uIDogJycsXG4gICAgICAgICAgICAgICAgZXZlbnREcmFnOiBldmVudERyYWdzW2tleV0gfHwgbnVsbCxcbiAgICAgICAgICAgICAgICBldmVudFJlc2l6ZTogZXZlbnRSZXNpemVzW2tleV0gfHwgbnVsbCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwbGl0UHJvcHM7XG4gICAgfVxuICAgIF9zcGxpdERhdGVTcGFuKGRhdGVTcGFuKSB7XG4gICAgICAgIGxldCBkYXRlU3BhbnMgPSB7fTtcbiAgICAgICAgaWYgKGRhdGVTcGFuKSB7XG4gICAgICAgICAgICBsZXQga2V5cyA9IHRoaXMuZ2V0S2V5c0ZvckRhdGVTcGFuKGRhdGVTcGFuKTtcbiAgICAgICAgICAgIGZvciAobGV0IGtleSBvZiBrZXlzKSB7XG4gICAgICAgICAgICAgICAgZGF0ZVNwYW5zW2tleV0gPSBkYXRlU3BhbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZVNwYW5zO1xuICAgIH1cbiAgICBfZ2V0S2V5c0ZvckV2ZW50RGVmcyhldmVudFN0b3JlKSB7XG4gICAgICAgIHJldHVybiBtYXBIYXNoKGV2ZW50U3RvcmUuZGVmcywgKGV2ZW50RGVmKSA9PiB0aGlzLmdldEtleXNGb3JFdmVudERlZihldmVudERlZikpO1xuICAgIH1cbiAgICBfc3BsaXRFdmVudFN0b3JlKGV2ZW50U3RvcmUsIGRlZktleXMpIHtcbiAgICAgICAgbGV0IHsgZGVmcywgaW5zdGFuY2VzIH0gPSBldmVudFN0b3JlO1xuICAgICAgICBsZXQgc3BsaXRTdG9yZXMgPSB7fTtcbiAgICAgICAgZm9yIChsZXQgZGVmSWQgaW4gZGVmcykge1xuICAgICAgICAgICAgZm9yIChsZXQga2V5IG9mIGRlZktleXNbZGVmSWRdKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFzcGxpdFN0b3Jlc1trZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwbGl0U3RvcmVzW2tleV0gPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3BsaXRTdG9yZXNba2V5XS5kZWZzW2RlZklkXSA9IGRlZnNbZGVmSWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICBsZXQgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgICAgICBmb3IgKGxldCBrZXkgb2YgZGVmS2V5c1tpbnN0YW5jZS5kZWZJZF0pIHtcbiAgICAgICAgICAgICAgICBpZiAoc3BsaXRTdG9yZXNba2V5XSkgeyAvLyBtdXN0IGhhdmUgYWxyZWFkeSBiZWVuIGNyZWF0ZWRcbiAgICAgICAgICAgICAgICAgICAgc3BsaXRTdG9yZXNba2V5XS5pbnN0YW5jZXNbaW5zdGFuY2VJZF0gPSBpbnN0YW5jZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwbGl0U3RvcmVzO1xuICAgIH1cbiAgICBfc3BsaXRJbmRpdmlkdWFsVWkoZXZlbnRVaUJhc2VzLCBkZWZLZXlzKSB7XG4gICAgICAgIGxldCBzcGxpdEhhc2hlcyA9IHt9O1xuICAgICAgICBmb3IgKGxldCBkZWZJZCBpbiBldmVudFVpQmFzZXMpIHtcbiAgICAgICAgICAgIGlmIChkZWZJZCkgeyAvLyBub3QgdGhlICcnIGtleVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGtleSBvZiBkZWZLZXlzW2RlZklkXSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNwbGl0SGFzaGVzW2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwbGl0SGFzaGVzW2tleV0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzcGxpdEhhc2hlc1trZXldW2RlZklkXSA9IGV2ZW50VWlCYXNlc1tkZWZJZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdEhhc2hlcztcbiAgICB9XG4gICAgX3NwbGl0SW50ZXJhY3Rpb24oaW50ZXJhY3Rpb24pIHtcbiAgICAgICAgbGV0IHNwbGl0U3RhdGVzID0ge307XG4gICAgICAgIGlmIChpbnRlcmFjdGlvbikge1xuICAgICAgICAgICAgbGV0IGFmZmVjdGVkU3RvcmVzID0gdGhpcy5fc3BsaXRFdmVudFN0b3JlKGludGVyYWN0aW9uLmFmZmVjdGVkRXZlbnRzLCB0aGlzLl9nZXRLZXlzRm9yRXZlbnREZWZzKGludGVyYWN0aW9uLmFmZmVjdGVkRXZlbnRzKSk7XG4gICAgICAgICAgICAvLyBjYW4ndCByZWx5IG9uIGRlZktleXMgYmVjYXVzZSBldmVudCBkYXRhIGlzIG11dGF0ZWRcbiAgICAgICAgICAgIGxldCBtdXRhdGVkS2V5c0J5RGVmSWQgPSB0aGlzLl9nZXRLZXlzRm9yRXZlbnREZWZzKGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMpO1xuICAgICAgICAgICAgbGV0IG11dGF0ZWRTdG9yZXMgPSB0aGlzLl9zcGxpdEV2ZW50U3RvcmUoaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cywgbXV0YXRlZEtleXNCeURlZklkKTtcbiAgICAgICAgICAgIGxldCBwb3B1bGF0ZSA9IChrZXkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXNwbGl0U3RhdGVzW2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgc3BsaXRTdGF0ZXNba2V5XSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFmZmVjdGVkRXZlbnRzOiBhZmZlY3RlZFN0b3Jlc1trZXldIHx8IEVNUFRZX0VWRU5UX1NUT1JFLFxuICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogbXV0YXRlZFN0b3Jlc1trZXldIHx8IEVNUFRZX0VWRU5UX1NUT1JFLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNFdmVudDogaW50ZXJhY3Rpb24uaXNFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIGFmZmVjdGVkU3RvcmVzKSB7XG4gICAgICAgICAgICAgICAgcG9wdWxhdGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiBtdXRhdGVkU3RvcmVzKSB7XG4gICAgICAgICAgICAgICAgcG9wdWxhdGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3BsaXRTdGF0ZXM7XG4gICAgfVxufVxuZnVuY3Rpb24gYnVpbGRFdmVudFVpRm9yS2V5KGFsbFVpLCBldmVudFVpRm9yS2V5LCBpbmRpdmlkdWFsVWkpIHtcbiAgICBsZXQgYmFzZVBhcnRzID0gW107XG4gICAgaWYgKGFsbFVpKSB7XG4gICAgICAgIGJhc2VQYXJ0cy5wdXNoKGFsbFVpKTtcbiAgICB9XG4gICAgaWYgKGV2ZW50VWlGb3JLZXkpIHtcbiAgICAgICAgYmFzZVBhcnRzLnB1c2goZXZlbnRVaUZvcktleSk7XG4gICAgfVxuICAgIGxldCBzdHVmZiA9IHtcbiAgICAgICAgJyc6IGNvbWJpbmVFdmVudFVpcyhiYXNlUGFydHMpLFxuICAgIH07XG4gICAgaWYgKGluZGl2aWR1YWxVaSkge1xuICAgICAgICBPYmplY3QuYXNzaWduKHN0dWZmLCBpbmRpdmlkdWFsVWkpO1xuICAgIH1cbiAgICByZXR1cm4gc3R1ZmY7XG59XG5cbmZ1bmN0aW9uIGdldERhdGVNZXRhKGRhdGUsIHRvZGF5UmFuZ2UsIG5vd0RhdGUsIGRhdGVQcm9maWxlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZG93OiBkYXRlLmdldFVUQ0RheSgpLFxuICAgICAgICBpc0Rpc2FibGVkOiBCb29sZWFuKGRhdGVQcm9maWxlICYmICghZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgfHwgIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGRhdGUpKSksXG4gICAgICAgIGlzT3RoZXI6IEJvb2xlYW4oZGF0ZVByb2ZpbGUgJiYgIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLCBkYXRlKSksXG4gICAgICAgIGlzVG9kYXk6IEJvb2xlYW4odG9kYXlSYW5nZSAmJiByYW5nZUNvbnRhaW5zTWFya2VyKHRvZGF5UmFuZ2UsIGRhdGUpKSxcbiAgICAgICAgaXNQYXN0OiBCb29sZWFuKG5vd0RhdGUgPyAoZGF0ZSA8IG5vd0RhdGUpIDogdG9kYXlSYW5nZSA/IChkYXRlIDwgdG9kYXlSYW5nZS5zdGFydCkgOiBmYWxzZSksXG4gICAgICAgIGlzRnV0dXJlOiBCb29sZWFuKG5vd0RhdGUgPyAoZGF0ZSA+IG5vd0RhdGUpIDogdG9kYXlSYW5nZSA/IChkYXRlID49IHRvZGF5UmFuZ2UuZW5kKSA6IGZhbHNlKSxcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0RGF5Q2xhc3NOYW1lcyhtZXRhLCB0aGVtZSkge1xuICAgIGxldCBjbGFzc05hbWVzID0gW1xuICAgICAgICAnZmMtZGF5JyxcbiAgICAgICAgYGZjLWRheS0ke0RBWV9JRFNbbWV0YS5kb3ddfWAsXG4gICAgXTtcbiAgICBpZiAobWV0YS5pc0Rpc2FibGVkKSB7XG4gICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtZGF5LWRpc2FibGVkJyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZiAobWV0YS5pc1RvZGF5KSB7XG4gICAgICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWRheS10b2RheScpO1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKHRoZW1lLmdldENsYXNzKCd0b2RheScpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YS5pc1Bhc3QpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtZGF5LXBhc3QnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YS5pc0Z1dHVyZSkge1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy1kYXktZnV0dXJlJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGEuaXNPdGhlcikge1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy1kYXktb3RoZXInKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xhc3NOYW1lcztcbn1cbmZ1bmN0aW9uIGdldFNsb3RDbGFzc05hbWVzKG1ldGEsIHRoZW1lKSB7XG4gICAgbGV0IGNsYXNzTmFtZXMgPSBbXG4gICAgICAgICdmYy1zbG90JyxcbiAgICAgICAgYGZjLXNsb3QtJHtEQVlfSURTW21ldGEuZG93XX1gLFxuICAgIF07XG4gICAgaWYgKG1ldGEuaXNEaXNhYmxlZCkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLXNsb3QtZGlzYWJsZWQnKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmIChtZXRhLmlzVG9kYXkpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtc2xvdC10b2RheScpO1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKHRoZW1lLmdldENsYXNzKCd0b2RheScpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YS5pc1Bhc3QpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtc2xvdC1wYXN0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGEuaXNGdXR1cmUpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtc2xvdC1mdXR1cmUnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xhc3NOYW1lcztcbn1cblxuY29uc3QgREFZX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdsb25nJywgZGF5OiAnbnVtZXJpYycgfSk7XG5jb25zdCBXRUVLX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7IHdlZWs6ICdsb25nJyB9KTtcbmZ1bmN0aW9uIGJ1aWxkTmF2TGlua0F0dHJzKGNvbnRleHQsIGRhdGVNYXJrZXIsIHZpZXdUeXBlID0gJ2RheScsIGlzVGFiYmFibGUgPSB0cnVlKSB7XG4gICAgY29uc3QgeyBkYXRlRW52LCBvcHRpb25zLCBjYWxlbmRhckFwaSB9ID0gY29udGV4dDtcbiAgICBsZXQgZGF0ZVN0ciA9IGRhdGVFbnYuZm9ybWF0KGRhdGVNYXJrZXIsIHZpZXdUeXBlID09PSAnd2VlaycgPyBXRUVLX0ZPUk1BVCA6IERBWV9GT1JNQVQpO1xuICAgIGlmIChvcHRpb25zLm5hdkxpbmtzKSB7XG4gICAgICAgIGxldCB6b25lZERhdGUgPSBkYXRlRW52LnRvRGF0ZShkYXRlTWFya2VyKTtcbiAgICAgICAgY29uc3QgaGFuZGxlSW50ZXJhY3Rpb24gPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGxldCBjdXN0b21BY3Rpb24gPSB2aWV3VHlwZSA9PT0gJ2RheScgPyBvcHRpb25zLm5hdkxpbmtEYXlDbGljayA6XG4gICAgICAgICAgICAgICAgdmlld1R5cGUgPT09ICd3ZWVrJyA/IG9wdGlvbnMubmF2TGlua1dlZWtDbGljayA6IG51bGw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGN1c3RvbUFjdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGN1c3RvbUFjdGlvbi5jYWxsKGNhbGVuZGFyQXBpLCBkYXRlRW52LnRvRGF0ZShkYXRlTWFya2VyKSwgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjdXN0b21BY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZXdUeXBlID0gY3VzdG9tQWN0aW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxlbmRhckFwaS56b29tVG8oZGF0ZU1hcmtlciwgdmlld1R5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7IHRpdGxlOiBmb3JtYXRXaXRoT3JkaW5hbHMob3B0aW9ucy5uYXZMaW5rSGludCwgW2RhdGVTdHIsIHpvbmVkRGF0ZV0sIGRhdGVTdHIpLCAnZGF0YS1uYXZsaW5rJzogJycgfSwgKGlzVGFiYmFibGVcbiAgICAgICAgICAgID8gY3JlYXRlQXJpYUNsaWNrQXR0cnMoaGFuZGxlSW50ZXJhY3Rpb24pXG4gICAgICAgICAgICA6IHsgb25DbGljazogaGFuZGxlSW50ZXJhY3Rpb24gfSkpO1xuICAgIH1cbiAgICByZXR1cm4geyAnYXJpYS1sYWJlbCc6IGRhdGVTdHIgfTtcbn1cblxubGV0IF9pc1J0bFNjcm9sbGJhck9uTGVmdCA9IG51bGw7XG5mdW5jdGlvbiBnZXRJc1J0bFNjcm9sbGJhck9uTGVmdCgpIHtcbiAgICBpZiAoX2lzUnRsU2Nyb2xsYmFyT25MZWZ0ID09PSBudWxsKSB7XG4gICAgICAgIF9pc1J0bFNjcm9sbGJhck9uTGVmdCA9IGNvbXB1dGVJc1J0bFNjcm9sbGJhck9uTGVmdCgpO1xuICAgIH1cbiAgICByZXR1cm4gX2lzUnRsU2Nyb2xsYmFyT25MZWZ0O1xufVxuZnVuY3Rpb24gY29tcHV0ZUlzUnRsU2Nyb2xsYmFyT25MZWZ0KCkge1xuICAgIGxldCBvdXRlckVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgYXBwbHlTdHlsZShvdXRlckVsLCB7XG4gICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICB0b3A6IC0xMDAwLFxuICAgICAgICBsZWZ0OiAwLFxuICAgICAgICBib3JkZXI6IDAsXG4gICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgIG92ZXJmbG93OiAnc2Nyb2xsJyxcbiAgICAgICAgZGlyZWN0aW9uOiAncnRsJyxcbiAgICB9KTtcbiAgICBvdXRlckVsLmlubmVySFRNTCA9ICc8ZGl2PjwvZGl2Pic7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChvdXRlckVsKTtcbiAgICBsZXQgaW5uZXJFbCA9IG91dGVyRWwuZmlyc3RDaGlsZDtcbiAgICBsZXQgcmVzID0gaW5uZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ID4gb3V0ZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuICAgIHJlbW92ZUVsZW1lbnQob3V0ZXJFbCk7XG4gICAgcmV0dXJuIHJlcztcbn1cblxubGV0IF9zY3JvbGxiYXJXaWR0aHM7XG5mdW5jdGlvbiBnZXRTY3JvbGxiYXJXaWR0aHMoKSB7XG4gICAgaWYgKCFfc2Nyb2xsYmFyV2lkdGhzKSB7XG4gICAgICAgIF9zY3JvbGxiYXJXaWR0aHMgPSBjb21wdXRlU2Nyb2xsYmFyV2lkdGhzKCk7XG4gICAgfVxuICAgIHJldHVybiBfc2Nyb2xsYmFyV2lkdGhzO1xufVxuZnVuY3Rpb24gY29tcHV0ZVNjcm9sbGJhcldpZHRocygpIHtcbiAgICBsZXQgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBlbC5zdHlsZS5vdmVyZmxvdyA9ICdzY3JvbGwnO1xuICAgIGVsLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBlbC5zdHlsZS50b3AgPSAnLTk5OTlweCc7XG4gICAgZWwuc3R5bGUubGVmdCA9ICctOTk5OXB4JztcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGVsKTtcbiAgICBsZXQgcmVzID0gY29tcHV0ZVNjcm9sbGJhcldpZHRoc0ZvckVsKGVsKTtcbiAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGVsKTtcbiAgICByZXR1cm4gcmVzO1xufVxuLy8gV0FSTklORzogd2lsbCBpbmNsdWRlIGJvcmRlclxuZnVuY3Rpb24gY29tcHV0ZVNjcm9sbGJhcldpZHRoc0ZvckVsKGVsKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogZWwub2Zmc2V0SGVpZ2h0IC0gZWwuY2xpZW50SGVpZ2h0LFxuICAgICAgICB5OiBlbC5vZmZzZXRXaWR0aCAtIGVsLmNsaWVudFdpZHRoLFxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVFZGdlcyhlbCwgZ2V0UGFkZGluZyA9IGZhbHNlKSB7XG4gICAgbGV0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgbGV0IGJvcmRlckxlZnQgPSBwYXJzZUludChjb21wdXRlZFN0eWxlLmJvcmRlckxlZnRXaWR0aCwgMTApIHx8IDA7XG4gICAgbGV0IGJvcmRlclJpZ2h0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5ib3JkZXJSaWdodFdpZHRoLCAxMCkgfHwgMDtcbiAgICBsZXQgYm9yZGVyVG9wID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5ib3JkZXJUb3BXaWR0aCwgMTApIHx8IDA7XG4gICAgbGV0IGJvcmRlckJvdHRvbSA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUuYm9yZGVyQm90dG9tV2lkdGgsIDEwKSB8fCAwO1xuICAgIGxldCBiYWRTY3JvbGxiYXJXaWR0aHMgPSBjb21wdXRlU2Nyb2xsYmFyV2lkdGhzRm9yRWwoZWwpOyAvLyBpbmNsdWRlcyBib3JkZXIhXG4gICAgbGV0IHNjcm9sbGJhckxlZnRSaWdodCA9IGJhZFNjcm9sbGJhcldpZHRocy55IC0gYm9yZGVyTGVmdCAtIGJvcmRlclJpZ2h0O1xuICAgIGxldCBzY3JvbGxiYXJCb3R0b20gPSBiYWRTY3JvbGxiYXJXaWR0aHMueCAtIGJvcmRlclRvcCAtIGJvcmRlckJvdHRvbTtcbiAgICBsZXQgcmVzID0ge1xuICAgICAgICBib3JkZXJMZWZ0LFxuICAgICAgICBib3JkZXJSaWdodCxcbiAgICAgICAgYm9yZGVyVG9wLFxuICAgICAgICBib3JkZXJCb3R0b20sXG4gICAgICAgIHNjcm9sbGJhckJvdHRvbSxcbiAgICAgICAgc2Nyb2xsYmFyTGVmdDogMCxcbiAgICAgICAgc2Nyb2xsYmFyUmlnaHQ6IDAsXG4gICAgfTtcbiAgICBpZiAoZ2V0SXNSdGxTY3JvbGxiYXJPbkxlZnQoKSAmJiBjb21wdXRlZFN0eWxlLmRpcmVjdGlvbiA9PT0gJ3J0bCcpIHsgLy8gaXMgdGhlIHNjcm9sbGJhciBvbiB0aGUgbGVmdCBzaWRlP1xuICAgICAgICByZXMuc2Nyb2xsYmFyTGVmdCA9IHNjcm9sbGJhckxlZnRSaWdodDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJlcy5zY3JvbGxiYXJSaWdodCA9IHNjcm9sbGJhckxlZnRSaWdodDtcbiAgICB9XG4gICAgaWYgKGdldFBhZGRpbmcpIHtcbiAgICAgICAgcmVzLnBhZGRpbmdMZWZ0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nTGVmdCwgMTApIHx8IDA7XG4gICAgICAgIHJlcy5wYWRkaW5nUmlnaHQgPSBwYXJzZUludChjb21wdXRlZFN0eWxlLnBhZGRpbmdSaWdodCwgMTApIHx8IDA7XG4gICAgICAgIHJlcy5wYWRkaW5nVG9wID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nVG9wLCAxMCkgfHwgMDtcbiAgICAgICAgcmVzLnBhZGRpbmdCb3R0b20gPSBwYXJzZUludChjb21wdXRlZFN0eWxlLnBhZGRpbmdCb3R0b20sIDEwKSB8fCAwO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gY29tcHV0ZUlubmVyUmVjdChlbCwgZ29XaXRoaW5QYWRkaW5nID0gZmFsc2UsIGRvRnJvbVdpbmRvd1ZpZXdwb3J0KSB7XG4gICAgbGV0IG91dGVyUmVjdCA9IGRvRnJvbVdpbmRvd1ZpZXdwb3J0ID8gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgOiBjb21wdXRlUmVjdChlbCk7XG4gICAgbGV0IGVkZ2VzID0gY29tcHV0ZUVkZ2VzKGVsLCBnb1dpdGhpblBhZGRpbmcpO1xuICAgIGxldCByZXMgPSB7XG4gICAgICAgIGxlZnQ6IG91dGVyUmVjdC5sZWZ0ICsgZWRnZXMuYm9yZGVyTGVmdCArIGVkZ2VzLnNjcm9sbGJhckxlZnQsXG4gICAgICAgIHJpZ2h0OiBvdXRlclJlY3QucmlnaHQgLSBlZGdlcy5ib3JkZXJSaWdodCAtIGVkZ2VzLnNjcm9sbGJhclJpZ2h0LFxuICAgICAgICB0b3A6IG91dGVyUmVjdC50b3AgKyBlZGdlcy5ib3JkZXJUb3AsXG4gICAgICAgIGJvdHRvbTogb3V0ZXJSZWN0LmJvdHRvbSAtIGVkZ2VzLmJvcmRlckJvdHRvbSAtIGVkZ2VzLnNjcm9sbGJhckJvdHRvbSxcbiAgICB9O1xuICAgIGlmIChnb1dpdGhpblBhZGRpbmcpIHtcbiAgICAgICAgcmVzLmxlZnQgKz0gZWRnZXMucGFkZGluZ0xlZnQ7XG4gICAgICAgIHJlcy5yaWdodCAtPSBlZGdlcy5wYWRkaW5nUmlnaHQ7XG4gICAgICAgIHJlcy50b3AgKz0gZWRnZXMucGFkZGluZ1RvcDtcbiAgICAgICAgcmVzLmJvdHRvbSAtPSBlZGdlcy5wYWRkaW5nQm90dG9tO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gY29tcHV0ZVJlY3QoZWwpIHtcbiAgICBsZXQgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IHJlY3QubGVmdCArIHdpbmRvdy5zY3JvbGxYLFxuICAgICAgICB0b3A6IHJlY3QudG9wICsgd2luZG93LnNjcm9sbFksXG4gICAgICAgIHJpZ2h0OiByZWN0LnJpZ2h0ICsgd2luZG93LnNjcm9sbFgsXG4gICAgICAgIGJvdHRvbTogcmVjdC5ib3R0b20gKyB3aW5kb3cuc2Nyb2xsWSxcbiAgICB9O1xufVxuZnVuY3Rpb24gY29tcHV0ZUNsaXBwZWRDbGllbnRSZWN0KGVsKSB7XG4gICAgbGV0IGNsaXBwaW5nUGFyZW50cyA9IGdldENsaXBwaW5nUGFyZW50cyhlbCk7XG4gICAgbGV0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBmb3IgKGxldCBjbGlwcGluZ1BhcmVudCBvZiBjbGlwcGluZ1BhcmVudHMpIHtcbiAgICAgICAgbGV0IGludGVyc2VjdGlvbiA9IGludGVyc2VjdFJlY3RzKHJlY3QsIGNsaXBwaW5nUGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpKTtcbiAgICAgICAgaWYgKGludGVyc2VjdGlvbikge1xuICAgICAgICAgICAgcmVjdCA9IGludGVyc2VjdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWN0O1xufVxuLy8gZG9lcyBub3QgcmV0dXJuIHdpbmRvd1xuZnVuY3Rpb24gZ2V0Q2xpcHBpbmdQYXJlbnRzKGVsKSB7XG4gICAgbGV0IHBhcmVudHMgPSBbXTtcbiAgICB3aGlsZSAoZWwgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgeyAvLyB3aWxsIHN0b3Agd2hlbiBnZXRzIHRvIGRvY3VtZW50IG9yIG51bGxcbiAgICAgICAgbGV0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICAgIGlmIChjb21wdXRlZFN0eWxlLnBvc2l0aW9uID09PSAnZml4ZWQnKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoKC8oYXV0b3xzY3JvbGwpLykudGVzdChjb21wdXRlZFN0eWxlLm92ZXJmbG93ICsgY29tcHV0ZWRTdHlsZS5vdmVyZmxvd1kgKyBjb21wdXRlZFN0eWxlLm92ZXJmbG93WCkpIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaChlbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWwgPSBlbC5wYXJlbnROb2RlO1xuICAgIH1cbiAgICByZXR1cm4gcGFyZW50cztcbn1cblxuLypcblJlY29yZHMgb2Zmc2V0IGluZm9ybWF0aW9uIGZvciBhIHNldCBvZiBlbGVtZW50cywgcmVsYXRpdmUgdG8gYW4gb3JpZ2luIGVsZW1lbnQuXG5DYW4gcmVjb3JkIHRoZSBsZWZ0L3JpZ2h0IE9SIHRoZSB0b3AvYm90dG9tIE9SIGJvdGguXG5Qcm92aWRlcyBtZXRob2RzIGZvciBxdWVyeWluZyB0aGUgY2FjaGUgYnkgcG9zaXRpb24uXG4qL1xuY2xhc3MgUG9zaXRpb25DYWNoZSB7XG4gICAgY29uc3RydWN0b3Iob3JpZ2luRWwsIGVscywgaXNIb3Jpem9udGFsLCBpc1ZlcnRpY2FsKSB7XG4gICAgICAgIHRoaXMuZWxzID0gZWxzO1xuICAgICAgICBsZXQgb3JpZ2luQ2xpZW50UmVjdCA9IHRoaXMub3JpZ2luQ2xpZW50UmVjdCA9IG9yaWdpbkVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyByZWxhdGl2ZSB0byB2aWV3cG9ydCB0b3AtbGVmdFxuICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICB0aGlzLmJ1aWxkRWxIb3Jpem9udGFscyhvcmlnaW5DbGllbnRSZWN0LmxlZnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1ZlcnRpY2FsKSB7XG4gICAgICAgICAgICB0aGlzLmJ1aWxkRWxWZXJ0aWNhbHMob3JpZ2luQ2xpZW50UmVjdC50b3ApO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIFBvcHVsYXRlcyB0aGUgbGVmdC9yaWdodCBpbnRlcm5hbCBjb29yZGluYXRlIGFycmF5c1xuICAgIGJ1aWxkRWxIb3Jpem9udGFscyhvcmlnaW5DbGllbnRMZWZ0KSB7XG4gICAgICAgIGxldCBsZWZ0cyA9IFtdO1xuICAgICAgICBsZXQgcmlnaHRzID0gW107XG4gICAgICAgIGZvciAobGV0IGVsIG9mIHRoaXMuZWxzKSB7XG4gICAgICAgICAgICBsZXQgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgbGVmdHMucHVzaChyZWN0LmxlZnQgLSBvcmlnaW5DbGllbnRMZWZ0KTtcbiAgICAgICAgICAgIHJpZ2h0cy5wdXNoKHJlY3QucmlnaHQgLSBvcmlnaW5DbGllbnRMZWZ0KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxlZnRzID0gbGVmdHM7XG4gICAgICAgIHRoaXMucmlnaHRzID0gcmlnaHRzO1xuICAgIH1cbiAgICAvLyBQb3B1bGF0ZXMgdGhlIHRvcC9ib3R0b20gaW50ZXJuYWwgY29vcmRpbmF0ZSBhcnJheXNcbiAgICBidWlsZEVsVmVydGljYWxzKG9yaWdpbkNsaWVudFRvcCkge1xuICAgICAgICBsZXQgdG9wcyA9IFtdO1xuICAgICAgICBsZXQgYm90dG9tcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBlbCBvZiB0aGlzLmVscykge1xuICAgICAgICAgICAgbGV0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHRvcHMucHVzaChyZWN0LnRvcCAtIG9yaWdpbkNsaWVudFRvcCk7XG4gICAgICAgICAgICBib3R0b21zLnB1c2gocmVjdC5ib3R0b20gLSBvcmlnaW5DbGllbnRUb3ApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudG9wcyA9IHRvcHM7XG4gICAgICAgIHRoaXMuYm90dG9tcyA9IGJvdHRvbXM7XG4gICAgfVxuICAgIC8vIEdpdmVuIGEgbGVmdCBvZmZzZXQgKGZyb20gZG9jdW1lbnQgbGVmdCksIHJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBlbCB0aGF0IGl0IGhvcml6b250YWxseSBpbnRlcnNlY3RzLlxuICAgIC8vIElmIG5vIGludGVyc2VjdGlvbiBpcyBtYWRlLCByZXR1cm5zIHVuZGVmaW5lZC5cbiAgICBsZWZ0VG9JbmRleChsZWZ0UG9zaXRpb24pIHtcbiAgICAgICAgbGV0IHsgbGVmdHMsIHJpZ2h0cyB9ID0gdGhpcztcbiAgICAgICAgbGV0IGxlbiA9IGxlZnRzLmxlbmd0aDtcbiAgICAgICAgbGV0IGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKGxlZnRQb3NpdGlvbiA+PSBsZWZ0c1tpXSAmJiBsZWZ0UG9zaXRpb24gPCByaWdodHNbaV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBUT0RPOiBiZXR0ZXJcbiAgICB9XG4gICAgLy8gR2l2ZW4gYSB0b3Agb2Zmc2V0IChmcm9tIGRvY3VtZW50IHRvcCksIHJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBlbCB0aGF0IGl0IHZlcnRpY2FsbHkgaW50ZXJzZWN0cy5cbiAgICAvLyBJZiBubyBpbnRlcnNlY3Rpb24gaXMgbWFkZSwgcmV0dXJucyB1bmRlZmluZWQuXG4gICAgdG9wVG9JbmRleCh0b3BQb3NpdGlvbikge1xuICAgICAgICBsZXQgeyB0b3BzLCBib3R0b21zIH0gPSB0aGlzO1xuICAgICAgICBsZXQgbGVuID0gdG9wcy5sZW5ndGg7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmICh0b3BQb3NpdGlvbiA+PSB0b3BzW2ldICYmIHRvcFBvc2l0aW9uIDwgYm90dG9tc1tpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7IC8vIFRPRE86IGJldHRlclxuICAgIH1cbiAgICAvLyBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgZWxlbWVudCBhdCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICBnZXRXaWR0aChsZWZ0SW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmlnaHRzW2xlZnRJbmRleF0gLSB0aGlzLmxlZnRzW2xlZnRJbmRleF07XG4gICAgfVxuICAgIC8vIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgZWxlbWVudCBhdCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICBnZXRIZWlnaHQodG9wSW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm90dG9tc1t0b3BJbmRleF0gLSB0aGlzLnRvcHNbdG9wSW5kZXhdO1xuICAgIH1cbiAgICBzaW1pbGFyVG8ob3RoZXJDYWNoZSkge1xuICAgICAgICByZXR1cm4gc2ltaWxhck51bUFycmF5cyh0aGlzLnRvcHMgfHwgW10sIG90aGVyQ2FjaGUudG9wcyB8fCBbXSkgJiZcbiAgICAgICAgICAgIHNpbWlsYXJOdW1BcnJheXModGhpcy5ib3R0b21zIHx8IFtdLCBvdGhlckNhY2hlLmJvdHRvbXMgfHwgW10pICYmXG4gICAgICAgICAgICBzaW1pbGFyTnVtQXJyYXlzKHRoaXMubGVmdHMgfHwgW10sIG90aGVyQ2FjaGUubGVmdHMgfHwgW10pICYmXG4gICAgICAgICAgICBzaW1pbGFyTnVtQXJyYXlzKHRoaXMucmlnaHRzIHx8IFtdLCBvdGhlckNhY2hlLnJpZ2h0cyB8fCBbXSk7XG4gICAgfVxufVxuZnVuY3Rpb24gc2ltaWxhck51bUFycmF5cyhhLCBiKSB7XG4gICAgY29uc3QgbGVuID0gYS5sZW5ndGg7XG4gICAgaWYgKGxlbiAhPT0gYi5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmIChNYXRoLnJvdW5kKGFbaV0pICE9PSBNYXRoLnJvdW5kKGJbaV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbi8qIGVzbGludCBtYXgtY2xhc3Nlcy1wZXItZmlsZTogXCJvZmZcIiAqL1xuLypcbkFuIG9iamVjdCBmb3IgZ2V0dGluZy9zZXR0aW5nIHNjcm9sbC1yZWxhdGVkIGluZm9ybWF0aW9uIGZvciBhbiBlbGVtZW50LlxuSW50ZXJuYWxseSwgdGhpcyBpcyBkb25lIHZlcnkgZGlmZmVyZW50bHkgZm9yIHdpbmRvdyB2ZXJzdXMgRE9NIGVsZW1lbnQsXG5zbyB0aGlzIG9iamVjdCBzZXJ2ZXMgYXMgYSBjb21tb24gaW50ZXJmYWNlLlxuKi9cbmNsYXNzIFNjcm9sbENvbnRyb2xsZXIge1xuICAgIGdldE1heFNjcm9sbFRvcCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KCkgLSB0aGlzLmdldENsaWVudEhlaWdodCgpO1xuICAgIH1cbiAgICBnZXRNYXhTY3JvbGxMZWZ0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxXaWR0aCgpIC0gdGhpcy5nZXRDbGllbnRXaWR0aCgpO1xuICAgIH1cbiAgICBjYW5TY3JvbGxWZXJ0aWNhbGx5KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRNYXhTY3JvbGxUb3AoKSA+IDA7XG4gICAgfVxuICAgIGNhblNjcm9sbEhvcml6b250YWxseSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWF4U2Nyb2xsTGVmdCgpID4gMDtcbiAgICB9XG4gICAgY2FuU2Nyb2xsVXAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFNjcm9sbFRvcCgpID4gMDtcbiAgICB9XG4gICAgY2FuU2Nyb2xsRG93bigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsVG9wKCkgPCB0aGlzLmdldE1heFNjcm9sbFRvcCgpO1xuICAgIH1cbiAgICBjYW5TY3JvbGxMZWZ0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxMZWZ0KCkgPiAwO1xuICAgIH1cbiAgICBjYW5TY3JvbGxSaWdodCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsTGVmdCgpIDwgdGhpcy5nZXRNYXhTY3JvbGxMZWZ0KCk7XG4gICAgfVxufVxuY2xhc3MgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIgZXh0ZW5kcyBTY3JvbGxDb250cm9sbGVyIHtcbiAgICBjb25zdHJ1Y3RvcihlbCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgfVxuICAgIGdldFNjcm9sbFRvcCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuc2Nyb2xsVG9wO1xuICAgIH1cbiAgICBnZXRTY3JvbGxMZWZ0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5zY3JvbGxMZWZ0O1xuICAgIH1cbiAgICBzZXRTY3JvbGxUb3AodG9wKSB7XG4gICAgICAgIHRoaXMuZWwuc2Nyb2xsVG9wID0gdG9wO1xuICAgIH1cbiAgICBzZXRTY3JvbGxMZWZ0KGxlZnQpIHtcbiAgICAgICAgdGhpcy5lbC5zY3JvbGxMZWZ0ID0gbGVmdDtcbiAgICB9XG4gICAgZ2V0U2Nyb2xsV2lkdGgoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbFdpZHRoO1xuICAgIH1cbiAgICBnZXRTY3JvbGxIZWlnaHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbEhlaWdodDtcbiAgICB9XG4gICAgZ2V0Q2xpZW50SGVpZ2h0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5jbGllbnRIZWlnaHQ7XG4gICAgfVxuICAgIGdldENsaWVudFdpZHRoKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5jbGllbnRXaWR0aDtcbiAgICB9XG59XG5jbGFzcyBXaW5kb3dTY3JvbGxDb250cm9sbGVyIGV4dGVuZHMgU2Nyb2xsQ29udHJvbGxlciB7XG4gICAgZ2V0U2Nyb2xsVG9wKCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnNjcm9sbFk7XG4gICAgfVxuICAgIGdldFNjcm9sbExlZnQoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuc2Nyb2xsWDtcbiAgICB9XG4gICAgc2V0U2Nyb2xsVG9wKG4pIHtcbiAgICAgICAgd2luZG93LnNjcm9sbCh3aW5kb3cuc2Nyb2xsWCwgbik7XG4gICAgfVxuICAgIHNldFNjcm9sbExlZnQobikge1xuICAgICAgICB3aW5kb3cuc2Nyb2xsKG4sIHdpbmRvdy5zY3JvbGxZKTtcbiAgICB9XG4gICAgZ2V0U2Nyb2xsV2lkdGgoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsV2lkdGg7XG4gICAgfVxuICAgIGdldFNjcm9sbEhlaWdodCgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQ7XG4gICAgfVxuICAgIGdldENsaWVudEhlaWdodCgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgfVxuICAgIGdldENsaWVudFdpZHRoKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoO1xuICAgIH1cbn1cblxuLypcbmFuIElOVEVSQUNUQUJMRSBkYXRlIGNvbXBvbmVudFxuXG5QVVJQT1NFUzpcbi0gaG9vayB1cCB0byBmZywgZmlsbCwgYW5kIG1pcnJvciByZW5kZXJlcnNcbi0gaW50ZXJmYWNlIGZvciBkcmFnZ2luZyBhbmQgaGl0c1xuKi9cbmNsYXNzIERhdGVDb21wb25lbnQgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy51aWQgPSBndWlkKCk7XG4gICAgfVxuICAgIC8vIEhpdCBTeXN0ZW1cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHByZXBhcmVIaXRzKCkge1xuICAgIH1cbiAgICBxdWVyeUhpdChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wLCBlbFdpZHRoLCBlbEhlaWdodCkge1xuICAgICAgICByZXR1cm4gbnVsbDsgLy8gdGhpcyBzaG91bGQgYmUgYWJzdHJhY3RcbiAgICB9XG4gICAgLy8gUG9pbnRlciBJbnRlcmFjdGlvbiBVdGlsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgaXNWYWxpZFNlZ0Rvd25FbChlbCkge1xuICAgICAgICByZXR1cm4gIXRoaXMucHJvcHMuZXZlbnREcmFnICYmIC8vIEhBQ0tcbiAgICAgICAgICAgICF0aGlzLnByb3BzLmV2ZW50UmVzaXplICYmIC8vIEhBQ0tcbiAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1ldmVudC1taXJyb3InKTtcbiAgICB9XG4gICAgaXNWYWxpZERhdGVEb3duRWwoZWwpIHtcbiAgICAgICAgcmV0dXJuICFlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1ldmVudDpub3QoLmZjLWJnLWV2ZW50KScpICYmXG4gICAgICAgICAgICAhZWxlbWVudENsb3Nlc3QoZWwsICcuZmMtbW9yZS1saW5rJykgJiYgLy8gYSBcIm1vcmUuLlwiIGxpbmtcbiAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChlbCwgJ2FbZGF0YS1uYXZsaW5rXScpICYmIC8vIGEgY2xpY2thYmxlIG5hdiBsaW5rXG4gICAgICAgICAgICAhZWxlbWVudENsb3Nlc3QoZWwsICcuZmMtcG9wb3ZlcicpOyAvLyBoYWNrXG4gICAgfVxufVxuXG5jbGFzcyBOYW1lZFRpbWVab25lSW1wbCB7XG4gICAgY29uc3RydWN0b3IodGltZVpvbmVOYW1lKSB7XG4gICAgICAgIHRoaXMudGltZVpvbmVOYW1lID0gdGltZVpvbmVOYW1lO1xuICAgIH1cbn1cblxuY2xhc3MgU2VnSGllcmFyY2h5IHtcbiAgICBjb25zdHJ1Y3RvcihnZXRFbnRyeVRoaWNrbmVzcyA9IChlbnRyeSkgPT4ge1xuICAgICAgICAvLyBpZiBubyB0aGlja25lc3Mga25vd24sIGFzc3VtZSAxIChpZiAwLCBzbyBzbWFsbCBpdCBhbHdheXMgZml0cylcbiAgICAgICAgcmV0dXJuIGVudHJ5LnRoaWNrbmVzcyB8fCAxO1xuICAgIH0pIHtcbiAgICAgICAgdGhpcy5nZXRFbnRyeVRoaWNrbmVzcyA9IGdldEVudHJ5VGhpY2tuZXNzO1xuICAgICAgICAvLyBzZXR0aW5nc1xuICAgICAgICB0aGlzLnN0cmljdE9yZGVyID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxsb3dSZXNsaWNpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5tYXhDb29yZCA9IC0xOyAvLyAtMSBtZWFucyBubyBtYXhcbiAgICAgICAgdGhpcy5tYXhTdGFja0NudCA9IC0xOyAvLyAtMSBtZWFucyBubyBtYXhcbiAgICAgICAgdGhpcy5sZXZlbENvb3JkcyA9IFtdOyAvLyBvcmRlcmVkXG4gICAgICAgIHRoaXMuZW50cmllc0J5TGV2ZWwgPSBbXTsgLy8gcGFyYWxsZWwgd2l0aCBsZXZlbENvb3Jkc1xuICAgICAgICB0aGlzLnN0YWNrQ250cyA9IHt9OyAvLyBUT0RPOiB1c2UgYmV0dGVyIHRlY2huaXF1ZSE/XG4gICAgfVxuICAgIGFkZFNlZ3MoaW5wdXRzKSB7XG4gICAgICAgIGxldCBoaWRkZW5FbnRyaWVzID0gW107XG4gICAgICAgIGZvciAobGV0IGlucHV0IG9mIGlucHV0cykge1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRFbnRyeShpbnB1dCwgaGlkZGVuRW50cmllcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhpZGRlbkVudHJpZXM7XG4gICAgfVxuICAgIGluc2VydEVudHJ5KGVudHJ5LCBoaWRkZW5FbnRyaWVzKSB7XG4gICAgICAgIGxldCBpbnNlcnRpb24gPSB0aGlzLmZpbmRJbnNlcnRpb24oZW50cnkpO1xuICAgICAgICBpZiAodGhpcy5pc0luc2VydGlvblZhbGlkKGluc2VydGlvbiwgZW50cnkpKSB7XG4gICAgICAgICAgICB0aGlzLmluc2VydEVudHJ5QXQoZW50cnksIGluc2VydGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUludmFsaWRJbnNlcnRpb24oaW5zZXJ0aW9uLCBlbnRyeSwgaGlkZGVuRW50cmllcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaXNJbnNlcnRpb25WYWxpZChpbnNlcnRpb24sIGVudHJ5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5tYXhDb29yZCA9PT0gLTEgfHwgaW5zZXJ0aW9uLmxldmVsQ29vcmQgKyB0aGlzLmdldEVudHJ5VGhpY2tuZXNzKGVudHJ5KSA8PSB0aGlzLm1heENvb3JkKSAmJlxuICAgICAgICAgICAgKHRoaXMubWF4U3RhY2tDbnQgPT09IC0xIHx8IGluc2VydGlvbi5zdGFja0NudCA8IHRoaXMubWF4U3RhY2tDbnQpO1xuICAgIH1cbiAgICBoYW5kbGVJbnZhbGlkSW5zZXJ0aW9uKGluc2VydGlvbiwgZW50cnksIGhpZGRlbkVudHJpZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuYWxsb3dSZXNsaWNpbmcgJiYgaW5zZXJ0aW9uLnRvdWNoaW5nRW50cnkpIHtcbiAgICAgICAgICAgIGNvbnN0IGhpZGRlbkVudHJ5ID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBlbnRyeSksIHsgc3BhbjogaW50ZXJzZWN0U3BhbnMoZW50cnkuc3BhbiwgaW5zZXJ0aW9uLnRvdWNoaW5nRW50cnkuc3BhbikgfSk7XG4gICAgICAgICAgICBoaWRkZW5FbnRyaWVzLnB1c2goaGlkZGVuRW50cnkpO1xuICAgICAgICAgICAgdGhpcy5zcGxpdEVudHJ5KGVudHJ5LCBpbnNlcnRpb24udG91Y2hpbmdFbnRyeSwgaGlkZGVuRW50cmllcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBoaWRkZW5FbnRyaWVzLnB1c2goZW50cnkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qXG4gICAgRG9lcyBOT1QgYWRkIHdoYXQgaGl0IHRoZSBgYmFycmllcmAgaW50byBoaWRkZW5FbnRyaWVzLiBTaG91bGQgYWxyZWFkeSBiZSBkb25lLlxuICAgICovXG4gICAgc3BsaXRFbnRyeShlbnRyeSwgYmFycmllciwgaGlkZGVuRW50cmllcykge1xuICAgICAgICBsZXQgZW50cnlTcGFuID0gZW50cnkuc3BhbjtcbiAgICAgICAgbGV0IGJhcnJpZXJTcGFuID0gYmFycmllci5zcGFuO1xuICAgICAgICBpZiAoZW50cnlTcGFuLnN0YXJ0IDwgYmFycmllclNwYW4uc3RhcnQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0RW50cnkoe1xuICAgICAgICAgICAgICAgIGluZGV4OiBlbnRyeS5pbmRleCxcbiAgICAgICAgICAgICAgICB0aGlja25lc3M6IGVudHJ5LnRoaWNrbmVzcyxcbiAgICAgICAgICAgICAgICBzcGFuOiB7IHN0YXJ0OiBlbnRyeVNwYW4uc3RhcnQsIGVuZDogYmFycmllclNwYW4uc3RhcnQgfSxcbiAgICAgICAgICAgIH0sIGhpZGRlbkVudHJpZXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbnRyeVNwYW4uZW5kID4gYmFycmllclNwYW4uZW5kKSB7XG4gICAgICAgICAgICB0aGlzLmluc2VydEVudHJ5KHtcbiAgICAgICAgICAgICAgICBpbmRleDogZW50cnkuaW5kZXgsXG4gICAgICAgICAgICAgICAgdGhpY2tuZXNzOiBlbnRyeS50aGlja25lc3MsXG4gICAgICAgICAgICAgICAgc3BhbjogeyBzdGFydDogYmFycmllclNwYW4uZW5kLCBlbmQ6IGVudHJ5U3Bhbi5lbmQgfSxcbiAgICAgICAgICAgIH0sIGhpZGRlbkVudHJpZXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGluc2VydEVudHJ5QXQoZW50cnksIGluc2VydGlvbikge1xuICAgICAgICBsZXQgeyBlbnRyaWVzQnlMZXZlbCwgbGV2ZWxDb29yZHMgfSA9IHRoaXM7XG4gICAgICAgIGlmIChpbnNlcnRpb24ubGF0ZXJhbCA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGNyZWF0ZSBhIG5ldyBsZXZlbFxuICAgICAgICAgICAgaW5zZXJ0QXQobGV2ZWxDb29yZHMsIGluc2VydGlvbi5sZXZlbCwgaW5zZXJ0aW9uLmxldmVsQ29vcmQpO1xuICAgICAgICAgICAgaW5zZXJ0QXQoZW50cmllc0J5TGV2ZWwsIGluc2VydGlvbi5sZXZlbCwgW2VudHJ5XSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBpbnNlcnQgaW50byBleGlzdGluZyBsZXZlbFxuICAgICAgICAgICAgaW5zZXJ0QXQoZW50cmllc0J5TGV2ZWxbaW5zZXJ0aW9uLmxldmVsXSwgaW5zZXJ0aW9uLmxhdGVyYWwsIGVudHJ5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YWNrQ250c1tidWlsZEVudHJ5S2V5KGVudHJ5KV0gPSBpbnNlcnRpb24uc3RhY2tDbnQ7XG4gICAgfVxuICAgIC8qXG4gICAgZG9lcyBub3QgY2FyZSBhYm91dCBsaW1pdHNcbiAgICAqL1xuICAgIGZpbmRJbnNlcnRpb24obmV3RW50cnkpIHtcbiAgICAgICAgbGV0IHsgbGV2ZWxDb29yZHMsIGVudHJpZXNCeUxldmVsLCBzdHJpY3RPcmRlciwgc3RhY2tDbnRzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgbGV2ZWxDbnQgPSBsZXZlbENvb3Jkcy5sZW5ndGg7XG4gICAgICAgIGxldCBjYW5kaWRhdGVDb29yZCA9IDA7XG4gICAgICAgIGxldCB0b3VjaGluZ0xldmVsID0gLTE7XG4gICAgICAgIGxldCB0b3VjaGluZ0xhdGVyYWwgPSAtMTtcbiAgICAgICAgbGV0IHRvdWNoaW5nRW50cnkgPSBudWxsO1xuICAgICAgICBsZXQgc3RhY2tDbnQgPSAwO1xuICAgICAgICBmb3IgKGxldCB0cmFja2luZ0xldmVsID0gMDsgdHJhY2tpbmdMZXZlbCA8IGxldmVsQ250OyB0cmFja2luZ0xldmVsICs9IDEpIHtcbiAgICAgICAgICAgIGNvbnN0IHRyYWNraW5nQ29vcmQgPSBsZXZlbENvb3Jkc1t0cmFja2luZ0xldmVsXTtcbiAgICAgICAgICAgIC8vIGlmIHRoZSBjdXJyZW50IGxldmVsIGlzIHBhc3QgdGhlIHBsYWNlZCBlbnRyeSwgd2UgaGF2ZSBmb3VuZCBhIGdvb2QgZW1wdHkgc3BhY2UgYW5kIGNhbiBzdG9wLlxuICAgICAgICAgICAgLy8gaWYgc3RyaWN0T3JkZXIsIGtlZXAgZmluZGluZyBtb3JlIGxhdGVyYWwgaW50ZXJzZWN0aW9ucy5cbiAgICAgICAgICAgIGlmICghc3RyaWN0T3JkZXIgJiYgdHJhY2tpbmdDb29yZCA+PSBjYW5kaWRhdGVDb29yZCArIHRoaXMuZ2V0RW50cnlUaGlja25lc3MobmV3RW50cnkpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdHJhY2tpbmdFbnRyaWVzID0gZW50cmllc0J5TGV2ZWxbdHJhY2tpbmdMZXZlbF07XG4gICAgICAgICAgICBsZXQgdHJhY2tpbmdFbnRyeTtcbiAgICAgICAgICAgIGxldCBzZWFyY2hSZXMgPSBiaW5hcnlTZWFyY2godHJhY2tpbmdFbnRyaWVzLCBuZXdFbnRyeS5zcGFuLnN0YXJ0LCBnZXRFbnRyeVNwYW5FbmQpOyAvLyBmaW5kIGZpcnN0IGVudHJ5IGFmdGVyIG5ld0VudHJ5J3MgZW5kXG4gICAgICAgICAgICBsZXQgbGF0ZXJhbEluZGV4ID0gc2VhcmNoUmVzWzBdICsgc2VhcmNoUmVzWzFdOyAvLyBpZiBleGFjdCBtYXRjaCAod2hpY2ggZG9lc24ndCBjb2xsaWRlKSwgZ28gdG8gbmV4dCBvbmVcbiAgICAgICAgICAgIHdoaWxlICggLy8gbG9vcCB0aHJvdWdoIGVudHJpZXMgdGhhdCBob3Jpem9udGFsbHkgaW50ZXJzZWN0XG4gICAgICAgICAgICAodHJhY2tpbmdFbnRyeSA9IHRyYWNraW5nRW50cmllc1tsYXRlcmFsSW5kZXhdKSAmJiAvLyBidXQgbm90IHBhc3QgdGhlIHdob2xlIGVudHJ5IGxpc3RcbiAgICAgICAgICAgICAgICB0cmFja2luZ0VudHJ5LnNwYW4uc3RhcnQgPCBuZXdFbnRyeS5zcGFuLmVuZCAvLyBhbmQgbm90IGVudGlyZWx5IHBhc3QgbmV3RW50cnlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGxldCB0cmFja2luZ0VudHJ5Qm90dG9tID0gdHJhY2tpbmdDb29yZCArIHRoaXMuZ2V0RW50cnlUaGlja25lc3ModHJhY2tpbmdFbnRyeSk7XG4gICAgICAgICAgICAgICAgLy8gaW50ZXJzZWN0cyBpbnRvIHRoZSB0b3Agb2YgdGhlIGNhbmRpZGF0ZT9cbiAgICAgICAgICAgICAgICBpZiAodHJhY2tpbmdFbnRyeUJvdHRvbSA+IGNhbmRpZGF0ZUNvb3JkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZUNvb3JkID0gdHJhY2tpbmdFbnRyeUJvdHRvbTtcbiAgICAgICAgICAgICAgICAgICAgdG91Y2hpbmdFbnRyeSA9IHRyYWNraW5nRW50cnk7XG4gICAgICAgICAgICAgICAgICAgIHRvdWNoaW5nTGV2ZWwgPSB0cmFja2luZ0xldmVsO1xuICAgICAgICAgICAgICAgICAgICB0b3VjaGluZ0xhdGVyYWwgPSBsYXRlcmFsSW5kZXg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGJ1dHRzIHVwIGFnYWluc3QgdG9wIG9mIGNhbmRpZGF0ZT8gKHdpbGwgaGFwcGVuIGlmIGp1c3QgaW50ZXJzZWN0ZWQgYXMgd2VsbClcbiAgICAgICAgICAgICAgICBpZiAodHJhY2tpbmdFbnRyeUJvdHRvbSA9PT0gY2FuZGlkYXRlQ29vcmQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYWNjdW11bGF0ZSB0aGUgaGlnaGVzdCBwb3NzaWJsZSBzdGFja0NudCBvZiB0aGUgdHJhY2tpbmdFbnRyaWVzIHRoYXQgYnV0dCB1cFxuICAgICAgICAgICAgICAgICAgICBzdGFja0NudCA9IE1hdGgubWF4KHN0YWNrQ250LCBzdGFja0NudHNbYnVpbGRFbnRyeUtleSh0cmFja2luZ0VudHJ5KV0gKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGF0ZXJhbEluZGV4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlIGRlc3RpbmF0aW9uIGxldmVsIHdpbGwgYmUgYWZ0ZXIgdG91Y2hpbmdFbnRyeSdzIGxldmVsLiBmaW5kIGl0XG4gICAgICAgIGxldCBkZXN0TGV2ZWwgPSAwO1xuICAgICAgICBpZiAodG91Y2hpbmdFbnRyeSkge1xuICAgICAgICAgICAgZGVzdExldmVsID0gdG91Y2hpbmdMZXZlbCArIDE7XG4gICAgICAgICAgICB3aGlsZSAoZGVzdExldmVsIDwgbGV2ZWxDbnQgJiYgbGV2ZWxDb29yZHNbZGVzdExldmVsXSA8IGNhbmRpZGF0ZUNvb3JkKSB7XG4gICAgICAgICAgICAgICAgZGVzdExldmVsICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgYWRkaW5nIHRvIGFuIGV4aXN0aW5nIGxldmVsLCBmaW5kIHdoZXJlIHRvIGluc2VydFxuICAgICAgICBsZXQgZGVzdExhdGVyYWwgPSAtMTtcbiAgICAgICAgaWYgKGRlc3RMZXZlbCA8IGxldmVsQ250ICYmIGxldmVsQ29vcmRzW2Rlc3RMZXZlbF0gPT09IGNhbmRpZGF0ZUNvb3JkKSB7XG4gICAgICAgICAgICBkZXN0TGF0ZXJhbCA9IGJpbmFyeVNlYXJjaChlbnRyaWVzQnlMZXZlbFtkZXN0TGV2ZWxdLCBuZXdFbnRyeS5zcGFuLmVuZCwgZ2V0RW50cnlTcGFuRW5kKVswXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdG91Y2hpbmdMZXZlbCxcbiAgICAgICAgICAgIHRvdWNoaW5nTGF0ZXJhbCxcbiAgICAgICAgICAgIHRvdWNoaW5nRW50cnksXG4gICAgICAgICAgICBzdGFja0NudCxcbiAgICAgICAgICAgIGxldmVsQ29vcmQ6IGNhbmRpZGF0ZUNvb3JkLFxuICAgICAgICAgICAgbGV2ZWw6IGRlc3RMZXZlbCxcbiAgICAgICAgICAgIGxhdGVyYWw6IGRlc3RMYXRlcmFsLFxuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBzb3J0ZWQgYnkgbGV2ZWxDb29yZCAobG93ZXN0IHRvIGhpZ2hlc3QpXG4gICAgdG9SZWN0cygpIHtcbiAgICAgICAgbGV0IHsgZW50cmllc0J5TGV2ZWwsIGxldmVsQ29vcmRzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgbGV2ZWxDbnQgPSBlbnRyaWVzQnlMZXZlbC5sZW5ndGg7XG4gICAgICAgIGxldCByZWN0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBsZXZlbCA9IDA7IGxldmVsIDwgbGV2ZWxDbnQ7IGxldmVsICs9IDEpIHtcbiAgICAgICAgICAgIGxldCBlbnRyaWVzID0gZW50cmllc0J5TGV2ZWxbbGV2ZWxdO1xuICAgICAgICAgICAgbGV0IGxldmVsQ29vcmQgPSBsZXZlbENvb3Jkc1tsZXZlbF07XG4gICAgICAgICAgICBmb3IgKGxldCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgcmVjdHMucHVzaChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGVudHJ5KSwgeyB0aGlja25lc3M6IHRoaXMuZ2V0RW50cnlUaGlja25lc3MoZW50cnkpLCBsZXZlbENvb3JkIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVjdHM7XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0RW50cnlTcGFuRW5kKGVudHJ5KSB7XG4gICAgcmV0dXJuIGVudHJ5LnNwYW4uZW5kO1xufVxuZnVuY3Rpb24gYnVpbGRFbnRyeUtleShlbnRyeSkge1xuICAgIHJldHVybiBlbnRyeS5pbmRleCArICc6JyArIGVudHJ5LnNwYW4uc3RhcnQ7XG59XG4vLyByZXR1cm5zIGdyb3VwcyB3aXRoIGVudHJpZXMgc29ydGVkIGJ5IGlucHV0IG9yZGVyXG5mdW5jdGlvbiBncm91cEludGVyc2VjdGluZ0VudHJpZXMoZW50cmllcykge1xuICAgIGxldCBtZXJnZXMgPSBbXTtcbiAgICBmb3IgKGxldCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICAgIGxldCBmaWx0ZXJlZE1lcmdlcyA9IFtdO1xuICAgICAgICBsZXQgaHVuZ3J5TWVyZ2UgPSB7XG4gICAgICAgICAgICBzcGFuOiBlbnRyeS5zcGFuLFxuICAgICAgICAgICAgZW50cmllczogW2VudHJ5XSxcbiAgICAgICAgfTtcbiAgICAgICAgZm9yIChsZXQgbWVyZ2Ugb2YgbWVyZ2VzKSB7XG4gICAgICAgICAgICBpZiAoaW50ZXJzZWN0U3BhbnMobWVyZ2Uuc3BhbiwgaHVuZ3J5TWVyZ2Uuc3BhbikpIHtcbiAgICAgICAgICAgICAgICBodW5ncnlNZXJnZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZW50cmllczogbWVyZ2UuZW50cmllcy5jb25jYXQoaHVuZ3J5TWVyZ2UuZW50cmllcyksXG4gICAgICAgICAgICAgICAgICAgIHNwYW46IGpvaW5TcGFucyhtZXJnZS5zcGFuLCBodW5ncnlNZXJnZS5zcGFuKSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZmlsdGVyZWRNZXJnZXMucHVzaChtZXJnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZmlsdGVyZWRNZXJnZXMucHVzaChodW5ncnlNZXJnZSk7XG4gICAgICAgIG1lcmdlcyA9IGZpbHRlcmVkTWVyZ2VzO1xuICAgIH1cbiAgICByZXR1cm4gbWVyZ2VzO1xufVxuZnVuY3Rpb24gam9pblNwYW5zKHNwYW4wLCBzcGFuMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiBNYXRoLm1pbihzcGFuMC5zdGFydCwgc3BhbjEuc3RhcnQpLFxuICAgICAgICBlbmQ6IE1hdGgubWF4KHNwYW4wLmVuZCwgc3BhbjEuZW5kKSxcbiAgICB9O1xufVxuZnVuY3Rpb24gaW50ZXJzZWN0U3BhbnMoc3BhbjAsIHNwYW4xKSB7XG4gICAgbGV0IHN0YXJ0ID0gTWF0aC5tYXgoc3BhbjAuc3RhcnQsIHNwYW4xLnN0YXJ0KTtcbiAgICBsZXQgZW5kID0gTWF0aC5taW4oc3BhbjAuZW5kLCBzcGFuMS5lbmQpO1xuICAgIGlmIChzdGFydCA8IGVuZCkge1xuICAgICAgICByZXR1cm4geyBzdGFydCwgZW5kIH07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuLy8gZ2VuZXJhbCB1dGlsXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGluc2VydEF0KGFyciwgaW5kZXgsIGl0ZW0pIHtcbiAgICBhcnIuc3BsaWNlKGluZGV4LCAwLCBpdGVtKTtcbn1cbmZ1bmN0aW9uIGJpbmFyeVNlYXJjaChhLCBzZWFyY2hWYWwsIGdldEl0ZW1WYWwpIHtcbiAgICBsZXQgc3RhcnRJbmRleCA9IDA7XG4gICAgbGV0IGVuZEluZGV4ID0gYS5sZW5ndGg7IC8vIGV4Y2x1c2l2ZVxuICAgIGlmICghZW5kSW5kZXggfHwgc2VhcmNoVmFsIDwgZ2V0SXRlbVZhbChhW3N0YXJ0SW5kZXhdKSkgeyAvLyBubyBpdGVtcyBPUiBiZWZvcmUgZmlyc3QgaXRlbVxuICAgICAgICByZXR1cm4gWzAsIDBdO1xuICAgIH1cbiAgICBpZiAoc2VhcmNoVmFsID4gZ2V0SXRlbVZhbChhW2VuZEluZGV4IC0gMV0pKSB7IC8vIGFmdGVyIGxhc3QgaXRlbVxuICAgICAgICByZXR1cm4gW2VuZEluZGV4LCAwXTtcbiAgICB9XG4gICAgd2hpbGUgKHN0YXJ0SW5kZXggPCBlbmRJbmRleCkge1xuICAgICAgICBsZXQgbWlkZGxlSW5kZXggPSBNYXRoLmZsb29yKHN0YXJ0SW5kZXggKyAoZW5kSW5kZXggLSBzdGFydEluZGV4KSAvIDIpO1xuICAgICAgICBsZXQgbWlkZGxlVmFsID0gZ2V0SXRlbVZhbChhW21pZGRsZUluZGV4XSk7XG4gICAgICAgIGlmIChzZWFyY2hWYWwgPCBtaWRkbGVWYWwpIHtcbiAgICAgICAgICAgIGVuZEluZGV4ID0gbWlkZGxlSW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoc2VhcmNoVmFsID4gbWlkZGxlVmFsKSB7XG4gICAgICAgICAgICBzdGFydEluZGV4ID0gbWlkZGxlSW5kZXggKyAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgeyAvLyBlcXVhbCFcbiAgICAgICAgICAgIHJldHVybiBbbWlkZGxlSW5kZXgsIDFdO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBbc3RhcnRJbmRleCwgMF07XG59XG5cbi8qXG5BbiBhYnN0cmFjdGlvbiBmb3IgYSBkcmFnZ2luZyBpbnRlcmFjdGlvbiBvcmlnaW5hdGluZyBvbiBhbiBldmVudC5cbkRvZXMgaGlnaGVyLWxldmVsIHRoaW5ncyB0aGFuIFBvaW50ZXJEcmFnZ2VyLCBzdWNoIGFzIHBvc3NpYmx5OlxuLSBhIFwibWlycm9yXCIgdGhhdCBtb3ZlcyB3aXRoIHRoZSBwb2ludGVyXG4tIGEgbWluaW11bSBudW1iZXIgb2YgcGl4ZWxzIG9yIG90aGVyIGNyaXRlcmlhIGZvciBhIHRydWUgZHJhZyB0byBiZWdpblxuXG5zdWJjbGFzc2VzIG11c3QgZW1pdDpcbi0gcG9pbnRlcmRvd25cbi0gZHJhZ3N0YXJ0XG4tIGRyYWdtb3ZlXG4tIHBvaW50ZXJ1cFxuLSBkcmFnZW5kXG4qL1xuY2xhc3MgRWxlbWVudERyYWdnaW5nIHtcbiAgICBjb25zdHJ1Y3RvcihlbCwgc2VsZWN0b3IpIHtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICB9XG4gICAgc2V0TWlycm9ySXNWaXNpYmxlKGJvb2wpIHtcbiAgICAgICAgLy8gb3B0aW9uYWwgaWYgc3ViY2xhc3MgZG9lc24ndCB3YW50IHRvIHN1cHBvcnQgYSBtaXJyb3JcbiAgICB9XG4gICAgc2V0TWlycm9yTmVlZHNSZXZlcnQoYm9vbCkge1xuICAgICAgICAvLyBvcHRpb25hbCBpZiBzdWJjbGFzcyBkb2Vzbid0IHdhbnQgdG8gc3VwcG9ydCBhIG1pcnJvclxuICAgIH1cbiAgICBzZXRBdXRvU2Nyb2xsRW5hYmxlZChib29sKSB7XG4gICAgICAgIC8vIG9wdGlvbmFsXG4gICAgfVxufVxuXG4vLyBUT0RPOiBnZXQgcmlkIG9mIHRoaXMgaW4gZmF2b3Igb2Ygb3B0aW9ucyBzeXN0ZW0sXG4vLyB0aG8gaXQncyByZWFsbHkgZWFzeSB0byBhY2Nlc3MgdGhpcyBnbG9iYWxseSByYXRoZXIgdGhhbiBwYXNzIHRocnUgb3B0aW9ucy5cbmNvbnN0IGNvbmZpZyA9IHt9O1xuXG4vKlxuSW5mb3JtYXRpb24gYWJvdXQgd2hhdCB3aWxsIGhhcHBlbiB3aGVuIGFuIGV4dGVybmFsIGVsZW1lbnQgaXMgZHJhZ2dlZC1hbmQtZHJvcHBlZFxub250byBhIGNhbGVuZGFyLiBDb250YWlucyBpbmZvcm1hdGlvbiBmb3IgY3JlYXRpbmcgYW4gZXZlbnQuXG4qL1xuY29uc3QgRFJBR19NRVRBX1JFRklORVJTID0ge1xuICAgIHN0YXJ0VGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgZHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIGNyZWF0ZTogQm9vbGVhbixcbiAgICBzb3VyY2VJZDogU3RyaW5nLFxufTtcbmZ1bmN0aW9uIHBhcnNlRHJhZ01ldGEocmF3KSB7XG4gICAgbGV0IHsgcmVmaW5lZCwgZXh0cmEgfSA9IHJlZmluZVByb3BzKHJhdywgRFJBR19NRVRBX1JFRklORVJTKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydFRpbWU6IHJlZmluZWQuc3RhcnRUaW1lIHx8IG51bGwsXG4gICAgICAgIGR1cmF0aW9uOiByZWZpbmVkLmR1cmF0aW9uIHx8IG51bGwsXG4gICAgICAgIGNyZWF0ZTogcmVmaW5lZC5jcmVhdGUgIT0gbnVsbCA/IHJlZmluZWQuY3JlYXRlIDogdHJ1ZSxcbiAgICAgICAgc291cmNlSWQ6IHJlZmluZWQuc291cmNlSWQsXG4gICAgICAgIGxlZnRvdmVyUHJvcHM6IGV4dHJhLFxuICAgIH07XG59XG5cbi8vIENvbXB1dGVzIGEgZGVmYXVsdCBjb2x1bW4gaGVhZGVyIGZvcm1hdHRpbmcgc3RyaW5nIGlmIGBjb2xGb3JtYXRgIGlzIG5vdCBleHBsaWNpdGx5IGRlZmluZWRcbmZ1bmN0aW9uIGNvbXB1dGVGYWxsYmFja0hlYWRlckZvcm1hdChkYXRlc1JlcERpc3RpbmN0RGF5cywgZGF5Q250KSB7XG4gICAgLy8gaWYgbW9yZSB0aGFuIG9uZSB3ZWVrIHJvdywgb3IgaWYgdGhlcmUgYXJlIGEgbG90IG9mIGNvbHVtbnMgd2l0aCBub3QgbXVjaCBzcGFjZSxcbiAgICAvLyBwdXQganVzdCB0aGUgZGF5IG51bWJlcnMgd2lsbCBiZSBpbiBlYWNoIGNlbGxcbiAgICBpZiAoIWRhdGVzUmVwRGlzdGluY3REYXlzIHx8IGRheUNudCA+IDEwKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrZGF5OiAnc2hvcnQnIH0pOyAvLyBcIlNhdFwiXG4gICAgfVxuICAgIGlmIChkYXlDbnQgPiAxKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrZGF5OiAnc2hvcnQnLCBtb250aDogJ251bWVyaWMnLCBkYXk6ICdudW1lcmljJywgb21pdENvbW1hczogdHJ1ZSB9KTsgLy8gXCJTYXQgMTEvMTJcIlxuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlRm9ybWF0dGVyKHsgd2Vla2RheTogJ2xvbmcnIH0pOyAvLyBcIlNhdHVyZGF5XCJcbn1cblxuY29uc3QgQ0xBU1NfTkFNRSA9ICdmYy1jb2wtaGVhZGVyLWNlbGwnOyAvLyBkbyB0aGUgY3VzaGlvbiB0b28/IG5vXG5mdW5jdGlvbiByZW5kZXJJbm5lciQxKHJlbmRlclByb3BzKSB7XG4gICAgcmV0dXJuIHJlbmRlclByb3BzLnRleHQ7XG59XG5cbi8vIEJBRCBuYW1lIGZvciB0aGlzIGNsYXNzIG5vdy4gdXNlZCBpbiB0aGUgSGVhZGVyXG5jbGFzcyBUYWJsZURhdGVDZWxsIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBkYXRlRW52LCBvcHRpb25zLCB0aGVtZSwgdmlld0FwaSB9ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgZGF0ZSwgZGF0ZVByb2ZpbGUgfSA9IHByb3BzO1xuICAgICAgICBsZXQgZGF5TWV0YSA9IGdldERhdGVNZXRhKGRhdGUsIHByb3BzLnRvZGF5UmFuZ2UsIG51bGwsIGRhdGVQcm9maWxlKTtcbiAgICAgICAgbGV0IGNsYXNzTmFtZXMgPSBbQ0xBU1NfTkFNRV0uY29uY2F0KGdldERheUNsYXNzTmFtZXMoZGF5TWV0YSwgdGhlbWUpKTtcbiAgICAgICAgbGV0IHRleHQgPSBkYXRlRW52LmZvcm1hdChkYXRlLCBwcm9wcy5kYXlIZWFkZXJGb3JtYXQpO1xuICAgICAgICAvLyBpZiBjb2xDbnQgaXMgMSwgd2UgYXJlIGFscmVhZHkgaW4gYSBkYXktdmlldyBhbmQgZG9uJ3QgbmVlZCBhIG5hdmxpbmtcbiAgICAgICAgbGV0IG5hdkxpbmtBdHRycyA9ICghZGF5TWV0YS5pc0Rpc2FibGVkICYmIHByb3BzLmNvbENudCA+IDEpXG4gICAgICAgICAgICA/IGJ1aWxkTmF2TGlua0F0dHJzKHRoaXMuY29udGV4dCwgZGF0ZSlcbiAgICAgICAgICAgIDoge307XG4gICAgICAgIGxldCBwdWJsaWNEYXRlID0gZGF0ZUVudi50b0RhdGUoZGF0ZSk7XG4gICAgICAgIC8vIHdvcmthcm91bmQgZm9yIEx1eG9uIChhbmQgbWF5YmUgbW9tZW50KSByZXR1cm5pbmcgcHJpb3ItZGF5cyB3aGVuIHN0YXJ0LW9mLWRheVxuICAgICAgICAvLyBpbiBEU1QgZ2FwOiBodHRwczovL2dpdGh1Yi5jb20vZnVsbGNhbGVuZGFyL2Z1bGxjYWxlbmRhci9pc3N1ZXMvNzYzM1xuICAgICAgICBpZiAoZGF0ZUVudi5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcHVibGljRGF0ZSA9IGFkZE1zKHB1YmxpY0RhdGUsIDM2MDAwMDApOyAvLyBhZGQgYW4gaG91clxuICAgICAgICB9XG4gICAgICAgIGxldCByZW5kZXJQcm9wcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHsgZGF0ZTogcHVibGljRGF0ZSwgdmlldzogdmlld0FwaSB9LCBwcm9wcy5leHRyYVJlbmRlclByb3BzKSwgeyB0ZXh0IH0pLCBkYXlNZXRhKTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KENvbnRlbnRDb250YWluZXIsIHsgZWxUYWc6IFwidGhcIiwgZWxDbGFzc2VzOiBjbGFzc05hbWVzLCBlbEF0dHJzOiBPYmplY3QuYXNzaWduKHsgcm9sZTogJ2NvbHVtbmhlYWRlcicsIGNvbFNwYW46IHByb3BzLmNvbFNwYW4sICdkYXRhLWRhdGUnOiAhZGF5TWV0YS5pc0Rpc2FibGVkID8gZm9ybWF0RGF5U3RyaW5nKGRhdGUpIDogdW5kZWZpbmVkIH0sIHByb3BzLmV4dHJhRGF0YUF0dHJzKSwgcmVuZGVyUHJvcHM6IHJlbmRlclByb3BzLCBnZW5lcmF0b3JOYW1lOiBcImRheUhlYWRlckNvbnRlbnRcIiwgY3VzdG9tR2VuZXJhdG9yOiBvcHRpb25zLmRheUhlYWRlckNvbnRlbnQsIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlcklubmVyJDEsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5kYXlIZWFkZXJDbGFzc05hbWVzLCBkaWRNb3VudDogb3B0aW9ucy5kYXlIZWFkZXJEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMuZGF5SGVhZGVyV2lsbFVubW91bnQgfSwgKElubmVyQ29udGFpbmVyKSA9PiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy1zY3JvbGxncmlkLXN5bmMtaW5uZXJcIiB9LCAhZGF5TWV0YS5pc0Rpc2FibGVkICYmIChjcmVhdGVFbGVtZW50KElubmVyQ29udGFpbmVyLCB7IGVsVGFnOiBcImFcIiwgZWxBdHRyczogbmF2TGlua0F0dHJzLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAnZmMtY29sLWhlYWRlci1jZWxsLWN1c2hpb24nLFxuICAgICAgICAgICAgICAgIHByb3BzLmlzU3RpY2t5ICYmICdmYy1zdGlja3knLFxuICAgICAgICAgICAgXSB9KSkpKSkpO1xuICAgIH1cbn1cblxuY29uc3QgV0VFS0RBWV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrZGF5OiAnbG9uZycgfSk7XG5jbGFzcyBUYWJsZURvd0NlbGwgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBkYXRlRW52LCB0aGVtZSwgdmlld0FwaSwgb3B0aW9ucyB9ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBsZXQgZGF0ZSA9IGFkZERheXMobmV3IERhdGUoMjU5MjAwMDAwKSwgcHJvcHMuZG93KTsgLy8gc3RhcnQgd2l0aCBTdW4sIDA0IEphbiAxOTcwIDAwOjAwOjAwIEdNVFxuICAgICAgICBsZXQgZGF0ZU1ldGEgPSB7XG4gICAgICAgICAgICBkb3c6IHByb3BzLmRvdyxcbiAgICAgICAgICAgIGlzRGlzYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgICAgaXNGdXR1cmU6IGZhbHNlLFxuICAgICAgICAgICAgaXNQYXN0OiBmYWxzZSxcbiAgICAgICAgICAgIGlzVG9kYXk6IGZhbHNlLFxuICAgICAgICAgICAgaXNPdGhlcjogZmFsc2UsXG4gICAgICAgIH07XG4gICAgICAgIGxldCB0ZXh0ID0gZGF0ZUVudi5mb3JtYXQoZGF0ZSwgcHJvcHMuZGF5SGVhZGVyRm9ybWF0KTtcbiAgICAgICAgbGV0IHJlbmRlclByb3BzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7IC8vIFRPRE86IG1ha2UgdGhpcyBwdWJsaWM/XG4gICAgICAgICAgICBkYXRlIH0sIGRhdGVNZXRhKSwgeyB2aWV3OiB2aWV3QXBpIH0pLCBwcm9wcy5leHRyYVJlbmRlclByb3BzKSwgeyB0ZXh0IH0pO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoQ29udGVudENvbnRhaW5lciwgeyBlbFRhZzogXCJ0aFwiLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICBDTEFTU19OQU1FLFxuICAgICAgICAgICAgICAgIC4uLmdldERheUNsYXNzTmFtZXMoZGF0ZU1ldGEsIHRoZW1lKSxcbiAgICAgICAgICAgICAgICAuLi4ocHJvcHMuZXh0cmFDbGFzc05hbWVzIHx8IFtdKSxcbiAgICAgICAgICAgIF0sIGVsQXR0cnM6IE9iamVjdC5hc3NpZ24oeyByb2xlOiAnY29sdW1uaGVhZGVyJywgY29sU3BhbjogcHJvcHMuY29sU3BhbiB9LCBwcm9wcy5leHRyYURhdGFBdHRycyksIHJlbmRlclByb3BzOiByZW5kZXJQcm9wcywgZ2VuZXJhdG9yTmFtZTogXCJkYXlIZWFkZXJDb250ZW50XCIsIGN1c3RvbUdlbmVyYXRvcjogb3B0aW9ucy5kYXlIZWFkZXJDb250ZW50LCBkZWZhdWx0R2VuZXJhdG9yOiByZW5kZXJJbm5lciQxLCBjbGFzc05hbWVHZW5lcmF0b3I6IG9wdGlvbnMuZGF5SGVhZGVyQ2xhc3NOYW1lcywgZGlkTW91bnQ6IG9wdGlvbnMuZGF5SGVhZGVyRGlkTW91bnQsIHdpbGxVbm1vdW50OiBvcHRpb25zLmRheUhlYWRlcldpbGxVbm1vdW50IH0sIChJbm5lckNvbnRlbnQpID0+IChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXNjcm9sbGdyaWQtc3luYy1pbm5lclwiIH0sXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KElubmVyQ29udGVudCwgeyBlbFRhZzogXCJhXCIsIGVsQ2xhc3NlczogW1xuICAgICAgICAgICAgICAgICAgICAnZmMtY29sLWhlYWRlci1jZWxsLWN1c2hpb24nLFxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5pc1N0aWNreSAmJiAnZmMtc3RpY2t5JyxcbiAgICAgICAgICAgICAgICBdLCBlbEF0dHJzOiB7XG4gICAgICAgICAgICAgICAgICAgICdhcmlhLWxhYmVsJzogZGF0ZUVudi5mb3JtYXQoZGF0ZSwgV0VFS0RBWV9GT1JNQVQpLFxuICAgICAgICAgICAgICAgIH0gfSkpKSkpO1xuICAgIH1cbn1cblxuY2xhc3MgRGF5SGVhZGVyIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuY3JlYXRlRGF5SGVhZGVyRm9ybWF0dGVyID0gbWVtb2l6ZShjcmVhdGVEYXlIZWFkZXJGb3JtYXR0ZXIpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IGRhdGVzLCBkYXRlUHJvZmlsZSwgZGF0ZXNSZXBEaXN0aW5jdERheXMsIHJlbmRlckludHJvIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBsZXQgZGF5SGVhZGVyRm9ybWF0ID0gdGhpcy5jcmVhdGVEYXlIZWFkZXJGb3JtYXR0ZXIoY29udGV4dC5vcHRpb25zLmRheUhlYWRlckZvcm1hdCwgZGF0ZXNSZXBEaXN0aW5jdERheXMsIGRhdGVzLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChOb3dUaW1lciwgeyB1bml0OiBcImRheVwiIH0sIChub3dEYXRlLCB0b2RheVJhbmdlKSA9PiAoY3JlYXRlRWxlbWVudChcInRyXCIsIHsgcm9sZTogXCJyb3dcIiB9LFxuICAgICAgICAgICAgcmVuZGVySW50cm8gJiYgcmVuZGVySW50cm8oJ2RheScpLFxuICAgICAgICAgICAgZGF0ZXMubWFwKChkYXRlKSA9PiAoZGF0ZXNSZXBEaXN0aW5jdERheXMgPyAoY3JlYXRlRWxlbWVudChUYWJsZURhdGVDZWxsLCB7IGtleTogZGF0ZS50b0lTT1N0cmluZygpLCBkYXRlOiBkYXRlLCBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2U6IHRvZGF5UmFuZ2UsIGNvbENudDogZGF0ZXMubGVuZ3RoLCBkYXlIZWFkZXJGb3JtYXQ6IGRheUhlYWRlckZvcm1hdCB9KSkgOiAoY3JlYXRlRWxlbWVudChUYWJsZURvd0NlbGwsIHsga2V5OiBkYXRlLmdldFVUQ0RheSgpLCBkb3c6IGRhdGUuZ2V0VVRDRGF5KCksIGRheUhlYWRlckZvcm1hdDogZGF5SGVhZGVyRm9ybWF0IH0pKSkpKSkpKTtcbiAgICB9XG59XG5mdW5jdGlvbiBjcmVhdGVEYXlIZWFkZXJGb3JtYXR0ZXIoZXhwbGljaXRGb3JtYXQsIGRhdGVzUmVwRGlzdGluY3REYXlzLCBkYXRlQ250KSB7XG4gICAgcmV0dXJuIGV4cGxpY2l0Rm9ybWF0IHx8IGNvbXB1dGVGYWxsYmFja0hlYWRlckZvcm1hdChkYXRlc1JlcERpc3RpbmN0RGF5cywgZGF0ZUNudCk7XG59XG5cbmNsYXNzIERheVNlcmllc01vZGVsIHtcbiAgICBjb25zdHJ1Y3RvcihyYW5nZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpIHtcbiAgICAgICAgbGV0IGRhdGUgPSByYW5nZS5zdGFydDtcbiAgICAgICAgbGV0IHsgZW5kIH0gPSByYW5nZTtcbiAgICAgICAgbGV0IGluZGljZXMgPSBbXTtcbiAgICAgICAgbGV0IGRhdGVzID0gW107XG4gICAgICAgIGxldCBkYXlJbmRleCA9IC0xO1xuICAgICAgICB3aGlsZSAoZGF0ZSA8IGVuZCkgeyAvLyBsb29wIGVhY2ggZGF5IGZyb20gc3RhcnQgdG8gZW5kXG4gICAgICAgICAgICBpZiAoZGF0ZVByb2ZpbGVHZW5lcmF0b3IuaXNIaWRkZW5EYXkoZGF0ZSkpIHtcbiAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goZGF5SW5kZXggKyAwLjUpOyAvLyBtYXJrIHRoYXQgaXQncyBiZXR3ZWVuIGluZGljZXNcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRheUluZGV4ICs9IDE7XG4gICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKGRheUluZGV4KTtcbiAgICAgICAgICAgICAgICBkYXRlcy5wdXNoKGRhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGF0ZSA9IGFkZERheXMoZGF0ZSwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kYXRlcyA9IGRhdGVzO1xuICAgICAgICB0aGlzLmluZGljZXMgPSBpbmRpY2VzO1xuICAgICAgICB0aGlzLmNudCA9IGRhdGVzLmxlbmd0aDtcbiAgICB9XG4gICAgc2xpY2VSYW5nZShyYW5nZSkge1xuICAgICAgICBsZXQgZmlyc3RJbmRleCA9IHRoaXMuZ2V0RGF0ZURheUluZGV4KHJhbmdlLnN0YXJ0KTsgLy8gaW5jbHVzaXZlIGZpcnN0IGluZGV4XG4gICAgICAgIGxldCBsYXN0SW5kZXggPSB0aGlzLmdldERhdGVEYXlJbmRleChhZGREYXlzKHJhbmdlLmVuZCwgLTEpKTsgLy8gaW5jbHVzaXZlIGxhc3QgaW5kZXhcbiAgICAgICAgbGV0IGNsaXBwZWRGaXJzdEluZGV4ID0gTWF0aC5tYXgoMCwgZmlyc3RJbmRleCk7XG4gICAgICAgIGxldCBjbGlwcGVkTGFzdEluZGV4ID0gTWF0aC5taW4odGhpcy5jbnQgLSAxLCBsYXN0SW5kZXgpO1xuICAgICAgICAvLyBkZWFsIHdpdGggaW4tYmV0d2VlbiBpbmRpY2VzXG4gICAgICAgIGNsaXBwZWRGaXJzdEluZGV4ID0gTWF0aC5jZWlsKGNsaXBwZWRGaXJzdEluZGV4KTsgLy8gaW4tYmV0d2VlbiBzdGFydHMgcm91bmQgdG8gbmV4dCBjZWxsXG4gICAgICAgIGNsaXBwZWRMYXN0SW5kZXggPSBNYXRoLmZsb29yKGNsaXBwZWRMYXN0SW5kZXgpOyAvLyBpbi1iZXR3ZWVuIGVuZHMgcm91bmQgdG8gcHJldiBjZWxsXG4gICAgICAgIGlmIChjbGlwcGVkRmlyc3RJbmRleCA8PSBjbGlwcGVkTGFzdEluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGZpcnN0SW5kZXg6IGNsaXBwZWRGaXJzdEluZGV4LFxuICAgICAgICAgICAgICAgIGxhc3RJbmRleDogY2xpcHBlZExhc3RJbmRleCxcbiAgICAgICAgICAgICAgICBpc1N0YXJ0OiBmaXJzdEluZGV4ID09PSBjbGlwcGVkRmlyc3RJbmRleCxcbiAgICAgICAgICAgICAgICBpc0VuZDogbGFzdEluZGV4ID09PSBjbGlwcGVkTGFzdEluZGV4LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gR2l2ZW4gYSBkYXRlLCByZXR1cm5zIGl0cyBjaHJvbm9sb2NpYWwgY2VsbC1pbmRleCBmcm9tIHRoZSBmaXJzdCBjZWxsIG9mIHRoZSBncmlkLlxuICAgIC8vIElmIHRoZSBkYXRlIGxpZXMgYmV0d2VlbiBjZWxscyAoYmVjYXVzZSBvZiBoaWRkZW5EYXlzKSwgcmV0dXJucyBhIGZsb2F0aW5nLXBvaW50IHZhbHVlIGJldHdlZW4gb2Zmc2V0cy5cbiAgICAvLyBJZiBiZWZvcmUgdGhlIGZpcnN0IG9mZnNldCwgcmV0dXJucyBhIG5lZ2F0aXZlIG51bWJlci5cbiAgICAvLyBJZiBhZnRlciB0aGUgbGFzdCBvZmZzZXQsIHJldHVybnMgYW4gb2Zmc2V0IHBhc3QgdGhlIGxhc3QgY2VsbCBvZmZzZXQuXG4gICAgLy8gT25seSB3b3JrcyBmb3IgKnN0YXJ0KiBkYXRlcyBvZiBjZWxscy4gV2lsbCBub3Qgd29yayBmb3IgZXhjbHVzaXZlIGVuZCBkYXRlcyBmb3IgY2VsbHMuXG4gICAgZ2V0RGF0ZURheUluZGV4KGRhdGUpIHtcbiAgICAgICAgbGV0IHsgaW5kaWNlcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IGRheU9mZnNldCA9IE1hdGguZmxvb3IoZGlmZkRheXModGhpcy5kYXRlc1swXSwgZGF0ZSkpO1xuICAgICAgICBpZiAoZGF5T2Zmc2V0IDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIGluZGljZXNbMF0gLSAxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkYXlPZmZzZXQgPj0gaW5kaWNlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV0gKyAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbmRpY2VzW2RheU9mZnNldF07XG4gICAgfVxufVxuXG5jbGFzcyBEYXlUYWJsZU1vZGVsIHtcbiAgICBjb25zdHJ1Y3RvcihkYXlTZXJpZXMsIGJyZWFrT25XZWVrcykge1xuICAgICAgICBsZXQgeyBkYXRlcyB9ID0gZGF5U2VyaWVzO1xuICAgICAgICBsZXQgZGF5c1BlclJvdztcbiAgICAgICAgbGV0IGZpcnN0RGF5O1xuICAgICAgICBsZXQgcm93Q250O1xuICAgICAgICBpZiAoYnJlYWtPbldlZWtzKSB7XG4gICAgICAgICAgICAvLyBjb3VudCBjb2x1bW5zIHVudGlsIHRoZSBkYXktb2Ytd2VlayByZXBlYXRzXG4gICAgICAgICAgICBmaXJzdERheSA9IGRhdGVzWzBdLmdldFVUQ0RheSgpO1xuICAgICAgICAgICAgZm9yIChkYXlzUGVyUm93ID0gMTsgZGF5c1BlclJvdyA8IGRhdGVzLmxlbmd0aDsgZGF5c1BlclJvdyArPSAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGVzW2RheXNQZXJSb3ddLmdldFVUQ0RheSgpID09PSBmaXJzdERheSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByb3dDbnQgPSBNYXRoLmNlaWwoZGF0ZXMubGVuZ3RoIC8gZGF5c1BlclJvdyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByb3dDbnQgPSAxO1xuICAgICAgICAgICAgZGF5c1BlclJvdyA9IGRhdGVzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd0NudCA9IHJvd0NudDtcbiAgICAgICAgdGhpcy5jb2xDbnQgPSBkYXlzUGVyUm93O1xuICAgICAgICB0aGlzLmRheVNlcmllcyA9IGRheVNlcmllcztcbiAgICAgICAgdGhpcy5jZWxscyA9IHRoaXMuYnVpbGRDZWxscygpO1xuICAgICAgICB0aGlzLmhlYWRlckRhdGVzID0gdGhpcy5idWlsZEhlYWRlckRhdGVzKCk7XG4gICAgfVxuICAgIGJ1aWxkQ2VsbHMoKSB7XG4gICAgICAgIGxldCByb3dzID0gW107XG4gICAgICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IHRoaXMucm93Q250OyByb3cgKz0gMSkge1xuICAgICAgICAgICAgbGV0IGNlbGxzID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCB0aGlzLmNvbENudDsgY29sICs9IDEpIHtcbiAgICAgICAgICAgICAgICBjZWxscy5wdXNoKHRoaXMuYnVpbGRDZWxsKHJvdywgY29sKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByb3dzLnB1c2goY2VsbHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dzO1xuICAgIH1cbiAgICBidWlsZENlbGwocm93LCBjb2wpIHtcbiAgICAgICAgbGV0IGRhdGUgPSB0aGlzLmRheVNlcmllcy5kYXRlc1tyb3cgKiB0aGlzLmNvbENudCArIGNvbF07XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBrZXk6IGRhdGUudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgIGRhdGUsXG4gICAgICAgIH07XG4gICAgfVxuICAgIGJ1aWxkSGVhZGVyRGF0ZXMoKSB7XG4gICAgICAgIGxldCBkYXRlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCB0aGlzLmNvbENudDsgY29sICs9IDEpIHtcbiAgICAgICAgICAgIGRhdGVzLnB1c2godGhpcy5jZWxsc1swXVtjb2xdLmRhdGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRlcztcbiAgICB9XG4gICAgc2xpY2VSYW5nZShyYW5nZSkge1xuICAgICAgICBsZXQgeyBjb2xDbnQgfSA9IHRoaXM7XG4gICAgICAgIGxldCBzZXJpZXNTZWcgPSB0aGlzLmRheVNlcmllcy5zbGljZVJhbmdlKHJhbmdlKTtcbiAgICAgICAgbGV0IHNlZ3MgPSBbXTtcbiAgICAgICAgaWYgKHNlcmllc1NlZykge1xuICAgICAgICAgICAgbGV0IHsgZmlyc3RJbmRleCwgbGFzdEluZGV4IH0gPSBzZXJpZXNTZWc7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSBmaXJzdEluZGV4O1xuICAgICAgICAgICAgd2hpbGUgKGluZGV4IDw9IGxhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgIGxldCByb3cgPSBNYXRoLmZsb29yKGluZGV4IC8gY29sQ250KTtcbiAgICAgICAgICAgICAgICBsZXQgbmV4dEluZGV4ID0gTWF0aC5taW4oKHJvdyArIDEpICogY29sQ250LCBsYXN0SW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgICBzZWdzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICByb3csXG4gICAgICAgICAgICAgICAgICAgIGZpcnN0Q29sOiBpbmRleCAlIGNvbENudCxcbiAgICAgICAgICAgICAgICAgICAgbGFzdENvbDogKG5leHRJbmRleCAtIDEpICUgY29sQ250LFxuICAgICAgICAgICAgICAgICAgICBpc1N0YXJ0OiBzZXJpZXNTZWcuaXNTdGFydCAmJiBpbmRleCA9PT0gZmlyc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgaXNFbmQ6IHNlcmllc1NlZy5pc0VuZCAmJiAobmV4dEluZGV4IC0gMSkgPT09IGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VncztcbiAgICB9XG59XG5cbmNsYXNzIFNsaWNlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc2xpY2VCdXNpbmVzc0hvdXJzID0gbWVtb2l6ZSh0aGlzLl9zbGljZUJ1c2luZXNzSG91cnMpO1xuICAgICAgICB0aGlzLnNsaWNlRGF0ZVNlbGVjdGlvbiA9IG1lbW9pemUodGhpcy5fc2xpY2VEYXRlU3Bhbik7XG4gICAgICAgIHRoaXMuc2xpY2VFdmVudFN0b3JlID0gbWVtb2l6ZSh0aGlzLl9zbGljZUV2ZW50U3RvcmUpO1xuICAgICAgICB0aGlzLnNsaWNlRXZlbnREcmFnID0gbWVtb2l6ZSh0aGlzLl9zbGljZUludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5zbGljZUV2ZW50UmVzaXplID0gbWVtb2l6ZSh0aGlzLl9zbGljZUludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5mb3JjZURheUlmTGlzdEl0ZW0gPSBmYWxzZTsgLy8gaGFja1xuICAgIH1cbiAgICBzbGljZVByb3BzKHByb3BzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY29udGV4dCwgLi4uZXh0cmFBcmdzKSB7XG4gICAgICAgIGxldCB7IGV2ZW50VWlCYXNlcyB9ID0gcHJvcHM7XG4gICAgICAgIGxldCBldmVudFNlZ3MgPSB0aGlzLnNsaWNlRXZlbnRTdG9yZShwcm9wcy5ldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCAuLi5leHRyYUFyZ3MpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvblNlZ3M6IHRoaXMuc2xpY2VEYXRlU2VsZWN0aW9uKHByb3BzLmRhdGVTZWxlY3Rpb24sIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBldmVudFVpQmFzZXMsIGNvbnRleHQsIC4uLmV4dHJhQXJncyksXG4gICAgICAgICAgICBidXNpbmVzc0hvdXJTZWdzOiB0aGlzLnNsaWNlQnVzaW5lc3NIb3Vycyhwcm9wcy5idXNpbmVzc0hvdXJzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY29udGV4dCwgLi4uZXh0cmFBcmdzKSxcbiAgICAgICAgICAgIGZnRXZlbnRTZWdzOiBldmVudFNlZ3MuZmcsXG4gICAgICAgICAgICBiZ0V2ZW50U2VnczogZXZlbnRTZWdzLmJnLFxuICAgICAgICAgICAgZXZlbnREcmFnOiB0aGlzLnNsaWNlRXZlbnREcmFnKHByb3BzLmV2ZW50RHJhZywgZXZlbnRVaUJhc2VzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgLi4uZXh0cmFBcmdzKSxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplOiB0aGlzLnNsaWNlRXZlbnRSZXNpemUocHJvcHMuZXZlbnRSZXNpemUsIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIC4uLmV4dHJhQXJncyksXG4gICAgICAgICAgICBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb24sXG4gICAgICAgIH07IC8vIFRPRE86IGdpdmUgaW50ZXJhY3Rpb25TZWdzP1xuICAgIH1cbiAgICBzbGljZU5vd0RhdGUoLy8gZG9lcyBub3QgbWVtb2l6ZVxuICAgIGRhdGUsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb250ZXh0LCAuLi5leHRyYUFyZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NsaWNlRGF0ZVNwYW4oeyByYW5nZTogeyBzdGFydDogZGF0ZSwgZW5kOiBhZGRNcyhkYXRlLCAxKSB9LCBhbGxEYXk6IGZhbHNlIH0sIC8vIGFkZCAxIG1zLCBwcm90ZWN0IGFnYWluc3QgbnVsbCByYW5nZVxuICAgICAgICBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwge30sIGNvbnRleHQsIC4uLmV4dHJhQXJncyk7XG4gICAgfVxuICAgIF9zbGljZUJ1c2luZXNzSG91cnMoYnVzaW5lc3NIb3VycywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbnRleHQsIC4uLmV4dHJhQXJncykge1xuICAgICAgICBpZiAoIWJ1c2luZXNzSG91cnMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fc2xpY2VFdmVudFN0b3JlKGV4cGFuZFJlY3VycmluZyhidXNpbmVzc0hvdXJzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBjb250ZXh0KSwge30sIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCAuLi5leHRyYUFyZ3MpLmJnO1xuICAgIH1cbiAgICBfc2xpY2VFdmVudFN0b3JlKGV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIC4uLmV4dHJhQXJncykge1xuICAgICAgICBpZiAoZXZlbnRTdG9yZSkge1xuICAgICAgICAgICAgbGV0IHJhbmdlUmVzID0gc2xpY2VFdmVudFN0b3JlKGV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgY29tcHV0ZUFjdGl2ZVJhbmdlKGRhdGVQcm9maWxlLCBCb29sZWFuKG5leHREYXlUaHJlc2hvbGQpKSwgbmV4dERheVRocmVzaG9sZCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGJnOiB0aGlzLnNsaWNlRXZlbnRSYW5nZXMocmFuZ2VSZXMuYmcsIGV4dHJhQXJncyksXG4gICAgICAgICAgICAgICAgZmc6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5mZywgZXh0cmFBcmdzKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgYmc6IFtdLCBmZzogW10gfTtcbiAgICB9XG4gICAgX3NsaWNlSW50ZXJhY3Rpb24oaW50ZXJhY3Rpb24sIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIC4uLmV4dHJhQXJncykge1xuICAgICAgICBpZiAoIWludGVyYWN0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmFuZ2VSZXMgPSBzbGljZUV2ZW50U3RvcmUoaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cywgZXZlbnRVaUJhc2VzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBuZXh0RGF5VGhyZXNob2xkKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNlZ3M6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5mZywgZXh0cmFBcmdzKSxcbiAgICAgICAgICAgIGFmZmVjdGVkSW5zdGFuY2VzOiBpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cy5pbnN0YW5jZXMsXG4gICAgICAgICAgICBpc0V2ZW50OiBpbnRlcmFjdGlvbi5pc0V2ZW50LFxuICAgICAgICB9O1xuICAgIH1cbiAgICBfc2xpY2VEYXRlU3BhbihkYXRlU3BhbiwgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGV2ZW50VWlCYXNlcywgY29udGV4dCwgLi4uZXh0cmFBcmdzKSB7XG4gICAgICAgIGlmICghZGF0ZVNwYW4pIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYWN0aXZlUmFuZ2UgPSBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpO1xuICAgICAgICBsZXQgYWN0aXZlRGF0ZVNwYW5SYW5nZSA9IGludGVyc2VjdFJhbmdlcyhkYXRlU3Bhbi5yYW5nZSwgYWN0aXZlUmFuZ2UpO1xuICAgICAgICBpZiAoYWN0aXZlRGF0ZVNwYW5SYW5nZSkge1xuICAgICAgICAgICAgZGF0ZVNwYW4gPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGRhdGVTcGFuKSwgeyByYW5nZTogYWN0aXZlRGF0ZVNwYW5SYW5nZSB9KTtcbiAgICAgICAgICAgIGxldCBldmVudFJhbmdlID0gZmFicmljYXRlRXZlbnRSYW5nZShkYXRlU3BhbiwgZXZlbnRVaUJhc2VzLCBjb250ZXh0KTtcbiAgICAgICAgICAgIGxldCBzZWdzID0gdGhpcy5zbGljZVJhbmdlKGRhdGVTcGFuLnJhbmdlLCAuLi5leHRyYUFyZ3MpO1xuICAgICAgICAgICAgZm9yIChsZXQgc2VnIG9mIHNlZ3MpIHtcbiAgICAgICAgICAgICAgICBzZWcuZXZlbnRSYW5nZSA9IGV2ZW50UmFuZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc2VncztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIC8qXG4gICAgXCJjb21wbGV0ZVwiIHNlZyBtZWFucyBpdCBoYXMgY29tcG9uZW50IGFuZCBldmVudFJhbmdlXG4gICAgKi9cbiAgICBzbGljZUV2ZW50UmFuZ2VzKGV2ZW50UmFuZ2VzLCBleHRyYUFyZ3MpIHtcbiAgICAgICAgbGV0IHNlZ3MgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgZXZlbnRSYW5nZSBvZiBldmVudFJhbmdlcykge1xuICAgICAgICAgICAgc2Vncy5wdXNoKC4uLnRoaXMuc2xpY2VFdmVudFJhbmdlKGV2ZW50UmFuZ2UsIGV4dHJhQXJncykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH1cbiAgICAvKlxuICAgIFwiY29tcGxldGVcIiBzZWcgbWVhbnMgaXQgaGFzIGNvbXBvbmVudCBhbmQgZXZlbnRSYW5nZVxuICAgICovXG4gICAgc2xpY2VFdmVudFJhbmdlKGV2ZW50UmFuZ2UsIGV4dHJhQXJncykge1xuICAgICAgICBsZXQgZGF0ZVJhbmdlID0gZXZlbnRSYW5nZS5yYW5nZTtcbiAgICAgICAgLy8gaGFjayB0byBtYWtlIG11bHRpLWRheSBldmVudHMgdGhhdCBhcmUgYmVpbmcgZm9yY2UtZGlzcGxheWVkIGFzIGxpc3QtaXRlbXMgdG8gdGFrZSB1cCBvbmx5IG9uZSBkYXlcbiAgICAgICAgaWYgKHRoaXMuZm9yY2VEYXlJZkxpc3RJdGVtICYmIGV2ZW50UmFuZ2UudWkuZGlzcGxheSA9PT0gJ2xpc3QtaXRlbScpIHtcbiAgICAgICAgICAgIGRhdGVSYW5nZSA9IHtcbiAgICAgICAgICAgICAgICBzdGFydDogZGF0ZVJhbmdlLnN0YXJ0LFxuICAgICAgICAgICAgICAgIGVuZDogYWRkRGF5cyhkYXRlUmFuZ2Uuc3RhcnQsIDEpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc2VncyA9IHRoaXMuc2xpY2VSYW5nZShkYXRlUmFuZ2UsIC4uLmV4dHJhQXJncyk7XG4gICAgICAgIGZvciAobGV0IHNlZyBvZiBzZWdzKSB7XG4gICAgICAgICAgICBzZWcuZXZlbnRSYW5nZSA9IGV2ZW50UmFuZ2U7XG4gICAgICAgICAgICBzZWcuaXNTdGFydCA9IGV2ZW50UmFuZ2UuaXNTdGFydCAmJiBzZWcuaXNTdGFydDtcbiAgICAgICAgICAgIHNlZy5pc0VuZCA9IGV2ZW50UmFuZ2UuaXNFbmQgJiYgc2VnLmlzRW5kO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH1cbn1cbi8qXG5mb3IgaW5jb3Jwb3JhdGluZyBzbG90TWluVGltZS9zbG90TWF4VGltZSBpZiBhcHByb3ByaWF0ZVxuVE9ETzogc2hvdWxkIGJlIHBhcnQgb2YgRGF0ZVByb2ZpbGUhXG5UaW1lbGluZURhdGVQcm9maWxlIGFscmVhZHkgZG9lcyB0aGlzIGJ0d1xuKi9cbmZ1bmN0aW9uIGNvbXB1dGVBY3RpdmVSYW5nZShkYXRlUHJvZmlsZSwgaXNDb21wb25lbnRBbGxEYXkpIHtcbiAgICBsZXQgcmFuZ2UgPSBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZTtcbiAgICBpZiAoaXNDb21wb25lbnRBbGxEYXkpIHtcbiAgICAgICAgcmV0dXJuIHJhbmdlO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogYWRkTXMocmFuZ2Uuc3RhcnQsIGRhdGVQcm9maWxlLnNsb3RNaW5UaW1lLm1pbGxpc2Vjb25kcyksXG4gICAgICAgIGVuZDogYWRkTXMocmFuZ2UuZW5kLCBkYXRlUHJvZmlsZS5zbG90TWF4VGltZS5taWxsaXNlY29uZHMgLSA4NjRlNSksIC8vIDg2NGU1ID0gbXMgaW4gYSBkYXlcbiAgICB9O1xufVxuXG4vLyBoaWdoLWxldmVsIHNlZ21lbnRpbmctYXdhcmUgdGVzdGVyIGZ1bmN0aW9uc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBpc0ludGVyYWN0aW9uVmFsaWQoaW50ZXJhY3Rpb24sIGRhdGVQcm9maWxlLCBjb250ZXh0KSB7XG4gICAgbGV0IHsgaW5zdGFuY2VzIH0gPSBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzO1xuICAgIGZvciAobGV0IGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgIGlmICghcmFuZ2VDb250YWluc1JhbmdlKGRhdGVQcm9maWxlLnZhbGlkUmFuZ2UsIGluc3RhbmNlc1tpbnN0YW5jZUlkXS5yYW5nZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaXNOZXdQcm9wc1ZhbGlkKHsgZXZlbnREcmFnOiBpbnRlcmFjdGlvbiB9LCBjb250ZXh0KTsgLy8gSEFDSzogdGhlIGV2ZW50RHJhZyBwcm9wcyBpcyB1c2VkIGZvciBBTEwgaW50ZXJhY3Rpb25zXG59XG5mdW5jdGlvbiBpc0RhdGVTZWxlY3Rpb25WYWxpZChkYXRlU2VsZWN0aW9uLCBkYXRlUHJvZmlsZSwgY29udGV4dCkge1xuICAgIGlmICghcmFuZ2VDb250YWluc1JhbmdlKGRhdGVQcm9maWxlLnZhbGlkUmFuZ2UsIGRhdGVTZWxlY3Rpb24ucmFuZ2UpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIGlzTmV3UHJvcHNWYWxpZCh7IGRhdGVTZWxlY3Rpb24gfSwgY29udGV4dCk7XG59XG5mdW5jdGlvbiBpc05ld1Byb3BzVmFsaWQobmV3UHJvcHMsIGNvbnRleHQpIHtcbiAgICBsZXQgY2FsZW5kYXJTdGF0ZSA9IGNvbnRleHQuZ2V0Q3VycmVudERhdGEoKTtcbiAgICBsZXQgcHJvcHMgPSBPYmplY3QuYXNzaWduKHsgYnVzaW5lc3NIb3VyczogY2FsZW5kYXJTdGF0ZS5idXNpbmVzc0hvdXJzLCBkYXRlU2VsZWN0aW9uOiAnJywgZXZlbnRTdG9yZTogY2FsZW5kYXJTdGF0ZS5ldmVudFN0b3JlLCBldmVudFVpQmFzZXM6IGNhbGVuZGFyU3RhdGUuZXZlbnRVaUJhc2VzLCBldmVudFNlbGVjdGlvbjogJycsIGV2ZW50RHJhZzogbnVsbCwgZXZlbnRSZXNpemU6IG51bGwgfSwgbmV3UHJvcHMpO1xuICAgIHJldHVybiAoY29udGV4dC5wbHVnaW5Ib29rcy5pc1Byb3BzVmFsaWQgfHwgaXNQcm9wc1ZhbGlkKShwcm9wcywgY29udGV4dCk7XG59XG5mdW5jdGlvbiBpc1Byb3BzVmFsaWQoc3RhdGUsIGNvbnRleHQsIGRhdGVTcGFuTWV0YSA9IHt9LCBmaWx0ZXJDb25maWcpIHtcbiAgICBpZiAoc3RhdGUuZXZlbnREcmFnICYmICFpc0ludGVyYWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY29udGV4dCwgZGF0ZVNwYW5NZXRhLCBmaWx0ZXJDb25maWcpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKHN0YXRlLmRhdGVTZWxlY3Rpb24gJiYgIWlzRGF0ZVNlbGVjdGlvblByb3BzVmFsaWQoc3RhdGUsIGNvbnRleHQsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuLy8gTW92aW5nIEV2ZW50IFZhbGlkYXRpb25cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gaXNJbnRlcmFjdGlvblByb3BzVmFsaWQoc3RhdGUsIGNvbnRleHQsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgbGV0IGN1cnJlbnRTdGF0ZSA9IGNvbnRleHQuZ2V0Q3VycmVudERhdGEoKTtcbiAgICBsZXQgaW50ZXJhY3Rpb24gPSBzdGF0ZS5ldmVudERyYWc7IC8vIEhBQ0s6IHRoZSBldmVudERyYWcgcHJvcHMgaXMgdXNlZCBmb3IgQUxMIGludGVyYWN0aW9uc1xuICAgIGxldCBzdWJqZWN0RXZlbnRTdG9yZSA9IGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHM7XG4gICAgbGV0IHN1YmplY3REZWZzID0gc3ViamVjdEV2ZW50U3RvcmUuZGVmcztcbiAgICBsZXQgc3ViamVjdEluc3RhbmNlcyA9IHN1YmplY3RFdmVudFN0b3JlLmluc3RhbmNlcztcbiAgICBsZXQgc3ViamVjdENvbmZpZ3MgPSBjb21waWxlRXZlbnRVaXMoc3ViamVjdERlZnMsIGludGVyYWN0aW9uLmlzRXZlbnQgP1xuICAgICAgICBzdGF0ZS5ldmVudFVpQmFzZXMgOlxuICAgICAgICB7ICcnOiBjdXJyZW50U3RhdGUuc2VsZWN0aW9uQ29uZmlnIH0pO1xuICAgIGlmIChmaWx0ZXJDb25maWcpIHtcbiAgICAgICAgc3ViamVjdENvbmZpZ3MgPSBtYXBIYXNoKHN1YmplY3RDb25maWdzLCBmaWx0ZXJDb25maWcpO1xuICAgIH1cbiAgICAvLyBleGNsdWRlIHRoZSBzdWJqZWN0IGV2ZW50cy4gVE9ETzogZXhjbHVkZSBkZWZzIHRvbz9cbiAgICBsZXQgb3RoZXJFdmVudFN0b3JlID0gZXhjbHVkZUluc3RhbmNlcyhzdGF0ZS5ldmVudFN0b3JlLCBpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cy5pbnN0YW5jZXMpO1xuICAgIGxldCBvdGhlckRlZnMgPSBvdGhlckV2ZW50U3RvcmUuZGVmcztcbiAgICBsZXQgb3RoZXJJbnN0YW5jZXMgPSBvdGhlckV2ZW50U3RvcmUuaW5zdGFuY2VzO1xuICAgIGxldCBvdGhlckNvbmZpZ3MgPSBjb21waWxlRXZlbnRVaXMob3RoZXJEZWZzLCBzdGF0ZS5ldmVudFVpQmFzZXMpO1xuICAgIGZvciAobGV0IHN1YmplY3RJbnN0YW5jZUlkIGluIHN1YmplY3RJbnN0YW5jZXMpIHtcbiAgICAgICAgbGV0IHN1YmplY3RJbnN0YW5jZSA9IHN1YmplY3RJbnN0YW5jZXNbc3ViamVjdEluc3RhbmNlSWRdO1xuICAgICAgICBsZXQgc3ViamVjdFJhbmdlID0gc3ViamVjdEluc3RhbmNlLnJhbmdlO1xuICAgICAgICBsZXQgc3ViamVjdENvbmZpZyA9IHN1YmplY3RDb25maWdzW3N1YmplY3RJbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIGxldCBzdWJqZWN0RGVmID0gc3ViamVjdERlZnNbc3ViamVjdEluc3RhbmNlLmRlZklkXTtcbiAgICAgICAgLy8gY29uc3RyYWludFxuICAgICAgICBpZiAoIWFsbENvbnN0cmFpbnRzUGFzcyhzdWJqZWN0Q29uZmlnLmNvbnN0cmFpbnRzLCBzdWJqZWN0UmFuZ2UsIG90aGVyRXZlbnRTdG9yZSwgc3RhdGUuYnVzaW5lc3NIb3VycywgY29udGV4dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdmVybGFwXG4gICAgICAgIGxldCB7IGV2ZW50T3ZlcmxhcCB9ID0gY29udGV4dC5vcHRpb25zO1xuICAgICAgICBsZXQgZXZlbnRPdmVybGFwRnVuYyA9IHR5cGVvZiBldmVudE92ZXJsYXAgPT09ICdmdW5jdGlvbicgPyBldmVudE92ZXJsYXAgOiBudWxsO1xuICAgICAgICBmb3IgKGxldCBvdGhlckluc3RhbmNlSWQgaW4gb3RoZXJJbnN0YW5jZXMpIHtcbiAgICAgICAgICAgIGxldCBvdGhlckluc3RhbmNlID0gb3RoZXJJbnN0YW5jZXNbb3RoZXJJbnN0YW5jZUlkXTtcbiAgICAgICAgICAgIC8vIGludGVyc2VjdCEgZXZhbHVhdGVcbiAgICAgICAgICAgIGlmIChyYW5nZXNJbnRlcnNlY3Qoc3ViamVjdFJhbmdlLCBvdGhlckluc3RhbmNlLnJhbmdlKSkge1xuICAgICAgICAgICAgICAgIGxldCBvdGhlck92ZXJsYXAgPSBvdGhlckNvbmZpZ3Nbb3RoZXJJbnN0YW5jZS5kZWZJZF0ub3ZlcmxhcDtcbiAgICAgICAgICAgICAgICAvLyBjb25zaWRlciB0aGUgb3RoZXIgZXZlbnQncyBvdmVybGFwLiBvbmx5IGRvIHRoaXMgaWYgdGhlIHN1YmplY3QgZXZlbnQgaXMgYSBcInJlYWxcIiBldmVudFxuICAgICAgICAgICAgICAgIGlmIChvdGhlck92ZXJsYXAgPT09IGZhbHNlICYmIGludGVyYWN0aW9uLmlzRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc3ViamVjdENvbmZpZy5vdmVybGFwID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChldmVudE92ZXJsYXBGdW5jICYmICFldmVudE92ZXJsYXBGdW5jKG5ldyBFdmVudEltcGwoY29udGV4dCwgb3RoZXJEZWZzW290aGVySW5zdGFuY2UuZGVmSWRdLCBvdGhlckluc3RhbmNlKSwgLy8gc3RpbGwgZXZlbnRcbiAgICAgICAgICAgICAgICBuZXcgRXZlbnRJbXBsKGNvbnRleHQsIHN1YmplY3REZWYsIHN1YmplY3RJbnN0YW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWxsb3cgKGEgZnVuY3Rpb24pXG4gICAgICAgIGxldCBjYWxlbmRhckV2ZW50U3RvcmUgPSBjdXJyZW50U3RhdGUuZXZlbnRTdG9yZTsgLy8gbmVlZCBnbG9iYWwtdG8tY2FsZW5kYXIsIG5vdCBsb2NhbCB0byBjb21wb25lbnQgKHNwbGl0dGFibGUpc3RhdGVcbiAgICAgICAgZm9yIChsZXQgc3ViamVjdEFsbG93IG9mIHN1YmplY3RDb25maWcuYWxsb3dzKSB7XG4gICAgICAgICAgICBsZXQgc3ViamVjdERhdGVTcGFuID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBkYXRlU3Bhbk1ldGEpLCB7IHJhbmdlOiBzdWJqZWN0SW5zdGFuY2UucmFuZ2UsIGFsbERheTogc3ViamVjdERlZi5hbGxEYXkgfSk7XG4gICAgICAgICAgICBsZXQgb3JpZ0RlZiA9IGNhbGVuZGFyRXZlbnRTdG9yZS5kZWZzW3N1YmplY3REZWYuZGVmSWRdO1xuICAgICAgICAgICAgbGV0IG9yaWdJbnN0YW5jZSA9IGNhbGVuZGFyRXZlbnRTdG9yZS5pbnN0YW5jZXNbc3ViamVjdEluc3RhbmNlSWRdO1xuICAgICAgICAgICAgbGV0IGV2ZW50QXBpO1xuICAgICAgICAgICAgaWYgKG9yaWdEZWYpIHsgLy8gd2FzIHByZXZpb3VzbHkgaW4gdGhlIGNhbGVuZGFyXG4gICAgICAgICAgICAgICAgZXZlbnRBcGkgPSBuZXcgRXZlbnRJbXBsKGNvbnRleHQsIG9yaWdEZWYsIG9yaWdJbnN0YW5jZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8gd2FzIGFuIGV4dGVybmFsIGV2ZW50XG4gICAgICAgICAgICAgICAgZXZlbnRBcGkgPSBuZXcgRXZlbnRJbXBsKGNvbnRleHQsIHN1YmplY3REZWYpOyAvLyBubyBpbnN0YW5jZSwgYmVjYXVzZSBoYWQgbm8gZGF0ZXNcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghc3ViamVjdEFsbG93KGJ1aWxkRGF0ZVNwYW5BcGlXaXRoQ29udGV4dChzdWJqZWN0RGF0ZVNwYW4sIGNvbnRleHQpLCBldmVudEFwaSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG4vLyBEYXRlIFNlbGVjdGlvbiBWYWxpZGF0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGlzRGF0ZVNlbGVjdGlvblByb3BzVmFsaWQoc3RhdGUsIGNvbnRleHQsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgbGV0IHJlbGV2YW50RXZlbnRTdG9yZSA9IHN0YXRlLmV2ZW50U3RvcmU7XG4gICAgbGV0IHJlbGV2YW50RGVmcyA9IHJlbGV2YW50RXZlbnRTdG9yZS5kZWZzO1xuICAgIGxldCByZWxldmFudEluc3RhbmNlcyA9IHJlbGV2YW50RXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgbGV0IHNlbGVjdGlvbiA9IHN0YXRlLmRhdGVTZWxlY3Rpb247XG4gICAgbGV0IHNlbGVjdGlvblJhbmdlID0gc2VsZWN0aW9uLnJhbmdlO1xuICAgIGxldCB7IHNlbGVjdGlvbkNvbmZpZyB9ID0gY29udGV4dC5nZXRDdXJyZW50RGF0YSgpO1xuICAgIGlmIChmaWx0ZXJDb25maWcpIHtcbiAgICAgICAgc2VsZWN0aW9uQ29uZmlnID0gZmlsdGVyQ29uZmlnKHNlbGVjdGlvbkNvbmZpZyk7XG4gICAgfVxuICAgIC8vIGNvbnN0cmFpbnRcbiAgICBpZiAoIWFsbENvbnN0cmFpbnRzUGFzcyhzZWxlY3Rpb25Db25maWcuY29uc3RyYWludHMsIHNlbGVjdGlvblJhbmdlLCByZWxldmFudEV2ZW50U3RvcmUsIHN0YXRlLmJ1c2luZXNzSG91cnMsIGNvbnRleHQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gb3ZlcmxhcFxuICAgIGxldCB7IHNlbGVjdE92ZXJsYXAgfSA9IGNvbnRleHQub3B0aW9ucztcbiAgICBsZXQgc2VsZWN0T3ZlcmxhcEZ1bmMgPSB0eXBlb2Ygc2VsZWN0T3ZlcmxhcCA9PT0gJ2Z1bmN0aW9uJyA/IHNlbGVjdE92ZXJsYXAgOiBudWxsO1xuICAgIGZvciAobGV0IHJlbGV2YW50SW5zdGFuY2VJZCBpbiByZWxldmFudEluc3RhbmNlcykge1xuICAgICAgICBsZXQgcmVsZXZhbnRJbnN0YW5jZSA9IHJlbGV2YW50SW5zdGFuY2VzW3JlbGV2YW50SW5zdGFuY2VJZF07XG4gICAgICAgIC8vIGludGVyc2VjdCEgZXZhbHVhdGVcbiAgICAgICAgaWYgKHJhbmdlc0ludGVyc2VjdChzZWxlY3Rpb25SYW5nZSwgcmVsZXZhbnRJbnN0YW5jZS5yYW5nZSkpIHtcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb25Db25maWcub3ZlcmxhcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZWN0T3ZlcmxhcEZ1bmMgJiYgIXNlbGVjdE92ZXJsYXBGdW5jKG5ldyBFdmVudEltcGwoY29udGV4dCwgcmVsZXZhbnREZWZzW3JlbGV2YW50SW5zdGFuY2UuZGVmSWRdLCByZWxldmFudEluc3RhbmNlKSwgbnVsbCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gYWxsb3cgKGEgZnVuY3Rpb24pXG4gICAgZm9yIChsZXQgc2VsZWN0aW9uQWxsb3cgb2Ygc2VsZWN0aW9uQ29uZmlnLmFsbG93cykge1xuICAgICAgICBsZXQgZnVsbERhdGVTcGFuID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBkYXRlU3Bhbk1ldGEpLCBzZWxlY3Rpb24pO1xuICAgICAgICBpZiAoIXNlbGVjdGlvbkFsbG93KGJ1aWxkRGF0ZVNwYW5BcGlXaXRoQ29udGV4dChmdWxsRGF0ZVNwYW4sIGNvbnRleHQpLCBudWxsKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuLy8gQ29uc3RyYWludCBVdGlsc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBhbGxDb25zdHJhaW50c1Bhc3MoY29uc3RyYWludHMsIHN1YmplY3RSYW5nZSwgb3RoZXJFdmVudFN0b3JlLCBidXNpbmVzc0hvdXJzVW5leHBhbmRlZCwgY29udGV4dCkge1xuICAgIGZvciAobGV0IGNvbnN0cmFpbnQgb2YgY29uc3RyYWludHMpIHtcbiAgICAgICAgaWYgKCFhbnlSYW5nZXNDb250YWluUmFuZ2UoY29uc3RyYWludFRvUmFuZ2VzKGNvbnN0cmFpbnQsIHN1YmplY3RSYW5nZSwgb3RoZXJFdmVudFN0b3JlLCBidXNpbmVzc0hvdXJzVW5leHBhbmRlZCwgY29udGV4dCksIHN1YmplY3RSYW5nZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbmZ1bmN0aW9uIGNvbnN0cmFpbnRUb1Jhbmdlcyhjb25zdHJhaW50LCBzdWJqZWN0UmFuZ2UsIC8vIGZvciBleHBhbmRpbmcgYSByZWN1cnJpbmcgY29uc3RyYWludCwgb3IgZXhwYW5kaW5nIGJ1c2luZXNzIGhvdXJzXG5vdGhlckV2ZW50U3RvcmUsIC8vIGZvciBpZiBjb25zdHJhaW50IGlzIGFuIGV2ZW4gZ3JvdXAgSURcbmJ1c2luZXNzSG91cnNVbmV4cGFuZGVkLCAvLyBmb3IgaWYgY29uc3RyYWludCBpcyAnYnVzaW5lc3NIb3VycydcbmNvbnRleHQpIHtcbiAgICBpZiAoY29uc3RyYWludCA9PT0gJ2J1c2luZXNzSG91cnMnKSB7XG4gICAgICAgIHJldHVybiBldmVudFN0b3JlVG9SYW5nZXMoZXhwYW5kUmVjdXJyaW5nKGJ1c2luZXNzSG91cnNVbmV4cGFuZGVkLCBzdWJqZWN0UmFuZ2UsIGNvbnRleHQpKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjb25zdHJhaW50ID09PSAnc3RyaW5nJykgeyAvLyBhbiBncm91cCBJRFxuICAgICAgICByZXR1cm4gZXZlbnRTdG9yZVRvUmFuZ2VzKGZpbHRlckV2ZW50U3RvcmVEZWZzKG90aGVyRXZlbnRTdG9yZSwgKGV2ZW50RGVmKSA9PiBldmVudERlZi5ncm91cElkID09PSBjb25zdHJhaW50KSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgY29uc3RyYWludCA9PT0gJ29iamVjdCcgJiYgY29uc3RyYWludCkgeyAvLyBub24tbnVsbCBvYmplY3RcbiAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmVUb1JhbmdlcyhleHBhbmRSZWN1cnJpbmcoY29uc3RyYWludCwgc3ViamVjdFJhbmdlLCBjb250ZXh0KSk7XG4gICAgfVxuICAgIHJldHVybiBbXTsgLy8gaWYgaXQncyBmYWxzZVxufVxuLy8gVE9ETzogbW92ZSB0byBldmVudC1zdG9yZSBmaWxlP1xuZnVuY3Rpb24gZXZlbnRTdG9yZVRvUmFuZ2VzKGV2ZW50U3RvcmUpIHtcbiAgICBsZXQgeyBpbnN0YW5jZXMgfSA9IGV2ZW50U3RvcmU7XG4gICAgbGV0IHJhbmdlcyA9IFtdO1xuICAgIGZvciAobGV0IGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgIHJhbmdlcy5wdXNoKGluc3RhbmNlc1tpbnN0YW5jZUlkXS5yYW5nZSk7XG4gICAgfVxuICAgIHJldHVybiByYW5nZXM7XG59XG4vLyBUT0RPOiBtb3ZlIHRvIGdlb20gZmlsZT9cbmZ1bmN0aW9uIGFueVJhbmdlc0NvbnRhaW5SYW5nZShvdXRlclJhbmdlcywgaW5uZXJSYW5nZSkge1xuICAgIGZvciAobGV0IG91dGVyUmFuZ2Ugb2Ygb3V0ZXJSYW5nZXMpIHtcbiAgICAgICAgaWYgKHJhbmdlQ29udGFpbnNSYW5nZShvdXRlclJhbmdlLCBpbm5lclJhbmdlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5jb25zdCBWSVNJQkxFX0hJRERFTl9SRSA9IC9eKHZpc2libGV8aGlkZGVuKSQvO1xuY2xhc3MgU2Nyb2xsZXIgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5oYW5kbGVFbCA9IChlbCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbCA9IGVsO1xuICAgICAgICAgICAgc2V0UmVmKHRoaXMucHJvcHMuZWxSZWYsIGVsKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgbGlxdWlkLCBsaXF1aWRJc0Fic29sdXRlIH0gPSBwcm9wcztcbiAgICAgICAgbGV0IGlzQWJzb2x1dGUgPSBsaXF1aWQgJiYgbGlxdWlkSXNBYnNvbHV0ZTtcbiAgICAgICAgbGV0IGNsYXNzTmFtZSA9IFsnZmMtc2Nyb2xsZXInXTtcbiAgICAgICAgaWYgKGxpcXVpZCkge1xuICAgICAgICAgICAgaWYgKGxpcXVpZElzQWJzb2x1dGUpIHtcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUucHVzaCgnZmMtc2Nyb2xsZXItbGlxdWlkLWFic29sdXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUucHVzaCgnZmMtc2Nyb2xsZXItbGlxdWlkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgcmVmOiB0aGlzLmhhbmRsZUVsLCBjbGFzc05hbWU6IGNsYXNzTmFtZS5qb2luKCcgJyksIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3dYOiBwcm9wcy5vdmVyZmxvd1gsXG4gICAgICAgICAgICAgICAgb3ZlcmZsb3dZOiBwcm9wcy5vdmVyZmxvd1ksXG4gICAgICAgICAgICAgICAgbGVmdDogKGlzQWJzb2x1dGUgJiYgLShwcm9wcy5vdmVyY29tZUxlZnQgfHwgMCkpIHx8ICcnLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiAoaXNBYnNvbHV0ZSAmJiAtKHByb3BzLm92ZXJjb21lUmlnaHQgfHwgMCkpIHx8ICcnLFxuICAgICAgICAgICAgICAgIGJvdHRvbTogKGlzQWJzb2x1dGUgJiYgLShwcm9wcy5vdmVyY29tZUJvdHRvbSB8fCAwKSkgfHwgJycsXG4gICAgICAgICAgICAgICAgbWFyZ2luTGVmdDogKCFpc0Fic29sdXRlICYmIC0ocHJvcHMub3ZlcmNvbWVMZWZ0IHx8IDApKSB8fCAnJyxcbiAgICAgICAgICAgICAgICBtYXJnaW5SaWdodDogKCFpc0Fic29sdXRlICYmIC0ocHJvcHMub3ZlcmNvbWVSaWdodCB8fCAwKSkgfHwgJycsXG4gICAgICAgICAgICAgICAgbWFyZ2luQm90dG9tOiAoIWlzQWJzb2x1dGUgJiYgLShwcm9wcy5vdmVyY29tZUJvdHRvbSB8fCAwKSkgfHwgJycsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiBwcm9wcy5tYXhIZWlnaHQgfHwgJycsXG4gICAgICAgICAgICB9IH0sIHByb3BzLmNoaWxkcmVuKSk7XG4gICAgfVxuICAgIG5lZWRzWFNjcm9sbGluZygpIHtcbiAgICAgICAgaWYgKFZJU0lCTEVfSElEREVOX1JFLnRlc3QodGhpcy5wcm9wcy5vdmVyZmxvd1gpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGVzdGluZyBzY3JvbGxXaWR0aD5jbGllbnRXaWR0aCBpcyB1bnJlbGlhYmxlIGNyb3NzLWJyb3dzZXIgd2hlbiBwaXhlbCBoZWlnaHRzIGFyZW4ndCBpbnRlZ2Vycy5cbiAgICAgICAgLy8gbXVjaCBtb3JlIHJlbGlhYmxlIHRvIHNlZSBpZiBjaGlsZHJlbiBhcmUgdGFsbGVyIHRoYW4gdGhlIHNjcm9sbGVyLCBldmVuIHRobyBkb2Vzbid0IGFjY291bnQgZm9yXG4gICAgICAgIC8vIGlubmVyLWNoaWxkIG1hcmdpbnMgYW5kIGFic29sdXRlIHBvc2l0aW9uaW5nXG4gICAgICAgIGxldCB7IGVsIH0gPSB0aGlzO1xuICAgICAgICBsZXQgcmVhbENsaWVudFdpZHRoID0gdGhpcy5lbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCAtIHRoaXMuZ2V0WVNjcm9sbGJhcldpZHRoKCk7XG4gICAgICAgIGxldCB7IGNoaWxkcmVuIH0gPSBlbDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgbGV0IGNoaWxkRWwgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgIGlmIChjaGlsZEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoID4gcmVhbENsaWVudFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBuZWVkc1lTY3JvbGxpbmcoKSB7XG4gICAgICAgIGlmIChWSVNJQkxFX0hJRERFTl9SRS50ZXN0KHRoaXMucHJvcHMub3ZlcmZsb3dZKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRlc3Rpbmcgc2Nyb2xsSGVpZ2h0PmNsaWVudEhlaWdodCBpcyB1bnJlbGlhYmxlIGNyb3NzLWJyb3dzZXIgd2hlbiBwaXhlbCBoZWlnaHRzIGFyZW4ndCBpbnRlZ2Vycy5cbiAgICAgICAgLy8gbXVjaCBtb3JlIHJlbGlhYmxlIHRvIHNlZSBpZiBjaGlsZHJlbiBhcmUgdGFsbGVyIHRoYW4gdGhlIHNjcm9sbGVyLCBldmVuIHRobyBkb2Vzbid0IGFjY291bnQgZm9yXG4gICAgICAgIC8vIGlubmVyLWNoaWxkIG1hcmdpbnMgYW5kIGFic29sdXRlIHBvc2l0aW9uaW5nXG4gICAgICAgIGxldCB7IGVsIH0gPSB0aGlzO1xuICAgICAgICBsZXQgcmVhbENsaWVudEhlaWdodCA9IHRoaXMuZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IC0gdGhpcy5nZXRYU2Nyb2xsYmFyV2lkdGgoKTtcbiAgICAgICAgbGV0IHsgY2hpbGRyZW4gfSA9IGVsO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBsZXQgY2hpbGRFbCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgaWYgKGNoaWxkRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0ID4gcmVhbENsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZ2V0WFNjcm9sbGJhcldpZHRoKCkge1xuICAgICAgICBpZiAoVklTSUJMRV9ISURERU5fUkUudGVzdCh0aGlzLnByb3BzLm92ZXJmbG93WCkpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmVsLm9mZnNldEhlaWdodCAtIHRoaXMuZWwuY2xpZW50SGVpZ2h0OyAvLyBvbmx5IHdvcmtzIGJlY2F1c2Ugd2UgZ3VhcmFudGVlIG5vIGJvcmRlcnMuIFRPRE86IGFkZCB0byBDU1Mgd2l0aCBpbXBvcnRhbnQ/XG4gICAgfVxuICAgIGdldFlTY3JvbGxiYXJXaWR0aCgpIHtcbiAgICAgICAgaWYgKFZJU0lCTEVfSElEREVOX1JFLnRlc3QodGhpcy5wcm9wcy5vdmVyZmxvd1kpKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5lbC5vZmZzZXRXaWR0aCAtIHRoaXMuZWwuY2xpZW50V2lkdGg7IC8vIG9ubHkgd29ya3MgYmVjYXVzZSB3ZSBndWFyYW50ZWUgbm8gYm9yZGVycy4gVE9ETzogYWRkIHRvIENTUyB3aXRoIGltcG9ydGFudD9cbiAgICB9XG59XG5cbi8qXG5UT0RPOiBzb21laG93IGluZmVyIE90aGVyQXJncyBmcm9tIG1hc3RlckNhbGxiYWNrP1xuVE9ETzogaW5mZXIgUmVmVHlwZSBmcm9tIG1hc3RlckNhbGxiYWNrIGlmIHByb3ZpZGVkXG4qL1xuY2xhc3MgUmVmTWFwIHtcbiAgICBjb25zdHJ1Y3RvcihtYXN0ZXJDYWxsYmFjaykge1xuICAgICAgICB0aGlzLm1hc3RlckNhbGxiYWNrID0gbWFzdGVyQ2FsbGJhY2s7XG4gICAgICAgIHRoaXMuY3VycmVudE1hcCA9IHt9O1xuICAgICAgICB0aGlzLmRlcHRocyA9IHt9O1xuICAgICAgICB0aGlzLmNhbGxiYWNrTWFwID0ge307XG4gICAgICAgIHRoaXMuaGFuZGxlVmFsdWUgPSAodmFsLCBrZXkpID0+IHtcbiAgICAgICAgICAgIGxldCB7IGRlcHRocywgY3VycmVudE1hcCB9ID0gdGhpcztcbiAgICAgICAgICAgIGxldCByZW1vdmVkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgYWRkZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh2YWwgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBmb3IgYnVnLi4uIEFDVFVBTExZOiBjYW4gcHJvYmFibHkgZG8gYXdheSB3aXRoIHRoaXMgbm93IHRoYXQgY2FsbGVycyBkb24ndCBzaGFyZSBudW1lcmljIGluZGljZXMgYW55bW9yZVxuICAgICAgICAgICAgICAgIHJlbW92ZWQgPSAoa2V5IGluIGN1cnJlbnRNYXApO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRNYXBba2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICBkZXB0aHNba2V5XSA9IChkZXB0aHNba2V5XSB8fCAwKSArIDE7XG4gICAgICAgICAgICAgICAgYWRkZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVwdGhzW2tleV0gLT0gMTtcbiAgICAgICAgICAgICAgICBpZiAoIWRlcHRoc1trZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBjdXJyZW50TWFwW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrTWFwW2tleV07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLm1hc3RlckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXN0ZXJDYWxsYmFjayhudWxsLCBTdHJpbmcoa2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhZGRlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1hc3RlckNhbGxiYWNrKHZhbCwgU3RyaW5nKGtleSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgY3JlYXRlUmVmKGtleSkge1xuICAgICAgICBsZXQgcmVmQ2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrTWFwW2tleV07XG4gICAgICAgIGlmICghcmVmQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJlZkNhbGxiYWNrID0gdGhpcy5jYWxsYmFja01hcFtrZXldID0gKHZhbCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlVmFsdWUodmFsLCBTdHJpbmcoa2V5KSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWZDYWxsYmFjaztcbiAgICB9XG4gICAgLy8gVE9ETzogY2hlY2sgY2FsbGVycyB0aGF0IGRvbid0IGNhcmUgYWJvdXQgb3JkZXIuIHNob3VsZCB1c2UgZ2V0QWxsIGluc3RlYWRcbiAgICAvLyBOT1RFOiB0aGlzIG1ldGhvZCBoYXMgYmVjb21lIGxlc3MgdmFsdWFibGUgbm93IHRoYXQgd2UgYXJlIGVuY291cmFnZWQgdG8gbWFwIG9yZGVyIGJ5IHNvbWUgb3RoZXIgaW5kZXhcbiAgICAvLyBUT0RPOiBwcm92aWRlIE9ORSBhcnJheS1leHBvcnQgZnVuY3Rpb24sIGJ1aWxkQXJyYXksIHdoaWNoIGZhaWxzIG9uIG5vbi1udW1lcmljIGluZGV4ZXMuIGNhbGxlciBjYW4gbWFuaXB1bGF0ZSBhbmQgXCJjb2xsZWN0XCJcbiAgICBjb2xsZWN0KHN0YXJ0SW5kZXgsIGVuZEluZGV4LCBzdGVwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0RnJvbUhhc2godGhpcy5jdXJyZW50TWFwLCBzdGFydEluZGV4LCBlbmRJbmRleCwgc3RlcCk7XG4gICAgfVxuICAgIGdldEFsbCgpIHtcbiAgICAgICAgcmV0dXJuIGhhc2hWYWx1ZXNUb0FycmF5KHRoaXMuY3VycmVudE1hcCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjb21wdXRlU2hyaW5rV2lkdGgoY2h1bmtFbHMpIHtcbiAgICBsZXQgc2hyaW5rQ2VsbHMgPSBmaW5kRWxlbWVudHMoY2h1bmtFbHMsICcuZmMtc2Nyb2xsZ3JpZC1zaHJpbmsnKTtcbiAgICBsZXQgbGFyZ2VzdFdpZHRoID0gMDtcbiAgICBmb3IgKGxldCBzaHJpbmtDZWxsIG9mIHNocmlua0NlbGxzKSB7XG4gICAgICAgIGxhcmdlc3RXaWR0aCA9IE1hdGgubWF4KGxhcmdlc3RXaWR0aCwgY29tcHV0ZVNtYWxsZXN0Q2VsbFdpZHRoKHNocmlua0NlbGwpKTtcbiAgICB9XG4gICAgcmV0dXJuIE1hdGguY2VpbChsYXJnZXN0V2lkdGgpOyAvLyA8dGFibGU+IGVsZW1lbnRzIHdvcmsgYmVzdCB3aXRoIGludGVnZXJzLiByb3VuZCB1cCB0byBlbnN1cmUgY29udGVudHMgZml0c1xufVxuZnVuY3Rpb24gZ2V0U2VjdGlvbkhhc0xpcXVpZEhlaWdodChwcm9wcywgc2VjdGlvbkNvbmZpZykge1xuICAgIHJldHVybiBwcm9wcy5saXF1aWQgJiYgc2VjdGlvbkNvbmZpZy5saXF1aWQ7IC8vIGRvZXMgdGhlIHNlY3Rpb24gZG8gbGlxdWlkLWhlaWdodD8gKG5lZWQgdG8gaGF2ZSB3aG9sZSBzY3JvbGxncmlkIGxpcXVpZC1oZWlnaHQgYXMgd2VsbClcbn1cbmZ1bmN0aW9uIGdldEFsbG93WVNjcm9sbGluZyhwcm9wcywgc2VjdGlvbkNvbmZpZykge1xuICAgIHJldHVybiBzZWN0aW9uQ29uZmlnLm1heEhlaWdodCAhPSBudWxsIHx8IC8vIGlmIGl0cyBwb3NzaWJsZSBmb3IgdGhlIGhlaWdodCB0byBtYXggb3V0LCB3ZSBtaWdodCBuZWVkIHNjcm9sbGJhcnNcbiAgICAgICAgZ2V0U2VjdGlvbkhhc0xpcXVpZEhlaWdodChwcm9wcywgc2VjdGlvbkNvbmZpZyk7IC8vIGlmIHRoZSBzZWN0aW9uIGlzIGxpcXVpZCBoZWlnaHQsIGl0IG1pZ2h0IGNvbmRlbnNlIGVub3VnaCB0byByZXF1aXJlIHNjcm9sbGJhcnNcbn1cbi8vIFRPRE86IE9OTFkgdXNlIGBhcmdgLiBmb3JjZSBvdXQgaW50ZXJuYWwgZnVuY3Rpb24gdG8gdXNlIHNhbWUgQVBJXG5mdW5jdGlvbiByZW5kZXJDaHVua0NvbnRlbnQoc2VjdGlvbkNvbmZpZywgY2h1bmtDb25maWcsIGFyZywgaXNIZWFkZXIpIHtcbiAgICBsZXQgeyBleHBhbmRSb3dzIH0gPSBhcmc7XG4gICAgbGV0IGNvbnRlbnQgPSB0eXBlb2YgY2h1bmtDb25maWcuY29udGVudCA9PT0gJ2Z1bmN0aW9uJyA/XG4gICAgICAgIGNodW5rQ29uZmlnLmNvbnRlbnQoYXJnKSA6XG4gICAgICAgIGNyZWF0ZUVsZW1lbnQoJ3RhYmxlJywge1xuICAgICAgICAgICAgcm9sZTogJ3ByZXNlbnRhdGlvbicsXG4gICAgICAgICAgICBjbGFzc05hbWU6IFtcbiAgICAgICAgICAgICAgICBjaHVua0NvbmZpZy50YWJsZUNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICBzZWN0aW9uQ29uZmlnLnN5bmNSb3dIZWlnaHRzID8gJ2ZjLXNjcm9sbGdyaWQtc3luYy10YWJsZScgOiAnJyxcbiAgICAgICAgICAgIF0uam9pbignICcpLFxuICAgICAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgICAgICBtaW5XaWR0aDogYXJnLnRhYmxlTWluV2lkdGgsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGFyZy5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGV4cGFuZFJvd3MgPyBhcmcuY2xpZW50SGVpZ2h0IDogJycsIC8vIGNzcyBgaGVpZ2h0YCBvbiBhIDx0YWJsZT4gc2VydmVzIGFzIGEgbWluLWhlaWdodFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSwgYXJnLnRhYmxlQ29sR3JvdXBOb2RlLCBjcmVhdGVFbGVtZW50KGlzSGVhZGVyID8gJ3RoZWFkJyA6ICd0Ym9keScsIHtcbiAgICAgICAgICAgIHJvbGU6ICdwcmVzZW50YXRpb24nLFxuICAgICAgICB9LCB0eXBlb2YgY2h1bmtDb25maWcucm93Q29udGVudCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICAgICAgPyBjaHVua0NvbmZpZy5yb3dDb250ZW50KGFyZylcbiAgICAgICAgICAgIDogY2h1bmtDb25maWcucm93Q29udGVudCkpO1xuICAgIHJldHVybiBjb250ZW50O1xufVxuZnVuY3Rpb24gaXNDb2xQcm9wc0VxdWFsKGNvbHMwLCBjb2xzMSkge1xuICAgIHJldHVybiBpc0FycmF5c0VxdWFsKGNvbHMwLCBjb2xzMSwgaXNQcm9wc0VxdWFsKTtcbn1cbmZ1bmN0aW9uIHJlbmRlck1pY3JvQ29sR3JvdXAoY29scywgc2hyaW5rV2lkdGgpIHtcbiAgICBsZXQgY29sTm9kZXMgPSBbXTtcbiAgICAvKlxuICAgIGZvciBDb2xQcm9wcyB3aXRoIHNwYW5zLCBpdCB3b3VsZCBoYXZlIGJlZW4gZ3JlYXQgdG8gbWFrZSBhIHNpbmdsZSA8Y29sIHNwYW49XCJcIj5cbiAgICBIT1dFVkVSLCBDaHJvbWUgd2FzIGdldHRpbmcgbWVzc2luZyB1cCBkaXN0cmlidXRpbmcgdGhlIHdpZHRoIHRvIDx0ZD4vPHRoPiBlbGVtZW50cyB3aXRoIGNvbHNwYW5zLlxuICAgIFNPTFVUSU9OOiBtYWtpbmcgaW5kaXZpZHVhbCA8Y29sPiBlbGVtZW50cyBtYWtlcyBDaHJvbWUgYmVoYXZlLlxuICAgICovXG4gICAgZm9yIChsZXQgY29sUHJvcHMgb2YgY29scykge1xuICAgICAgICBsZXQgc3BhbiA9IGNvbFByb3BzLnNwYW4gfHwgMTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzcGFuOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGNvbE5vZGVzLnB1c2goY3JlYXRlRWxlbWVudChcImNvbFwiLCB7IHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBjb2xQcm9wcy53aWR0aCA9PT0gJ3NocmluaycgPyBzYW5pdGl6ZVNocmlua1dpZHRoKHNocmlua1dpZHRoKSA6IChjb2xQcm9wcy53aWR0aCB8fCAnJyksXG4gICAgICAgICAgICAgICAgICAgIG1pbldpZHRoOiBjb2xQcm9wcy5taW5XaWR0aCB8fCAnJyxcbiAgICAgICAgICAgICAgICB9IH0pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlRWxlbWVudCgnY29sZ3JvdXAnLCB7fSwgLi4uY29sTm9kZXMpO1xufVxuZnVuY3Rpb24gc2FuaXRpemVTaHJpbmtXaWR0aChzaHJpbmtXaWR0aCkge1xuICAgIC8qIHdoeSA0PyBpZiB3ZSBkbyAwLCBpdCB3aWxsIGtpbGwgYW55IGJvcmRlciwgd2hpY2ggYXJlIG5lZWRlZCBmb3IgY29tcHV0ZVNtYWxsZXN0Q2VsbFdpZHRoXG4gICAgNCBhY2NvdW50cyBmb3IgMiAyLXBpeGVsIGJvcmRlcnMuIFRPRE86IGJldHRlciBzb2x1dGlvbj8gKi9cbiAgICByZXR1cm4gc2hyaW5rV2lkdGggPT0gbnVsbCA/IDQgOiBzaHJpbmtXaWR0aDtcbn1cbmZ1bmN0aW9uIGhhc1Nocmlua1dpZHRoKGNvbHMpIHtcbiAgICBmb3IgKGxldCBjb2wgb2YgY29scykge1xuICAgICAgICBpZiAoY29sLndpZHRoID09PSAnc2hyaW5rJykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gZ2V0U2Nyb2xsR3JpZENsYXNzTmFtZXMobGlxdWlkLCBjb250ZXh0KSB7XG4gICAgbGV0IGNsYXNzTmFtZXMgPSBbXG4gICAgICAgICdmYy1zY3JvbGxncmlkJyxcbiAgICAgICAgY29udGV4dC50aGVtZS5nZXRDbGFzcygndGFibGUnKSxcbiAgICBdO1xuICAgIGlmIChsaXF1aWQpIHtcbiAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy1zY3JvbGxncmlkLWxpcXVpZCcpO1xuICAgIH1cbiAgICByZXR1cm4gY2xhc3NOYW1lcztcbn1cbmZ1bmN0aW9uIGdldFNlY3Rpb25DbGFzc05hbWVzKHNlY3Rpb25Db25maWcsIHdob2xlVGFibGVWR3Jvdykge1xuICAgIGxldCBjbGFzc05hbWVzID0gW1xuICAgICAgICAnZmMtc2Nyb2xsZ3JpZC1zZWN0aW9uJyxcbiAgICAgICAgYGZjLXNjcm9sbGdyaWQtc2VjdGlvbi0ke3NlY3Rpb25Db25maWcudHlwZX1gLFxuICAgICAgICBzZWN0aW9uQ29uZmlnLmNsYXNzTmFtZSwgLy8gdXNlZD9cbiAgICBdO1xuICAgIGlmICh3aG9sZVRhYmxlVkdyb3cgJiYgc2VjdGlvbkNvbmZpZy5saXF1aWQgJiYgc2VjdGlvbkNvbmZpZy5tYXhIZWlnaHQgPT0gbnVsbCkge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLXNjcm9sbGdyaWQtc2VjdGlvbi1saXF1aWQnKTtcbiAgICB9XG4gICAgaWYgKHNlY3Rpb25Db25maWcuaXNTdGlja3kpIHtcbiAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy1zY3JvbGxncmlkLXNlY3Rpb24tc3RpY2t5Jyk7XG4gICAgfVxuICAgIHJldHVybiBjbGFzc05hbWVzO1xufVxuZnVuY3Rpb24gcmVuZGVyU2Nyb2xsU2hpbShhcmcpIHtcbiAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtc2Nyb2xsZ3JpZC1zdGlja3ktc2hpbVwiLCBzdHlsZToge1xuICAgICAgICAgICAgd2lkdGg6IGFyZy5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgIG1pbldpZHRoOiBhcmcudGFibGVNaW5XaWR0aCxcbiAgICAgICAgfSB9KSk7XG59XG5mdW5jdGlvbiBnZXRTdGlja3lIZWFkZXJEYXRlcyhvcHRpb25zKSB7XG4gICAgbGV0IHsgc3RpY2t5SGVhZGVyRGF0ZXMgfSA9IG9wdGlvbnM7XG4gICAgaWYgKHN0aWNreUhlYWRlckRhdGVzID09IG51bGwgfHwgc3RpY2t5SGVhZGVyRGF0ZXMgPT09ICdhdXRvJykge1xuICAgICAgICBzdGlja3lIZWFkZXJEYXRlcyA9IG9wdGlvbnMuaGVpZ2h0ID09PSAnYXV0bycgfHwgb3B0aW9ucy52aWV3SGVpZ2h0ID09PSAnYXV0byc7XG4gICAgfVxuICAgIHJldHVybiBzdGlja3lIZWFkZXJEYXRlcztcbn1cbmZ1bmN0aW9uIGdldFN0aWNreUZvb3RlclNjcm9sbGJhcihvcHRpb25zKSB7XG4gICAgbGV0IHsgc3RpY2t5Rm9vdGVyU2Nyb2xsYmFyIH0gPSBvcHRpb25zO1xuICAgIGlmIChzdGlja3lGb290ZXJTY3JvbGxiYXIgPT0gbnVsbCB8fCBzdGlja3lGb290ZXJTY3JvbGxiYXIgPT09ICdhdXRvJykge1xuICAgICAgICBzdGlja3lGb290ZXJTY3JvbGxiYXIgPSBvcHRpb25zLmhlaWdodCA9PT0gJ2F1dG8nIHx8IG9wdGlvbnMudmlld0hlaWdodCA9PT0gJ2F1dG8nO1xuICAgIH1cbiAgICByZXR1cm4gc3RpY2t5Rm9vdGVyU2Nyb2xsYmFyO1xufVxuXG5jbGFzcyBTaW1wbGVTY3JvbGxHcmlkIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMucHJvY2Vzc0NvbHMgPSBtZW1vaXplKChhKSA9PiBhLCBpc0NvbFByb3BzRXF1YWwpOyAvLyBzbyB3ZSBnZXQgc2FtZSBgY29sc2AgcHJvcHMgZXZlcnkgdGltZVxuICAgICAgICAvLyB5dWNreSB0byBtZW1vaXplIFZOb2RlcywgYnV0IG11Y2ggbW9yZSBlZmZpY2llbnQgZm9yIGNvbnN1bWVyc1xuICAgICAgICB0aGlzLnJlbmRlck1pY3JvQ29sR3JvdXAgPSBtZW1vaXplKHJlbmRlck1pY3JvQ29sR3JvdXApO1xuICAgICAgICB0aGlzLnNjcm9sbGVyUmVmcyA9IG5ldyBSZWZNYXAoKTtcbiAgICAgICAgdGhpcy5zY3JvbGxlckVsUmVmcyA9IG5ldyBSZWZNYXAodGhpcy5faGFuZGxlU2Nyb2xsZXJFbC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHNocmlua1dpZHRoOiBudWxsLFxuICAgICAgICAgICAgZm9yY2VZU2Nyb2xsYmFyczogZmFsc2UsXG4gICAgICAgICAgICBzY3JvbGxlckNsaWVudFdpZHRoczoge30sXG4gICAgICAgICAgICBzY3JvbGxlckNsaWVudEhlaWdodHM6IHt9LFxuICAgICAgICB9O1xuICAgICAgICAvLyBUT0RPOiBjYW4gZG8gYSByZWFsbHkgc2ltcGxlIHByaW50LXZpZXcuIGRvbnQgbmVlZCB0byBqb2luIHJvd3NcbiAgICAgICAgdGhpcy5oYW5kbGVTaXppbmcgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNhZmVTZXRTdGF0ZShPYmplY3QuYXNzaWduKHsgc2hyaW5rV2lkdGg6IHRoaXMuY29tcHV0ZVNocmlua1dpZHRoKCkgfSwgdGhpcy5jb21wdXRlU2Nyb2xsZXJEaW1zKCkpKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcywgc3RhdGUsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCBzZWN0aW9uQ29uZmlncyA9IHByb3BzLnNlY3Rpb25zIHx8IFtdO1xuICAgICAgICBsZXQgY29scyA9IHRoaXMucHJvY2Vzc0NvbHMocHJvcHMuY29scyk7XG4gICAgICAgIGxldCBtaWNyb0NvbEdyb3VwTm9kZSA9IHRoaXMucmVuZGVyTWljcm9Db2xHcm91cChjb2xzLCBzdGF0ZS5zaHJpbmtXaWR0aCk7XG4gICAgICAgIGxldCBjbGFzc05hbWVzID0gZ2V0U2Nyb2xsR3JpZENsYXNzTmFtZXMocHJvcHMubGlxdWlkLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKHByb3BzLmNvbGxhcHNpYmxlV2lkdGgpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtc2Nyb2xsZ3JpZC1jb2xsYXBzaWJsZScpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IG1ha2UgRFJZXG4gICAgICAgIGxldCBjb25maWdDbnQgPSBzZWN0aW9uQ29uZmlncy5sZW5ndGg7XG4gICAgICAgIGxldCBjb25maWdJID0gMDtcbiAgICAgICAgbGV0IGN1cnJlbnRDb25maWc7XG4gICAgICAgIGxldCBoZWFkU2VjdGlvbk5vZGVzID0gW107XG4gICAgICAgIGxldCBib2R5U2VjdGlvbk5vZGVzID0gW107XG4gICAgICAgIGxldCBmb290U2VjdGlvbk5vZGVzID0gW107XG4gICAgICAgIHdoaWxlIChjb25maWdJIDwgY29uZmlnQ250ICYmIChjdXJyZW50Q29uZmlnID0gc2VjdGlvbkNvbmZpZ3NbY29uZmlnSV0pLnR5cGUgPT09ICdoZWFkZXInKSB7XG4gICAgICAgICAgICBoZWFkU2VjdGlvbk5vZGVzLnB1c2godGhpcy5yZW5kZXJTZWN0aW9uKGN1cnJlbnRDb25maWcsIG1pY3JvQ29sR3JvdXBOb2RlLCB0cnVlKSk7XG4gICAgICAgICAgICBjb25maWdJICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKGNvbmZpZ0kgPCBjb25maWdDbnQgJiYgKGN1cnJlbnRDb25maWcgPSBzZWN0aW9uQ29uZmlnc1tjb25maWdJXSkudHlwZSA9PT0gJ2JvZHknKSB7XG4gICAgICAgICAgICBib2R5U2VjdGlvbk5vZGVzLnB1c2godGhpcy5yZW5kZXJTZWN0aW9uKGN1cnJlbnRDb25maWcsIG1pY3JvQ29sR3JvdXBOb2RlLCBmYWxzZSkpO1xuICAgICAgICAgICAgY29uZmlnSSArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChjb25maWdJIDwgY29uZmlnQ250ICYmIChjdXJyZW50Q29uZmlnID0gc2VjdGlvbkNvbmZpZ3NbY29uZmlnSV0pLnR5cGUgPT09ICdmb290ZXInKSB7XG4gICAgICAgICAgICBmb290U2VjdGlvbk5vZGVzLnB1c2godGhpcy5yZW5kZXJTZWN0aW9uKGN1cnJlbnRDb25maWcsIG1pY3JvQ29sR3JvdXBOb2RlLCB0cnVlKSk7XG4gICAgICAgICAgICBjb25maWdJICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZmlyZWZveCBidWc6IHdoZW4gc2V0dGluZyBoZWlnaHQgb24gdGFibGUgYW5kIHRoZXJlIGlzIGEgdGhlYWQgb3IgdGZvb3QsXG4gICAgICAgIC8vIHRoZSBuZWNlc3NhcnkgaGVpZ2h0OjEwMCUgb24gdGhlIGxpcXVpZC1oZWlnaHQgYm9keSBzZWN0aW9uIGZvcmNlcyB0aGUgKndob2xlKiB0YWJsZSB0byBiZSB0YWxsZXIuIChidWcgIzU1MjQpXG4gICAgICAgIC8vIHVzZSBnZXRDYW5WR3Jvd1dpdGhpbkNlbGwgYXMgYSB3YXkgdG8gZGV0ZWN0IHRhYmxlLXN0dXBpZCBmaXJlZm94LlxuICAgICAgICAvLyBpZiBzbywgdXNlIGEgc2ltcGxlciBkb20gc3RydWN0dXJlLCBqYW0gZXZlcnl0aGluZyBpbnRvIGEgbG9uZSB0Ym9keS5cbiAgICAgICAgbGV0IGlzQnVnZ3kgPSAhZ2V0Q2FuVkdyb3dXaXRoaW5DZWxsKCk7XG4gICAgICAgIGNvbnN0IHJvbGVBdHRycyA9IHsgcm9sZTogJ3Jvd2dyb3VwJyB9O1xuICAgICAgICByZXR1cm4gY3JlYXRlRWxlbWVudCgndGFibGUnLCB7XG4gICAgICAgICAgICByb2xlOiAnZ3JpZCcsXG4gICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZXMuam9pbignICcpLFxuICAgICAgICAgICAgc3R5bGU6IHsgaGVpZ2h0OiBwcm9wcy5oZWlnaHQgfSxcbiAgICAgICAgfSwgQm9vbGVhbighaXNCdWdneSAmJiBoZWFkU2VjdGlvbk5vZGVzLmxlbmd0aCkgJiYgY3JlYXRlRWxlbWVudCgndGhlYWQnLCByb2xlQXR0cnMsIC4uLmhlYWRTZWN0aW9uTm9kZXMpLCBCb29sZWFuKCFpc0J1Z2d5ICYmIGJvZHlTZWN0aW9uTm9kZXMubGVuZ3RoKSAmJiBjcmVhdGVFbGVtZW50KCd0Ym9keScsIHJvbGVBdHRycywgLi4uYm9keVNlY3Rpb25Ob2RlcyksIEJvb2xlYW4oIWlzQnVnZ3kgJiYgZm9vdFNlY3Rpb25Ob2Rlcy5sZW5ndGgpICYmIGNyZWF0ZUVsZW1lbnQoJ3Rmb290Jywgcm9sZUF0dHJzLCAuLi5mb290U2VjdGlvbk5vZGVzKSwgaXNCdWdneSAmJiBjcmVhdGVFbGVtZW50KCd0Ym9keScsIHJvbGVBdHRycywgLi4uaGVhZFNlY3Rpb25Ob2RlcywgLi4uYm9keVNlY3Rpb25Ob2RlcywgLi4uZm9vdFNlY3Rpb25Ob2RlcykpO1xuICAgIH1cbiAgICByZW5kZXJTZWN0aW9uKHNlY3Rpb25Db25maWcsIG1pY3JvQ29sR3JvdXBOb2RlLCBpc0hlYWRlcikge1xuICAgICAgICBpZiAoJ291dGVyQ29udGVudCcgaW4gc2VjdGlvbkNvbmZpZykge1xuICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCB7IGtleTogc2VjdGlvbkNvbmZpZy5rZXkgfSwgc2VjdGlvbkNvbmZpZy5vdXRlckNvbnRlbnQpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7IGtleTogc2VjdGlvbkNvbmZpZy5rZXksIHJvbGU6IFwicHJlc2VudGF0aW9uXCIsIGNsYXNzTmFtZTogZ2V0U2VjdGlvbkNsYXNzTmFtZXMoc2VjdGlvbkNvbmZpZywgdGhpcy5wcm9wcy5saXF1aWQpLmpvaW4oJyAnKSB9LCB0aGlzLnJlbmRlckNodW5rVGQoc2VjdGlvbkNvbmZpZywgbWljcm9Db2xHcm91cE5vZGUsIHNlY3Rpb25Db25maWcuY2h1bmssIGlzSGVhZGVyKSkpO1xuICAgIH1cbiAgICByZW5kZXJDaHVua1RkKHNlY3Rpb25Db25maWcsIG1pY3JvQ29sR3JvdXBOb2RlLCBjaHVua0NvbmZpZywgaXNIZWFkZXIpIHtcbiAgICAgICAgaWYgKCdvdXRlckNvbnRlbnQnIGluIGNodW5rQ29uZmlnKSB7XG4gICAgICAgICAgICByZXR1cm4gY2h1bmtDb25maWcub3V0ZXJDb250ZW50O1xuICAgICAgICB9XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBmb3JjZVlTY3JvbGxiYXJzLCBzY3JvbGxlckNsaWVudFdpZHRocywgc2Nyb2xsZXJDbGllbnRIZWlnaHRzIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICBsZXQgbmVlZHNZU2Nyb2xsaW5nID0gZ2V0QWxsb3dZU2Nyb2xsaW5nKHByb3BzLCBzZWN0aW9uQ29uZmlnKTsgLy8gVE9ETzogZG8gbGF6aWx5LiBkbyBpbiBzZWN0aW9uIGNvbmZpZz9cbiAgICAgICAgbGV0IGlzTGlxdWlkID0gZ2V0U2VjdGlvbkhhc0xpcXVpZEhlaWdodChwcm9wcywgc2VjdGlvbkNvbmZpZyk7XG4gICAgICAgIC8vIGZvciBgIXByb3BzLmxpcXVpZGAgLSBpcyBXSE9MRSBzY3JvbGxncmlkIG5hdHVyYWwgaGVpZ2h0P1xuICAgICAgICAvLyBUT0RPOiBkbyBzYW1lIHRoaW5nIGluIGFkdmFuY2VkIHNjcm9sbGdyaWQ/IHByb2xseSBub3QgYi9jIGFsd2F5cyBoYXMgaG9yaXpvbnRhbCBzY3JvbGxiYXJzXG4gICAgICAgIGxldCBvdmVyZmxvd1kgPSAhcHJvcHMubGlxdWlkID8gJ3Zpc2libGUnIDpcbiAgICAgICAgICAgIGZvcmNlWVNjcm9sbGJhcnMgPyAnc2Nyb2xsJyA6XG4gICAgICAgICAgICAgICAgIW5lZWRzWVNjcm9sbGluZyA/ICdoaWRkZW4nIDpcbiAgICAgICAgICAgICAgICAgICAgJ2F1dG8nO1xuICAgICAgICBsZXQgc2VjdGlvbktleSA9IHNlY3Rpb25Db25maWcua2V5O1xuICAgICAgICBsZXQgY29udGVudCA9IHJlbmRlckNodW5rQ29udGVudChzZWN0aW9uQ29uZmlnLCBjaHVua0NvbmZpZywge1xuICAgICAgICAgICAgdGFibGVDb2xHcm91cE5vZGU6IG1pY3JvQ29sR3JvdXBOb2RlLFxuICAgICAgICAgICAgdGFibGVNaW5XaWR0aDogJycsXG4gICAgICAgICAgICBjbGllbnRXaWR0aDogKCFwcm9wcy5jb2xsYXBzaWJsZVdpZHRoICYmIHNjcm9sbGVyQ2xpZW50V2lkdGhzW3NlY3Rpb25LZXldICE9PSB1bmRlZmluZWQpID8gc2Nyb2xsZXJDbGllbnRXaWR0aHNbc2VjdGlvbktleV0gOiBudWxsLFxuICAgICAgICAgICAgY2xpZW50SGVpZ2h0OiBzY3JvbGxlckNsaWVudEhlaWdodHNbc2VjdGlvbktleV0gIT09IHVuZGVmaW5lZCA/IHNjcm9sbGVyQ2xpZW50SGVpZ2h0c1tzZWN0aW9uS2V5XSA6IG51bGwsXG4gICAgICAgICAgICBleHBhbmRSb3dzOiBzZWN0aW9uQ29uZmlnLmV4cGFuZFJvd3MsXG4gICAgICAgICAgICBzeW5jUm93SGVpZ2h0czogZmFsc2UsXG4gICAgICAgICAgICByb3dTeW5jSGVpZ2h0czogW10sXG4gICAgICAgICAgICByZXBvcnRSb3dIZWlnaHRDaGFuZ2U6ICgpID0+IHsgfSxcbiAgICAgICAgfSwgaXNIZWFkZXIpO1xuICAgICAgICByZXR1cm4gY3JlYXRlRWxlbWVudChpc0hlYWRlciA/ICd0aCcgOiAndGQnLCB7XG4gICAgICAgICAgICByZWY6IGNodW5rQ29uZmlnLmVsUmVmLFxuICAgICAgICAgICAgcm9sZTogJ3ByZXNlbnRhdGlvbicsXG4gICAgICAgIH0sIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IGBmYy1zY3JvbGxlci1oYXJuZXNzJHtpc0xpcXVpZCA/ICcgZmMtc2Nyb2xsZXItaGFybmVzcy1saXF1aWQnIDogJyd9YCB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChTY3JvbGxlciwgeyByZWY6IHRoaXMuc2Nyb2xsZXJSZWZzLmNyZWF0ZVJlZihzZWN0aW9uS2V5KSwgZWxSZWY6IHRoaXMuc2Nyb2xsZXJFbFJlZnMuY3JlYXRlUmVmKHNlY3Rpb25LZXkpLCBvdmVyZmxvd1k6IG92ZXJmbG93WSwgb3ZlcmZsb3dYOiAhcHJvcHMubGlxdWlkID8gJ3Zpc2libGUnIDogJ2hpZGRlbicgLyogbmF0dXJhbCBoZWlnaHQ/ICovLCBtYXhIZWlnaHQ6IHNlY3Rpb25Db25maWcubWF4SGVpZ2h0LCBsaXF1aWQ6IGlzTGlxdWlkLCBsaXF1aWRJc0Fic29sdXRlIC8vIGJlY2F1c2UgaXRzIHdpdGhpbiBhIGhhcm5lc3NcbiAgICAgICAgICAgICAgICA6IHRydWUgfSwgY29udGVudCkpKTtcbiAgICB9XG4gICAgX2hhbmRsZVNjcm9sbGVyRWwoc2Nyb2xsZXJFbCwga2V5KSB7XG4gICAgICAgIGxldCBzZWN0aW9uID0gZ2V0U2VjdGlvbkJ5S2V5KHRoaXMucHJvcHMuc2VjdGlvbnMsIGtleSk7XG4gICAgICAgIGlmIChzZWN0aW9uKSB7XG4gICAgICAgICAgICBzZXRSZWYoc2VjdGlvbi5jaHVuay5zY3JvbGxlckVsUmVmLCBzY3JvbGxlckVsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVTaXppbmcoKTtcbiAgICAgICAgdGhpcy5jb250ZXh0LmFkZFJlc2l6ZUhhbmRsZXIodGhpcy5oYW5kbGVTaXppbmcpO1xuICAgIH1cbiAgICBjb21wb25lbnREaWRVcGRhdGUoKSB7XG4gICAgICAgIC8vIFRPRE86IG5lZWQgYmV0dGVyIHNvbHV0aW9uIHdoZW4gc3RhdGUgY29udGFpbnMgbm9uLXNpemluZyB0aGluZ3NcbiAgICAgICAgdGhpcy5oYW5kbGVTaXppbmcoKTtcbiAgICB9XG4gICAgY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgICAgIHRoaXMuY29udGV4dC5yZW1vdmVSZXNpemVIYW5kbGVyKHRoaXMuaGFuZGxlU2l6aW5nKTtcbiAgICB9XG4gICAgY29tcHV0ZVNocmlua1dpZHRoKCkge1xuICAgICAgICByZXR1cm4gaGFzU2hyaW5rV2lkdGgodGhpcy5wcm9wcy5jb2xzKVxuICAgICAgICAgICAgPyBjb21wdXRlU2hyaW5rV2lkdGgodGhpcy5zY3JvbGxlckVsUmVmcy5nZXRBbGwoKSlcbiAgICAgICAgICAgIDogMDtcbiAgICB9XG4gICAgY29tcHV0ZVNjcm9sbGVyRGltcygpIHtcbiAgICAgICAgbGV0IHNjcm9sbGJhcldpZHRoID0gZ2V0U2Nyb2xsYmFyV2lkdGhzKCk7XG4gICAgICAgIGxldCB7IHNjcm9sbGVyUmVmcywgc2Nyb2xsZXJFbFJlZnMgfSA9IHRoaXM7XG4gICAgICAgIGxldCBmb3JjZVlTY3JvbGxiYXJzID0gZmFsc2U7XG4gICAgICAgIGxldCBzY3JvbGxlckNsaWVudFdpZHRocyA9IHt9O1xuICAgICAgICBsZXQgc2Nyb2xsZXJDbGllbnRIZWlnaHRzID0ge307XG4gICAgICAgIGZvciAobGV0IHNlY3Rpb25LZXkgaW4gc2Nyb2xsZXJSZWZzLmN1cnJlbnRNYXApIHtcbiAgICAgICAgICAgIGxldCBzY3JvbGxlciA9IHNjcm9sbGVyUmVmcy5jdXJyZW50TWFwW3NlY3Rpb25LZXldO1xuICAgICAgICAgICAgaWYgKHNjcm9sbGVyICYmIHNjcm9sbGVyLm5lZWRzWVNjcm9sbGluZygpKSB7XG4gICAgICAgICAgICAgICAgZm9yY2VZU2Nyb2xsYmFycyA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgc2VjdGlvbiBvZiB0aGlzLnByb3BzLnNlY3Rpb25zKSB7XG4gICAgICAgICAgICBsZXQgc2VjdGlvbktleSA9IHNlY3Rpb24ua2V5O1xuICAgICAgICAgICAgbGV0IHNjcm9sbGVyRWwgPSBzY3JvbGxlckVsUmVmcy5jdXJyZW50TWFwW3NlY3Rpb25LZXldO1xuICAgICAgICAgICAgaWYgKHNjcm9sbGVyRWwpIHtcbiAgICAgICAgICAgICAgICBsZXQgaGFybmVzc0VsID0gc2Nyb2xsZXJFbC5wYXJlbnROb2RlOyAvLyBUT0RPOiB3ZWlyZCB3YXkgdG8gZ2V0IHRoaXMuIG5lZWQgaGFybmVzcyBiL2MgZG9lc24ndCBpbmNsdWRlIHRhYmxlIGJvcmRlcnNcbiAgICAgICAgICAgICAgICBzY3JvbGxlckNsaWVudFdpZHRoc1tzZWN0aW9uS2V5XSA9IE1hdGguZmxvb3IoaGFybmVzc0VsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC0gKGZvcmNlWVNjcm9sbGJhcnNcbiAgICAgICAgICAgICAgICAgICAgPyBzY3JvbGxiYXJXaWR0aC55IC8vIHVzZSBnbG9iYWwgYmVjYXVzZSBzY3JvbGxlciBtaWdodCBub3QgaGF2ZSBzY3JvbGxiYXJzIHlldCBidXQgd2lsbCBuZWVkIHRoZW0gaW4gZnV0dXJlXG4gICAgICAgICAgICAgICAgICAgIDogMCkpO1xuICAgICAgICAgICAgICAgIHNjcm9sbGVyQ2xpZW50SGVpZ2h0c1tzZWN0aW9uS2V5XSA9IE1hdGguZmxvb3IoaGFybmVzc0VsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZm9yY2VZU2Nyb2xsYmFycywgc2Nyb2xsZXJDbGllbnRXaWR0aHMsIHNjcm9sbGVyQ2xpZW50SGVpZ2h0cyB9O1xuICAgIH1cbn1cblNpbXBsZVNjcm9sbEdyaWQuYWRkU3RhdGVFcXVhbGl0eSh7XG4gICAgc2Nyb2xsZXJDbGllbnRXaWR0aHM6IGlzUHJvcHNFcXVhbCxcbiAgICBzY3JvbGxlckNsaWVudEhlaWdodHM6IGlzUHJvcHNFcXVhbCxcbn0pO1xuZnVuY3Rpb24gZ2V0U2VjdGlvbkJ5S2V5KHNlY3Rpb25zLCBrZXkpIHtcbiAgICBmb3IgKGxldCBzZWN0aW9uIG9mIHNlY3Rpb25zKSB7XG4gICAgICAgIGlmIChzZWN0aW9uLmtleSA9PT0ga2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gc2VjdGlvbjtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuY2xhc3MgRXZlbnRDb250YWluZXIgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgLy8gbWVtb1xuICAgICAgICB0aGlzLmJ1aWxkUHVibGljRXZlbnQgPSBtZW1vaXplKChjb250ZXh0LCBldmVudERlZiwgZXZlbnRJbnN0YW5jZSkgPT4gbmV3IEV2ZW50SW1wbChjb250ZXh0LCBldmVudERlZiwgZXZlbnRJbnN0YW5jZSkpO1xuICAgICAgICB0aGlzLmhhbmRsZUVsID0gKGVsKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgICAgICAgICBzZXRSZWYodGhpcy5wcm9wcy5lbFJlZiwgZWwpO1xuICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgICAgc2V0RWxTZWcoZWwsIHRoaXMucHJvcHMuc2VnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBjb25zdCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBjb25zdCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgICAgIGNvbnN0IHsgc2VnIH0gPSBwcm9wcztcbiAgICAgICAgY29uc3QgeyBldmVudFJhbmdlIH0gPSBzZWc7XG4gICAgICAgIGNvbnN0IHsgdWkgfSA9IGV2ZW50UmFuZ2U7XG4gICAgICAgIGNvbnN0IHJlbmRlclByb3BzID0ge1xuICAgICAgICAgICAgZXZlbnQ6IHRoaXMuYnVpbGRQdWJsaWNFdmVudChjb250ZXh0LCBldmVudFJhbmdlLmRlZiwgZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICB2aWV3OiBjb250ZXh0LnZpZXdBcGksXG4gICAgICAgICAgICB0aW1lVGV4dDogcHJvcHMudGltZVRleHQsXG4gICAgICAgICAgICB0ZXh0Q29sb3I6IHVpLnRleHRDb2xvcixcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogdWkuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgYm9yZGVyQ29sb3I6IHVpLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgaXNEcmFnZ2FibGU6ICFwcm9wcy5kaXNhYmxlRHJhZ2dpbmcgJiYgY29tcHV0ZVNlZ0RyYWdnYWJsZShzZWcsIGNvbnRleHQpLFxuICAgICAgICAgICAgaXNTdGFydFJlc2l6YWJsZTogIXByb3BzLmRpc2FibGVSZXNpemluZyAmJiBjb21wdXRlU2VnU3RhcnRSZXNpemFibGUoc2VnLCBjb250ZXh0KSxcbiAgICAgICAgICAgIGlzRW5kUmVzaXphYmxlOiAhcHJvcHMuZGlzYWJsZVJlc2l6aW5nICYmIGNvbXB1dGVTZWdFbmRSZXNpemFibGUoc2VnKSxcbiAgICAgICAgICAgIGlzTWlycm9yOiBCb29sZWFuKHByb3BzLmlzRHJhZ2dpbmcgfHwgcHJvcHMuaXNSZXNpemluZyB8fCBwcm9wcy5pc0RhdGVTZWxlY3RpbmcpLFxuICAgICAgICAgICAgaXNTdGFydDogQm9vbGVhbihzZWcuaXNTdGFydCksXG4gICAgICAgICAgICBpc0VuZDogQm9vbGVhbihzZWcuaXNFbmQpLFxuICAgICAgICAgICAgaXNQYXN0OiBCb29sZWFuKHByb3BzLmlzUGFzdCksXG4gICAgICAgICAgICBpc0Z1dHVyZTogQm9vbGVhbihwcm9wcy5pc0Z1dHVyZSksXG4gICAgICAgICAgICBpc1RvZGF5OiBCb29sZWFuKHByb3BzLmlzVG9kYXkpLFxuICAgICAgICAgICAgaXNTZWxlY3RlZDogQm9vbGVhbihwcm9wcy5pc1NlbGVjdGVkKSxcbiAgICAgICAgICAgIGlzRHJhZ2dpbmc6IEJvb2xlYW4ocHJvcHMuaXNEcmFnZ2luZyksXG4gICAgICAgICAgICBpc1Jlc2l6aW5nOiBCb29sZWFuKHByb3BzLmlzUmVzaXppbmcpLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoQ29udGVudENvbnRhaW5lciwgeyBlbFJlZjogdGhpcy5oYW5kbGVFbCwgZWxUYWc6IHByb3BzLmVsVGFnLCBlbEF0dHJzOiBwcm9wcy5lbEF0dHJzLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAuLi5nZXRFdmVudENsYXNzTmFtZXMocmVuZGVyUHJvcHMpLFxuICAgICAgICAgICAgICAgIC4uLnNlZy5ldmVudFJhbmdlLnVpLmNsYXNzTmFtZXMsXG4gICAgICAgICAgICAgICAgLi4uKHByb3BzLmVsQ2xhc3NlcyB8fCBbXSksXG4gICAgICAgICAgICBdLCBlbFN0eWxlOiBwcm9wcy5lbFN0eWxlLCByZW5kZXJQcm9wczogcmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IFwiZXZlbnRDb250ZW50XCIsIGN1c3RvbUdlbmVyYXRvcjogb3B0aW9ucy5ldmVudENvbnRlbnQsIGRlZmF1bHRHZW5lcmF0b3I6IHByb3BzLmRlZmF1bHRHZW5lcmF0b3IsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5ldmVudENsYXNzTmFtZXMsIGRpZE1vdW50OiBvcHRpb25zLmV2ZW50RGlkTW91bnQsIHdpbGxVbm1vdW50OiBvcHRpb25zLmV2ZW50V2lsbFVubW91bnQgfSwgcHJvcHMuY2hpbGRyZW4pKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkVXBkYXRlKHByZXZQcm9wcykge1xuICAgICAgICBpZiAodGhpcy5lbCAmJiB0aGlzLnByb3BzLnNlZyAhPT0gcHJldlByb3BzLnNlZykge1xuICAgICAgICAgICAgc2V0RWxTZWcodGhpcy5lbCwgdGhpcy5wcm9wcy5zZWcpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBzaG91bGQgbm90IGJlIGEgcHVyZWNvbXBvbmVudFxuY2xhc3MgU3RhbmRhcmRFdmVudCBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgICAgIGxldCB7IHNlZyB9ID0gcHJvcHM7XG4gICAgICAgIGxldCB7IHVpIH0gPSBzZWcuZXZlbnRSYW5nZTtcbiAgICAgICAgbGV0IHRpbWVGb3JtYXQgPSBvcHRpb25zLmV2ZW50VGltZUZvcm1hdCB8fCBwcm9wcy5kZWZhdWx0VGltZUZvcm1hdDtcbiAgICAgICAgbGV0IHRpbWVUZXh0ID0gYnVpbGRTZWdUaW1lVGV4dChzZWcsIHRpbWVGb3JtYXQsIGNvbnRleHQsIHByb3BzLmRlZmF1bHREaXNwbGF5RXZlbnRUaW1lLCBwcm9wcy5kZWZhdWx0RGlzcGxheUV2ZW50RW5kKTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEV2ZW50Q29udGFpbmVyLCBPYmplY3QuYXNzaWduKHt9LCBwcm9wcyAvKiBpbmNsdWRlcyBlbFJlZiAqLywgeyBlbFRhZzogXCJhXCIsIGVsU3R5bGU6IHtcbiAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogdWkuYm9yZGVyQ29sb3IsXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yOiB1aS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICB9LCBlbEF0dHJzOiBnZXRTZWdBbmNob3JBdHRycyhzZWcsIGNvbnRleHQpLCBkZWZhdWx0R2VuZXJhdG9yOiByZW5kZXJJbm5lckNvbnRlbnQkMSwgdGltZVRleHQ6IHRpbWVUZXh0IH0pLCAoSW5uZXJDb250ZW50LCBldmVudENvbnRlbnRBcmcpID0+IChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChJbm5lckNvbnRlbnQsIHsgZWxUYWc6IFwiZGl2XCIsIGVsQ2xhc3NlczogWydmYy1ldmVudC1tYWluJ10sIGVsU3R5bGU6IHsgY29sb3I6IGV2ZW50Q29udGVudEFyZy50ZXh0Q29sb3IgfSB9KSxcbiAgICAgICAgICAgIEJvb2xlYW4oZXZlbnRDb250ZW50QXJnLmlzU3RhcnRSZXNpemFibGUpICYmIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWV2ZW50LXJlc2l6ZXIgZmMtZXZlbnQtcmVzaXplci1zdGFydFwiIH0pKSxcbiAgICAgICAgICAgIEJvb2xlYW4oZXZlbnRDb250ZW50QXJnLmlzRW5kUmVzaXphYmxlKSAmJiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy1ldmVudC1yZXNpemVyIGZjLWV2ZW50LXJlc2l6ZXItZW5kXCIgfSkpKSkpKTtcbiAgICB9XG59XG5TdGFuZGFyZEV2ZW50LmFkZFByb3BzRXF1YWxpdHkoe1xuICAgIHNlZzogaXNQcm9wc0VxdWFsLFxufSk7XG5mdW5jdGlvbiByZW5kZXJJbm5lckNvbnRlbnQkMShpbm5lclByb3BzKSB7XG4gICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWV2ZW50LW1haW4tZnJhbWVcIiB9LFxuICAgICAgICBpbm5lclByb3BzLnRpbWVUZXh0ICYmIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWV2ZW50LXRpbWVcIiB9LCBpbm5lclByb3BzLnRpbWVUZXh0KSksXG4gICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtZXZlbnQtdGl0bGUtY29udGFpbmVyXCIgfSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtZXZlbnQtdGl0bGUgZmMtc3RpY2t5XCIgfSwgaW5uZXJQcm9wcy5ldmVudC50aXRsZSB8fCBjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLCBcIlxcdTAwQTBcIikpKSkpO1xufVxuXG5jb25zdCBOb3dJbmRpY2F0b3JDb250YWluZXIgPSAocHJvcHMpID0+IChjcmVhdGVFbGVtZW50KFZpZXdDb250ZXh0VHlwZS5Db25zdW1lciwgbnVsbCwgKGNvbnRleHQpID0+IHtcbiAgICBsZXQgeyBvcHRpb25zIH0gPSBjb250ZXh0O1xuICAgIGxldCByZW5kZXJQcm9wcyA9IHtcbiAgICAgICAgaXNBeGlzOiBwcm9wcy5pc0F4aXMsXG4gICAgICAgIGRhdGU6IGNvbnRleHQuZGF0ZUVudi50b0RhdGUocHJvcHMuZGF0ZSksXG4gICAgICAgIHZpZXc6IGNvbnRleHQudmlld0FwaSxcbiAgICB9O1xuICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChDb250ZW50Q29udGFpbmVyLCB7IGVsUmVmOiBwcm9wcy5lbFJlZiwgZWxUYWc6IHByb3BzLmVsVGFnIHx8ICdkaXYnLCBlbEF0dHJzOiBwcm9wcy5lbEF0dHJzLCBlbENsYXNzZXM6IHByb3BzLmVsQ2xhc3NlcywgZWxTdHlsZTogcHJvcHMuZWxTdHlsZSwgcmVuZGVyUHJvcHM6IHJlbmRlclByb3BzLCBnZW5lcmF0b3JOYW1lOiBcIm5vd0luZGljYXRvckNvbnRlbnRcIiwgY3VzdG9tR2VuZXJhdG9yOiBvcHRpb25zLm5vd0luZGljYXRvckNvbnRlbnQsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5ub3dJbmRpY2F0b3JDbGFzc05hbWVzLCBkaWRNb3VudDogb3B0aW9ucy5ub3dJbmRpY2F0b3JEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMubm93SW5kaWNhdG9yV2lsbFVubW91bnQgfSwgcHJvcHMuY2hpbGRyZW4pKTtcbn0pKTtcblxuY29uc3QgREFZX05VTV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoeyBkYXk6ICdudW1lcmljJyB9KTtcbmNsYXNzIERheUNlbGxDb250YWluZXIgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5yZWZpbmVSZW5kZXJQcm9wcyA9IG1lbW9pemVPYmpBcmcocmVmaW5lUmVuZGVyUHJvcHMpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBvcHRpb25zIH0gPSBjb250ZXh0O1xuICAgICAgICBsZXQgcmVuZGVyUHJvcHMgPSB0aGlzLnJlZmluZVJlbmRlclByb3BzKHtcbiAgICAgICAgICAgIGRhdGU6IHByb3BzLmRhdGUsXG4gICAgICAgICAgICBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICB0b2RheVJhbmdlOiBwcm9wcy50b2RheVJhbmdlLFxuICAgICAgICAgICAgaXNNb250aFN0YXJ0OiBwcm9wcy5pc01vbnRoU3RhcnQgfHwgZmFsc2UsXG4gICAgICAgICAgICBzaG93RGF5TnVtYmVyOiBwcm9wcy5zaG93RGF5TnVtYmVyLFxuICAgICAgICAgICAgZXh0cmFSZW5kZXJQcm9wczogcHJvcHMuZXh0cmFSZW5kZXJQcm9wcyxcbiAgICAgICAgICAgIHZpZXdBcGk6IGNvbnRleHQudmlld0FwaSxcbiAgICAgICAgICAgIGRhdGVFbnY6IGNvbnRleHQuZGF0ZUVudixcbiAgICAgICAgICAgIG1vbnRoU3RhcnRGb3JtYXQ6IG9wdGlvbnMubW9udGhTdGFydEZvcm1hdCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChDb250ZW50Q29udGFpbmVyLCB7IGVsUmVmOiBwcm9wcy5lbFJlZiwgZWxUYWc6IHByb3BzLmVsVGFnLCBlbEF0dHJzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByb3BzLmVsQXR0cnMpLCAocmVuZGVyUHJvcHMuaXNEaXNhYmxlZCA/IHt9IDogeyAnZGF0YS1kYXRlJzogZm9ybWF0RGF5U3RyaW5nKHByb3BzLmRhdGUpIH0pKSwgZWxDbGFzc2VzOiBbXG4gICAgICAgICAgICAgICAgLi4uZ2V0RGF5Q2xhc3NOYW1lcyhyZW5kZXJQcm9wcywgY29udGV4dC50aGVtZSksXG4gICAgICAgICAgICAgICAgLi4uKHByb3BzLmVsQ2xhc3NlcyB8fCBbXSksXG4gICAgICAgICAgICBdLCBlbFN0eWxlOiBwcm9wcy5lbFN0eWxlLCByZW5kZXJQcm9wczogcmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IFwiZGF5Q2VsbENvbnRlbnRcIiwgY3VzdG9tR2VuZXJhdG9yOiBvcHRpb25zLmRheUNlbGxDb250ZW50LCBkZWZhdWx0R2VuZXJhdG9yOiBwcm9wcy5kZWZhdWx0R2VuZXJhdG9yLCBjbGFzc05hbWVHZW5lcmF0b3I6IFxuICAgICAgICAgICAgLy8gZG9uJ3QgdXNlIGN1c3RvbSBjbGFzc05hbWVzIGlmIGRpc2FibGVkXG4gICAgICAgICAgICByZW5kZXJQcm9wcy5pc0Rpc2FibGVkID8gdW5kZWZpbmVkIDogb3B0aW9ucy5kYXlDZWxsQ2xhc3NOYW1lcywgZGlkTW91bnQ6IG9wdGlvbnMuZGF5Q2VsbERpZE1vdW50LCB3aWxsVW5tb3VudDogb3B0aW9ucy5kYXlDZWxsV2lsbFVubW91bnQgfSwgcHJvcHMuY2hpbGRyZW4pKTtcbiAgICB9XG59XG5mdW5jdGlvbiBoYXNDdXN0b21EYXlDZWxsQ29udGVudChvcHRpb25zKSB7XG4gICAgcmV0dXJuIEJvb2xlYW4ob3B0aW9ucy5kYXlDZWxsQ29udGVudCB8fCBoYXNDdXN0b21SZW5kZXJpbmdIYW5kbGVyKCdkYXlDZWxsQ29udGVudCcsIG9wdGlvbnMpKTtcbn1cbmZ1bmN0aW9uIHJlZmluZVJlbmRlclByb3BzKHJhdykge1xuICAgIGxldCB7IGRhdGUsIGRhdGVFbnYsIGRhdGVQcm9maWxlLCBpc01vbnRoU3RhcnQgfSA9IHJhdztcbiAgICBsZXQgZGF5TWV0YSA9IGdldERhdGVNZXRhKGRhdGUsIHJhdy50b2RheVJhbmdlLCBudWxsLCBkYXRlUHJvZmlsZSk7XG4gICAgbGV0IGRheU51bWJlclRleHQgPSByYXcuc2hvd0RheU51bWJlciA/IChkYXRlRW52LmZvcm1hdChkYXRlLCBpc01vbnRoU3RhcnQgPyByYXcubW9udGhTdGFydEZvcm1hdCA6IERBWV9OVU1fRk9STUFUKSkgOiAnJztcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oeyBkYXRlOiBkYXRlRW52LnRvRGF0ZShkYXRlKSwgdmlldzogcmF3LnZpZXdBcGkgfSwgZGF5TWV0YSksIHsgaXNNb250aFN0YXJ0LFxuICAgICAgICBkYXlOdW1iZXJUZXh0IH0pLCByYXcuZXh0cmFSZW5kZXJQcm9wcyk7XG59XG5cbmNsYXNzIEJnRXZlbnQgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBzZWcgfSA9IHByb3BzO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoRXZlbnRDb250YWluZXIsIHsgZWxUYWc6IFwiZGl2XCIsIGVsQ2xhc3NlczogWydmYy1iZy1ldmVudCddLCBlbFN0eWxlOiB7IGJhY2tncm91bmRDb2xvcjogc2VnLmV2ZW50UmFuZ2UudWkuYmFja2dyb3VuZENvbG9yIH0sIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlcklubmVyQ29udGVudCwgc2VnOiBzZWcsIHRpbWVUZXh0OiBcIlwiLCBpc0RyYWdnaW5nOiBmYWxzZSwgaXNSZXNpemluZzogZmFsc2UsIGlzRGF0ZVNlbGVjdGluZzogZmFsc2UsIGlzU2VsZWN0ZWQ6IGZhbHNlLCBpc1Bhc3Q6IHByb3BzLmlzUGFzdCwgaXNGdXR1cmU6IHByb3BzLmlzRnV0dXJlLCBpc1RvZGF5OiBwcm9wcy5pc1RvZGF5LCBkaXNhYmxlRHJhZ2dpbmc6IHRydWUsIGRpc2FibGVSZXNpemluZzogdHJ1ZSB9KSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVuZGVySW5uZXJDb250ZW50KHByb3BzKSB7XG4gICAgbGV0IHsgdGl0bGUgfSA9IHByb3BzLmV2ZW50O1xuICAgIHJldHVybiB0aXRsZSAmJiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy1ldmVudC10aXRsZVwiIH0sIHByb3BzLmV2ZW50LnRpdGxlKSk7XG59XG5mdW5jdGlvbiByZW5kZXJGaWxsKGZpbGxUeXBlKSB7XG4gICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBgZmMtJHtmaWxsVHlwZX1gIH0pKTtcbn1cblxuY29uc3QgV2Vla051bWJlckNvbnRhaW5lciA9IChwcm9wcykgPT4gKGNyZWF0ZUVsZW1lbnQoVmlld0NvbnRleHRUeXBlLkNvbnN1bWVyLCBudWxsLCAoY29udGV4dCkgPT4ge1xuICAgIGxldCB7IGRhdGVFbnYsIG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgbGV0IHsgZGF0ZSB9ID0gcHJvcHM7XG4gICAgbGV0IGZvcm1hdCA9IG9wdGlvbnMud2Vla051bWJlckZvcm1hdCB8fCBwcm9wcy5kZWZhdWx0Rm9ybWF0O1xuICAgIGxldCBudW0gPSBkYXRlRW52LmNvbXB1dGVXZWVrTnVtYmVyKGRhdGUpOyAvLyBUT0RPOiBzb21laG93IHVzZSBmb3IgZm9ybWF0dGluZyBhcyB3ZWxsP1xuICAgIGxldCB0ZXh0ID0gZGF0ZUVudi5mb3JtYXQoZGF0ZSwgZm9ybWF0KTtcbiAgICBsZXQgcmVuZGVyUHJvcHMgPSB7IG51bSwgdGV4dCwgZGF0ZSB9O1xuICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChDb250ZW50Q29udGFpbmVyIC8vIHdoeSBpc24ndCBXZWVrTnVtYmVyQ29udGVudEFyZyBiZWluZyBhdXRvLWRldGVjdGVkP1xuICAgICwgeyBlbFJlZjogcHJvcHMuZWxSZWYsIGVsVGFnOiBwcm9wcy5lbFRhZywgZWxBdHRyczogcHJvcHMuZWxBdHRycywgZWxDbGFzc2VzOiBwcm9wcy5lbENsYXNzZXMsIGVsU3R5bGU6IHByb3BzLmVsU3R5bGUsIHJlbmRlclByb3BzOiByZW5kZXJQcm9wcywgZ2VuZXJhdG9yTmFtZTogXCJ3ZWVrTnVtYmVyQ29udGVudFwiLCBjdXN0b21HZW5lcmF0b3I6IG9wdGlvbnMud2Vla051bWJlckNvbnRlbnQsIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlcklubmVyLCBjbGFzc05hbWVHZW5lcmF0b3I6IG9wdGlvbnMud2Vla051bWJlckNsYXNzTmFtZXMsIGRpZE1vdW50OiBvcHRpb25zLndlZWtOdW1iZXJEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMud2Vla051bWJlcldpbGxVbm1vdW50IH0sIHByb3BzLmNoaWxkcmVuKSk7XG59KSk7XG5mdW5jdGlvbiByZW5kZXJJbm5lcihpbm5lclByb3BzKSB7XG4gICAgcmV0dXJuIGlubmVyUHJvcHMudGV4dDtcbn1cblxuY29uc3QgUEFERElOR19GUk9NX1ZJRVdQT1JUID0gMTA7XG5jbGFzcyBQb3BvdmVyIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICB0aXRsZUlkOiBnZXRVbmlxdWVEb21JZCgpLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVJvb3RFbCA9IChlbCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yb290RWwgPSBlbDtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLmVsUmVmKSB7XG4gICAgICAgICAgICAgICAgc2V0UmVmKHRoaXMucHJvcHMuZWxSZWYsIGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLy8gVHJpZ2dlcmVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzICphbnl3aGVyZSogaW4gdGhlIGRvY3VtZW50LCBmb3IgdGhlIGF1dG9IaWRlIGZlYXR1cmVcbiAgICAgICAgdGhpcy5oYW5kbGVEb2N1bWVudE1vdXNlRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgLy8gb25seSBoaWRlIHRoZSBwb3BvdmVyIGlmIHRoZSBjbGljayBoYXBwZW5lZCBvdXRzaWRlIHRoZSBwb3BvdmVyXG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBnZXRFdmVudFRhcmdldFZpYVJvb3QoZXYpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnJvb3RFbC5jb250YWlucyh0YXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVDbG9zZUNsaWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRG9jdW1lbnRLZXlEb3duID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXYua2V5ID09PSAnRXNjYXBlJykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2xvc2VDbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZUNsb3NlQ2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBvbkNsb3NlIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICAgICAgaWYgKG9uQ2xvc2UpIHtcbiAgICAgICAgICAgICAgICBvbkNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgdGhlbWUsIG9wdGlvbnMgfSA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgbGV0IHsgcHJvcHMsIHN0YXRlIH0gPSB0aGlzO1xuICAgICAgICBsZXQgY2xhc3NOYW1lcyA9IFtcbiAgICAgICAgICAgICdmYy1wb3BvdmVyJyxcbiAgICAgICAgICAgIHRoZW1lLmdldENsYXNzKCdwb3BvdmVyJyksXG4gICAgICAgIF0uY29uY2F0KHByb3BzLmV4dHJhQ2xhc3NOYW1lcyB8fCBbXSk7XG4gICAgICAgIHJldHVybiBjcmVhdGVQb3J0YWwoY3JlYXRlRWxlbWVudChcImRpdlwiLCBPYmplY3QuYXNzaWduKHt9LCBwcm9wcy5leHRyYUF0dHJzLCB7IGlkOiBwcm9wcy5pZCwgY2xhc3NOYW1lOiBjbGFzc05hbWVzLmpvaW4oJyAnKSwgXCJhcmlhLWxhYmVsbGVkYnlcIjogc3RhdGUudGl0bGVJZCwgcmVmOiB0aGlzLmhhbmRsZVJvb3RFbCB9KSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6ICdmYy1wb3BvdmVyLWhlYWRlciAnICsgdGhlbWUuZ2V0Q2xhc3MoJ3BvcG92ZXJIZWFkZXInKSB9LFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHsgY2xhc3NOYW1lOiBcImZjLXBvcG92ZXItdGl0bGVcIiwgaWQ6IHN0YXRlLnRpdGxlSWQgfSwgcHJvcHMudGl0bGUpLFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHsgY2xhc3NOYW1lOiAnZmMtcG9wb3Zlci1jbG9zZSAnICsgdGhlbWUuZ2V0SWNvbkNsYXNzKCdjbG9zZScpLCB0aXRsZTogb3B0aW9ucy5jbG9zZUhpbnQsIG9uQ2xpY2s6IHRoaXMuaGFuZGxlQ2xvc2VDbGljayB9KSksXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiAnZmMtcG9wb3Zlci1ib2R5ICcgKyB0aGVtZS5nZXRDbGFzcygncG9wb3ZlckNvbnRlbnQnKSB9LCBwcm9wcy5jaGlsZHJlbikpLCBwcm9wcy5wYXJlbnRFbCk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmhhbmRsZURvY3VtZW50TW91c2VEb3duKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlRG9jdW1lbnRLZXlEb3duKTtcbiAgICAgICAgdGhpcy51cGRhdGVTaXplKCk7XG4gICAgfVxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmhhbmRsZURvY3VtZW50TW91c2VEb3duKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlRG9jdW1lbnRLZXlEb3duKTtcbiAgICB9XG4gICAgdXBkYXRlU2l6ZSgpIHtcbiAgICAgICAgbGV0IHsgaXNSdGwgfSA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgbGV0IHsgYWxpZ25tZW50RWwsIGFsaWduR3JpZFRvcCB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IHsgcm9vdEVsIH0gPSB0aGlzO1xuICAgICAgICBsZXQgYWxpZ25tZW50UmVjdCA9IGNvbXB1dGVDbGlwcGVkQ2xpZW50UmVjdChhbGlnbm1lbnRFbCk7XG4gICAgICAgIGlmIChhbGlnbm1lbnRSZWN0KSB7XG4gICAgICAgICAgICBsZXQgcG9wb3ZlckRpbXMgPSByb290RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAvLyBwb3NpdGlvbiByZWxhdGl2ZSB0byB2aWV3cG9ydFxuICAgICAgICAgICAgbGV0IHBvcG92ZXJUb3AgPSBhbGlnbkdyaWRUb3BcbiAgICAgICAgICAgICAgICA/IGVsZW1lbnRDbG9zZXN0KGFsaWdubWVudEVsLCAnLmZjLXNjcm9sbGdyaWQnKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3BcbiAgICAgICAgICAgICAgICA6IGFsaWdubWVudFJlY3QudG9wO1xuICAgICAgICAgICAgbGV0IHBvcG92ZXJMZWZ0ID0gaXNSdGwgPyBhbGlnbm1lbnRSZWN0LnJpZ2h0IC0gcG9wb3ZlckRpbXMud2lkdGggOiBhbGlnbm1lbnRSZWN0LmxlZnQ7XG4gICAgICAgICAgICAvLyBjb25zdHJhaW5cbiAgICAgICAgICAgIHBvcG92ZXJUb3AgPSBNYXRoLm1heChwb3BvdmVyVG9wLCBQQURESU5HX0ZST01fVklFV1BPUlQpO1xuICAgICAgICAgICAgcG9wb3ZlckxlZnQgPSBNYXRoLm1pbihwb3BvdmVyTGVmdCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoIC0gUEFERElOR19GUk9NX1ZJRVdQT1JUIC0gcG9wb3ZlckRpbXMud2lkdGgpO1xuICAgICAgICAgICAgcG9wb3ZlckxlZnQgPSBNYXRoLm1heChwb3BvdmVyTGVmdCwgUEFERElOR19GUk9NX1ZJRVdQT1JUKTtcbiAgICAgICAgICAgIGxldCBvcmlnaW4gPSByb290RWwub2Zmc2V0UGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgYXBwbHlTdHlsZShyb290RWwsIHtcbiAgICAgICAgICAgICAgICB0b3A6IHBvcG92ZXJUb3AgLSBvcmlnaW4udG9wLFxuICAgICAgICAgICAgICAgIGxlZnQ6IHBvcG92ZXJMZWZ0IC0gb3JpZ2luLmxlZnQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuY2xhc3MgTW9yZVBvcG92ZXIgZXh0ZW5kcyBEYXRlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5oYW5kbGVSb290RWwgPSAocm9vdEVsKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJvb3RFbCA9IHJvb3RFbDtcbiAgICAgICAgICAgIGlmIChyb290RWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRleHQucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGVsOiByb290RWwsXG4gICAgICAgICAgICAgICAgICAgIHVzZUV2ZW50Q2VudGVyOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udGV4dC51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgb3B0aW9ucywgZGF0ZUVudiB9ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgc3RhcnREYXRlLCB0b2RheVJhbmdlLCBkYXRlUHJvZmlsZSB9ID0gcHJvcHM7XG4gICAgICAgIGxldCB0aXRsZSA9IGRhdGVFbnYuZm9ybWF0KHN0YXJ0RGF0ZSwgb3B0aW9ucy5kYXlQb3BvdmVyRm9ybWF0KTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KERheUNlbGxDb250YWluZXIsIHsgZWxSZWY6IHRoaXMuaGFuZGxlUm9vdEVsLCBkYXRlOiBzdGFydERhdGUsIGRhdGVQcm9maWxlOiBkYXRlUHJvZmlsZSwgdG9kYXlSYW5nZTogdG9kYXlSYW5nZSB9LCAoSW5uZXJDb250ZW50LCByZW5kZXJQcm9wcywgZWxBdHRycykgPT4gKGNyZWF0ZUVsZW1lbnQoUG9wb3ZlciwgeyBlbFJlZjogZWxBdHRycy5yZWYsIGlkOiBwcm9wcy5pZCwgdGl0bGU6IHRpdGxlLCBleHRyYUNsYXNzTmFtZXM6IFsnZmMtbW9yZS1wb3BvdmVyJ10uY29uY2F0KGVsQXR0cnMuY2xhc3NOYW1lIHx8IFtdKSwgZXh0cmFBdHRyczogZWxBdHRycyAvKiBUT0RPOiBtYWtlIHRoZXNlIHRpbWUtYmFzZWQgd2hlbiBub3Qgd2hvbGUtZGF5PyAqLywgcGFyZW50RWw6IHByb3BzLnBhcmVudEVsLCBhbGlnbm1lbnRFbDogcHJvcHMuYWxpZ25tZW50RWwsIGFsaWduR3JpZFRvcDogcHJvcHMuYWxpZ25HcmlkVG9wLCBvbkNsb3NlOiBwcm9wcy5vbkNsb3NlIH0sXG4gICAgICAgICAgICBoYXNDdXN0b21EYXlDZWxsQ29udGVudChvcHRpb25zKSAmJiAoY3JlYXRlRWxlbWVudChJbm5lckNvbnRlbnQsIHsgZWxUYWc6IFwiZGl2XCIsIGVsQ2xhc3NlczogWydmYy1tb3JlLXBvcG92ZXItbWlzYyddIH0pKSxcbiAgICAgICAgICAgIHByb3BzLmNoaWxkcmVuKSkpKTtcbiAgICB9XG4gICAgcXVlcnlIaXQocG9zaXRpb25MZWZ0LCBwb3NpdGlvblRvcCwgZWxXaWR0aCwgZWxIZWlnaHQpIHtcbiAgICAgICAgbGV0IHsgcm9vdEVsLCBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgaWYgKHBvc2l0aW9uTGVmdCA+PSAwICYmIHBvc2l0aW9uTGVmdCA8IGVsV2lkdGggJiZcbiAgICAgICAgICAgIHBvc2l0aW9uVG9wID49IDAgJiYgcG9zaXRpb25Ub3AgPCBlbEhlaWdodCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICAgICAgZGF0ZVNwYW46IE9iamVjdC5hc3NpZ24oeyBhbGxEYXk6ICFwcm9wcy5mb3JjZVRpbWVkLCByYW5nZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHByb3BzLnN0YXJ0RGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogcHJvcHMuZW5kRGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgfSB9LCBwcm9wcy5leHRyYURhdGVTcGFuKSxcbiAgICAgICAgICAgICAgICBkYXlFbDogcm9vdEVsLFxuICAgICAgICAgICAgICAgIHJlY3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAwLFxuICAgICAgICAgICAgICAgICAgICByaWdodDogZWxXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiBlbEhlaWdodCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxheWVyOiAxLCAvLyBpbXBvcnRhbnQgd2hlbiBjb21wYXJpbmcgd2l0aCBoaXRzIGZyb20gb3RoZXIgY29tcG9uZW50c1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59XG5cbmNsYXNzIE1vcmVMaW5rQ29udGFpbmVyIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBpc1BvcG92ZXJPcGVuOiBmYWxzZSxcbiAgICAgICAgICAgIHBvcG92ZXJJZDogZ2V0VW5pcXVlRG9tSWQoKSxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVMaW5rRWwgPSAobGlua0VsKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxpbmtFbCA9IGxpbmtFbDtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLmVsUmVmKSB7XG4gICAgICAgICAgICAgICAgc2V0UmVmKHRoaXMucHJvcHMuZWxSZWYsIGxpbmtFbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlQ2xpY2sgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGxldCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICAgICAgbGV0IHsgbW9yZUxpbmtDbGljayB9ID0gY29udGV4dC5vcHRpb25zO1xuICAgICAgICAgICAgbGV0IGRhdGUgPSBjb21wdXRlUmFuZ2UocHJvcHMpLnN0YXJ0O1xuICAgICAgICAgICAgZnVuY3Rpb24gYnVpbGRQdWJsaWNTZWcoc2VnKSB7XG4gICAgICAgICAgICAgICAgbGV0IHsgZGVmLCBpbnN0YW5jZSwgcmFuZ2UgfSA9IHNlZy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRJbXBsKGNvbnRleHQsIGRlZiwgaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBzdGFydDogY29udGV4dC5kYXRlRW52LnRvRGF0ZShyYW5nZS5zdGFydCksXG4gICAgICAgICAgICAgICAgICAgIGVuZDogY29udGV4dC5kYXRlRW52LnRvRGF0ZShyYW5nZS5lbmQpLFxuICAgICAgICAgICAgICAgICAgICBpc1N0YXJ0OiBzZWcuaXNTdGFydCxcbiAgICAgICAgICAgICAgICAgICAgaXNFbmQ6IHNlZy5pc0VuZCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtb3JlTGlua0NsaWNrID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgbW9yZUxpbmtDbGljayA9IG1vcmVMaW5rQ2xpY2soe1xuICAgICAgICAgICAgICAgICAgICBkYXRlLFxuICAgICAgICAgICAgICAgICAgICBhbGxEYXk6IEJvb2xlYW4ocHJvcHMuYWxsRGF5RGF0ZSksXG4gICAgICAgICAgICAgICAgICAgIGFsbFNlZ3M6IHByb3BzLmFsbFNlZ3MubWFwKGJ1aWxkUHVibGljU2VnKSxcbiAgICAgICAgICAgICAgICAgICAgaGlkZGVuU2VnczogcHJvcHMuaGlkZGVuU2Vncy5tYXAoYnVpbGRQdWJsaWNTZWcpLFxuICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgdmlldzogY29udGV4dC52aWV3QXBpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtb3JlTGlua0NsaWNrIHx8IG1vcmVMaW5rQ2xpY2sgPT09ICdwb3BvdmVyJykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBpc1BvcG92ZXJPcGVuOiB0cnVlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG1vcmVMaW5rQ2xpY2sgPT09ICdzdHJpbmcnKSB7IC8vIGEgdmlldyBuYW1lXG4gICAgICAgICAgICAgICAgY29udGV4dC5jYWxlbmRhckFwaS56b29tVG8oZGF0ZSwgbW9yZUxpbmtDbGljayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9wb3ZlckNsb3NlID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGlzUG9wb3Zlck9wZW46IGZhbHNlIH0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBzdGF0ZSB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFZpZXdDb250ZXh0VHlwZS5Db25zdW1lciwgbnVsbCwgKGNvbnRleHQpID0+IHtcbiAgICAgICAgICAgIGxldCB7IHZpZXdBcGksIG9wdGlvbnMsIGNhbGVuZGFyQXBpIH0gPSBjb250ZXh0O1xuICAgICAgICAgICAgbGV0IHsgbW9yZUxpbmtUZXh0IH0gPSBvcHRpb25zO1xuICAgICAgICAgICAgbGV0IHsgbW9yZUNudCB9ID0gcHJvcHM7XG4gICAgICAgICAgICBsZXQgcmFuZ2UgPSBjb21wdXRlUmFuZ2UocHJvcHMpO1xuICAgICAgICAgICAgbGV0IHRleHQgPSB0eXBlb2YgbW9yZUxpbmtUZXh0ID09PSAnZnVuY3Rpb24nIC8vIFRPRE86IGV2ZW50dWFsbHkgdXNlIGZvcm1hdFdpdGhPcmRpbmFsc1xuICAgICAgICAgICAgICAgID8gbW9yZUxpbmtUZXh0LmNhbGwoY2FsZW5kYXJBcGksIG1vcmVDbnQpXG4gICAgICAgICAgICAgICAgOiBgKyR7bW9yZUNudH0gJHttb3JlTGlua1RleHR9YDtcbiAgICAgICAgICAgIGxldCBoaW50ID0gZm9ybWF0V2l0aE9yZGluYWxzKG9wdGlvbnMubW9yZUxpbmtIaW50LCBbbW9yZUNudF0sIHRleHQpO1xuICAgICAgICAgICAgbGV0IHJlbmRlclByb3BzID0ge1xuICAgICAgICAgICAgICAgIG51bTogbW9yZUNudCxcbiAgICAgICAgICAgICAgICBzaG9ydFRleHQ6IGArJHttb3JlQ250fWAsXG4gICAgICAgICAgICAgICAgdGV4dCxcbiAgICAgICAgICAgICAgICB2aWV3OiB2aWV3QXBpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChGcmFnbWVudCwgbnVsbCxcbiAgICAgICAgICAgICAgICBCb29sZWFuKHByb3BzLm1vcmVDbnQpICYmIChjcmVhdGVFbGVtZW50KENvbnRlbnRDb250YWluZXIsIHsgZWxUYWc6IHByb3BzLmVsVGFnIHx8ICdhJywgZWxSZWY6IHRoaXMuaGFuZGxlTGlua0VsLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLihwcm9wcy5lbENsYXNzZXMgfHwgW10pLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLW1vcmUtbGluaycsXG4gICAgICAgICAgICAgICAgICAgIF0sIGVsU3R5bGU6IHByb3BzLmVsU3R5bGUsIGVsQXR0cnM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcm9wcy5lbEF0dHJzKSwgY3JlYXRlQXJpYUNsaWNrQXR0cnModGhpcy5oYW5kbGVDbGljaykpLCB7IHRpdGxlOiBoaW50LCAnYXJpYS1leHBhbmRlZCc6IHN0YXRlLmlzUG9wb3Zlck9wZW4sICdhcmlhLWNvbnRyb2xzJzogc3RhdGUuaXNQb3BvdmVyT3BlbiA/IHN0YXRlLnBvcG92ZXJJZCA6ICcnIH0pLCByZW5kZXJQcm9wczogcmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IFwibW9yZUxpbmtDb250ZW50XCIsIGN1c3RvbUdlbmVyYXRvcjogb3B0aW9ucy5tb3JlTGlua0NvbnRlbnQsIGRlZmF1bHRHZW5lcmF0b3I6IHByb3BzLmRlZmF1bHRHZW5lcmF0b3IgfHwgcmVuZGVyTW9yZUxpbmtJbm5lciwgY2xhc3NOYW1lR2VuZXJhdG9yOiBvcHRpb25zLm1vcmVMaW5rQ2xhc3NOYW1lcywgZGlkTW91bnQ6IG9wdGlvbnMubW9yZUxpbmtEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMubW9yZUxpbmtXaWxsVW5tb3VudCB9LCBwcm9wcy5jaGlsZHJlbikpLFxuICAgICAgICAgICAgICAgIHN0YXRlLmlzUG9wb3Zlck9wZW4gJiYgKGNyZWF0ZUVsZW1lbnQoTW9yZVBvcG92ZXIsIHsgaWQ6IHN0YXRlLnBvcG92ZXJJZCwgc3RhcnREYXRlOiByYW5nZS5zdGFydCwgZW5kRGF0ZTogcmFuZ2UuZW5kLCBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2U6IHByb3BzLnRvZGF5UmFuZ2UsIGV4dHJhRGF0ZVNwYW46IHByb3BzLmV4dHJhRGF0ZVNwYW4sIHBhcmVudEVsOiB0aGlzLnBhcmVudEVsLCBhbGlnbm1lbnRFbDogcHJvcHMuYWxpZ25tZW50RWxSZWYgP1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuYWxpZ25tZW50RWxSZWYuY3VycmVudCA6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmtFbCwgYWxpZ25HcmlkVG9wOiBwcm9wcy5hbGlnbkdyaWRUb3AsIGZvcmNlVGltZWQ6IHByb3BzLmZvcmNlVGltZWQsIG9uQ2xvc2U6IHRoaXMuaGFuZGxlUG9wb3ZlckNsb3NlIH0sIHByb3BzLnBvcG92ZXJDb250ZW50KCkpKSkpO1xuICAgICAgICB9KSk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICB0aGlzLnVwZGF0ZVBhcmVudEVsKCk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZFVwZGF0ZSgpIHtcbiAgICAgICAgdGhpcy51cGRhdGVQYXJlbnRFbCgpO1xuICAgIH1cbiAgICB1cGRhdGVQYXJlbnRFbCgpIHtcbiAgICAgICAgaWYgKHRoaXMubGlua0VsKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudEVsID0gZWxlbWVudENsb3Nlc3QodGhpcy5saW5rRWwsICcuZmMtdmlldy1oYXJuZXNzJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiByZW5kZXJNb3JlTGlua0lubmVyKHByb3BzKSB7XG4gICAgcmV0dXJuIHByb3BzLnRleHQ7XG59XG5mdW5jdGlvbiBjb21wdXRlUmFuZ2UocHJvcHMpIHtcbiAgICBpZiAocHJvcHMuYWxsRGF5RGF0ZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IHByb3BzLmFsbERheURhdGUsXG4gICAgICAgICAgICBlbmQ6IGFkZERheXMocHJvcHMuYWxsRGF5RGF0ZSwgMSksXG4gICAgICAgIH07XG4gICAgfVxuICAgIGxldCB7IGhpZGRlblNlZ3MgfSA9IHByb3BzO1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiBjb21wdXRlRWFybGllc3RTZWdTdGFydChoaWRkZW5TZWdzKSxcbiAgICAgICAgZW5kOiBjb21wdXRlTGF0ZXN0U2VnRW5kKGhpZGRlblNlZ3MpLFxuICAgIH07XG59XG5mdW5jdGlvbiBjb21wdXRlRWFybGllc3RTZWdTdGFydChzZWdzKSB7XG4gICAgcmV0dXJuIHNlZ3MucmVkdWNlKHBpY2tFYXJsaWVzdFN0YXJ0KS5ldmVudFJhbmdlLnJhbmdlLnN0YXJ0O1xufVxuZnVuY3Rpb24gcGlja0VhcmxpZXN0U3RhcnQoc2VnMCwgc2VnMSkge1xuICAgIHJldHVybiBzZWcwLmV2ZW50UmFuZ2UucmFuZ2Uuc3RhcnQgPCBzZWcxLmV2ZW50UmFuZ2UucmFuZ2Uuc3RhcnQgPyBzZWcwIDogc2VnMTtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVMYXRlc3RTZWdFbmQoc2Vncykge1xuICAgIHJldHVybiBzZWdzLnJlZHVjZShwaWNrTGF0ZXN0RW5kKS5ldmVudFJhbmdlLnJhbmdlLmVuZDtcbn1cbmZ1bmN0aW9uIHBpY2tMYXRlc3RFbmQoc2VnMCwgc2VnMSkge1xuICAgIHJldHVybiBzZWcwLmV2ZW50UmFuZ2UucmFuZ2UuZW5kID4gc2VnMS5ldmVudFJhbmdlLnJhbmdlLmVuZCA/IHNlZzAgOiBzZWcxO1xufVxuXG5jbGFzcyBTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlcnMgPSBbXTtcbiAgICB9XG4gICAgc2V0KHZhbHVlKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFZhbHVlID0gdmFsdWU7XG4gICAgICAgIGZvciAobGV0IGhhbmRsZXIgb2YgdGhpcy5oYW5kbGVycykge1xuICAgICAgICAgICAgaGFuZGxlcih2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgc3Vic2NyaWJlKGhhbmRsZXIpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVycy5wdXNoKGhhbmRsZXIpO1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaGFuZGxlcih0aGlzLmN1cnJlbnRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qXG5TdWJzY3JpYmVycyB3aWxsIGdldCBhIExJU1Qgb2YgQ3VzdG9tUmVuZGVyaW5nc1xuKi9cbmNsYXNzIEN1c3RvbVJlbmRlcmluZ1N0b3JlIGV4dGVuZHMgU3RvcmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLm1hcCA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgLy8gZm9yIGNvbnNpc3RlbnQgb3JkZXJcbiAgICBoYW5kbGUoY3VzdG9tUmVuZGVyaW5nKSB7XG4gICAgICAgIGNvbnN0IHsgbWFwIH0gPSB0aGlzO1xuICAgICAgICBsZXQgdXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoY3VzdG9tUmVuZGVyaW5nLmlzQWN0aXZlKSB7XG4gICAgICAgICAgICBtYXAuc2V0KGN1c3RvbVJlbmRlcmluZy5pZCwgY3VzdG9tUmVuZGVyaW5nKTtcbiAgICAgICAgICAgIHVwZGF0ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG1hcC5oYXMoY3VzdG9tUmVuZGVyaW5nLmlkKSkge1xuICAgICAgICAgICAgbWFwLmRlbGV0ZShjdXN0b21SZW5kZXJpbmcuaWQpO1xuICAgICAgICAgICAgdXBkYXRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVwZGF0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0KG1hcCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCB7IGxpc3RlbkJ5U2VsZWN0b3IgYXMgJCwgbWVtb2l6ZU9iakFyZyBhcyBBLCBCYXNlQ29tcG9uZW50IGFzIEIsIENvbnRlbnRDb250YWluZXIgYXMgQywgRGVsYXllZFJ1bm5lciBhcyBELCBpc1Byb3BzRXF1YWwgYXMgRSwgRW1pdHRlciBhcyBGLCByYW5nZUNvbnRhaW5zTWFya2VyIGFzIEcsIGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSBhcyBILCByZWR1Y2VFdmVudFN0b3JlIGFzIEksIHJlem9uZUV2ZW50U3RvcmVEYXRlcyBhcyBKLCBtZXJnZVJhd09wdGlvbnMgYXMgSywgQkFTRV9PUFRJT05fUkVGSU5FUlMgYXMgTCwgQ0FMRU5EQVJfTElTVEVORVJfUkVGSU5FUlMgYXMgTSwgQ0FMRU5EQVJfT1BUSU9OX1JFRklORVJTIGFzIE4sIENPTVBMRVhfT1BUSU9OX0NPTVBBUkFUT1JTIGFzIE8sIFZJRVdfT1BUSU9OX1JFRklORVJTIGFzIFAsIERhdGVFbnYgYXMgUSwgRGF0ZVByb2ZpbGVHZW5lcmF0b3IgYXMgUiwgY3JlYXRlRXZlbnRVaSBhcyBTLCBUaGVtZSBhcyBULCBwYXJzZUJ1c2luZXNzSG91cnMgYXMgVSwgVmlld0NvbnRleHRUeXBlIGFzIFYsIHNldFJlZiBhcyBXLCBJbnRlcmFjdGlvbiBhcyBYLCBnZXRFbFNlZyBhcyBZLCBlbGVtZW50Q2xvc2VzdCBhcyBaLCBFdmVudEltcGwgYXMgXywgbWFwSGFzaCBhcyBhLCBwcmV2ZW50RGVmYXVsdCBhcyBhJCwgbGlzdGVuVG9Ib3ZlckJ5U2VsZWN0b3IgYXMgYTAsIFB1cmVDb21wb25lbnQgYXMgYTEsIGJ1aWxkVmlld0NvbnRleHQgYXMgYTIsIGdldFVuaXF1ZURvbUlkIGFzIGEzLCBwYXJzZUludGVyYWN0aW9uU2V0dGluZ3MgYXMgYTQsIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZSBhcyBhNSwgTm93VGltZXIgYXMgYTYsIENhbGVuZGFySW1wbCBhcyBhNywgZmx1c2hTeW5jIGFzIGE4LCBDYWxlbmRhclJvb3QgYXMgYTksIG1lbW9pemVBcnJheWxpa2UgYXMgYUEsIG1lbW9pemVIYXNobGlrZSBhcyBhQiwgaW50ZXJzZWN0UmVjdHMgYXMgYUMsIHBvaW50SW5zaWRlUmVjdCBhcyBhRCwgY29uc3RyYWluUG9pbnQgYXMgYUUsIGdldFJlY3RDZW50ZXIgYXMgYUYsIGRpZmZQb2ludHMgYXMgYUcsIHRyYW5zbGF0ZVJlY3QgYXMgYUgsIGNvbXBhcmVPYmpzIGFzIGFJLCBjb2xsZWN0RnJvbUhhc2ggYXMgYUosIGZpbmRFbGVtZW50cyBhcyBhSywgZmluZERpcmVjdENoaWxkcmVuIGFzIGFMLCByZW1vdmVFbGVtZW50IGFzIGFNLCBhcHBseVN0eWxlIGFzIGFOLCBlbGVtZW50TWF0Y2hlcyBhcyBhTywgZ2V0RXZlbnRUYXJnZXRWaWFSb290IGFzIGFQLCBwYXJzZUNsYXNzTmFtZXMgYXMgYVEsIGdldENhblZHcm93V2l0aGluQ2VsbCBhcyBhUiwgbWVyZ2VFdmVudFN0b3JlcyBhcyBhUywgZ2V0UmVsZXZhbnRFdmVudHMgYXMgYVQsIGV2ZW50VHVwbGVUb1N0b3JlIGFzIGFVLCBjb21iaW5lRXZlbnRVaXMgYXMgYVYsIFNwbGl0dGVyIGFzIGFXLCBnZXREYXlDbGFzc05hbWVzIGFzIGFYLCBnZXREYXRlTWV0YSBhcyBhWSwgZ2V0U2xvdENsYXNzTmFtZXMgYXMgYVosIGJ1aWxkTmF2TGlua0F0dHJzIGFzIGFfLCBSZW5kZXJJZCBhcyBhYSwgZW5zdXJlRWxIYXNTdHlsZXMgYXMgYWIsIGFwcGx5U3R5bGVQcm9wIGFzIGFjLCBzbGljZUV2ZW50U3RvcmUgYXMgYWQsIEpzb25SZXF1ZXN0RXJyb3IgYXMgYWUsIGNyZWF0ZUNvbnRleHQgYXMgYWYsIHJlZmluZVByb3BzIGFzIGFnLCBjcmVhdGVFdmVudEluc3RhbmNlIGFzIGFoLCBwYXJzZUV2ZW50RGVmIGFzIGFpLCByZWZpbmVFdmVudERlZiBhcyBhaiwgcGFkU3RhcnQgYXMgYWssIGlzSW50IGFzIGFsLCBwYXJzZUZpZWxkU3BlY3MgYXMgYW0sIGNvbXBhcmVCeUZpZWxkU3BlY3MgYXMgYW4sIGZsZXhpYmxlQ29tcGFyZSBhcyBhbywgcHJldmVudFNlbGVjdGlvbiBhcyBhcCwgYWxsb3dTZWxlY3Rpb24gYXMgYXEsIHByZXZlbnRDb250ZXh0TWVudSBhcyBhciwgYWxsb3dDb250ZXh0TWVudSBhcyBhcywgY29tcGFyZU51bWJlcnMgYXMgYXQsIGVuYWJsZUN1cnNvciBhcyBhdSwgZGlzYWJsZUN1cnNvciBhcyBhdiwgY29tcHV0ZVZpc2libGVEYXlSYW5nZSBhcyBhdywgaXNNdWx0aURheVJhbmdlIGFzIGF4LCBkaWZmRGF0ZXMgYXMgYXksIHJlbW92ZUV4YWN0IGFzIGF6LCBidWlsZFZpZXdDbGFzc05hbWVzIGFzIGIsIHJlbmRlck1pY3JvQ29sR3JvdXAgYXMgYiQsIHdoZW5UcmFuc2l0aW9uRG9uZSBhcyBiMCwgY29tcHV0ZUlubmVyUmVjdCBhcyBiMSwgY29tcHV0ZUVkZ2VzIGFzIGIyLCBnZXRDbGlwcGluZ1BhcmVudHMgYXMgYjMsIGNvbXB1dGVSZWN0IGFzIGI0LCByYW5nZXNFcXVhbCBhcyBiNSwgcmFuZ2VzSW50ZXJzZWN0IGFzIGI2LCByYW5nZUNvbnRhaW5zUmFuZ2UgYXMgYjcsIFBvc2l0aW9uQ2FjaGUgYXMgYjgsIFNjcm9sbENvbnRyb2xsZXIgYXMgYjksIGdldEVudHJ5U3BhbkVuZCBhcyBiQSwgYmluYXJ5U2VhcmNoIGFzIGJCLCBncm91cEludGVyc2VjdGluZ0VudHJpZXMgYXMgYkMsIGludGVyc2VjdFNwYW5zIGFzIGJELCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZSBhcyBiRSwgRWxlbWVudERyYWdnaW5nIGFzIGJGLCBjb25maWcgYXMgYkcsIHBhcnNlRHJhZ01ldGEgYXMgYkgsIERheUhlYWRlciBhcyBiSSwgY29tcHV0ZUZhbGxiYWNrSGVhZGVyRm9ybWF0IGFzIGJKLCBUYWJsZURhdGVDZWxsIGFzIGJLLCBUYWJsZURvd0NlbGwgYXMgYkwsIERheVNlcmllc01vZGVsIGFzIGJNLCBoYXNCZ1JlbmRlcmluZyBhcyBiTiwgYnVpbGRTZWdUaW1lVGV4dCBhcyBiTywgc29ydEV2ZW50U2VncyBhcyBiUCwgZ2V0U2VnTWV0YSBhcyBiUSwgYnVpbGRFdmVudFJhbmdlS2V5IGFzIGJSLCBnZXRTZWdBbmNob3JBdHRycyBhcyBiUywgRGF5VGFibGVNb2RlbCBhcyBiVCwgU2xpY2VyIGFzIGJVLCBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlIGFzIGJWLCBpc1Byb3BzVmFsaWQgYXMgYlcsIGlzSW50ZXJhY3Rpb25WYWxpZCBhcyBiWCwgaXNEYXRlU2VsZWN0aW9uVmFsaWQgYXMgYlksIFNpbXBsZVNjcm9sbEdyaWQgYXMgYlosIGhhc1Nocmlua1dpZHRoIGFzIGJfLCBFbGVtZW50U2Nyb2xsQ29udHJvbGxlciBhcyBiYSwgV2luZG93U2Nyb2xsQ29udHJvbGxlciBhcyBiYiwgRGF0ZUNvbXBvbmVudCBhcyBiYywgaXNEYXRlU3BhbnNFcXVhbCBhcyBiZCwgYWRkTXMgYXMgYmUsIGFkZFdlZWtzIGFzIGJmLCBkaWZmV2Vla3MgYXMgYmcsIGRpZmZXaG9sZVdlZWtzIGFzIGJoLCBkaWZmRGF5QW5kVGltZSBhcyBiaSwgZGlmZkRheXMgYXMgYmosIGlzVmFsaWREYXRlIGFzIGJrLCBhc0NsZWFuRGF5cyBhcyBibCwgbXVsdGlwbHlEdXJhdGlvbiBhcyBibSwgYWRkRHVyYXRpb25zIGFzIGJuLCBhc1JvdWdoTWludXRlcyBhcyBibywgYXNSb3VnaFNlY29uZHMgYXMgYnAsIGFzUm91Z2hNcyBhcyBicSwgd2hvbGVEaXZpZGVEdXJhdGlvbnMgYXMgYnIsIGZvcm1hdElzb1RpbWVTdHJpbmcgYXMgYnMsIGZvcm1hdERheVN0cmluZyBhcyBidCwgYnVpbGRJc29TdHJpbmcgYXMgYnUsIGZvcm1hdElzb01vbnRoU3RyIGFzIGJ2LCBOYW1lZFRpbWVab25lSW1wbCBhcyBidywgcGFyc2UgYXMgYngsIFNlZ0hpZXJhcmNoeSBhcyBieSwgYnVpbGRFbnRyeUtleSBhcyBieiwgZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yIGFzIGMsIGdldFNjcm9sbEdyaWRDbGFzc05hbWVzIGFzIGMwLCBnZXRTZWN0aW9uQ2xhc3NOYW1lcyBhcyBjMSwgZ2V0U2VjdGlvbkhhc0xpcXVpZEhlaWdodCBhcyBjMiwgZ2V0QWxsb3dZU2Nyb2xsaW5nIGFzIGMzLCByZW5kZXJDaHVua0NvbnRlbnQgYXMgYzQsIGNvbXB1dGVTaHJpbmtXaWR0aCBhcyBjNSwgc2FuaXRpemVTaHJpbmtXaWR0aCBhcyBjNiwgaXNDb2xQcm9wc0VxdWFsIGFzIGM3LCByZW5kZXJTY3JvbGxTaGltIGFzIGM4LCBnZXRTdGlja3lGb290ZXJTY3JvbGxiYXIgYXMgYzksIGdldFN0aWNreUhlYWRlckRhdGVzIGFzIGNhLCBTY3JvbGxlciBhcyBjYiwgZ2V0U2Nyb2xsYmFyV2lkdGhzIGFzIGNjLCBSZWZNYXAgYXMgY2QsIGdldElzUnRsU2Nyb2xsYmFyT25MZWZ0IGFzIGNlLCBTY3JvbGxSZXNwb25kZXIgYXMgY2YsIFN0YW5kYXJkRXZlbnQgYXMgY2csIE5vd0luZGljYXRvckNvbnRhaW5lciBhcyBjaCwgRGF5Q2VsbENvbnRhaW5lciBhcyBjaSwgaGFzQ3VzdG9tRGF5Q2VsbENvbnRlbnQgYXMgY2osIEV2ZW50Q29udGFpbmVyIGFzIGNrLCByZW5kZXJGaWxsIGFzIGNsLCBCZ0V2ZW50IGFzIGNtLCBXZWVrTnVtYmVyQ29udGFpbmVyIGFzIGNuLCBNb3JlTGlua0NvbnRhaW5lciBhcyBjbywgY29tcHV0ZUVhcmxpZXN0U2VnU3RhcnQgYXMgY3AsIFZpZXdDb250YWluZXIgYXMgY3EsIHRyaWdnZXJEYXRlU2VsZWN0IGFzIGNyLCBnZXREZWZhdWx0RXZlbnRFbmQgYXMgY3MsIGluamVjdFN0eWxlcyBhcyBjdCwgYnVpbGRFbEF0dHJzIGFzIGN1LCBDdXN0b21SZW5kZXJpbmdTdG9yZSBhcyBjdiwgY3JlYXRlRHVyYXRpb24gYXMgZCwgQkFTRV9PUFRJT05fREVGQVVMVFMgYXMgZSwgYXJyYXlUb0hhc2ggYXMgZiwgZ3VpZCBhcyBnLCBmaWx0ZXJIYXNoIGFzIGgsIGlzQXJyYXlzRXF1YWwgYXMgaSwgYnVpbGRFdmVudFNvdXJjZVJlZmluZXJzIGFzIGosIGZvcm1hdFdpdGhPcmRpbmFscyBhcyBrLCBidWlsZFJhbmdlQXBpV2l0aFRpbWVab25lIGFzIGwsIG1lcmdlUHJvcHMgYXMgbSwgaWRlbnRpdHkgYXMgbiwgaW50ZXJzZWN0UmFuZ2VzIGFzIG8sIHBhcnNlRXZlbnRTb3VyY2UgYXMgcCwgc3RhcnRPZkRheSBhcyBxLCByZXF1ZXN0SnNvbiBhcyByLCBzdWJ0cmFjdER1cmF0aW9ucyBhcyBzLCBhZGREYXlzIGFzIHQsIHVucHJvbWlzaWZ5IGFzIHUsIGhhc2hWYWx1ZXNUb0FycmF5IGFzIHYsIGJ1aWxkRXZlbnRBcGlzIGFzIHcsIGNyZWF0ZUZvcm1hdHRlciBhcyB4LCBkaWZmV2hvbGVEYXlzIGFzIHksIG1lbW9pemUgYXMgeiB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///113\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 114:
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Component: () => (/* binding */ x),\n/* harmony export */ Fragment: () => (/* binding */ _),\n/* harmony export */ cloneElement: () => (/* binding */ F),\n/* harmony export */ createContext: () => (/* binding */ G),\n/* harmony export */ createElement: () => (/* binding */ y),\n/* harmony export */ createRef: () => (/* binding */ d),\n/* harmony export */ h: () => (/* binding */ y),\n/* harmony export */ hydrate: () => (/* binding */ E),\n/* harmony export */ isValidElement: () => (/* binding */ i),\n/* harmony export */ options: () => (/* binding */ l),\n/* harmony export */ render: () => (/* binding */ D),\n/* harmony export */ toChildArray: () => (/* binding */ j)\n/* harmony export */ });\nvar n,l,u,i,t,r,o,f,e,c={},s=[],a=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function h(n,l){for(var u in l)n[u]=l[u];return n}function v(n){var l=n.parentNode;l&&l.removeChild(n)}function y(l,u,i){var t,r,o,f={};for(o in u)\"key\"==o?t=u[o]:\"ref\"==o?r=u[o]:f[o]=u[o];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),\"function\"==typeof l&&null!=l.defaultProps)for(o in l.defaultProps)void 0===f[o]&&(f[o]=l.defaultProps[o]);return p(l,f,t,r,null)}function p(n,i,t,r,o){var f={type:n,props:i,key:t,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++u:o};return null==o&&null!=l.vnode&&l.vnode(f),f}function d(){return{current:null}}function _(n){return n.children}function k(n,l,u,i,t){var r;for(r in u)\"children\"===r||\"key\"===r||r in l||g(n,r,null,u[r],i);for(r in l)t&&\"function\"!=typeof l[r]||\"children\"===r||\"key\"===r||\"value\"===r||\"checked\"===r||u[r]===l[r]||g(n,r,l[r],u[r],i)}function b(n,l,u){\"-\"===l[0]?n.setProperty(l,null==u?\"\":u):n[l]=null==u?\"\":\"number\"!=typeof u||a.test(l)?u:u+\"px\"}function g(n,l,u,i,t){var r;n:if(\"style\"===l)if(\"string\"==typeof u)n.style.cssText=u;else{if(\"string\"==typeof i&&(n.style.cssText=i=\"\"),i)for(l in i)u&&l in u||b(n.style,l,\"\");if(u)for(l in u)i&&u[l]===i[l]||b(n.style,l,u[l])}else if(\"o\"===l[0]&&\"n\"===l[1])r=l!==(l=l.replace(/Capture$/,\"\")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+r]=u,u?i||n.addEventListener(l,r?w:m,r):n.removeEventListener(l,r?w:m,r);else if(\"dangerouslySetInnerHTML\"!==l){if(t)l=l.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(\"width\"!==l&&\"height\"!==l&&\"href\"!==l&&\"list\"!==l&&\"form\"!==l&&\"tabIndex\"!==l&&\"download\"!==l&&l in n)try{n[l]=null==u?\"\":u;break n}catch(n){}\"function\"==typeof u||(null==u||!1===u&&-1==l.indexOf(\"-\")?n.removeAttribute(l):n.setAttribute(l,u))}}function m(n){t=!0;try{return this.l[n.type+!1](l.event?l.event(n):n)}finally{t=!1}}function w(n){t=!0;try{return this.l[n.type+!0](l.event?l.event(n):n)}finally{t=!1}}function x(n,l){this.props=n,this.context=l}function A(n,l){if(null==l)return n.__?A(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return\"function\"==typeof n.type?A(n):null}function P(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return P(n)}}function C(n){t?setTimeout(n):f(n)}function T(n){(!n.__d&&(n.__d=!0)&&r.push(n)&&!$.__r++||o!==l.debounceRendering)&&((o=l.debounceRendering)||C)($)}function $(){var n,l,u,i,t,o,f,e;for(r.sort(function(n,l){return n.__v.__b-l.__v.__b});n=r.shift();)n.__d&&(l=r.length,i=void 0,t=void 0,f=(o=(u=n).__v).__e,(e=u.__P)&&(i=[],(t=h({},o)).__v=o.__v+1,M(e,o,t,u.__n,void 0!==e.ownerSVGElement,null!=o.__h?[f]:null,i,null==f?A(o):f,o.__h),N(i,o),o.__e!=f&&P(o)),r.length>l&&r.sort(function(n,l){return n.__v.__b-l.__v.__b}));$.__r=0}function H(n,l,u,i,t,r,o,f,e,a){var h,v,y,d,k,b,g,m=i&&i.__k||s,w=m.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(d=u.__k[h]=null==(d=l[h])||\"boolean\"==typeof d?null:\"string\"==typeof d||\"number\"==typeof d||\"bigint\"==typeof d?p(null,d,null,null,d):Array.isArray(d)?p(_,{children:d},null,null,null):d.__b>0?p(d.type,d.props,d.key,d.ref?d.ref:null,d.__v):d)){if(d.__=u,d.__b=u.__b+1,null===(y=m[h])||y&&d.key==y.key&&d.type===y.type)m[h]=void 0;else for(v=0;v<w;v++){if((y=m[v])&&d.key==y.key&&d.type===y.type){m[v]=void 0;break}y=null}M(n,d,y=y||c,t,r,o,f,e,a),k=d.__e,(v=d.ref)&&y.ref!=v&&(g||(g=[]),y.ref&&g.push(y.ref,null,d),g.push(v,d.__c||k,d)),null!=k?(null==b&&(b=k),\"function\"==typeof d.type&&d.__k===y.__k?d.__d=e=I(d,e,n):e=z(n,d,y,m,k,e),\"function\"==typeof u.type&&(u.__d=e)):e&&y.__e==e&&e.parentNode!=n&&(e=A(y))}for(u.__e=b,h=w;h--;)null!=m[h]&&(\"function\"==typeof u.type&&null!=m[h].__e&&m[h].__e==u.__d&&(u.__d=L(i).nextSibling),q(m[h],m[h]));if(g)for(h=0;h<g.length;h++)S(g[h],g[++h],g[++h])}function I(n,l,u){for(var i,t=n.__k,r=0;t&&r<t.length;r++)(i=t[r])&&(i.__=n,l=\"function\"==typeof i.type?I(i,l,u):z(u,i,i,t,i.__e,l));return l}function j(n,l){return l=l||[],null==n||\"boolean\"==typeof n||(Array.isArray(n)?n.some(function(n){j(n,l)}):l.push(n)),l}function z(n,l,u,i,t,r){var o,f,e;if(void 0!==l.__d)o=l.__d,l.__d=void 0;else if(null==u||t!=r||null==t.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(t),o=null;else{for(f=r,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,r),o=r}return void 0!==o?o:t.nextSibling}function L(n){var l,u,i;if(null==n.type||\"string\"==typeof n.type)return n.__e;if(n.__k)for(l=n.__k.length-1;l>=0;l--)if((u=n.__k[l])&&(i=L(u)))return i;return null}function M(n,u,i,t,r,o,f,e,c){var s,a,v,y,p,d,k,b,g,m,w,A,P,C,T,$=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,o=[e]),(s=l.__b)&&s(u);try{n:if(\"function\"==typeof $){if(b=u.props,g=(s=$.contextType)&&t[s.__c],m=s?g?g.props.value:s.__:t,i.__c?k=(a=u.__c=i.__c).__=a.__E:(\"prototype\"in $&&$.prototype.render?u.__c=a=new $(b,m):(u.__c=a=new x(b,m),a.constructor=$,a.render=B),g&&g.sub(a),a.props=b,a.state||(a.state={}),a.context=m,a.__n=t,v=a.__d=!0,a.__h=[],a._sb=[]),null==a.__s&&(a.__s=a.state),null!=$.getDerivedStateFromProps&&(a.__s==a.state&&(a.__s=h({},a.__s)),h(a.__s,$.getDerivedStateFromProps(b,a.__s))),y=a.props,p=a.state,a.__v=u,v)null==$.getDerivedStateFromProps&&null!=a.componentWillMount&&a.componentWillMount(),null!=a.componentDidMount&&a.__h.push(a.componentDidMount);else{if(null==$.getDerivedStateFromProps&&b!==y&&null!=a.componentWillReceiveProps&&a.componentWillReceiveProps(b,m),!a.__e&&null!=a.shouldComponentUpdate&&!1===a.shouldComponentUpdate(b,a.__s,m)||u.__v===i.__v){for(u.__v!==i.__v&&(a.props=b,a.state=a.__s,a.__d=!1),u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u)}),w=0;w<a._sb.length;w++)a.__h.push(a._sb[w]);a._sb=[],a.__h.length&&f.push(a);break n}null!=a.componentWillUpdate&&a.componentWillUpdate(b,a.__s,m),null!=a.componentDidUpdate&&a.__h.push(function(){a.componentDidUpdate(y,p,d)})}if(a.context=m,a.props=b,a.__P=n,A=l.__r,P=0,\"prototype\"in $&&$.prototype.render){for(a.state=a.__s,a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),C=0;C<a._sb.length;C++)a.__h.push(a._sb[C]);a._sb=[]}else do{a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),a.state=a.__s}while(a.__d&&++P<25);a.state=a.__s,null!=a.getChildContext&&(t=h(h({},t),a.getChildContext())),v||null==a.getSnapshotBeforeUpdate||(d=a.getSnapshotBeforeUpdate(y,p)),T=null!=s&&s.type===_&&null==s.key?s.props.children:s,H(n,Array.isArray(T)?T:[T],u,i,t,r,o,f,e,c),a.base=u.__e,u.__h=null,a.__h.length&&f.push(a),k&&(a.__E=a.__=null),a.__e=!1}else null==o&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=O(i.__e,u,i,t,r,o,f,c);(s=l.diffed)&&s(u)}catch(n){u.__v=null,(c||null!=o)&&(u.__e=e,u.__h=!!c,o[o.indexOf(e)]=null),l.__e(n,u,i)}}function N(n,u){l.__c&&l.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u)})}catch(n){l.__e(n,u.__v)}})}function O(l,u,i,t,r,o,f,e){var s,a,h,y=i.props,p=u.props,d=u.type,_=0;if(\"svg\"===d&&(r=!0),null!=o)for(;_<o.length;_++)if((s=o[_])&&\"setAttribute\"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,o[_]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=r?document.createElementNS(\"http://www.w3.org/2000/svg\",d):document.createElement(d,p.is&&p),o=null,e=!1}if(null===d)y===p||e&&l.data===p||(l.data=p);else{if(o=o&&n.call(l.childNodes),a=(y=i.props||c).dangerouslySetInnerHTML,h=p.dangerouslySetInnerHTML,!e){if(null!=o)for(y={},_=0;_<l.attributes.length;_++)y[l.attributes[_].name]=l.attributes[_].value;(h||a)&&(h&&(a&&h.__html==a.__html||h.__html===l.innerHTML)||(l.innerHTML=h&&h.__html||\"\"))}if(k(l,p,y,r,e),h)u.__k=[];else if(_=u.props.children,H(l,Array.isArray(_)?_:[_],u,i,t,r&&\"foreignObject\"!==d,o,f,o?o[0]:i.__k&&A(i,0),e),null!=o)for(_=o.length;_--;)null!=o[_]&&v(o[_]);e||(\"value\"in p&&void 0!==(_=p.value)&&(_!==l.value||\"progress\"===d&&!_||\"option\"===d&&_!==y.value)&&g(l,\"value\",_,y.value,!1),\"checked\"in p&&void 0!==(_=p.checked)&&_!==l.checked&&g(l,\"checked\",_,y.checked,!1))}return l}function S(n,u,i){try{\"function\"==typeof n?n(u):n.current=u}catch(n){l.__e(n,i)}}function q(n,u,i){var t,r;if(l.unmount&&l.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||S(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount()}catch(n){l.__e(n,u)}t.base=t.__P=null,n.__c=void 0}if(t=n.__k)for(r=0;r<t.length;r++)t[r]&&q(t[r],u,i||\"function\"!=typeof n.type);i||null==n.__e||v(n.__e),n.__=n.__e=n.__d=void 0}function B(n,l,u){return this.constructor(n,u)}function D(u,i,t){var r,o,f;l.__&&l.__(u,i),o=(r=\"function\"==typeof t)?null:t&&t.__k||i.__k,f=[],M(i,u=(!r&&t||i).__k=y(_,null,[u]),o||c,c,void 0!==i.ownerSVGElement,!r&&t?[t]:o?null:i.firstChild?n.call(i.childNodes):null,f,!r&&t?t:o?o.__e:i.firstChild,r),N(f,u)}function E(n,l){D(n,l,E)}function F(l,u,i){var t,r,o,f=h({},l.props);for(o in u)\"key\"==o?t=u[o]:\"ref\"==o?r=u[o]:f[o]=u[o];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),p(l.type,f,t||l.key,r||l.ref,null)}function G(n,l){var u={__c:l=\"__cC\"+e++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,i;return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(function(n){n.__e=!0,T(n)})},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=s.slice,l={__e:function(n,l,u,i){for(var t,r,o;l=l.__;)if((t=l.__c)&&!t.__)try{if((r=t.constructor)&&null!=r.getDerivedStateFromError&&(t.setState(r.getDerivedStateFromError(n)),o=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),o=t.__d),o)return t.__E=t}catch(l){n=l}throw n}},u=0,i=function(n){return null!=n&&void 0===n.constructor},t=!1,x.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=h({},this.state),\"function\"==typeof n&&(n=n(h({},u),this.props)),n&&h(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),T(this))},x.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),T(this))},x.prototype.render=_,r=[],f=\"function\"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,$.__r=0,e=0;\n//# sourceMappingURL=preact.module.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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ZWUvLi9ub2RlX21vZHVsZXMvcHJlYWN0L2Rpc3QvcHJlYWN0Lm1vZHVsZS5qcz9kYTY1Il0sInNvdXJjZXNDb250ZW50IjpbInZhciBuLGwsdSxpLHQscixvLGYsZSxjPXt9LHM9W10sYT0vYWNpdHxleCg/OnN8Z3xufHB8JCl8cnBofGdyaWR8b3dzfG1uY3xudHd8aW5lW2NoXXx6b298Xm9yZHxpdGVyYS9pO2Z1bmN0aW9uIGgobixsKXtmb3IodmFyIHUgaW4gbCluW3VdPWxbdV07cmV0dXJuIG59ZnVuY3Rpb24gdihuKXt2YXIgbD1uLnBhcmVudE5vZGU7bCYmbC5yZW1vdmVDaGlsZChuKX1mdW5jdGlvbiB5KGwsdSxpKXt2YXIgdCxyLG8sZj17fTtmb3IobyBpbiB1KVwia2V5XCI9PW8/dD11W29dOlwicmVmXCI9PW8/cj11W29dOmZbb109dVtvXTtpZihhcmd1bWVudHMubGVuZ3RoPjImJihmLmNoaWxkcmVuPWFyZ3VtZW50cy5sZW5ndGg+Mz9uLmNhbGwoYXJndW1lbnRzLDIpOmkpLFwiZnVuY3Rpb25cIj09dHlwZW9mIGwmJm51bGwhPWwuZGVmYXVsdFByb3BzKWZvcihvIGluIGwuZGVmYXVsdFByb3BzKXZvaWQgMD09PWZbb10mJihmW29dPWwuZGVmYXVsdFByb3BzW29dKTtyZXR1cm4gcChsLGYsdCxyLG51bGwpfWZ1bmN0aW9uIHAobixpLHQscixvKXt2YXIgZj17dHlwZTpuLHByb3BzOmksa2V5OnQscmVmOnIsX19rOm51bGwsX186bnVsbCxfX2I6MCxfX2U6bnVsbCxfX2Q6dm9pZCAwLF9fYzpudWxsLF9faDpudWxsLGNvbnN0cnVjdG9yOnZvaWQgMCxfX3Y6bnVsbD09bz8rK3U6b307cmV0dXJuIG51bGw9PW8mJm51bGwhPWwudm5vZGUmJmwudm5vZGUoZiksZn1mdW5jdGlvbiBkKCl7cmV0dXJue2N1cnJlbnQ6bnVsbH19ZnVuY3Rpb24gXyhuKXtyZXR1cm4gbi5jaGlsZHJlbn1mdW5jdGlvbiBrKG4sbCx1LGksdCl7dmFyIHI7Zm9yKHIgaW4gdSlcImNoaWxkcmVuXCI9PT1yfHxcImtleVwiPT09cnx8ciBpbiBsfHxnKG4scixudWxsLHVbcl0saSk7Zm9yKHIgaW4gbCl0JiZcImZ1bmN0aW9uXCIhPXR5cGVvZiBsW3JdfHxcImNoaWxkcmVuXCI9PT1yfHxcImtleVwiPT09cnx8XCJ2YWx1ZVwiPT09cnx8XCJjaGVja2VkXCI9PT1yfHx1W3JdPT09bFtyXXx8ZyhuLHIsbFtyXSx1W3JdLGkpfWZ1bmN0aW9uIGIobixsLHUpe1wiLVwiPT09bFswXT9uLnNldFByb3BlcnR5KGwsbnVsbD09dT9cIlwiOnUpOm5bbF09bnVsbD09dT9cIlwiOlwibnVtYmVyXCIhPXR5cGVvZiB1fHxhLnRlc3QobCk/dTp1K1wicHhcIn1mdW5jdGlvbiBnKG4sbCx1LGksdCl7dmFyIHI7bjppZihcInN0eWxlXCI9PT1sKWlmKFwic3RyaW5nXCI9PXR5cGVvZiB1KW4uc3R5bGUuY3NzVGV4dD11O2Vsc2V7aWYoXCJzdHJpbmdcIj09dHlwZW9mIGkmJihuLnN0eWxlLmNzc1RleHQ9aT1cIlwiKSxpKWZvcihsIGluIGkpdSYmbCBpbiB1fHxiKG4uc3R5bGUsbCxcIlwiKTtpZih1KWZvcihsIGluIHUpaSYmdVtsXT09PWlbbF18fGIobi5zdHlsZSxsLHVbbF0pfWVsc2UgaWYoXCJvXCI9PT1sWzBdJiZcIm5cIj09PWxbMV0pcj1sIT09KGw9bC5yZXBsYWNlKC9DYXB0dXJlJC8sXCJcIikpLGw9bC50b0xvd2VyQ2FzZSgpaW4gbj9sLnRvTG93ZXJDYXNlKCkuc2xpY2UoMik6bC5zbGljZSgyKSxuLmx8fChuLmw9e30pLG4ubFtsK3JdPXUsdT9pfHxuLmFkZEV2ZW50TGlzdGVuZXIobCxyP3c6bSxyKTpuLnJlbW92ZUV2ZW50TGlzdGVuZXIobCxyP3c6bSxyKTtlbHNlIGlmKFwiZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUxcIiE9PWwpe2lmKHQpbD1sLnJlcGxhY2UoL3hsaW5rKEh8OmgpLyxcImhcIikucmVwbGFjZSgvc05hbWUkLyxcInNcIik7ZWxzZSBpZihcIndpZHRoXCIhPT1sJiZcImhlaWdodFwiIT09bCYmXCJocmVmXCIhPT1sJiZcImxpc3RcIiE9PWwmJlwiZm9ybVwiIT09bCYmXCJ0YWJJbmRleFwiIT09bCYmXCJkb3dubG9hZFwiIT09bCYmbCBpbiBuKXRyeXtuW2xdPW51bGw9PXU/XCJcIjp1O2JyZWFrIG59Y2F0Y2gobil7fVwiZnVuY3Rpb25cIj09dHlwZW9mIHV8fChudWxsPT11fHwhMT09PXUmJi0xPT1sLmluZGV4T2YoXCItXCIpP24ucmVtb3ZlQXR0cmlidXRlKGwpOm4uc2V0QXR0cmlidXRlKGwsdSkpfX1mdW5jdGlvbiBtKG4pe3Q9ITA7dHJ5e3JldHVybiB0aGlzLmxbbi50eXBlKyExXShsLmV2ZW50P2wuZXZlbnQobik6bil9ZmluYWxseXt0PSExfX1mdW5jdGlvbiB3KG4pe3Q9ITA7dHJ5e3JldHVybiB0aGlzLmxbbi50eXBlKyEwXShsLmV2ZW50P2wuZXZlbnQobik6bil9ZmluYWxseXt0PSExfX1mdW5jdGlvbiB4KG4sbCl7dGhpcy5wcm9wcz1uLHRoaXMuY29udGV4dD1sfWZ1bmN0aW9uIEEobixsKXtpZihudWxsPT1sKXJldHVybiBuLl9fP0Eobi5fXyxuLl9fLl9fay5pbmRleE9mKG4pKzEpOm51bGw7Zm9yKHZhciB1O2w8bi5fX2subGVuZ3RoO2wrKylpZihudWxsIT0odT1uLl9fa1tsXSkmJm51bGwhPXUuX19lKXJldHVybiB1Ll9fZTtyZXR1cm5cImZ1bmN0aW9uXCI9PXR5cGVvZiBuLnR5cGU/QShuKTpudWxsfWZ1bmN0aW9uIFAobil7dmFyIGwsdTtpZihudWxsIT0obj1uLl9fKSYmbnVsbCE9bi5fX2Mpe2ZvcihuLl9fZT1uLl9fYy5iYXNlPW51bGwsbD0wO2w8bi5fX2subGVuZ3RoO2wrKylpZihudWxsIT0odT1uLl9fa1tsXSkmJm51bGwhPXUuX19lKXtuLl9fZT1uLl9fYy5iYXNlPXUuX19lO2JyZWFrfXJldHVybiBQKG4pfX1mdW5jdGlvbiBDKG4pe3Q/c2V0VGltZW91dChuKTpmKG4pfWZ1bmN0aW9uIFQobil7KCFuLl9fZCYmKG4uX19kPSEwKSYmci5wdXNoKG4pJiYhJC5fX3IrK3x8byE9PWwuZGVib3VuY2VSZW5kZXJpbmcpJiYoKG89bC5kZWJvdW5jZVJlbmRlcmluZyl8fEMpKCQpfWZ1bmN0aW9uICQoKXt2YXIgbixsLHUsaSx0LG8sZixlO2ZvcihyLnNvcnQoZnVuY3Rpb24obixsKXtyZXR1cm4gbi5fX3YuX19iLWwuX192Ll9fYn0pO249ci5zaGlmdCgpOyluLl9fZCYmKGw9ci5sZW5ndGgsaT12b2lkIDAsdD12b2lkIDAsZj0obz0odT1uKS5fX3YpLl9fZSwoZT11Ll9fUCkmJihpPVtdLCh0PWgoe30sbykpLl9fdj1vLl9fdisxLE0oZSxvLHQsdS5fX24sdm9pZCAwIT09ZS5vd25lclNWR0VsZW1lbnQsbnVsbCE9by5fX2g/W2ZdOm51bGwsaSxudWxsPT1mP0Eobyk6ZixvLl9faCksTihpLG8pLG8uX19lIT1mJiZQKG8pKSxyLmxlbmd0aD5sJiZyLnNvcnQoZnVuY3Rpb24obixsKXtyZXR1cm4gbi5fX3YuX19iLWwuX192Ll9fYn0pKTskLl9fcj0wfWZ1bmN0aW9uIEgobixsLHUsaSx0LHIsbyxmLGUsYSl7dmFyIGgsdix5LGQsayxiLGcsbT1pJiZpLl9fa3x8cyx3PW0ubGVuZ3RoO2Zvcih1Ll9faz1bXSxoPTA7aDxsLmxlbmd0aDtoKyspaWYobnVsbCE9KGQ9dS5fX2tbaF09bnVsbD09KGQ9bFtoXSl8fFwiYm9vbGVhblwiPT10eXBlb2YgZD9udWxsOlwic3RyaW5nXCI9PXR5cGVvZiBkfHxcIm51bWJlclwiPT10eXBlb2YgZHx8XCJiaWdpbnRcIj09dHlwZW9mIGQ/cChudWxsLGQsbnVsbCxudWxsLGQpOkFycmF5LmlzQXJyYXkoZCk/cChfLHtjaGlsZHJlbjpkfSxudWxsLG51bGwsbnVsbCk6ZC5fX2I+MD9wKGQudHlwZSxkLnByb3BzLGQua2V5LGQucmVmP2QucmVmOm51bGwsZC5fX3YpOmQpKXtpZihkLl9fPXUsZC5fX2I9dS5fX2IrMSxudWxsPT09KHk9bVtoXSl8fHkmJmQua2V5PT15LmtleSYmZC50eXBlPT09eS50eXBlKW1baF09dm9pZCAwO2Vsc2UgZm9yKHY9MDt2PHc7disrKXtpZigoeT1tW3ZdKSYmZC5rZXk9PXkua2V5JiZkLnR5cGU9PT15LnR5cGUpe21bdl09dm9pZCAwO2JyZWFrfXk9bnVsbH1NKG4sZCx5PXl8fGMsdCxyLG8sZixlLGEpLGs9ZC5fX2UsKHY9ZC5yZWYpJiZ5LnJlZiE9diYmKGd8fChnPVtdKSx5LnJlZiYmZy5wdXNoKHkucmVmLG51bGwsZCksZy5wdXNoKHYsZC5fX2N8fGssZCkpLG51bGwhPWs/KG51bGw9PWImJihiPWspLFwiZnVuY3Rpb25cIj09dHlwZW9mIGQudHlwZSYmZC5fX2s9PT15Ll9faz9kLl9fZD1lPUkoZCxlLG4pOmU9eihuLGQseSxtLGssZSksXCJmdW5jdGlvblwiPT10eXBlb2YgdS50eXBlJiYodS5fX2Q9ZSkpOmUmJnkuX19lPT1lJiZlLnBhcmVudE5vZGUhPW4mJihlPUEoeSkpfWZvcih1Ll9fZT1iLGg9dztoLS07KW51bGwhPW1baF0mJihcImZ1bmN0aW9uXCI9PXR5cGVvZiB1LnR5cGUmJm51bGwhPW1baF0uX19lJiZtW2hdLl9fZT09dS5fX2QmJih1Ll9fZD1MKGkpLm5leHRTaWJsaW5nKSxxKG1baF0sbVtoXSkpO2lmKGcpZm9yKGg9MDtoPGcubGVuZ3RoO2grKylTKGdbaF0sZ1srK2hdLGdbKytoXSl9ZnVuY3Rpb24gSShuLGwsdSl7Zm9yKHZhciBpLHQ9bi5fX2sscj0wO3QmJnI8dC5sZW5ndGg7cisrKShpPXRbcl0pJiYoaS5fXz1uLGw9XCJmdW5jdGlvblwiPT10eXBlb2YgaS50eXBlP0koaSxsLHUpOnoodSxpLGksdCxpLl9fZSxsKSk7cmV0dXJuIGx9ZnVuY3Rpb24gaihuLGwpe3JldHVybiBsPWx8fFtdLG51bGw9PW58fFwiYm9vbGVhblwiPT10eXBlb2Ygbnx8KEFycmF5LmlzQXJyYXkobik/bi5zb21lKGZ1bmN0aW9uKG4pe2oobixsKX0pOmwucHVzaChuKSksbH1mdW5jdGlvbiB6KG4sbCx1LGksdCxyKXt2YXIgbyxmLGU7aWYodm9pZCAwIT09bC5fX2Qpbz1sLl9fZCxsLl9fZD12b2lkIDA7ZWxzZSBpZihudWxsPT11fHx0IT1yfHxudWxsPT10LnBhcmVudE5vZGUpbjppZihudWxsPT1yfHxyLnBhcmVudE5vZGUhPT1uKW4uYXBwZW5kQ2hpbGQodCksbz1udWxsO2Vsc2V7Zm9yKGY9cixlPTA7KGY9Zi5uZXh0U2libGluZykmJmU8aS5sZW5ndGg7ZSs9MSlpZihmPT10KWJyZWFrIG47bi5pbnNlcnRCZWZvcmUodCxyKSxvPXJ9cmV0dXJuIHZvaWQgMCE9PW8/bzp0Lm5leHRTaWJsaW5nfWZ1bmN0aW9uIEwobil7dmFyIGwsdSxpO2lmKG51bGw9PW4udHlwZXx8XCJzdHJpbmdcIj09dHlwZW9mIG4udHlwZSlyZXR1cm4gbi5fX2U7aWYobi5fX2spZm9yKGw9bi5fX2subGVuZ3RoLTE7bD49MDtsLS0paWYoKHU9bi5fX2tbbF0pJiYoaT1MKHUpKSlyZXR1cm4gaTtyZXR1cm4gbnVsbH1mdW5jdGlvbiBNKG4sdSxpLHQscixvLGYsZSxjKXt2YXIgcyxhLHYseSxwLGQsayxiLGcsbSx3LEEsUCxDLFQsJD11LnR5cGU7aWYodm9pZCAwIT09dS5jb25zdHJ1Y3RvcilyZXR1cm4gbnVsbDtudWxsIT1pLl9faCYmKGM9aS5fX2gsZT11Ll9fZT1pLl9fZSx1Ll9faD1udWxsLG89W2VdKSwocz1sLl9fYikmJnModSk7dHJ5e246aWYoXCJmdW5jdGlvblwiPT10eXBlb2YgJCl7aWYoYj11LnByb3BzLGc9KHM9JC5jb250ZXh0VHlwZSkmJnRbcy5fX2NdLG09cz9nP2cucHJvcHMudmFsdWU6cy5fXzp0LGkuX19jP2s9KGE9dS5fX2M9aS5fX2MpLl9fPWEuX19FOihcInByb3RvdHlwZVwiaW4gJCYmJC5wcm90b3R5cGUucmVuZGVyP3UuX19jPWE9bmV3ICQoYixtKToodS5fX2M9YT1uZXcgeChiLG0pLGEuY29uc3RydWN0b3I9JCxhLnJlbmRlcj1CKSxnJiZnLnN1YihhKSxhLnByb3BzPWIsYS5zdGF0ZXx8KGEuc3RhdGU9e30pLGEuY29udGV4dD1tLGEuX19uPXQsdj1hLl9fZD0hMCxhLl9faD1bXSxhLl9zYj1bXSksbnVsbD09YS5fX3MmJihhLl9fcz1hLnN0YXRlKSxudWxsIT0kLmdldERlcml2ZWRTdGF0ZUZyb21Qcm9wcyYmKGEuX19zPT1hLnN0YXRlJiYoYS5fX3M9aCh7fSxhLl9fcykpLGgoYS5fX3MsJC5nZXREZXJpdmVkU3RhdGVGcm9tUHJvcHMoYixhLl9fcykpKSx5PWEucHJvcHMscD1hLnN0YXRlLGEuX192PXUsdiludWxsPT0kLmdldERlcml2ZWRTdGF0ZUZyb21Qcm9wcyYmbnVsbCE9YS5jb21wb25lbnRXaWxsTW91bnQmJmEuY29tcG9uZW50V2lsbE1vdW50KCksbnVsbCE9YS5jb21wb25lbnREaWRNb3VudCYmYS5fX2gucHVzaChhLmNvbXBvbmVudERpZE1vdW50KTtlbHNle2lmKG51bGw9PSQuZ2V0RGVyaXZlZFN0YXRlRnJvbVByb3BzJiZiIT09eSYmbnVsbCE9YS5jb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzJiZhLmNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHMoYixtKSwhYS5fX2UmJm51bGwhPWEuc2hvdWxkQ29tcG9uZW50VXBkYXRlJiYhMT09PWEuc2hvdWxkQ29tcG9uZW50VXBkYXRlKGIsYS5fX3MsbSl8fHUuX192PT09aS5fX3Ype2Zvcih1Ll9fdiE9PWkuX192JiYoYS5wcm9wcz1iLGEuc3RhdGU9YS5fX3MsYS5fX2Q9ITEpLHUuX19lPWkuX19lLHUuX19rPWkuX19rLHUuX19rLmZvckVhY2goZnVuY3Rpb24obil7biYmKG4uX189dSl9KSx3PTA7dzxhLl9zYi5sZW5ndGg7dysrKWEuX19oLnB1c2goYS5fc2Jbd10pO2EuX3NiPVtdLGEuX19oLmxlbmd0aCYmZi5wdXNoKGEpO2JyZWFrIG59bnVsbCE9YS5jb21wb25lbnRXaWxsVXBkYXRlJiZhLmNvbXBvbmVudFdpbGxVcGRhdGUoYixhLl9fcyxtKSxudWxsIT1hLmNvbXBvbmVudERpZFVwZGF0ZSYmYS5fX2gucHVzaChmdW5jdGlvbigpe2EuY29tcG9uZW50RGlkVXBkYXRlKHkscCxkKX0pfWlmKGEuY29udGV4dD1tLGEucHJvcHM9YixhLl9fUD1uLEE9bC5fX3IsUD0wLFwicHJvdG90eXBlXCJpbiAkJiYkLnByb3RvdHlwZS5yZW5kZXIpe2ZvcihhLnN0YXRlPWEuX19zLGEuX19kPSExLEEmJkEodSkscz1hLnJlbmRlcihhLnByb3BzLGEuc3RhdGUsYS5jb250ZXh0KSxDPTA7QzxhLl9zYi5sZW5ndGg7QysrKWEuX19oLnB1c2goYS5fc2JbQ10pO2EuX3NiPVtdfWVsc2UgZG97YS5fX2Q9ITEsQSYmQSh1KSxzPWEucmVuZGVyKGEucHJvcHMsYS5zdGF0ZSxhLmNvbnRleHQpLGEuc3RhdGU9YS5fX3N9d2hpbGUoYS5fX2QmJisrUDwyNSk7YS5zdGF0ZT1hLl9fcyxudWxsIT1hLmdldENoaWxkQ29udGV4dCYmKHQ9aChoKHt9LHQpLGEuZ2V0Q2hpbGRDb250ZXh0KCkpKSx2fHxudWxsPT1hLmdldFNuYXBzaG90QmVmb3JlVXBkYXRlfHwoZD1hLmdldFNuYXBzaG90QmVmb3JlVXBkYXRlKHkscCkpLFQ9bnVsbCE9cyYmcy50eXBlPT09XyYmbnVsbD09cy5rZXk/cy5wcm9wcy5jaGlsZHJlbjpzLEgobixBcnJheS5pc0FycmF5KFQpP1Q6W1RdLHUsaSx0LHIsbyxmLGUsYyksYS5iYXNlPXUuX19lLHUuX19oPW51bGwsYS5fX2gubGVuZ3RoJiZmLnB1c2goYSksayYmKGEuX19FPWEuX189bnVsbCksYS5fX2U9ITF9ZWxzZSBudWxsPT1vJiZ1Ll9fdj09PWkuX192Pyh1Ll9faz1pLl9fayx1Ll9fZT1pLl9fZSk6dS5fX2U9TyhpLl9fZSx1LGksdCxyLG8sZixjKTsocz1sLmRpZmZlZCkmJnModSl9Y2F0Y2gobil7dS5fX3Y9bnVsbCwoY3x8bnVsbCE9bykmJih1Ll9fZT1lLHUuX19oPSEhYyxvW28uaW5kZXhPZihlKV09bnVsbCksbC5fX2Uobix1LGkpfX1mdW5jdGlvbiBOKG4sdSl7bC5fX2MmJmwuX19jKHUsbiksbi5zb21lKGZ1bmN0aW9uKHUpe3RyeXtuPXUuX19oLHUuX19oPVtdLG4uc29tZShmdW5jdGlvbihuKXtuLmNhbGwodSl9KX1jYXRjaChuKXtsLl9fZShuLHUuX192KX19KX1mdW5jdGlvbiBPKGwsdSxpLHQscixvLGYsZSl7dmFyIHMsYSxoLHk9aS5wcm9wcyxwPXUucHJvcHMsZD11LnR5cGUsXz0wO2lmKFwic3ZnXCI9PT1kJiYocj0hMCksbnVsbCE9bylmb3IoO188by5sZW5ndGg7XysrKWlmKChzPW9bX10pJiZcInNldEF0dHJpYnV0ZVwiaW4gcz09ISFkJiYoZD9zLmxvY2FsTmFtZT09PWQ6Mz09PXMubm9kZVR5cGUpKXtsPXMsb1tfXT1udWxsO2JyZWFrfWlmKG51bGw9PWwpe2lmKG51bGw9PT1kKXJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShwKTtsPXI/ZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixkKTpkb2N1bWVudC5jcmVhdGVFbGVtZW50KGQscC5pcyYmcCksbz1udWxsLGU9ITF9aWYobnVsbD09PWQpeT09PXB8fGUmJmwuZGF0YT09PXB8fChsLmRhdGE9cCk7ZWxzZXtpZihvPW8mJm4uY2FsbChsLmNoaWxkTm9kZXMpLGE9KHk9aS5wcm9wc3x8YykuZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUwsaD1wLmRhbmdlcm91c2x5U2V0SW5uZXJIVE1MLCFlKXtpZihudWxsIT1vKWZvcih5PXt9LF89MDtfPGwuYXR0cmlidXRlcy5sZW5ndGg7XysrKXlbbC5hdHRyaWJ1dGVzW19dLm5hbWVdPWwuYXR0cmlidXRlc1tfXS52YWx1ZTsoaHx8YSkmJihoJiYoYSYmaC5fX2h0bWw9PWEuX19odG1sfHxoLl9faHRtbD09PWwuaW5uZXJIVE1MKXx8KGwuaW5uZXJIVE1MPWgmJmguX19odG1sfHxcIlwiKSl9aWYoayhsLHAseSxyLGUpLGgpdS5fX2s9W107ZWxzZSBpZihfPXUucHJvcHMuY2hpbGRyZW4sSChsLEFycmF5LmlzQXJyYXkoXyk/XzpbX10sdSxpLHQsciYmXCJmb3JlaWduT2JqZWN0XCIhPT1kLG8sZixvP29bMF06aS5fX2smJkEoaSwwKSxlKSxudWxsIT1vKWZvcihfPW8ubGVuZ3RoO18tLTspbnVsbCE9b1tfXSYmdihvW19dKTtlfHwoXCJ2YWx1ZVwiaW4gcCYmdm9pZCAwIT09KF89cC52YWx1ZSkmJihfIT09bC52YWx1ZXx8XCJwcm9ncmVzc1wiPT09ZCYmIV98fFwib3B0aW9uXCI9PT1kJiZfIT09eS52YWx1ZSkmJmcobCxcInZhbHVlXCIsXyx5LnZhbHVlLCExKSxcImNoZWNrZWRcImluIHAmJnZvaWQgMCE9PShfPXAuY2hlY2tlZCkmJl8hPT1sLmNoZWNrZWQmJmcobCxcImNoZWNrZWRcIixfLHkuY2hlY2tlZCwhMSkpfXJldHVybiBsfWZ1bmN0aW9uIFMobix1LGkpe3RyeXtcImZ1bmN0aW9uXCI9PXR5cGVvZiBuP24odSk6bi5jdXJyZW50PXV9Y2F0Y2gobil7bC5fX2UobixpKX19ZnVuY3Rpb24gcShuLHUsaSl7dmFyIHQscjtpZihsLnVubW91bnQmJmwudW5tb3VudChuKSwodD1uLnJlZikmJih0LmN1cnJlbnQmJnQuY3VycmVudCE9PW4uX19lfHxTKHQsbnVsbCx1KSksbnVsbCE9KHQ9bi5fX2MpKXtpZih0LmNvbXBvbmVudFdpbGxVbm1vdW50KXRyeXt0LmNvbXBvbmVudFdpbGxVbm1vdW50KCl9Y2F0Y2gobil7bC5fX2Uobix1KX10LmJhc2U9dC5fX1A9bnVsbCxuLl9fYz12b2lkIDB9aWYodD1uLl9faylmb3Iocj0wO3I8dC5sZW5ndGg7cisrKXRbcl0mJnEodFtyXSx1LGl8fFwiZnVuY3Rpb25cIiE9dHlwZW9mIG4udHlwZSk7aXx8bnVsbD09bi5fX2V8fHYobi5fX2UpLG4uX189bi5fX2U9bi5fX2Q9dm9pZCAwfWZ1bmN0aW9uIEIobixsLHUpe3JldHVybiB0aGlzLmNvbnN0cnVjdG9yKG4sdSl9ZnVuY3Rpb24gRCh1LGksdCl7dmFyIHIsbyxmO2wuX18mJmwuX18odSxpKSxvPShyPVwiZnVuY3Rpb25cIj09dHlwZW9mIHQpP251bGw6dCYmdC5fX2t8fGkuX19rLGY9W10sTShpLHU9KCFyJiZ0fHxpKS5fX2s9eShfLG51bGwsW3VdKSxvfHxjLGMsdm9pZCAwIT09aS5vd25lclNWR0VsZW1lbnQsIXImJnQ/W3RdOm8/bnVsbDppLmZpcnN0Q2hpbGQ/bi5jYWxsKGkuY2hpbGROb2Rlcyk6bnVsbCxmLCFyJiZ0P3Q6bz9vLl9fZTppLmZpcnN0Q2hpbGQsciksTihmLHUpfWZ1bmN0aW9uIEUobixsKXtEKG4sbCxFKX1mdW5jdGlvbiBGKGwsdSxpKXt2YXIgdCxyLG8sZj1oKHt9LGwucHJvcHMpO2ZvcihvIGluIHUpXCJrZXlcIj09bz90PXVbb106XCJyZWZcIj09bz9yPXVbb106ZltvXT11W29dO3JldHVybiBhcmd1bWVudHMubGVuZ3RoPjImJihmLmNoaWxkcmVuPWFyZ3VtZW50cy5sZW5ndGg+Mz9uLmNhbGwoYXJndW1lbnRzLDIpOmkpLHAobC50eXBlLGYsdHx8bC5rZXkscnx8bC5yZWYsbnVsbCl9ZnVuY3Rpb24gRyhuLGwpe3ZhciB1PXtfX2M6bD1cIl9fY0NcIitlKyssX186bixDb25zdW1lcjpmdW5jdGlvbihuLGwpe3JldHVybiBuLmNoaWxkcmVuKGwpfSxQcm92aWRlcjpmdW5jdGlvbihuKXt2YXIgdSxpO3JldHVybiB0aGlzLmdldENoaWxkQ29udGV4dHx8KHU9W10sKGk9e30pW2xdPXRoaXMsdGhpcy5nZXRDaGlsZENvbnRleHQ9ZnVuY3Rpb24oKXtyZXR1cm4gaX0sdGhpcy5zaG91bGRDb21wb25lbnRVcGRhdGU9ZnVuY3Rpb24obil7dGhpcy5wcm9wcy52YWx1ZSE9PW4udmFsdWUmJnUuc29tZShmdW5jdGlvbihuKXtuLl9fZT0hMCxUKG4pfSl9LHRoaXMuc3ViPWZ1bmN0aW9uKG4pe3UucHVzaChuKTt2YXIgbD1uLmNvbXBvbmVudFdpbGxVbm1vdW50O24uY29tcG9uZW50V2lsbFVubW91bnQ9ZnVuY3Rpb24oKXt1LnNwbGljZSh1LmluZGV4T2YobiksMSksbCYmbC5jYWxsKG4pfX0pLG4uY2hpbGRyZW59fTtyZXR1cm4gdS5Qcm92aWRlci5fXz11LkNvbnN1bWVyLmNvbnRleHRUeXBlPXV9bj1zLnNsaWNlLGw9e19fZTpmdW5jdGlvbihuLGwsdSxpKXtmb3IodmFyIHQscixvO2w9bC5fXzspaWYoKHQ9bC5fX2MpJiYhdC5fXyl0cnl7aWYoKHI9dC5jb25zdHJ1Y3RvcikmJm51bGwhPXIuZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yJiYodC5zZXRTdGF0ZShyLmdldERlcml2ZWRTdGF0ZUZyb21FcnJvcihuKSksbz10Ll9fZCksbnVsbCE9dC5jb21wb25lbnREaWRDYXRjaCYmKHQuY29tcG9uZW50RGlkQ2F0Y2gobixpfHx7fSksbz10Ll9fZCksbylyZXR1cm4gdC5fX0U9dH1jYXRjaChsKXtuPWx9dGhyb3cgbn19LHU9MCxpPWZ1bmN0aW9uKG4pe3JldHVybiBudWxsIT1uJiZ2b2lkIDA9PT1uLmNvbnN0cnVjdG9yfSx0PSExLHgucHJvdG90eXBlLnNldFN0YXRlPWZ1bmN0aW9uKG4sbCl7dmFyIHU7dT1udWxsIT10aGlzLl9fcyYmdGhpcy5fX3MhPT10aGlzLnN0YXRlP3RoaXMuX19zOnRoaXMuX19zPWgoe30sdGhpcy5zdGF0ZSksXCJmdW5jdGlvblwiPT10eXBlb2YgbiYmKG49bihoKHt9LHUpLHRoaXMucHJvcHMpKSxuJiZoKHUsbiksbnVsbCE9biYmdGhpcy5fX3YmJihsJiZ0aGlzLl9zYi5wdXNoKGwpLFQodGhpcykpfSx4LnByb3RvdHlwZS5mb3JjZVVwZGF0ZT1mdW5jdGlvbihuKXt0aGlzLl9fdiYmKHRoaXMuX19lPSEwLG4mJnRoaXMuX19oLnB1c2gobiksVCh0aGlzKSl9LHgucHJvdG90eXBlLnJlbmRlcj1fLHI9W10sZj1cImZ1bmN0aW9uXCI9PXR5cGVvZiBQcm9taXNlP1Byb21pc2UucHJvdG90eXBlLnRoZW4uYmluZChQcm9taXNlLnJlc29sdmUoKSk6c2V0VGltZW91dCwkLl9fcj0wLGU9MDtleHBvcnR7eCBhcyBDb21wb25lbnQsXyBhcyBGcmFnbWVudCxGIGFzIGNsb25lRWxlbWVudCxHIGFzIGNyZWF0ZUNvbnRleHQseSBhcyBjcmVhdGVFbGVtZW50LGQgYXMgY3JlYXRlUmVmLHkgYXMgaCxFIGFzIGh5ZHJhdGUsaSBhcyBpc1ZhbGlkRWxlbWVudCxsIGFzIG9wdGlvbnMsRCBhcyByZW5kZXIsaiBhcyB0b0NoaWxkQXJyYXl9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cHJlYWN0Lm1vZHVsZS5qcy5tYXBcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///114\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 115:
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Children: () => (/* binding */ O),\n/* harmony export */ Component: () => (/* reexport safe */ preact__WEBPACK_IMPORTED_MODULE_0__.Component),\n/* harmony export */ Fragment: () => (/* reexport safe */ preact__WEBPACK_IMPORTED_MODULE_0__.Fragment),\n/* harmony export */ PureComponent: () => (/* binding */ w),\n/* harmony export */ StrictMode: () => (/* binding */ vn),\n/* harmony export */ Suspense: () => (/* binding */ D),\n/* harmony export */ SuspenseList: () => (/* binding */ V),\n/* harmony export */ __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: () => (/* binding */ rn),\n/* harmony export */ cloneElement: () => (/* binding */ cn),\n/* harmony export */ createContext: () => (/* reexport safe */ preact__WEBPACK_IMPORTED_MODULE_0__.createContext),\n/* harmony export */ createElement: () => (/* reexport safe */ preact__WEBPACK_IMPORTED_MODULE_0__.createElement),\n/* harmony export */ createFactory: () => (/* binding */ on),\n/* harmony export */ createPortal: () => (/* binding */ j),\n/* harmony export */ createRef: () => (/* reexport safe */ preact__WEBPACK_IMPORTED_MODULE_0__.createRef),\n/* harmony export */ \"default\": () => (/* binding */ bn),\n/* harmony export */ findDOMNode: () => (/* binding */ an),\n/* harmony export */ flushSync: () => (/* binding */ hn),\n/* harmony export */ forwardRef: () => (/* binding */ k),\n/* harmony export */ hydrate: () => (/* binding */ q),\n/* harmony export */ isValidElement: () => (/* binding */ ln),\n/* harmony export */ lazy: () => (/* binding */ M),\n/* harmony export */ memo: () => (/* binding */ R),\n/* harmony export */ render: () => (/* binding */ Y),\n/* harmony export */ startTransition: () => (/* binding */ dn),\n/* harmony export */ unmountComponentAtNode: () => (/* binding */ fn),\n/* harmony export */ unstable_batchedUpdates: () => (/* binding */ sn),\n/* harmony export */ useCallback: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useCallback),\n/* harmony export */ useContext: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useContext),\n/* harmony export */ useDebugValue: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useDebugValue),\n/* harmony export */ useDeferredValue: () => (/* binding */ pn),\n/* harmony export */ useEffect: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useEffect),\n/* harmony export */ useErrorBoundary: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useErrorBoundary),\n/* harmony export */ useId: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useId),\n/* harmony export */ useImperativeHandle: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useImperativeHandle),\n/* harmony export */ useInsertionEffect: () => (/* binding */ yn),\n/* harmony export */ useLayoutEffect: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useLayoutEffect),\n/* harmony export */ useMemo: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useMemo),\n/* harmony export */ useReducer: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useReducer),\n/* harmony export */ useRef: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useRef),\n/* harmony export */ useState: () => (/* reexport safe */ preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useState),\n/* harmony export */ useSyncExternalStore: () => (/* binding */ _n),\n/* harmony export */ useTransition: () => (/* binding */ mn),\n/* harmony export */ version: () => (/* binding */ un)\n/* harmony export */ });\n/* harmony import */ var preact__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(114);\n/* harmony import */ var preact_hooks__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(116);\nfunction g(n,t){for(var e in t)n[e]=t[e];return n}function C(n,t){for(var e in n)if(\"__source\"!==e&&!(e in t))return!0;for(var r in t)if(\"__source\"!==r&&n[r]!==t[r])return!0;return!1}function E(n,t){return n===t&&(0!==n||1/n==1/t)||n!=n&&t!=t}function w(n){this.props=n}function R(n,e){function r(n){var t=this.props.ref,r=t==n.ref;return!r&&t&&(t.call?t(null):t.current=null),e?!e(this.props,n)||!r:C(this.props,n)}function u(e){return this.shouldComponentUpdate=r,(0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(n,e)}return u.displayName=\"Memo(\"+(n.displayName||n.name)+\")\",u.prototype.isReactComponent=!0,u.__f=!0,u}(w.prototype=new preact__WEBPACK_IMPORTED_MODULE_0__.Component).isPureReactComponent=!0,w.prototype.shouldComponentUpdate=function(n,t){return C(this.props,n)||C(this.state,t)};var x=preact__WEBPACK_IMPORTED_MODULE_0__.options.__b;preact__WEBPACK_IMPORTED_MODULE_0__.options.__b=function(n){n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),x&&x(n)};var N=\"undefined\"!=typeof Symbol&&Symbol.for&&Symbol.for(\"react.forward_ref\")||3911;function k(n){function t(t){var e=g({},t);return delete e.ref,n(e,t.ref||null)}return t.$$typeof=N,t.render=t,t.prototype.isReactComponent=t.__f=!0,t.displayName=\"ForwardRef(\"+(n.displayName||n.name)+\")\",t}var A=function(n,t){return null==n?null:(0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)((0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)(n).map(t))},O={map:A,forEach:A,count:function(n){return n?(0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)(n).length:0},only:function(n){var t=(0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)(n);if(1!==t.length)throw\"Children.only\";return t[0]},toArray:preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray},T=preact__WEBPACK_IMPORTED_MODULE_0__.options.__e;preact__WEBPACK_IMPORTED_MODULE_0__.options.__e=function(n,t,e,r){if(n.then)for(var u,o=t;o=o.__;)if((u=o.__c)&&u.__c)return null==t.__e&&(t.__e=e.__e,t.__k=e.__k),u.__c(n,t);T(n,t,e,r)};var I=preact__WEBPACK_IMPORTED_MODULE_0__.options.unmount;function L(n,t,e){return n&&(n.__c&&n.__c.__H&&(n.__c.__H.__.forEach(function(n){\"function\"==typeof n.__c&&n.__c()}),n.__c.__H=null),null!=(n=g({},n)).__c&&(n.__c.__P===e&&(n.__c.__P=t),n.__c=null),n.__k=n.__k&&n.__k.map(function(n){return L(n,t,e)})),n}function U(n,t,e){return n&&(n.__v=null,n.__k=n.__k&&n.__k.map(function(n){return U(n,t,e)}),n.__c&&n.__c.__P===t&&(n.__e&&e.insertBefore(n.__e,n.__d),n.__c.__e=!0,n.__c.__P=e)),n}function D(){this.__u=0,this.t=null,this.__b=null}function F(n){var t=n.__.__c;return t&&t.__a&&t.__a(n)}function M(n){var e,r,u;function o(o){if(e||(e=n()).then(function(n){r=n.default||n},function(n){u=n}),u)throw u;if(!r)throw e;return (0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(r,o)}return o.displayName=\"Lazy\",o.__f=!0,o}function V(){this.u=null,this.o=null}preact__WEBPACK_IMPORTED_MODULE_0__.options.unmount=function(n){var t=n.__c;t&&t.__R&&t.__R(),t&&!0===n.__h&&(n.type=null),I&&I(n)},(D.prototype=new preact__WEBPACK_IMPORTED_MODULE_0__.Component).__c=function(n,t){var e=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(e);var u=F(r.__v),o=!1,i=function(){o||(o=!0,e.__R=null,u?u(l):l())};e.__R=i;var l=function(){if(!--r.__u){if(r.state.__a){var n=r.state.__a;r.__v.__k[0]=U(n,n.__c.__P,n.__c.__O)}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate()}},c=!0===t.__h;r.__u++||c||r.setState({__a:r.__b=r.__v.__k[0]}),n.then(i,i)},D.prototype.componentWillUnmount=function(){this.t=[]},D.prototype.render=function(n,e){if(this.__b){if(this.__v.__k){var r=document.createElement(\"div\"),o=this.__v.__k[0].__c;this.__v.__k[0]=L(this.__b,r,o.__O=o.__P)}this.__b=null}var i=e.__a&&(0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(preact__WEBPACK_IMPORTED_MODULE_0__.Fragment,null,n.fallback);return i&&(i.__h=null),[(0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(preact__WEBPACK_IMPORTED_MODULE_0__.Fragment,null,e.__a?null:n.children),i]};var W=function(n,t,e){if(++e[1]===e[0]&&n.o.delete(t),n.props.revealOrder&&(\"t\"!==n.props.revealOrder[0]||!n.o.size))for(e=n.u;e;){for(;e.length>3;)e.pop()();if(e[1]<e[0])break;n.u=e=e[2]}};function P(n){return this.getChildContext=function(){return n.context},n.children}function $(n){var e=this,r=n.i;e.componentWillUnmount=function(){(0,preact__WEBPACK_IMPORTED_MODULE_0__.render)(null,e.l),e.l=null,e.i=null},e.i&&e.i!==r&&e.componentWillUnmount(),n.__v?(e.l||(e.i=r,e.l={nodeType:1,parentNode:r,childNodes:[],appendChild:function(n){this.childNodes.push(n),e.i.appendChild(n)},insertBefore:function(n,t){this.childNodes.push(n),e.i.appendChild(n)},removeChild:function(n){this.childNodes.splice(this.childNodes.indexOf(n)>>>1,1),e.i.removeChild(n)}}),(0,preact__WEBPACK_IMPORTED_MODULE_0__.render)((0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)(P,{context:e.context},n.__v),e.l)):e.l&&e.componentWillUnmount()}function j(n,e){var r=(0,preact__WEBPACK_IMPORTED_MODULE_0__.createElement)($,{__v:n,i:e});return r.containerInfo=e,r}(V.prototype=new preact__WEBPACK_IMPORTED_MODULE_0__.Component).__a=function(n){var t=this,e=F(t.__v),r=t.o.get(n);return r[0]++,function(u){var o=function(){t.props.revealOrder?(r.push(u),W(t,n,r)):u()};e?e(o):o()}},V.prototype.render=function(n){this.u=null,this.o=new Map;var t=(0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)(n.children);n.revealOrder&&\"b\"===n.revealOrder[0]&&t.reverse();for(var e=t.length;e--;)this.o.set(t[e],this.u=[1,0,this.u]);return n.children},V.prototype.componentDidUpdate=V.prototype.componentDidMount=function(){var n=this;this.o.forEach(function(t,e){W(n,e,t)})};var z=\"undefined\"!=typeof Symbol&&Symbol.for&&Symbol.for(\"react.element\")||60103,B=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,H=\"undefined\"!=typeof document,Z=function(n){return(\"undefined\"!=typeof Symbol&&\"symbol\"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(n)};function Y(n,t,e){return null==t.__k&&(t.textContent=\"\"),(0,preact__WEBPACK_IMPORTED_MODULE_0__.render)(n,t),\"function\"==typeof e&&e(),n?n.__c:null}function q(n,t,e){return (0,preact__WEBPACK_IMPORTED_MODULE_0__.hydrate)(n,t),\"function\"==typeof e&&e(),n?n.__c:null}preact__WEBPACK_IMPORTED_MODULE_0__.Component.prototype.isReactComponent={},[\"componentWillMount\",\"componentWillReceiveProps\",\"componentWillUpdate\"].forEach(function(t){Object.defineProperty(preact__WEBPACK_IMPORTED_MODULE_0__.Component.prototype,t,{configurable:!0,get:function(){return this[\"UNSAFE_\"+t]},set:function(n){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:n})}})});var G=preact__WEBPACK_IMPORTED_MODULE_0__.options.event;function J(){}function K(){return this.cancelBubble}function Q(){return this.defaultPrevented}preact__WEBPACK_IMPORTED_MODULE_0__.options.event=function(n){return G&&(n=G(n)),n.persist=J,n.isPropagationStopped=K,n.isDefaultPrevented=Q,n.nativeEvent=n};var X,nn={configurable:!0,get:function(){return this.class}},tn=preact__WEBPACK_IMPORTED_MODULE_0__.options.vnode;preact__WEBPACK_IMPORTED_MODULE_0__.options.vnode=function(n){var t=n.type,e=n.props,u=e;if(\"string\"==typeof t){var o=-1===t.indexOf(\"-\");for(var i in u={},e){var l=e[i];H&&\"children\"===i&&\"noscript\"===t||\"value\"===i&&\"defaultValue\"in e&&null==l||(\"defaultValue\"===i&&\"value\"in e&&null==e.value?i=\"value\":\"download\"===i&&!0===l?l=\"\":/ondoubleclick/i.test(i)?i=\"ondblclick\":/^onchange(textarea|input)/i.test(i+t)&&!Z(e.type)?i=\"oninput\":/^onfocus$/i.test(i)?i=\"onfocusin\":/^onblur$/i.test(i)?i=\"onfocusout\":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i)?i=i.toLowerCase():o&&B.test(i)?i=i.replace(/[A-Z0-9]/g,\"-$&\").toLowerCase():null===l&&(l=void 0),/^oninput$/i.test(i)&&(i=i.toLowerCase(),u[i]&&(i=\"oninputCapture\")),u[i]=l)}\"select\"==t&&u.multiple&&Array.isArray(u.value)&&(u.value=(0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)(e.children).forEach(function(n){n.props.selected=-1!=u.value.indexOf(n.props.value)})),\"select\"==t&&null!=u.defaultValue&&(u.value=(0,preact__WEBPACK_IMPORTED_MODULE_0__.toChildArray)(e.children).forEach(function(n){n.props.selected=u.multiple?-1!=u.defaultValue.indexOf(n.props.value):u.defaultValue==n.props.value})),n.props=u,e.class!=e.className&&(nn.enumerable=\"className\"in e,null!=e.className&&(u.class=e.className),Object.defineProperty(u,\"className\",nn))}n.$$typeof=z,tn&&tn(n)};var en=preact__WEBPACK_IMPORTED_MODULE_0__.options.__r;preact__WEBPACK_IMPORTED_MODULE_0__.options.__r=function(n){en&&en(n),X=n.__c};var rn={ReactCurrentDispatcher:{current:{readContext:function(n){return X.__n[n.__c].props.value}}}},un=\"17.0.2\";function on(n){return preact__WEBPACK_IMPORTED_MODULE_0__.createElement.bind(null,n)}function ln(n){return!!n&&n.$$typeof===z}function cn(n){return ln(n)?preact__WEBPACK_IMPORTED_MODULE_0__.cloneElement.apply(null,arguments):n}function fn(n){return!!n.__k&&((0,preact__WEBPACK_IMPORTED_MODULE_0__.render)(null,n),!0)}function an(n){return n&&(n.base||1===n.nodeType&&n)||null}var sn=function(n,t){return n(t)},hn=function(n,t){return n(t)},vn=preact__WEBPACK_IMPORTED_MODULE_0__.Fragment;function dn(n){n()}function pn(n){return n}function mn(){return[!1,dn]}var yn=preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useLayoutEffect;function _n(n,t){var e=t(),r=(0,preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useState)({h:{__:e,v:t}}),u=r[0].h,o=r[1];return (0,preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useLayoutEffect)(function(){u.__=e,u.v=t,E(u.__,t())||o({h:u})},[n,e,t]),(0,preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useEffect)(function(){return E(u.__,u.v())||o({h:u}),n(function(){E(u.__,u.v())||o({h:u})})},[n]),e}var bn={useState:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useState,useId:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useId,useReducer:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useReducer,useEffect:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useEffect,useLayoutEffect:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useLayoutEffect,useInsertionEffect:yn,useTransition:mn,useDeferredValue:pn,useSyncExternalStore:_n,startTransition:dn,useRef:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useRef,useImperativeHandle:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useImperativeHandle,useMemo:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useMemo,useCallback:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useCallback,useContext:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useContext,useDebugValue:preact_hooks__WEBPACK_IMPORTED_MODULE_1__.useDebugValue,version:\"17.0.2\",Children:O,render:Y,hydrate:q,unmountComponentAtNode:fn,createPortal:j,createElement:preact__WEBPACK_IMPORTED_MODULE_0__.createElement,createContext:preact__WEBPACK_IMPORTED_MODULE_0__.createContext,createFactory:on,cloneElement:cn,createRef:preact__WEBPACK_IMPORTED_MODULE_0__.createRef,Fragment:preact__WEBPACK_IMPORTED_MODULE_0__.Fragment,isValidElement:ln,findDOMNode:an,Component:preact__WEBPACK_IMPORTED_MODULE_0__.Component,PureComponent:w,memo:R,forwardRef:k,flushSync:hn,unstable_batchedUpdates:sn,StrictMode:vn,Suspense:D,SuspenseList:V,lazy:M,__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:rn};\n//# sourceMappingURL=compat.module.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QW1DLGFBQWEsZUFBZSxPQUFPLGlEQUFDLGNBQWMsZUFBZSwwQkFBMEIsZUFBZSxhQUFhLGdEQUFDLHlCQUF5QixlQUFlLGdCQUFnQiw4Q0FBQyxhQUFhLGVBQWUsNENBQTRDLHFCQUFxQixZQUFZLGtCQUFrQixZQUFZLElBQUksNENBQUMsQ0FBQyxlQUFlLElBQUksZUFBZSxTQUFTLGNBQWMsY0FBYyxPQUFPLHlEQUFDLENBQUMsaUJBQWlCLFlBQVksc0RBQUMsRUFBRSxHQUFHLFVBQVUsa0JBQWtCLE9BQU8sNkRBQUMsWUFBWSw2QkFBNkIsSUFBSSxFQUFFLFVBQVUsdURBQUMsWUFBWSx5QkFBeUIsSUFBSSxlQUFlLGtCQUFrQixJQUFJLEVBQUUsRUFBRSxRQUFRLFFBQVEsU0FBUyxrREFBQyxPQUFPLCtDQUFDLFlBQVksb0RBQUMsV0FBVyxtREFBQyxpQkFBaUIseURBQUMsOEdBQThHLGdEQUFDLHFCQUFxQiw2REFBQyxTQUFTLGlEQUFDLGFBQWEscURBQUMsWUFBWSxvREFBQyxlQUFlLHVEQUFDLHVHQUF1RyxpREFBQyxlQUFlLGlEQUFDLDRDQUE0Qyw2Q0FBQyxVQUFVLDRDQUFDLDRDQUE0Qyw2Q0FBQyxtTEFBK3JCO0FBQ2xsUyIsInNvdXJjZXMiOlsid2VicGFjazovL2FyY2hpdGVjdHVpLWh0bWwtZnJlZS8uL25vZGVfbW9kdWxlcy9wcmVhY3QvY29tcGF0L2Rpc3QvY29tcGF0Lm1vZHVsZS5qcz8xNWQxIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydHtDb21wb25lbnQgYXMgbixjcmVhdGVFbGVtZW50IGFzIHQsb3B0aW9ucyBhcyBlLHRvQ2hpbGRBcnJheSBhcyByLEZyYWdtZW50IGFzIHUscmVuZGVyIGFzIG8saHlkcmF0ZSBhcyBpLGNyZWF0ZUNvbnRleHQgYXMgbCxjcmVhdGVSZWYgYXMgYyxjbG9uZUVsZW1lbnQgYXMgZn1mcm9tXCJwcmVhY3RcIjtleHBvcnR7Q29tcG9uZW50LEZyYWdtZW50LGNyZWF0ZUNvbnRleHQsY3JlYXRlRWxlbWVudCxjcmVhdGVSZWZ9ZnJvbVwicHJlYWN0XCI7aW1wb3J0e3VzZVN0YXRlIGFzIGEsdXNlSWQgYXMgcyx1c2VSZWR1Y2VyIGFzIGgsdXNlRWZmZWN0IGFzIHYsdXNlTGF5b3V0RWZmZWN0IGFzIGQsdXNlUmVmIGFzIHAsdXNlSW1wZXJhdGl2ZUhhbmRsZSBhcyBtLHVzZU1lbW8gYXMgeSx1c2VDYWxsYmFjayBhcyBfLHVzZUNvbnRleHQgYXMgYix1c2VEZWJ1Z1ZhbHVlIGFzIFN9ZnJvbVwicHJlYWN0L2hvb2tzXCI7ZXhwb3J0KmZyb21cInByZWFjdC9ob29rc1wiO2Z1bmN0aW9uIGcobix0KXtmb3IodmFyIGUgaW4gdCluW2VdPXRbZV07cmV0dXJuIG59ZnVuY3Rpb24gQyhuLHQpe2Zvcih2YXIgZSBpbiBuKWlmKFwiX19zb3VyY2VcIiE9PWUmJiEoZSBpbiB0KSlyZXR1cm4hMDtmb3IodmFyIHIgaW4gdClpZihcIl9fc291cmNlXCIhPT1yJiZuW3JdIT09dFtyXSlyZXR1cm4hMDtyZXR1cm4hMX1mdW5jdGlvbiBFKG4sdCl7cmV0dXJuIG49PT10JiYoMCE9PW58fDEvbj09MS90KXx8biE9biYmdCE9dH1mdW5jdGlvbiB3KG4pe3RoaXMucHJvcHM9bn1mdW5jdGlvbiBSKG4sZSl7ZnVuY3Rpb24gcihuKXt2YXIgdD10aGlzLnByb3BzLnJlZixyPXQ9PW4ucmVmO3JldHVybiFyJiZ0JiYodC5jYWxsP3QobnVsbCk6dC5jdXJyZW50PW51bGwpLGU/IWUodGhpcy5wcm9wcyxuKXx8IXI6Qyh0aGlzLnByb3BzLG4pfWZ1bmN0aW9uIHUoZSl7cmV0dXJuIHRoaXMuc2hvdWxkQ29tcG9uZW50VXBkYXRlPXIsdChuLGUpfXJldHVybiB1LmRpc3BsYXlOYW1lPVwiTWVtbyhcIisobi5kaXNwbGF5TmFtZXx8bi5uYW1lKStcIilcIix1LnByb3RvdHlwZS5pc1JlYWN0Q29tcG9uZW50PSEwLHUuX19mPSEwLHV9KHcucHJvdG90eXBlPW5ldyBuKS5pc1B1cmVSZWFjdENvbXBvbmVudD0hMCx3LnByb3RvdHlwZS5zaG91bGRDb21wb25lbnRVcGRhdGU9ZnVuY3Rpb24obix0KXtyZXR1cm4gQyh0aGlzLnByb3BzLG4pfHxDKHRoaXMuc3RhdGUsdCl9O3ZhciB4PWUuX19iO2UuX19iPWZ1bmN0aW9uKG4pe24udHlwZSYmbi50eXBlLl9fZiYmbi5yZWYmJihuLnByb3BzLnJlZj1uLnJlZixuLnJlZj1udWxsKSx4JiZ4KG4pfTt2YXIgTj1cInVuZGVmaW5lZFwiIT10eXBlb2YgU3ltYm9sJiZTeW1ib2wuZm9yJiZTeW1ib2wuZm9yKFwicmVhY3QuZm9yd2FyZF9yZWZcIil8fDM5MTE7ZnVuY3Rpb24gayhuKXtmdW5jdGlvbiB0KHQpe3ZhciBlPWcoe30sdCk7cmV0dXJuIGRlbGV0ZSBlLnJlZixuKGUsdC5yZWZ8fG51bGwpfXJldHVybiB0LiQkdHlwZW9mPU4sdC5yZW5kZXI9dCx0LnByb3RvdHlwZS5pc1JlYWN0Q29tcG9uZW50PXQuX19mPSEwLHQuZGlzcGxheU5hbWU9XCJGb3J3YXJkUmVmKFwiKyhuLmRpc3BsYXlOYW1lfHxuLm5hbWUpK1wiKVwiLHR9dmFyIEE9ZnVuY3Rpb24obix0KXtyZXR1cm4gbnVsbD09bj9udWxsOnIocihuKS5tYXAodCkpfSxPPXttYXA6QSxmb3JFYWNoOkEsY291bnQ6ZnVuY3Rpb24obil7cmV0dXJuIG4/cihuKS5sZW5ndGg6MH0sb25seTpmdW5jdGlvbihuKXt2YXIgdD1yKG4pO2lmKDEhPT10Lmxlbmd0aCl0aHJvd1wiQ2hpbGRyZW4ub25seVwiO3JldHVybiB0WzBdfSx0b0FycmF5OnJ9LFQ9ZS5fX2U7ZS5fX2U9ZnVuY3Rpb24obix0LGUscil7aWYobi50aGVuKWZvcih2YXIgdSxvPXQ7bz1vLl9fOylpZigodT1vLl9fYykmJnUuX19jKXJldHVybiBudWxsPT10Ll9fZSYmKHQuX19lPWUuX19lLHQuX19rPWUuX19rKSx1Ll9fYyhuLHQpO1Qobix0LGUscil9O3ZhciBJPWUudW5tb3VudDtmdW5jdGlvbiBMKG4sdCxlKXtyZXR1cm4gbiYmKG4uX19jJiZuLl9fYy5fX0gmJihuLl9fYy5fX0guX18uZm9yRWFjaChmdW5jdGlvbihuKXtcImZ1bmN0aW9uXCI9PXR5cGVvZiBuLl9fYyYmbi5fX2MoKX0pLG4uX19jLl9fSD1udWxsKSxudWxsIT0obj1nKHt9LG4pKS5fX2MmJihuLl9fYy5fX1A9PT1lJiYobi5fX2MuX19QPXQpLG4uX19jPW51bGwpLG4uX19rPW4uX19rJiZuLl9fay5tYXAoZnVuY3Rpb24obil7cmV0dXJuIEwobix0LGUpfSkpLG59ZnVuY3Rpb24gVShuLHQsZSl7cmV0dXJuIG4mJihuLl9fdj1udWxsLG4uX19rPW4uX19rJiZuLl9fay5tYXAoZnVuY3Rpb24obil7cmV0dXJuIFUobix0LGUpfSksbi5fX2MmJm4uX19jLl9fUD09PXQmJihuLl9fZSYmZS5pbnNlcnRCZWZvcmUobi5fX2Usbi5fX2QpLG4uX19jLl9fZT0hMCxuLl9fYy5fX1A9ZSkpLG59ZnVuY3Rpb24gRCgpe3RoaXMuX191PTAsdGhpcy50PW51bGwsdGhpcy5fX2I9bnVsbH1mdW5jdGlvbiBGKG4pe3ZhciB0PW4uX18uX19jO3JldHVybiB0JiZ0Ll9fYSYmdC5fX2Eobil9ZnVuY3Rpb24gTShuKXt2YXIgZSxyLHU7ZnVuY3Rpb24gbyhvKXtpZihlfHwoZT1uKCkpLnRoZW4oZnVuY3Rpb24obil7cj1uLmRlZmF1bHR8fG59LGZ1bmN0aW9uKG4pe3U9bn0pLHUpdGhyb3cgdTtpZighcil0aHJvdyBlO3JldHVybiB0KHIsbyl9cmV0dXJuIG8uZGlzcGxheU5hbWU9XCJMYXp5XCIsby5fX2Y9ITAsb31mdW5jdGlvbiBWKCl7dGhpcy51PW51bGwsdGhpcy5vPW51bGx9ZS51bm1vdW50PWZ1bmN0aW9uKG4pe3ZhciB0PW4uX19jO3QmJnQuX19SJiZ0Ll9fUigpLHQmJiEwPT09bi5fX2gmJihuLnR5cGU9bnVsbCksSSYmSShuKX0sKEQucHJvdG90eXBlPW5ldyBuKS5fX2M9ZnVuY3Rpb24obix0KXt2YXIgZT10Ll9fYyxyPXRoaXM7bnVsbD09ci50JiYoci50PVtdKSxyLnQucHVzaChlKTt2YXIgdT1GKHIuX192KSxvPSExLGk9ZnVuY3Rpb24oKXtvfHwobz0hMCxlLl9fUj1udWxsLHU/dShsKTpsKCkpfTtlLl9fUj1pO3ZhciBsPWZ1bmN0aW9uKCl7aWYoIS0tci5fX3Upe2lmKHIuc3RhdGUuX19hKXt2YXIgbj1yLnN0YXRlLl9fYTtyLl9fdi5fX2tbMF09VShuLG4uX19jLl9fUCxuLl9fYy5fX08pfXZhciB0O2ZvcihyLnNldFN0YXRlKHtfX2E6ci5fX2I9bnVsbH0pO3Q9ci50LnBvcCgpOyl0LmZvcmNlVXBkYXRlKCl9fSxjPSEwPT09dC5fX2g7ci5fX3UrK3x8Y3x8ci5zZXRTdGF0ZSh7X19hOnIuX19iPXIuX192Ll9fa1swXX0pLG4udGhlbihpLGkpfSxELnByb3RvdHlwZS5jb21wb25lbnRXaWxsVW5tb3VudD1mdW5jdGlvbigpe3RoaXMudD1bXX0sRC5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKG4sZSl7aWYodGhpcy5fX2Ipe2lmKHRoaXMuX192Ll9fayl7dmFyIHI9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKSxvPXRoaXMuX192Ll9fa1swXS5fX2M7dGhpcy5fX3YuX19rWzBdPUwodGhpcy5fX2IscixvLl9fTz1vLl9fUCl9dGhpcy5fX2I9bnVsbH12YXIgaT1lLl9fYSYmdCh1LG51bGwsbi5mYWxsYmFjayk7cmV0dXJuIGkmJihpLl9faD1udWxsKSxbdCh1LG51bGwsZS5fX2E/bnVsbDpuLmNoaWxkcmVuKSxpXX07dmFyIFc9ZnVuY3Rpb24obix0LGUpe2lmKCsrZVsxXT09PWVbMF0mJm4uby5kZWxldGUodCksbi5wcm9wcy5yZXZlYWxPcmRlciYmKFwidFwiIT09bi5wcm9wcy5yZXZlYWxPcmRlclswXXx8IW4uby5zaXplKSlmb3IoZT1uLnU7ZTspe2Zvcig7ZS5sZW5ndGg+MzspZS5wb3AoKSgpO2lmKGVbMV08ZVswXSlicmVhaztuLnU9ZT1lWzJdfX07ZnVuY3Rpb24gUChuKXtyZXR1cm4gdGhpcy5nZXRDaGlsZENvbnRleHQ9ZnVuY3Rpb24oKXtyZXR1cm4gbi5jb250ZXh0fSxuLmNoaWxkcmVufWZ1bmN0aW9uICQobil7dmFyIGU9dGhpcyxyPW4uaTtlLmNvbXBvbmVudFdpbGxVbm1vdW50PWZ1bmN0aW9uKCl7byhudWxsLGUubCksZS5sPW51bGwsZS5pPW51bGx9LGUuaSYmZS5pIT09ciYmZS5jb21wb25lbnRXaWxsVW5tb3VudCgpLG4uX192PyhlLmx8fChlLmk9cixlLmw9e25vZGVUeXBlOjEscGFyZW50Tm9kZTpyLGNoaWxkTm9kZXM6W10sYXBwZW5kQ2hpbGQ6ZnVuY3Rpb24obil7dGhpcy5jaGlsZE5vZGVzLnB1c2gobiksZS5pLmFwcGVuZENoaWxkKG4pfSxpbnNlcnRCZWZvcmU6ZnVuY3Rpb24obix0KXt0aGlzLmNoaWxkTm9kZXMucHVzaChuKSxlLmkuYXBwZW5kQ2hpbGQobil9LHJlbW92ZUNoaWxkOmZ1bmN0aW9uKG4pe3RoaXMuY2hpbGROb2Rlcy5zcGxpY2UodGhpcy5jaGlsZE5vZGVzLmluZGV4T2Yobik+Pj4xLDEpLGUuaS5yZW1vdmVDaGlsZChuKX19KSxvKHQoUCx7Y29udGV4dDplLmNvbnRleHR9LG4uX192KSxlLmwpKTplLmwmJmUuY29tcG9uZW50V2lsbFVubW91bnQoKX1mdW5jdGlvbiBqKG4sZSl7dmFyIHI9dCgkLHtfX3Y6bixpOmV9KTtyZXR1cm4gci5jb250YWluZXJJbmZvPWUscn0oVi5wcm90b3R5cGU9bmV3IG4pLl9fYT1mdW5jdGlvbihuKXt2YXIgdD10aGlzLGU9Rih0Ll9fdikscj10Lm8uZ2V0KG4pO3JldHVybiByWzBdKyssZnVuY3Rpb24odSl7dmFyIG89ZnVuY3Rpb24oKXt0LnByb3BzLnJldmVhbE9yZGVyPyhyLnB1c2godSksVyh0LG4scikpOnUoKX07ZT9lKG8pOm8oKX19LFYucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbihuKXt0aGlzLnU9bnVsbCx0aGlzLm89bmV3IE1hcDt2YXIgdD1yKG4uY2hpbGRyZW4pO24ucmV2ZWFsT3JkZXImJlwiYlwiPT09bi5yZXZlYWxPcmRlclswXSYmdC5yZXZlcnNlKCk7Zm9yKHZhciBlPXQubGVuZ3RoO2UtLTspdGhpcy5vLnNldCh0W2VdLHRoaXMudT1bMSwwLHRoaXMudV0pO3JldHVybiBuLmNoaWxkcmVufSxWLnByb3RvdHlwZS5jb21wb25lbnREaWRVcGRhdGU9Vi5wcm90b3R5cGUuY29tcG9uZW50RGlkTW91bnQ9ZnVuY3Rpb24oKXt2YXIgbj10aGlzO3RoaXMuby5mb3JFYWNoKGZ1bmN0aW9uKHQsZSl7VyhuLGUsdCl9KX07dmFyIHo9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIFN5bWJvbCYmU3ltYm9sLmZvciYmU3ltYm9sLmZvcihcInJlYWN0LmVsZW1lbnRcIil8fDYwMTAzLEI9L14oPzphY2NlbnR8YWxpZ25tZW50fGFyYWJpY3xiYXNlbGluZXxjYXB8Y2xpcCg/IVBhdGhVKXxjb2xvcnxkb21pbmFudHxmaWxsfGZsb29kfGZvbnR8Z2x5cGgoPyFSKXxob3JpenxpbWFnZXxsZXR0ZXJ8bGlnaHRpbmd8bWFya2VyKD8hSHxXfFUpfG92ZXJsaW5lfHBhaW50fHBvaW50ZXJ8c2hhcGV8c3RvcHxzdHJpa2V0aHJvdWdofHN0cm9rZXx0ZXh0KD8hTCl8dHJhbnNmb3JtfHVuZGVybGluZXx1bmljb2RlfHVuaXRzfHZ8dmVjdG9yfHZlcnR8d29yZHx3cml0aW5nfHgoPyFDKSlbQS1aXS8sSD1cInVuZGVmaW5lZFwiIT10eXBlb2YgZG9jdW1lbnQsWj1mdW5jdGlvbihuKXtyZXR1cm4oXCJ1bmRlZmluZWRcIiE9dHlwZW9mIFN5bWJvbCYmXCJzeW1ib2xcIj09dHlwZW9mIFN5bWJvbCgpPy9maWx8Y2hlfHJhZC9pOi9maWx8Y2hlfHJhL2kpLnRlc3Qobil9O2Z1bmN0aW9uIFkobix0LGUpe3JldHVybiBudWxsPT10Ll9fayYmKHQudGV4dENvbnRlbnQ9XCJcIiksbyhuLHQpLFwiZnVuY3Rpb25cIj09dHlwZW9mIGUmJmUoKSxuP24uX19jOm51bGx9ZnVuY3Rpb24gcShuLHQsZSl7cmV0dXJuIGkobix0KSxcImZ1bmN0aW9uXCI9PXR5cGVvZiBlJiZlKCksbj9uLl9fYzpudWxsfW4ucHJvdG90eXBlLmlzUmVhY3RDb21wb25lbnQ9e30sW1wiY29tcG9uZW50V2lsbE1vdW50XCIsXCJjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzXCIsXCJjb21wb25lbnRXaWxsVXBkYXRlXCJdLmZvckVhY2goZnVuY3Rpb24odCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KG4ucHJvdG90eXBlLHQse2NvbmZpZ3VyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc1tcIlVOU0FGRV9cIit0XX0sc2V0OmZ1bmN0aW9uKG4pe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLHQse2NvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMCx2YWx1ZTpufSl9fSl9KTt2YXIgRz1lLmV2ZW50O2Z1bmN0aW9uIEooKXt9ZnVuY3Rpb24gSygpe3JldHVybiB0aGlzLmNhbmNlbEJ1YmJsZX1mdW5jdGlvbiBRKCl7cmV0dXJuIHRoaXMuZGVmYXVsdFByZXZlbnRlZH1lLmV2ZW50PWZ1bmN0aW9uKG4pe3JldHVybiBHJiYobj1HKG4pKSxuLnBlcnNpc3Q9SixuLmlzUHJvcGFnYXRpb25TdG9wcGVkPUssbi5pc0RlZmF1bHRQcmV2ZW50ZWQ9USxuLm5hdGl2ZUV2ZW50PW59O3ZhciBYLG5uPXtjb25maWd1cmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY2xhc3N9fSx0bj1lLnZub2RlO2Uudm5vZGU9ZnVuY3Rpb24obil7dmFyIHQ9bi50eXBlLGU9bi5wcm9wcyx1PWU7aWYoXCJzdHJpbmdcIj09dHlwZW9mIHQpe3ZhciBvPS0xPT09dC5pbmRleE9mKFwiLVwiKTtmb3IodmFyIGkgaW4gdT17fSxlKXt2YXIgbD1lW2ldO0gmJlwiY2hpbGRyZW5cIj09PWkmJlwibm9zY3JpcHRcIj09PXR8fFwidmFsdWVcIj09PWkmJlwiZGVmYXVsdFZhbHVlXCJpbiBlJiZudWxsPT1sfHwoXCJkZWZhdWx0VmFsdWVcIj09PWkmJlwidmFsdWVcImluIGUmJm51bGw9PWUudmFsdWU/aT1cInZhbHVlXCI6XCJkb3dubG9hZFwiPT09aSYmITA9PT1sP2w9XCJcIjovb25kb3VibGVjbGljay9pLnRlc3QoaSk/aT1cIm9uZGJsY2xpY2tcIjovXm9uY2hhbmdlKHRleHRhcmVhfGlucHV0KS9pLnRlc3QoaSt0KSYmIVooZS50eXBlKT9pPVwib25pbnB1dFwiOi9eb25mb2N1cyQvaS50ZXN0KGkpP2k9XCJvbmZvY3VzaW5cIjovXm9uYmx1ciQvaS50ZXN0KGkpP2k9XCJvbmZvY3Vzb3V0XCI6L15vbihBbml8VHJhfFRvdXxCZWZvcmVJbnB8Q29tcG8pLy50ZXN0KGkpP2k9aS50b0xvd2VyQ2FzZSgpOm8mJkIudGVzdChpKT9pPWkucmVwbGFjZSgvW0EtWjAtOV0vZyxcIi0kJlwiKS50b0xvd2VyQ2FzZSgpOm51bGw9PT1sJiYobD12b2lkIDApLC9eb25pbnB1dCQvaS50ZXN0KGkpJiYoaT1pLnRvTG93ZXJDYXNlKCksdVtpXSYmKGk9XCJvbmlucHV0Q2FwdHVyZVwiKSksdVtpXT1sKX1cInNlbGVjdFwiPT10JiZ1Lm11bHRpcGxlJiZBcnJheS5pc0FycmF5KHUudmFsdWUpJiYodS52YWx1ZT1yKGUuY2hpbGRyZW4pLmZvckVhY2goZnVuY3Rpb24obil7bi5wcm9wcy5zZWxlY3RlZD0tMSE9dS52YWx1ZS5pbmRleE9mKG4ucHJvcHMudmFsdWUpfSkpLFwic2VsZWN0XCI9PXQmJm51bGwhPXUuZGVmYXVsdFZhbHVlJiYodS52YWx1ZT1yKGUuY2hpbGRyZW4pLmZvckVhY2goZnVuY3Rpb24obil7bi5wcm9wcy5zZWxlY3RlZD11Lm11bHRpcGxlPy0xIT11LmRlZmF1bHRWYWx1ZS5pbmRleE9mKG4ucHJvcHMudmFsdWUpOnUuZGVmYXVsdFZhbHVlPT1uLnByb3BzLnZhbHVlfSkpLG4ucHJvcHM9dSxlLmNsYXNzIT1lLmNsYXNzTmFtZSYmKG5uLmVudW1lcmFibGU9XCJjbGFzc05hbWVcImluIGUsbnVsbCE9ZS5jbGFzc05hbWUmJih1LmNsYXNzPWUuY2xhc3NOYW1lKSxPYmplY3QuZGVmaW5lUHJvcGVydHkodSxcImNsYXNzTmFtZVwiLG5uKSl9bi4kJHR5cGVvZj16LHRuJiZ0bihuKX07dmFyIGVuPWUuX19yO2UuX19yPWZ1bmN0aW9uKG4pe2VuJiZlbihuKSxYPW4uX19jfTt2YXIgcm49e1JlYWN0Q3VycmVudERpc3BhdGNoZXI6e2N1cnJlbnQ6e3JlYWRDb250ZXh0OmZ1bmN0aW9uKG4pe3JldHVybiBYLl9fbltuLl9fY10ucHJvcHMudmFsdWV9fX19LHVuPVwiMTcuMC4yXCI7ZnVuY3Rpb24gb24obil7cmV0dXJuIHQuYmluZChudWxsLG4pfWZ1bmN0aW9uIGxuKG4pe3JldHVybiEhbiYmbi4kJHR5cGVvZj09PXp9ZnVuY3Rpb24gY24obil7cmV0dXJuIGxuKG4pP2YuYXBwbHkobnVsbCxhcmd1bWVudHMpOm59ZnVuY3Rpb24gZm4obil7cmV0dXJuISFuLl9fayYmKG8obnVsbCxuKSwhMCl9ZnVuY3Rpb24gYW4obil7cmV0dXJuIG4mJihuLmJhc2V8fDE9PT1uLm5vZGVUeXBlJiZuKXx8bnVsbH12YXIgc249ZnVuY3Rpb24obix0KXtyZXR1cm4gbih0KX0saG49ZnVuY3Rpb24obix0KXtyZXR1cm4gbih0KX0sdm49dTtmdW5jdGlvbiBkbihuKXtuKCl9ZnVuY3Rpb24gcG4obil7cmV0dXJuIG59ZnVuY3Rpb24gbW4oKXtyZXR1cm5bITEsZG5dfXZhciB5bj1kO2Z1bmN0aW9uIF9uKG4sdCl7dmFyIGU9dCgpLHI9YSh7aDp7X186ZSx2OnR9fSksdT1yWzBdLmgsbz1yWzFdO3JldHVybiBkKGZ1bmN0aW9uKCl7dS5fXz1lLHUudj10LEUodS5fXyx0KCkpfHxvKHtoOnV9KX0sW24sZSx0XSksdihmdW5jdGlvbigpe3JldHVybiBFKHUuX18sdS52KCkpfHxvKHtoOnV9KSxuKGZ1bmN0aW9uKCl7RSh1Ll9fLHUudigpKXx8byh7aDp1fSl9KX0sW25dKSxlfXZhciBibj17dXNlU3RhdGU6YSx1c2VJZDpzLHVzZVJlZHVjZXI6aCx1c2VFZmZlY3Q6dix1c2VMYXlvdXRFZmZlY3Q6ZCx1c2VJbnNlcnRpb25FZmZlY3Q6eW4sdXNlVHJhbnNpdGlvbjptbix1c2VEZWZlcnJlZFZhbHVlOnBuLHVzZVN5bmNFeHRlcm5hbFN0b3JlOl9uLHN0YXJ0VHJhbnNpdGlvbjpkbix1c2VSZWY6cCx1c2VJbXBlcmF0aXZlSGFuZGxlOm0sdXNlTWVtbzp5LHVzZUNhbGxiYWNrOl8sdXNlQ29udGV4dDpiLHVzZURlYnVnVmFsdWU6Uyx2ZXJzaW9uOlwiMTcuMC4yXCIsQ2hpbGRyZW46TyxyZW5kZXI6WSxoeWRyYXRlOnEsdW5tb3VudENvbXBvbmVudEF0Tm9kZTpmbixjcmVhdGVQb3J0YWw6aixjcmVhdGVFbGVtZW50OnQsY3JlYXRlQ29udGV4dDpsLGNyZWF0ZUZhY3Rvcnk6b24sY2xvbmVFbGVtZW50OmNuLGNyZWF0ZVJlZjpjLEZyYWdtZW50OnUsaXNWYWxpZEVsZW1lbnQ6bG4sZmluZERPTU5vZGU6YW4sQ29tcG9uZW50Om4sUHVyZUNvbXBvbmVudDp3LG1lbW86Uixmb3J3YXJkUmVmOmssZmx1c2hTeW5jOmhuLHVuc3RhYmxlX2JhdGNoZWRVcGRhdGVzOnNuLFN0cmljdE1vZGU6dm4sU3VzcGVuc2U6RCxTdXNwZW5zZUxpc3Q6VixsYXp5Ok0sX19TRUNSRVRfSU5URVJOQUxTX0RPX05PVF9VU0VfT1JfWU9VX1dJTExfQkVfRklSRUQ6cm59O2V4cG9ydHtPIGFzIENoaWxkcmVuLHcgYXMgUHVyZUNvbXBvbmVudCx2biBhcyBTdHJpY3RNb2RlLEQgYXMgU3VzcGVuc2UsViBhcyBTdXNwZW5zZUxpc3Qscm4gYXMgX19TRUNSRVRfSU5URVJOQUxTX0RPX05PVF9VU0VfT1JfWU9VX1dJTExfQkVfRklSRUQsY24gYXMgY2xvbmVFbGVtZW50LG9uIGFzIGNyZWF0ZUZhY3RvcnksaiBhcyBjcmVhdGVQb3J0YWwsYm4gYXMgZGVmYXVsdCxhbiBhcyBmaW5kRE9NTm9kZSxobiBhcyBmbHVzaFN5bmMsayBhcyBmb3J3YXJkUmVmLHEgYXMgaHlkcmF0ZSxsbiBhcyBpc1ZhbGlkRWxlbWVudCxNIGFzIGxhenksUiBhcyBtZW1vLFkgYXMgcmVuZGVyLGRuIGFzIHN0YXJ0VHJhbnNpdGlvbixmbiBhcyB1bm1vdW50Q29tcG9uZW50QXROb2RlLHNuIGFzIHVuc3RhYmxlX2JhdGNoZWRVcGRhdGVzLHBuIGFzIHVzZURlZmVycmVkVmFsdWUseW4gYXMgdXNlSW5zZXJ0aW9uRWZmZWN0LF9uIGFzIHVzZVN5bmNFeHRlcm5hbFN0b3JlLG1uIGFzIHVzZVRyYW5zaXRpb24sdW4gYXMgdmVyc2lvbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb21wYXQubW9kdWxlLmpzLm1hcFxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///115\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 116:
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useCallback: () => (/* binding */ T),\n/* harmony export */ useContext: () => (/* binding */ q),\n/* harmony export */ useDebugValue: () => (/* binding */ x),\n/* harmony export */ useEffect: () => (/* binding */ h),\n/* harmony export */ useErrorBoundary: () => (/* binding */ P),\n/* harmony export */ useId: () => (/* binding */ V),\n/* harmony export */ useImperativeHandle: () => (/* binding */ A),\n/* harmony export */ useLayoutEffect: () => (/* binding */ s),\n/* harmony export */ useMemo: () => (/* binding */ F),\n/* harmony export */ useReducer: () => (/* binding */ y),\n/* harmony export */ useRef: () => (/* binding */ _),\n/* harmony export */ useState: () => (/* binding */ p)\n/* harmony export */ });\n/* harmony import */ var preact__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(114);\nvar t,r,u,i,o=0,f=[],c=[],e=preact__WEBPACK_IMPORTED_MODULE_0__.options.__b,a=preact__WEBPACK_IMPORTED_MODULE_0__.options.__r,v=preact__WEBPACK_IMPORTED_MODULE_0__.options.diffed,l=preact__WEBPACK_IMPORTED_MODULE_0__.options.__c,m=preact__WEBPACK_IMPORTED_MODULE_0__.options.unmount;function d(t,u){preact__WEBPACK_IMPORTED_MODULE_0__.options.__h&&preact__WEBPACK_IMPORTED_MODULE_0__.options.__h(r,t,o||u),o=0;var i=r.__H||(r.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({__V:c}),i.__[t]}function p(n){return o=1,y(B,n)}function y(n,u,i){var o=d(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):B(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}))}],o.__c=r,!r.u)){r.u=!0;var f=r.shouldComponentUpdate;r.shouldComponentUpdate=function(n,t,r){if(!o.__c.__H)return!0;var u=o.__c.__H.__.filter(function(n){return n.__c});if(u.every(function(n){return!n.__N}))return!f||f.call(this,n,t,r);var i=!1;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0)}}),!(!i&&o.__c.props===n)&&(!f||f.call(this,n,t,r))}}return o.__N||o.__}function h(u,i){var o=d(t++,3);!preact__WEBPACK_IMPORTED_MODULE_0__.options.__s&&z(o.__H,i)&&(o.__=u,o.i=i,r.__H.__h.push(o))}function s(u,i){var o=d(t++,4);!preact__WEBPACK_IMPORTED_MODULE_0__.options.__s&&z(o.__H,i)&&(o.__=u,o.i=i,r.__h.push(o))}function _(n){return o=5,F(function(){return{current:n}},[])}function A(n,t,r){o=6,s(function(){return\"function\"==typeof n?(n(t()),function(){return n(null)}):n?(n.current=t(),function(){return n.current=null}):void 0},null==r?r:r.concat(n))}function F(n,r){var u=d(t++,7);return z(u.__H,r)?(u.__V=n(),u.i=r,u.__h=n,u.__V):u.__}function T(n,t){return o=8,F(function(){return n},t)}function q(n){var u=r.context[n.__c],i=d(t++,9);return i.c=n,u?(null==i.__&&(i.__=!0,u.sub(r)),u.props.value):n.__}function x(t,r){preact__WEBPACK_IMPORTED_MODULE_0__.options.useDebugValue&&preact__WEBPACK_IMPORTED_MODULE_0__.options.useDebugValue(r?r(t):t)}function P(n){var u=d(t++,10),i=p();return u.__=n,r.componentDidCatch||(r.componentDidCatch=function(n,t){u.__&&u.__(n,t),i[1](n)}),[i[0],function(){i[1](void 0)}]}function V(){var n=d(t++,11);if(!n.__){for(var u=r.__v;null!==u&&!u.__m&&null!==u.__;)u=u.__;var i=u.__m||(u.__m=[0,0]);n.__=\"P\"+i[0]+\"-\"+i[1]++}return n.__}function b(){for(var t;t=f.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(k),t.__H.__h.forEach(w),t.__H.__h=[]}catch(r){t.__H.__h=[],preact__WEBPACK_IMPORTED_MODULE_0__.options.__e(r,t.__v)}}preact__WEBPACK_IMPORTED_MODULE_0__.options.__b=function(n){r=null,e&&e(n)},preact__WEBPACK_IMPORTED_MODULE_0__.options.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=c,n.__N=n.i=void 0})):(i.__h.forEach(k),i.__h.forEach(w),i.__h=[])),u=r},preact__WEBPACK_IMPORTED_MODULE_0__.options.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==f.push(o)&&i===preact__WEBPACK_IMPORTED_MODULE_0__.options.requestAnimationFrame||((i=preact__WEBPACK_IMPORTED_MODULE_0__.options.requestAnimationFrame)||j)(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==c&&(n.__=n.__V),n.i=void 0,n.__V=c})),u=r=null},preact__WEBPACK_IMPORTED_MODULE_0__.options.__c=function(t,r){r.some(function(t){try{t.__h.forEach(k),t.__h=t.__h.filter(function(n){return!n.__||w(n)})}catch(u){r.some(function(n){n.__h&&(n.__h=[])}),r=[],preact__WEBPACK_IMPORTED_MODULE_0__.options.__e(u,t.__v)}}),l&&l(t,r)},preact__WEBPACK_IMPORTED_MODULE_0__.options.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{k(n)}catch(n){r=n}}),u.__H=void 0,r&&preact__WEBPACK_IMPORTED_MODULE_0__.options.__e(r,u.__v))};var g=\"function\"==typeof requestAnimationFrame;function j(n){var t,r=function(){clearTimeout(u),g&&cancelAnimationFrame(t),setTimeout(n)},u=setTimeout(r,100);g&&(t=requestAnimationFrame(r))}function k(n){var t=r,u=n.__c;\"function\"==typeof u&&(n.__c=void 0,u()),r=t}function w(n){var t=r;n.__c=n.__(),r=t}function z(n,t){return!n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function B(n,t){return\"function\"==typeof t?t(n):t}\n//# sourceMappingURL=hooks.module.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTE2LmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBaUMsNEJBQTRCLDJDQUFDLE9BQU8sMkNBQUMsT0FBTywyQ0FBQyxVQUFVLDJDQUFDLE9BQU8sMkNBQUMsU0FBUyxnQkFBZ0IsMkNBQUMsTUFBTSwyQ0FBQyxtQkFBbUIscUJBQXFCLGFBQWEsRUFBRSxrQ0FBa0MsTUFBTSxVQUFVLGNBQWMsa0JBQWtCLGtCQUFrQixlQUFlLHVEQUF1RCx3Q0FBd0MsMkNBQTJDLEdBQUcsaUJBQWlCLE9BQU8sOEJBQThCLHdDQUF3Qyx1QkFBdUIsc0NBQXNDLGFBQWEsRUFBRSx1QkFBdUIsYUFBYSwrQkFBK0IsU0FBUyw2QkFBNkIsVUFBVSxjQUFjLDZDQUE2QyxvREFBb0QsbUJBQW1CLGdCQUFnQixlQUFlLENBQUMsMkNBQUMsbURBQW1ELGdCQUFnQixlQUFlLENBQUMsMkNBQUMsK0NBQStDLGNBQWMsd0JBQXdCLE9BQU8sV0FBVyxLQUFLLGtCQUFrQixpQkFBaUIsOENBQThDLGVBQWUsOEJBQThCLHNCQUFzQixTQUFTLHdCQUF3QixnQkFBZ0IsZUFBZSx1REFBdUQsZ0JBQWdCLHdCQUF3QixTQUFTLElBQUksY0FBYyxrQ0FBa0MsbUVBQW1FLGdCQUFnQiwyQ0FBQyxnQkFBZ0IsMkNBQUMseUJBQXlCLGNBQWMsc0JBQXNCLHNFQUFzRSx3QkFBd0IsbUJBQW1CLGFBQWEsRUFBRSxhQUFhLGdCQUFnQixVQUFVLGdCQUFnQiw4QkFBOEIsUUFBUSwyQkFBMkIseUJBQXlCLFlBQVksYUFBYSxVQUFVLFlBQVkscUJBQXFCLHVEQUF1RCxTQUFTLGFBQWEsMkNBQUMsZUFBZSwyQ0FBQyxpQkFBaUIsZUFBZSxDQUFDLDJDQUFDLGlCQUFpQixZQUFZLG9CQUFvQixzREFBc0QsNkNBQTZDLHFEQUFxRCxDQUFDLDJDQUFDLG9CQUFvQixRQUFRLFlBQVksaURBQWlELDJDQUFDLDRCQUE0QiwyQ0FBQyw2REFBNkQsNERBQTRELFlBQVksQ0FBQywyQ0FBQyxtQkFBbUIsbUJBQW1CLElBQUksZ0RBQWdELGtCQUFrQixFQUFFLFNBQVMsbUJBQW1CLGtCQUFrQixPQUFPLDJDQUFDLGVBQWUsWUFBWSxDQUFDLDJDQUFDLHFCQUFxQixRQUFRLGNBQWMsd0NBQXdDLElBQUksS0FBSyxTQUFTLEtBQUssa0JBQWtCLDJDQUFDLGdCQUFnQiwrQ0FBK0MsY0FBYyxtQkFBbUIseURBQXlELHFCQUFxQixnQ0FBZ0MsY0FBYyxnQkFBZ0IsNkNBQTZDLGNBQWMsUUFBUSxpQkFBaUIsZ0JBQWdCLG9EQUFvRCxnQkFBZ0IsRUFBRSxnQkFBZ0Isa0NBQW1QO0FBQ2g4RyIsInNvdXJjZXMiOlsid2VicGFjazovL2FyY2hpdGVjdHVpLWh0bWwtZnJlZS8uL25vZGVfbW9kdWxlcy9wcmVhY3QvaG9va3MvZGlzdC9ob29rcy5tb2R1bGUuanM/MzBlYyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnR7b3B0aW9ucyBhcyBufWZyb21cInByZWFjdFwiO3ZhciB0LHIsdSxpLG89MCxmPVtdLGM9W10sZT1uLl9fYixhPW4uX19yLHY9bi5kaWZmZWQsbD1uLl9fYyxtPW4udW5tb3VudDtmdW5jdGlvbiBkKHQsdSl7bi5fX2gmJm4uX19oKHIsdCxvfHx1KSxvPTA7dmFyIGk9ci5fX0h8fChyLl9fSD17X186W10sX19oOltdfSk7cmV0dXJuIHQ+PWkuX18ubGVuZ3RoJiZpLl9fLnB1c2goe19fVjpjfSksaS5fX1t0XX1mdW5jdGlvbiBwKG4pe3JldHVybiBvPTEseShCLG4pfWZ1bmN0aW9uIHkobix1LGkpe3ZhciBvPWQodCsrLDIpO2lmKG8udD1uLCFvLl9fYyYmKG8uX189W2k/aSh1KTpCKHZvaWQgMCx1KSxmdW5jdGlvbihuKXt2YXIgdD1vLl9fTj9vLl9fTlswXTpvLl9fWzBdLHI9by50KHQsbik7dCE9PXImJihvLl9fTj1bcixvLl9fWzFdXSxvLl9fYy5zZXRTdGF0ZSh7fSkpfV0sby5fX2M9ciwhci51KSl7ci51PSEwO3ZhciBmPXIuc2hvdWxkQ29tcG9uZW50VXBkYXRlO3Iuc2hvdWxkQ29tcG9uZW50VXBkYXRlPWZ1bmN0aW9uKG4sdCxyKXtpZighby5fX2MuX19IKXJldHVybiEwO3ZhciB1PW8uX19jLl9fSC5fXy5maWx0ZXIoZnVuY3Rpb24obil7cmV0dXJuIG4uX19jfSk7aWYodS5ldmVyeShmdW5jdGlvbihuKXtyZXR1cm4hbi5fX059KSlyZXR1cm4hZnx8Zi5jYWxsKHRoaXMsbix0LHIpO3ZhciBpPSExO3JldHVybiB1LmZvckVhY2goZnVuY3Rpb24obil7aWYobi5fX04pe3ZhciB0PW4uX19bMF07bi5fXz1uLl9fTixuLl9fTj12b2lkIDAsdCE9PW4uX19bMF0mJihpPSEwKX19KSwhKCFpJiZvLl9fYy5wcm9wcz09PW4pJiYoIWZ8fGYuY2FsbCh0aGlzLG4sdCxyKSl9fXJldHVybiBvLl9fTnx8by5fX31mdW5jdGlvbiBoKHUsaSl7dmFyIG89ZCh0KyssMyk7IW4uX19zJiZ6KG8uX19ILGkpJiYoby5fXz11LG8uaT1pLHIuX19ILl9faC5wdXNoKG8pKX1mdW5jdGlvbiBzKHUsaSl7dmFyIG89ZCh0KyssNCk7IW4uX19zJiZ6KG8uX19ILGkpJiYoby5fXz11LG8uaT1pLHIuX19oLnB1c2gobykpfWZ1bmN0aW9uIF8obil7cmV0dXJuIG89NSxGKGZ1bmN0aW9uKCl7cmV0dXJue2N1cnJlbnQ6bn19LFtdKX1mdW5jdGlvbiBBKG4sdCxyKXtvPTYscyhmdW5jdGlvbigpe3JldHVyblwiZnVuY3Rpb25cIj09dHlwZW9mIG4/KG4odCgpKSxmdW5jdGlvbigpe3JldHVybiBuKG51bGwpfSk6bj8obi5jdXJyZW50PXQoKSxmdW5jdGlvbigpe3JldHVybiBuLmN1cnJlbnQ9bnVsbH0pOnZvaWQgMH0sbnVsbD09cj9yOnIuY29uY2F0KG4pKX1mdW5jdGlvbiBGKG4scil7dmFyIHU9ZCh0KyssNyk7cmV0dXJuIHoodS5fX0gscik/KHUuX19WPW4oKSx1Lmk9cix1Ll9faD1uLHUuX19WKTp1Ll9ffWZ1bmN0aW9uIFQobix0KXtyZXR1cm4gbz04LEYoZnVuY3Rpb24oKXtyZXR1cm4gbn0sdCl9ZnVuY3Rpb24gcShuKXt2YXIgdT1yLmNvbnRleHRbbi5fX2NdLGk9ZCh0KyssOSk7cmV0dXJuIGkuYz1uLHU/KG51bGw9PWkuX18mJihpLl9fPSEwLHUuc3ViKHIpKSx1LnByb3BzLnZhbHVlKTpuLl9ffWZ1bmN0aW9uIHgodCxyKXtuLnVzZURlYnVnVmFsdWUmJm4udXNlRGVidWdWYWx1ZShyP3IodCk6dCl9ZnVuY3Rpb24gUChuKXt2YXIgdT1kKHQrKywxMCksaT1wKCk7cmV0dXJuIHUuX189bixyLmNvbXBvbmVudERpZENhdGNofHwoci5jb21wb25lbnREaWRDYXRjaD1mdW5jdGlvbihuLHQpe3UuX18mJnUuX18obix0KSxpWzFdKG4pfSksW2lbMF0sZnVuY3Rpb24oKXtpWzFdKHZvaWQgMCl9XX1mdW5jdGlvbiBWKCl7dmFyIG49ZCh0KyssMTEpO2lmKCFuLl9fKXtmb3IodmFyIHU9ci5fX3Y7bnVsbCE9PXUmJiF1Ll9fbSYmbnVsbCE9PXUuX187KXU9dS5fXzt2YXIgaT11Ll9fbXx8KHUuX19tPVswLDBdKTtuLl9fPVwiUFwiK2lbMF0rXCItXCIraVsxXSsrfXJldHVybiBuLl9ffWZ1bmN0aW9uIGIoKXtmb3IodmFyIHQ7dD1mLnNoaWZ0KCk7KWlmKHQuX19QJiZ0Ll9fSCl0cnl7dC5fX0guX19oLmZvckVhY2goayksdC5fX0guX19oLmZvckVhY2godyksdC5fX0guX19oPVtdfWNhdGNoKHIpe3QuX19ILl9faD1bXSxuLl9fZShyLHQuX192KX19bi5fX2I9ZnVuY3Rpb24obil7cj1udWxsLGUmJmUobil9LG4uX19yPWZ1bmN0aW9uKG4pe2EmJmEobiksdD0wO3ZhciBpPShyPW4uX19jKS5fX0g7aSYmKHU9PT1yPyhpLl9faD1bXSxyLl9faD1bXSxpLl9fLmZvckVhY2goZnVuY3Rpb24obil7bi5fX04mJihuLl9fPW4uX19OKSxuLl9fVj1jLG4uX19OPW4uaT12b2lkIDB9KSk6KGkuX19oLmZvckVhY2goayksaS5fX2guZm9yRWFjaCh3KSxpLl9faD1bXSkpLHU9cn0sbi5kaWZmZWQ9ZnVuY3Rpb24odCl7diYmdih0KTt2YXIgbz10Ll9fYztvJiZvLl9fSCYmKG8uX19ILl9faC5sZW5ndGgmJigxIT09Zi5wdXNoKG8pJiZpPT09bi5yZXF1ZXN0QW5pbWF0aW9uRnJhbWV8fCgoaT1uLnJlcXVlc3RBbmltYXRpb25GcmFtZSl8fGopKGIpKSxvLl9fSC5fXy5mb3JFYWNoKGZ1bmN0aW9uKG4pe24uaSYmKG4uX19IPW4uaSksbi5fX1YhPT1jJiYobi5fXz1uLl9fViksbi5pPXZvaWQgMCxuLl9fVj1jfSkpLHU9cj1udWxsfSxuLl9fYz1mdW5jdGlvbih0LHIpe3Iuc29tZShmdW5jdGlvbih0KXt0cnl7dC5fX2guZm9yRWFjaChrKSx0Ll9faD10Ll9faC5maWx0ZXIoZnVuY3Rpb24obil7cmV0dXJuIW4uX198fHcobil9KX1jYXRjaCh1KXtyLnNvbWUoZnVuY3Rpb24obil7bi5fX2gmJihuLl9faD1bXSl9KSxyPVtdLG4uX19lKHUsdC5fX3YpfX0pLGwmJmwodCxyKX0sbi51bm1vdW50PWZ1bmN0aW9uKHQpe20mJm0odCk7dmFyIHIsdT10Ll9fYzt1JiZ1Ll9fSCYmKHUuX19ILl9fLmZvckVhY2goZnVuY3Rpb24obil7dHJ5e2sobil9Y2F0Y2gobil7cj1ufX0pLHUuX19IPXZvaWQgMCxyJiZuLl9fZShyLHUuX192KSl9O3ZhciBnPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVlc3RBbmltYXRpb25GcmFtZTtmdW5jdGlvbiBqKG4pe3ZhciB0LHI9ZnVuY3Rpb24oKXtjbGVhclRpbWVvdXQodSksZyYmY2FuY2VsQW5pbWF0aW9uRnJhbWUodCksc2V0VGltZW91dChuKX0sdT1zZXRUaW1lb3V0KHIsMTAwKTtnJiYodD1yZXF1ZXN0QW5pbWF0aW9uRnJhbWUocikpfWZ1bmN0aW9uIGsobil7dmFyIHQ9cix1PW4uX19jO1wiZnVuY3Rpb25cIj09dHlwZW9mIHUmJihuLl9fYz12b2lkIDAsdSgpKSxyPXR9ZnVuY3Rpb24gdyhuKXt2YXIgdD1yO24uX19jPW4uX18oKSxyPXR9ZnVuY3Rpb24geihuLHQpe3JldHVybiFufHxuLmxlbmd0aCE9PXQubGVuZ3RofHx0LnNvbWUoZnVuY3Rpb24odCxyKXtyZXR1cm4gdCE9PW5bcl19KX1mdW5jdGlvbiBCKG4sdCl7cmV0dXJuXCJmdW5jdGlvblwiPT10eXBlb2YgdD90KG4pOnR9ZXhwb3J0e1QgYXMgdXNlQ2FsbGJhY2sscSBhcyB1c2VDb250ZXh0LHggYXMgdXNlRGVidWdWYWx1ZSxoIGFzIHVzZUVmZmVjdCxQIGFzIHVzZUVycm9yQm91bmRhcnksViBhcyB1c2VJZCxBIGFzIHVzZUltcGVyYXRpdmVIYW5kbGUscyBhcyB1c2VMYXlvdXRFZmZlY3QsRiBhcyB1c2VNZW1vLHkgYXMgdXNlUmVkdWNlcixfIGFzIHVzZVJlZixwIGFzIHVzZVN0YXRlfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWhvb2tzLm1vZHVsZS5qcy5tYXBcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///116\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 117:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Draggable: () => (/* binding */ ExternalDraggable),\n/* harmony export */ ThirdPartyDraggable: () => (/* binding */ ThirdPartyDraggable),\n/* harmony export */ \"default\": () => (/* binding */ index)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(112);\n/* harmony import */ var _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(113);\n\n\n\n_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bG.touchMouseIgnoreWait = 500;\nlet ignoreMouseDepth = 0;\nlet listenerCnt = 0;\nlet isWindowTouchMoveCancelled = false;\n/*\nUses a \"pointer\" abstraction, which monitors UI events for both mouse and touch.\nTracks when the pointer \"drags\" on a certain element, meaning down+move+up.\n\nAlso, tracks if there was touch-scrolling.\nAlso, can prevent touch-scrolling from happening.\nAlso, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.\n\nemits:\n- pointerdown\n- pointermove\n- pointerup\n*/\nclass PointerDragging {\n constructor(containerEl) {\n this.subjectEl = null;\n // options that can be directly assigned by caller\n this.selector = ''; // will cause subjectEl in all emitted events to be this element\n this.handleSelector = '';\n this.shouldIgnoreMove = false;\n this.shouldWatchScroll = true; // for simulating pointermove on scroll\n // internal states\n this.isDragging = false;\n this.isTouchDragging = false;\n this.wasTouchScroll = false;\n // Mouse\n // ----------------------------------------------------------------------------------------------------\n this.handleMouseDown = (ev) => {\n if (!this.shouldIgnoreMouse() &&\n isPrimaryMouseButton(ev) &&\n this.tryStart(ev)) {\n let pev = this.createEventFromMouse(ev, true);\n this.emitter.trigger('pointerdown', pev);\n this.initScrollWatch(pev);\n if (!this.shouldIgnoreMove) {\n document.addEventListener('mousemove', this.handleMouseMove);\n }\n document.addEventListener('mouseup', this.handleMouseUp);\n }\n };\n this.handleMouseMove = (ev) => {\n let pev = this.createEventFromMouse(ev);\n this.recordCoords(pev);\n this.emitter.trigger('pointermove', pev);\n };\n this.handleMouseUp = (ev) => {\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n this.emitter.trigger('pointerup', this.createEventFromMouse(ev));\n this.cleanup(); // call last so that pointerup has access to props\n };\n // Touch\n // ----------------------------------------------------------------------------------------------------\n this.handleTouchStart = (ev) => {\n if (this.tryStart(ev)) {\n this.isTouchDragging = true;\n let pev = this.createEventFromTouch(ev, true);\n this.emitter.trigger('pointerdown', pev);\n this.initScrollWatch(pev);\n // unlike mouse, need to attach to target, not document\n // https://stackoverflow.com/a/45760014\n let targetEl = ev.target;\n if (!this.shouldIgnoreMove) {\n targetEl.addEventListener('touchmove', this.handleTouchMove);\n }\n targetEl.addEventListener('touchend', this.handleTouchEnd);\n targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end\n // attach a handler to get called when ANY scroll action happens on the page.\n // this was impossible to do with normal on/off because 'scroll' doesn't bubble.\n // http://stackoverflow.com/a/32954565/96342\n window.addEventListener('scroll', this.handleTouchScroll, true);\n }\n };\n this.handleTouchMove = (ev) => {\n let pev = this.createEventFromTouch(ev);\n this.recordCoords(pev);\n this.emitter.trigger('pointermove', pev);\n };\n this.handleTouchEnd = (ev) => {\n if (this.isDragging) { // done to guard against touchend followed by touchcancel\n let targetEl = ev.target;\n targetEl.removeEventListener('touchmove', this.handleTouchMove);\n targetEl.removeEventListener('touchend', this.handleTouchEnd);\n targetEl.removeEventListener('touchcancel', this.handleTouchEnd);\n window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true\n this.emitter.trigger('pointerup', this.createEventFromTouch(ev));\n this.cleanup(); // call last so that pointerup has access to props\n this.isTouchDragging = false;\n startIgnoringMouse();\n }\n };\n this.handleTouchScroll = () => {\n this.wasTouchScroll = true;\n };\n this.handleScroll = (ev) => {\n if (!this.shouldIgnoreMove) {\n let pageX = (window.scrollX - this.prevScrollX) + this.prevPageX;\n let pageY = (window.scrollY - this.prevScrollY) + this.prevPageY;\n this.emitter.trigger('pointermove', {\n origEvent: ev,\n isTouch: this.isTouchDragging,\n subjectEl: this.subjectEl,\n pageX,\n pageY,\n deltaX: pageX - this.origPageX,\n deltaY: pageY - this.origPageY,\n });\n }\n };\n this.containerEl = containerEl;\n this.emitter = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.F();\n containerEl.addEventListener('mousedown', this.handleMouseDown);\n containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });\n listenerCreated();\n }\n destroy() {\n this.containerEl.removeEventListener('mousedown', this.handleMouseDown);\n this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });\n listenerDestroyed();\n }\n tryStart(ev) {\n let subjectEl = this.querySubjectEl(ev);\n let downEl = ev.target;\n if (subjectEl &&\n (!this.handleSelector || (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(downEl, this.handleSelector))) {\n this.subjectEl = subjectEl;\n this.isDragging = true; // do this first so cancelTouchScroll will work\n this.wasTouchScroll = false;\n return true;\n }\n return false;\n }\n cleanup() {\n isWindowTouchMoveCancelled = false;\n this.isDragging = false;\n this.subjectEl = null;\n // keep wasTouchScroll around for later access\n this.destroyScrollWatch();\n }\n querySubjectEl(ev) {\n if (this.selector) {\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(ev.target, this.selector);\n }\n return this.containerEl;\n }\n shouldIgnoreMouse() {\n return ignoreMouseDepth || this.isTouchDragging;\n }\n // can be called by user of this class, to cancel touch-based scrolling for the current drag\n cancelTouchScroll() {\n if (this.isDragging) {\n isWindowTouchMoveCancelled = true;\n }\n }\n // Scrolling that simulates pointermoves\n // ----------------------------------------------------------------------------------------------------\n initScrollWatch(ev) {\n if (this.shouldWatchScroll) {\n this.recordCoords(ev);\n window.addEventListener('scroll', this.handleScroll, true); // useCapture=true\n }\n }\n recordCoords(ev) {\n if (this.shouldWatchScroll) {\n this.prevPageX = ev.pageX;\n this.prevPageY = ev.pageY;\n this.prevScrollX = window.scrollX;\n this.prevScrollY = window.scrollY;\n }\n }\n destroyScrollWatch() {\n if (this.shouldWatchScroll) {\n window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true\n }\n }\n // Event Normalization\n // ----------------------------------------------------------------------------------------------------\n createEventFromMouse(ev, isFirst) {\n let deltaX = 0;\n let deltaY = 0;\n // TODO: repeat code\n if (isFirst) {\n this.origPageX = ev.pageX;\n this.origPageY = ev.pageY;\n }\n else {\n deltaX = ev.pageX - this.origPageX;\n deltaY = ev.pageY - this.origPageY;\n }\n return {\n origEvent: ev,\n isTouch: false,\n subjectEl: this.subjectEl,\n pageX: ev.pageX,\n pageY: ev.pageY,\n deltaX,\n deltaY,\n };\n }\n createEventFromTouch(ev, isFirst) {\n let touches = ev.touches;\n let pageX;\n let pageY;\n let deltaX = 0;\n let deltaY = 0;\n // if touch coords available, prefer,\n // because FF would give bad ev.pageX ev.pageY\n if (touches && touches.length) {\n pageX = touches[0].pageX;\n pageY = touches[0].pageY;\n }\n else {\n pageX = ev.pageX;\n pageY = ev.pageY;\n }\n // TODO: repeat code\n if (isFirst) {\n this.origPageX = pageX;\n this.origPageY = pageY;\n }\n else {\n deltaX = pageX - this.origPageX;\n deltaY = pageY - this.origPageY;\n }\n return {\n origEvent: ev,\n isTouch: true,\n subjectEl: this.subjectEl,\n pageX,\n pageY,\n deltaX,\n deltaY,\n };\n }\n}\n// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)\nfunction isPrimaryMouseButton(ev) {\n return ev.button === 0 && !ev.ctrlKey;\n}\n// Ignoring fake mouse events generated by touch\n// ----------------------------------------------------------------------------------------------------\nfunction startIgnoringMouse() {\n ignoreMouseDepth += 1;\n setTimeout(() => {\n ignoreMouseDepth -= 1;\n }, _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bG.touchMouseIgnoreWait);\n}\n// We want to attach touchmove as early as possible for Safari\n// ----------------------------------------------------------------------------------------------------\nfunction listenerCreated() {\n listenerCnt += 1;\n if (listenerCnt === 1) {\n window.addEventListener('touchmove', onWindowTouchMove, { passive: false });\n }\n}\nfunction listenerDestroyed() {\n listenerCnt -= 1;\n if (!listenerCnt) {\n window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });\n }\n}\nfunction onWindowTouchMove(ev) {\n if (isWindowTouchMoveCancelled) {\n ev.preventDefault();\n }\n}\n\n/*\nAn effect in which an element follows the movement of a pointer across the screen.\nThe moving element is a clone of some other element.\nMust call start + handleMove + stop.\n*/\nclass ElementMirror {\n constructor() {\n this.isVisible = false; // must be explicitly enabled\n this.sourceEl = null;\n this.mirrorEl = null;\n this.sourceElRect = null; // screen coords relative to viewport\n // options that can be set directly by caller\n this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues\n this.zIndex = 9999;\n this.revertDuration = 0;\n }\n start(sourceEl, pageX, pageY) {\n this.sourceEl = sourceEl;\n this.sourceElRect = this.sourceEl.getBoundingClientRect();\n this.origScreenX = pageX - window.scrollX;\n this.origScreenY = pageY - window.scrollY;\n this.deltaX = 0;\n this.deltaY = 0;\n this.updateElPosition();\n }\n handleMove(pageX, pageY) {\n this.deltaX = (pageX - window.scrollX) - this.origScreenX;\n this.deltaY = (pageY - window.scrollY) - this.origScreenY;\n this.updateElPosition();\n }\n // can be called before start\n setIsVisible(bool) {\n if (bool) {\n if (!this.isVisible) {\n if (this.mirrorEl) {\n this.mirrorEl.style.display = '';\n }\n this.isVisible = bool; // needs to happen before updateElPosition\n this.updateElPosition(); // because was not updating the position while invisible\n }\n }\n else if (this.isVisible) {\n if (this.mirrorEl) {\n this.mirrorEl.style.display = 'none';\n }\n this.isVisible = bool;\n }\n }\n // always async\n stop(needsRevertAnimation, callback) {\n let done = () => {\n this.cleanup();\n callback();\n };\n if (needsRevertAnimation &&\n this.mirrorEl &&\n this.isVisible &&\n this.revertDuration && // if 0, transition won't work\n (this.deltaX || this.deltaY) // if same coords, transition won't work\n ) {\n this.doRevertAnimation(done, this.revertDuration);\n }\n else {\n setTimeout(done, 0);\n }\n }\n doRevertAnimation(callback, revertDuration) {\n let mirrorEl = this.mirrorEl;\n let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened\n mirrorEl.style.transition =\n 'top ' + revertDuration + 'ms,' +\n 'left ' + revertDuration + 'ms';\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aN)(mirrorEl, {\n left: finalSourceElRect.left,\n top: finalSourceElRect.top,\n });\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b0)(mirrorEl, () => {\n mirrorEl.style.transition = '';\n callback();\n });\n }\n cleanup() {\n if (this.mirrorEl) {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aM)(this.mirrorEl);\n this.mirrorEl = null;\n }\n this.sourceEl = null;\n }\n updateElPosition() {\n if (this.sourceEl && this.isVisible) {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aN)(this.getMirrorEl(), {\n left: this.sourceElRect.left + this.deltaX,\n top: this.sourceElRect.top + this.deltaY,\n });\n }\n }\n getMirrorEl() {\n let sourceElRect = this.sourceElRect;\n let mirrorEl = this.mirrorEl;\n if (!mirrorEl) {\n mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true\n // we don't want long taps or any mouse interaction causing selection/menus.\n // would use preventSelection(), but that prevents selectstart, causing problems.\n mirrorEl.style.userSelect = 'none';\n mirrorEl.style.webkitUserSelect = 'none';\n mirrorEl.style.pointerEvents = 'none';\n mirrorEl.classList.add('fc-event-dragging');\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aN)(mirrorEl, {\n position: 'fixed',\n zIndex: this.zIndex,\n visibility: '',\n boxSizing: 'border-box',\n width: sourceElRect.right - sourceElRect.left,\n height: sourceElRect.bottom - sourceElRect.top,\n right: 'auto',\n bottom: 'auto',\n margin: 0,\n });\n this.parentNode.appendChild(mirrorEl);\n }\n return mirrorEl;\n }\n}\n\n/*\nIs a cache for a given element's scroll information (all the info that ScrollController stores)\nin addition the \"client rectangle\" of the element.. the area within the scrollbars.\n\nThe cache can be in one of two modes:\n- doesListening:false - ignores when the container is scrolled by someone else\n- doesListening:true - watch for scrolling and update the cache\n*/\nclass ScrollGeomCache extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b9 {\n constructor(scrollController, doesListening) {\n super();\n this.handleScroll = () => {\n this.scrollTop = this.scrollController.getScrollTop();\n this.scrollLeft = this.scrollController.getScrollLeft();\n this.handleScrollChange();\n };\n this.scrollController = scrollController;\n this.doesListening = doesListening;\n this.scrollTop = this.origScrollTop = scrollController.getScrollTop();\n this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();\n this.scrollWidth = scrollController.getScrollWidth();\n this.scrollHeight = scrollController.getScrollHeight();\n this.clientWidth = scrollController.getClientWidth();\n this.clientHeight = scrollController.getClientHeight();\n this.clientRect = this.computeClientRect(); // do last in case it needs cached values\n if (this.doesListening) {\n this.getEventTarget().addEventListener('scroll', this.handleScroll);\n }\n }\n destroy() {\n if (this.doesListening) {\n this.getEventTarget().removeEventListener('scroll', this.handleScroll);\n }\n }\n getScrollTop() {\n return this.scrollTop;\n }\n getScrollLeft() {\n return this.scrollLeft;\n }\n setScrollTop(top) {\n this.scrollController.setScrollTop(top);\n if (!this.doesListening) {\n // we are not relying on the element to normalize out-of-bounds scroll values\n // so we need to sanitize ourselves\n this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);\n this.handleScrollChange();\n }\n }\n setScrollLeft(top) {\n this.scrollController.setScrollLeft(top);\n if (!this.doesListening) {\n // we are not relying on the element to normalize out-of-bounds scroll values\n // so we need to sanitize ourselves\n this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);\n this.handleScrollChange();\n }\n }\n getClientWidth() {\n return this.clientWidth;\n }\n getClientHeight() {\n return this.clientHeight;\n }\n getScrollWidth() {\n return this.scrollWidth;\n }\n getScrollHeight() {\n return this.scrollHeight;\n }\n handleScrollChange() {\n }\n}\n\nclass ElementScrollGeomCache extends ScrollGeomCache {\n constructor(el, doesListening) {\n super(new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ba(el), doesListening);\n }\n getEventTarget() {\n return this.scrollController.el;\n }\n computeClientRect() {\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b1)(this.scrollController.el);\n }\n}\n\nclass WindowScrollGeomCache extends ScrollGeomCache {\n constructor(doesListening) {\n super(new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bb(), doesListening);\n }\n getEventTarget() {\n return window;\n }\n computeClientRect() {\n return {\n left: this.scrollLeft,\n right: this.scrollLeft + this.clientWidth,\n top: this.scrollTop,\n bottom: this.scrollTop + this.clientHeight,\n };\n }\n // the window is the only scroll object that changes it's rectangle relative\n // to the document's topleft as it scrolls\n handleScrollChange() {\n this.clientRect = this.computeClientRect();\n }\n}\n\n// If available we are using native \"performance\" API instead of \"Date\"\n// Read more about it on MDN:\n// https://developer.mozilla.org/en-US/docs/Web/API/Performance\nconst getTime = typeof performance === 'function' ? performance.now : Date.now;\n/*\nFor a pointer interaction, automatically scrolls certain scroll containers when the pointer\napproaches the edge.\n\nThe caller must call start + handleMove + stop.\n*/\nclass AutoScroller {\n constructor() {\n // options that can be set by caller\n this.isEnabled = true;\n this.scrollQuery = [window, '.fc-scroller'];\n this.edgeThreshold = 50; // pixels\n this.maxVelocity = 300; // pixels per second\n // internal state\n this.pointerScreenX = null;\n this.pointerScreenY = null;\n this.isAnimating = false;\n this.scrollCaches = null;\n // protect against the initial pointerdown being too close to an edge and starting the scroll\n this.everMovedUp = false;\n this.everMovedDown = false;\n this.everMovedLeft = false;\n this.everMovedRight = false;\n this.animate = () => {\n if (this.isAnimating) { // wasn't cancelled between animation calls\n let edge = this.computeBestEdge(this.pointerScreenX + window.scrollX, this.pointerScreenY + window.scrollY);\n if (edge) {\n let now = getTime();\n this.handleSide(edge, (now - this.msSinceRequest) / 1000);\n this.requestAnimation(now);\n }\n else {\n this.isAnimating = false; // will stop animation\n }\n }\n };\n }\n start(pageX, pageY, scrollStartEl) {\n if (this.isEnabled) {\n this.scrollCaches = this.buildCaches(scrollStartEl);\n this.pointerScreenX = null;\n this.pointerScreenY = null;\n this.everMovedUp = false;\n this.everMovedDown = false;\n this.everMovedLeft = false;\n this.everMovedRight = false;\n this.handleMove(pageX, pageY);\n }\n }\n handleMove(pageX, pageY) {\n if (this.isEnabled) {\n let pointerScreenX = pageX - window.scrollX;\n let pointerScreenY = pageY - window.scrollY;\n let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;\n let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;\n if (yDelta < 0) {\n this.everMovedUp = true;\n }\n else if (yDelta > 0) {\n this.everMovedDown = true;\n }\n if (xDelta < 0) {\n this.everMovedLeft = true;\n }\n else if (xDelta > 0) {\n this.everMovedRight = true;\n }\n this.pointerScreenX = pointerScreenX;\n this.pointerScreenY = pointerScreenY;\n if (!this.isAnimating) {\n this.isAnimating = true;\n this.requestAnimation(getTime());\n }\n }\n }\n stop() {\n if (this.isEnabled) {\n this.isAnimating = false; // will stop animation\n for (let scrollCache of this.scrollCaches) {\n scrollCache.destroy();\n }\n this.scrollCaches = null;\n }\n }\n requestAnimation(now) {\n this.msSinceRequest = now;\n requestAnimationFrame(this.animate);\n }\n handleSide(edge, seconds) {\n let { scrollCache } = edge;\n let { edgeThreshold } = this;\n let invDistance = edgeThreshold - edge.distance;\n let velocity = // the closer to the edge, the faster we scroll\n ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic\n this.maxVelocity * seconds;\n let sign = 1;\n switch (edge.name) {\n case 'left':\n sign = -1;\n // falls through\n case 'right':\n scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);\n break;\n case 'top':\n sign = -1;\n // falls through\n case 'bottom':\n scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);\n break;\n }\n }\n // left/top are relative to document topleft\n computeBestEdge(left, top) {\n let { edgeThreshold } = this;\n let bestSide = null;\n let scrollCaches = this.scrollCaches || [];\n for (let scrollCache of scrollCaches) {\n let rect = scrollCache.clientRect;\n let leftDist = left - rect.left;\n let rightDist = rect.right - left;\n let topDist = top - rect.top;\n let bottomDist = rect.bottom - top;\n // completely within the rect?\n if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {\n if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&\n (!bestSide || bestSide.distance > topDist)) {\n bestSide = { scrollCache, name: 'top', distance: topDist };\n }\n if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&\n (!bestSide || bestSide.distance > bottomDist)) {\n bestSide = { scrollCache, name: 'bottom', distance: bottomDist };\n }\n /*\n TODO: fix broken RTL scrolling. canScrollLeft always returning false\n https://github.com/fullcalendar/fullcalendar/issues/4837\n */\n if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&\n (!bestSide || bestSide.distance > leftDist)) {\n bestSide = { scrollCache, name: 'left', distance: leftDist };\n }\n if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&\n (!bestSide || bestSide.distance > rightDist)) {\n bestSide = { scrollCache, name: 'right', distance: rightDist };\n }\n }\n }\n return bestSide;\n }\n buildCaches(scrollStartEl) {\n return this.queryScrollEls(scrollStartEl).map((el) => {\n if (el === window) {\n return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls\n }\n return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls\n });\n }\n queryScrollEls(scrollStartEl) {\n let els = [];\n for (let query of this.scrollQuery) {\n if (typeof query === 'object') {\n els.push(query);\n }\n else {\n /*\n TODO: in the future, always have auto-scroll happen on element where current Hit came from\n Ticket: https://github.com/fullcalendar/fullcalendar/issues/4593\n */\n els.push(...Array.prototype.slice.call(scrollStartEl.getRootNode().querySelectorAll(query)));\n }\n }\n return els;\n }\n}\n\n/*\nMonitors dragging on an element. Has a number of high-level features:\n- minimum distance required before dragging\n- minimum wait time (\"delay\") before dragging\n- a mirror element that follows the pointer\n*/\nclass FeaturefulElementDragging extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bF {\n constructor(containerEl, selector) {\n super(containerEl);\n this.containerEl = containerEl;\n // options that can be directly set by caller\n // the caller can also set the PointerDragging's options as well\n this.delay = null;\n this.minDistance = 0;\n this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag\n this.mirrorNeedsRevert = false;\n this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup\n this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation\n this.isDelayEnded = false;\n this.isDistanceSurpassed = false;\n this.delayTimeoutId = null;\n this.onPointerDown = (ev) => {\n if (!this.isDragging) { // so new drag doesn't happen while revert animation is going\n this.isInteracting = true;\n this.isDelayEnded = false;\n this.isDistanceSurpassed = false;\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ap)(document.body);\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ar)(document.body);\n // prevent links from being visited if there's an eventual drag.\n // also prevents selection in older browsers (maybe?).\n // not necessary for touch, besides, browser would complain about passiveness.\n if (!ev.isTouch) {\n ev.origEvent.preventDefault();\n }\n this.emitter.trigger('pointerdown', ev);\n if (this.isInteracting && // not destroyed via pointerdown handler\n !this.pointer.shouldIgnoreMove) {\n // actions related to initiating dragstart+dragmove+dragend...\n this.mirror.setIsVisible(false); // reset. caller must set-visible\n this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down\n this.startDelay(ev);\n if (!this.minDistance) {\n this.handleDistanceSurpassed(ev);\n }\n }\n }\n };\n this.onPointerMove = (ev) => {\n if (this.isInteracting) {\n this.emitter.trigger('pointermove', ev);\n if (!this.isDistanceSurpassed) {\n let minDistance = this.minDistance;\n let distanceSq; // current distance from the origin, squared\n let { deltaX, deltaY } = ev;\n distanceSq = deltaX * deltaX + deltaY * deltaY;\n if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem\n this.handleDistanceSurpassed(ev);\n }\n }\n if (this.isDragging) {\n // a real pointer move? (not one simulated by scrolling)\n if (ev.origEvent.type !== 'scroll') {\n this.mirror.handleMove(ev.pageX, ev.pageY);\n this.autoScroller.handleMove(ev.pageX, ev.pageY);\n }\n this.emitter.trigger('dragmove', ev);\n }\n }\n };\n this.onPointerUp = (ev) => {\n if (this.isInteracting) {\n this.isInteracting = false;\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aq)(document.body);\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.as)(document.body);\n this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert\n if (this.isDragging) {\n this.autoScroller.stop();\n this.tryStopDrag(ev); // which will stop the mirror\n }\n if (this.delayTimeoutId) {\n clearTimeout(this.delayTimeoutId);\n this.delayTimeoutId = null;\n }\n }\n };\n let pointer = this.pointer = new PointerDragging(containerEl);\n pointer.emitter.on('pointerdown', this.onPointerDown);\n pointer.emitter.on('pointermove', this.onPointerMove);\n pointer.emitter.on('pointerup', this.onPointerUp);\n if (selector) {\n pointer.selector = selector;\n }\n this.mirror = new ElementMirror();\n this.autoScroller = new AutoScroller();\n }\n destroy() {\n this.pointer.destroy();\n // HACK: simulate a pointer-up to end the current drag\n // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)\n this.onPointerUp({});\n }\n startDelay(ev) {\n if (typeof this.delay === 'number') {\n this.delayTimeoutId = setTimeout(() => {\n this.delayTimeoutId = null;\n this.handleDelayEnd(ev);\n }, this.delay); // not assignable to number!\n }\n else {\n this.handleDelayEnd(ev);\n }\n }\n handleDelayEnd(ev) {\n this.isDelayEnded = true;\n this.tryStartDrag(ev);\n }\n handleDistanceSurpassed(ev) {\n this.isDistanceSurpassed = true;\n this.tryStartDrag(ev);\n }\n tryStartDrag(ev) {\n if (this.isDelayEnded && this.isDistanceSurpassed) {\n if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {\n this.isDragging = true;\n this.mirrorNeedsRevert = false;\n this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);\n this.emitter.trigger('dragstart', ev);\n if (this.touchScrollAllowed === false) {\n this.pointer.cancelTouchScroll();\n }\n }\n }\n }\n tryStopDrag(ev) {\n // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events\n // that come from the document to fire beforehand. much more convenient this way.\n this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));\n }\n stopDrag(ev) {\n this.isDragging = false;\n this.emitter.trigger('dragend', ev);\n }\n // fill in the implementations...\n setIgnoreMove(bool) {\n this.pointer.shouldIgnoreMove = bool;\n }\n setMirrorIsVisible(bool) {\n this.mirror.setIsVisible(bool);\n }\n setMirrorNeedsRevert(bool) {\n this.mirrorNeedsRevert = bool;\n }\n setAutoScrollEnabled(bool) {\n this.autoScroller.isEnabled = bool;\n }\n}\n\n/*\nWhen this class is instantiated, it records the offset of an element (relative to the document topleft),\nand continues to monitor scrolling, updating the cached coordinates if it needs to.\nDoes not access the DOM after instantiation, so highly performant.\n\nAlso keeps track of all scrolling/overflow:hidden containers that are parents of the given element\nand an determine if a given point is inside the combined clipping rectangle.\n*/\nclass OffsetTracker {\n constructor(el) {\n this.el = el;\n this.origRect = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b4)(el);\n // will work fine for divs that have overflow:hidden\n this.scrollCaches = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b3)(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));\n }\n destroy() {\n for (let scrollCache of this.scrollCaches) {\n scrollCache.destroy();\n }\n }\n computeLeft() {\n let left = this.origRect.left;\n for (let scrollCache of this.scrollCaches) {\n left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();\n }\n return left;\n }\n computeTop() {\n let top = this.origRect.top;\n for (let scrollCache of this.scrollCaches) {\n top += scrollCache.origScrollTop - scrollCache.getScrollTop();\n }\n return top;\n }\n isWithinClipping(pageX, pageY) {\n let point = { left: pageX, top: pageY };\n for (let scrollCache of this.scrollCaches) {\n if (!isIgnoredClipping(scrollCache.getEventTarget()) &&\n !(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aD)(point, scrollCache.clientRect)) {\n return false;\n }\n }\n return true;\n }\n}\n// certain clipping containers should never constrain interactions, like <html> and <body>\n// https://github.com/fullcalendar/fullcalendar/issues/3615\nfunction isIgnoredClipping(node) {\n let tagName = node.tagName;\n return tagName === 'HTML' || tagName === 'BODY';\n}\n\n/*\nTracks movement over multiple droppable areas (aka \"hits\")\nthat exist in one or more DateComponents.\nRelies on an existing draggable.\n\nemits:\n- pointerdown\n- dragstart\n- hitchange - fires initially, even if not over a hit\n- pointerup\n- (hitchange - again, to null, if ended over a hit)\n- dragend\n*/\nclass HitDragging {\n constructor(dragging, droppableStore) {\n // options that can be set by caller\n this.useSubjectCenter = false;\n this.requireInitial = true; // if doesn't start out on a hit, won't emit any events\n this.disablePointCheck = false;\n this.initialHit = null;\n this.movingHit = null;\n this.finalHit = null; // won't ever be populated if shouldIgnoreMove\n this.handlePointerDown = (ev) => {\n let { dragging } = this;\n this.initialHit = null;\n this.movingHit = null;\n this.finalHit = null;\n this.prepareHits();\n this.processFirstCoord(ev);\n if (this.initialHit || !this.requireInitial) {\n dragging.setIgnoreMove(false);\n // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(\n this.emitter.trigger('pointerdown', ev);\n }\n else {\n dragging.setIgnoreMove(true);\n }\n };\n this.handleDragStart = (ev) => {\n this.emitter.trigger('dragstart', ev);\n this.handleMove(ev, true); // force = fire even if initially null\n };\n this.handleDragMove = (ev) => {\n this.emitter.trigger('dragmove', ev);\n this.handleMove(ev);\n };\n this.handlePointerUp = (ev) => {\n this.releaseHits();\n this.emitter.trigger('pointerup', ev);\n };\n this.handleDragEnd = (ev) => {\n if (this.movingHit) {\n this.emitter.trigger('hitupdate', null, true, ev);\n }\n this.finalHit = this.movingHit;\n this.movingHit = null;\n this.emitter.trigger('dragend', ev);\n };\n this.droppableStore = droppableStore;\n dragging.emitter.on('pointerdown', this.handlePointerDown);\n dragging.emitter.on('dragstart', this.handleDragStart);\n dragging.emitter.on('dragmove', this.handleDragMove);\n dragging.emitter.on('pointerup', this.handlePointerUp);\n dragging.emitter.on('dragend', this.handleDragEnd);\n this.dragging = dragging;\n this.emitter = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.F();\n }\n // sets initialHit\n // sets coordAdjust\n processFirstCoord(ev) {\n let origPoint = { left: ev.pageX, top: ev.pageY };\n let adjustedPoint = origPoint;\n let subjectEl = ev.subjectEl;\n let subjectRect;\n if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot\n subjectRect = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b4)(subjectEl);\n adjustedPoint = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aE)(adjustedPoint, subjectRect);\n }\n let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);\n if (initialHit) {\n if (this.useSubjectCenter && subjectRect) {\n let slicedSubjectRect = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aC)(subjectRect, initialHit.rect);\n if (slicedSubjectRect) {\n adjustedPoint = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aF)(slicedSubjectRect);\n }\n }\n this.coordAdjust = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aG)(adjustedPoint, origPoint);\n }\n else {\n this.coordAdjust = { left: 0, top: 0 };\n }\n }\n handleMove(ev, forceHandle) {\n let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);\n if (forceHandle || !isHitsEqual(this.movingHit, hit)) {\n this.movingHit = hit;\n this.emitter.trigger('hitupdate', hit, false, ev);\n }\n }\n prepareHits() {\n this.offsetTrackers = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.a)(this.droppableStore, (interactionSettings) => {\n interactionSettings.component.prepareHits();\n return new OffsetTracker(interactionSettings.el);\n });\n }\n releaseHits() {\n let { offsetTrackers } = this;\n for (let id in offsetTrackers) {\n offsetTrackers[id].destroy();\n }\n this.offsetTrackers = {};\n }\n queryHitForOffset(offsetLeft, offsetTop) {\n let { droppableStore, offsetTrackers } = this;\n let bestHit = null;\n for (let id in droppableStore) {\n let component = droppableStore[id].component;\n let offsetTracker = offsetTrackers[id];\n if (offsetTracker && // wasn't destroyed mid-drag\n offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {\n let originLeft = offsetTracker.computeLeft();\n let originTop = offsetTracker.computeTop();\n let positionLeft = offsetLeft - originLeft;\n let positionTop = offsetTop - originTop;\n let { origRect } = offsetTracker;\n let width = origRect.right - origRect.left;\n let height = origRect.bottom - origRect.top;\n if (\n // must be within the element's bounds\n positionLeft >= 0 && positionLeft < width &&\n positionTop >= 0 && positionTop < height) {\n let hit = component.queryHit(positionLeft, positionTop, width, height);\n if (hit && (\n // make sure the hit is within activeRange, meaning it's not a dead cell\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.b7)(hit.dateProfile.activeRange, hit.dateSpan.range)) &&\n // Ensure the component we are querying for the hit is accessibly my the pointer\n // Prevents obscured calendars (ex: under a modal dialog) from accepting hit\n // https://github.com/fullcalendar/fullcalendar/issues/5026\n (this.disablePointCheck ||\n offsetTracker.el.contains(offsetTracker.el.getRootNode().elementFromPoint(\n // add-back origins to get coordinate relative to top-left of window viewport\n positionLeft + originLeft - window.scrollX, positionTop + originTop - window.scrollY))) &&\n (!bestHit || hit.layer > bestHit.layer)) {\n hit.componentId = id;\n hit.context = component.context;\n // TODO: better way to re-orient rectangle\n hit.rect.left += originLeft;\n hit.rect.right += originLeft;\n hit.rect.top += originTop;\n hit.rect.bottom += originTop;\n bestHit = hit;\n }\n }\n }\n }\n return bestHit;\n }\n}\nfunction isHitsEqual(hit0, hit1) {\n if (!hit0 && !hit1) {\n return true;\n }\n if (Boolean(hit0) !== Boolean(hit1)) {\n return false;\n }\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bd)(hit0.dateSpan, hit1.dateSpan);\n}\n\nfunction buildDatePointApiWithContext(dateSpan, context) {\n let props = {};\n for (let transform of context.pluginHooks.datePointTransforms) {\n Object.assign(props, transform(dateSpan, context));\n }\n Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));\n return props;\n}\nfunction buildDatePointApi(span, dateEnv) {\n return {\n date: dateEnv.toDate(span.range.start),\n dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),\n allDay: span.allDay,\n };\n}\n\n/*\nMonitors when the user clicks on a specific date/time of a component.\nA pointerdown+pointerup on the same \"hit\" constitutes a click.\n*/\nclass DateClicking extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.X {\n constructor(settings) {\n super(settings);\n this.handlePointerDown = (pev) => {\n let { dragging } = this;\n let downEl = pev.origEvent.target;\n // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired\n dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));\n };\n // won't even fire if moving was ignored\n this.handleDragEnd = (ev) => {\n let { component } = this;\n let { pointer } = this.dragging;\n if (!pointer.wasTouchScroll) {\n let { initialHit, finalHit } = this.hitDragging;\n if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {\n let { context } = component;\n let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view });\n context.emitter.trigger('dateClick', arg);\n }\n }\n };\n // we DO want to watch pointer moves because otherwise finalHit won't get populated\n this.dragging = new FeaturefulElementDragging(settings.el);\n this.dragging.autoScroller.isEnabled = false;\n let hitDragging = this.hitDragging = new HitDragging(this.dragging, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bE)(settings));\n hitDragging.emitter.on('pointerdown', this.handlePointerDown);\n hitDragging.emitter.on('dragend', this.handleDragEnd);\n }\n destroy() {\n this.dragging.destroy();\n }\n}\n\n/*\nTracks when the user selects a portion of time of a component,\nconstituted by a drag over date cells, with a possible delay at the beginning of the drag.\n*/\nclass DateSelecting extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.X {\n constructor(settings) {\n super(settings);\n this.dragSelection = null;\n this.handlePointerDown = (ev) => {\n let { component, dragging } = this;\n let { options } = component.context;\n let canSelect = options.selectable &&\n component.isValidDateDownEl(ev.origEvent.target);\n // don't bother to watch expensive moves if component won't do selection\n dragging.setIgnoreMove(!canSelect);\n // if touch, require user to hold down\n dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;\n };\n this.handleDragStart = (ev) => {\n this.component.context.calendarApi.unselect(ev); // unselect previous selections\n };\n this.handleHitUpdate = (hit, isFinal) => {\n let { context } = this.component;\n let dragSelection = null;\n let isInvalid = false;\n if (hit) {\n let initialHit = this.hitDragging.initialHit;\n let disallowed = hit.componentId === initialHit.componentId\n && this.isHitComboAllowed\n && !this.isHitComboAllowed(initialHit, hit);\n if (!disallowed) {\n dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);\n }\n if (!dragSelection || !(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bY)(dragSelection, hit.dateProfile, context)) {\n isInvalid = true;\n dragSelection = null;\n }\n }\n if (dragSelection) {\n context.dispatch({ type: 'SELECT_DATES', selection: dragSelection });\n }\n else if (!isFinal) { // only unselect if moved away while dragging\n context.dispatch({ type: 'UNSELECT_DATES' });\n }\n if (!isInvalid) {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.au)();\n }\n else {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.av)();\n }\n if (!isFinal) {\n this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging\n }\n };\n this.handlePointerUp = (pev) => {\n if (this.dragSelection) {\n // selection is already rendered, so just need to report selection\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.cr)(this.dragSelection, pev, this.component.context);\n this.dragSelection = null;\n }\n };\n let { component } = settings;\n let { options } = component.context;\n let dragging = this.dragging = new FeaturefulElementDragging(settings.el);\n dragging.touchScrollAllowed = false;\n dragging.minDistance = options.selectMinDistance || 0;\n dragging.autoScroller.isEnabled = options.dragScroll;\n let hitDragging = this.hitDragging = new HitDragging(this.dragging, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bE)(settings));\n hitDragging.emitter.on('pointerdown', this.handlePointerDown);\n hitDragging.emitter.on('dragstart', this.handleDragStart);\n hitDragging.emitter.on('hitupdate', this.handleHitUpdate);\n hitDragging.emitter.on('pointerup', this.handlePointerUp);\n }\n destroy() {\n this.dragging.destroy();\n }\n}\nfunction getComponentTouchDelay$1(component) {\n let { options } = component.context;\n let delay = options.selectLongPressDelay;\n if (delay == null) {\n delay = options.longPressDelay;\n }\n return delay;\n}\nfunction joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {\n let dateSpan0 = hit0.dateSpan;\n let dateSpan1 = hit1.dateSpan;\n let ms = [\n dateSpan0.range.start,\n dateSpan0.range.end,\n dateSpan1.range.start,\n dateSpan1.range.end,\n ];\n ms.sort(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.at);\n let props = {};\n for (let transformer of dateSelectionTransformers) {\n let res = transformer(hit0, hit1);\n if (res === false) {\n return null;\n }\n if (res) {\n Object.assign(props, res);\n }\n }\n props.range = { start: ms[0], end: ms[3] };\n props.allDay = dateSpan0.allDay;\n return props;\n}\n\nclass EventDragging extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.X {\n constructor(settings) {\n super(settings);\n // internal state\n this.subjectEl = null;\n this.subjectSeg = null; // the seg being selected/dragged\n this.isDragging = false;\n this.eventRange = null;\n this.relevantEvents = null; // the events being dragged\n this.receivingContext = null;\n this.validMutation = null;\n this.mutatedRelevantEvents = null;\n this.handlePointerDown = (ev) => {\n let origTarget = ev.origEvent.target;\n let { component, dragging } = this;\n let { mirror } = dragging;\n let { options } = component.context;\n let initialContext = component.context;\n this.subjectEl = ev.subjectEl;\n let subjectSeg = this.subjectSeg = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Y)(ev.subjectEl);\n let eventRange = this.eventRange = subjectSeg.eventRange;\n let eventInstanceId = eventRange.instance.instanceId;\n this.relevantEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aT)(initialContext.getCurrentData().eventStore, eventInstanceId);\n dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;\n dragging.delay =\n // only do a touch delay if touch and this event hasn't been selected yet\n (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?\n getComponentTouchDelay(component) :\n null;\n if (options.fixedMirrorParent) {\n mirror.parentNode = options.fixedMirrorParent;\n }\n else {\n mirror.parentNode = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(origTarget, '.fc');\n }\n mirror.revertDuration = options.dragRevertDuration;\n let isValid = component.isValidSegDownEl(origTarget) &&\n !(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(origTarget, '.fc-event-resizer'); // NOT on a resizer\n dragging.setIgnoreMove(!isValid);\n // disable dragging for elements that are resizable (ie, selectable)\n // but are not draggable\n this.isDragging = isValid &&\n ev.subjectEl.classList.contains('fc-event-draggable');\n };\n this.handleDragStart = (ev) => {\n let initialContext = this.component.context;\n let eventRange = this.eventRange;\n let eventInstanceId = eventRange.instance.instanceId;\n if (ev.isTouch) {\n // need to select a different event?\n if (eventInstanceId !== this.component.props.eventSelection) {\n initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId });\n }\n }\n else {\n // if now using mouse, but was previous touch interaction, clear selected event\n initialContext.dispatch({ type: 'UNSELECT_EVENT' });\n }\n if (this.isDragging) {\n initialContext.calendarApi.unselect(ev); // unselect *date* selection\n initialContext.emitter.trigger('eventDragStart', {\n el: this.subjectEl,\n event: new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(initialContext, eventRange.def, eventRange.instance),\n jsEvent: ev.origEvent,\n view: initialContext.viewApi,\n });\n }\n };\n this.handleHitUpdate = (hit, isFinal) => {\n if (!this.isDragging) {\n return;\n }\n let relevantEvents = this.relevantEvents;\n let initialHit = this.hitDragging.initialHit;\n let initialContext = this.component.context;\n // states based on new hit\n let receivingContext = null;\n let mutation = null;\n let mutatedRelevantEvents = null;\n let isInvalid = false;\n let interaction = {\n affectedEvents: relevantEvents,\n mutatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)(),\n isEvent: true,\n };\n if (hit) {\n receivingContext = hit.context;\n let receivingOptions = receivingContext.options;\n if (initialContext === receivingContext ||\n (receivingOptions.editable && receivingOptions.droppable)) {\n mutation = computeEventMutation(initialHit, hit, this.eventRange.instance.range.start, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);\n if (mutation) {\n mutatedRelevantEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bV)(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);\n interaction.mutatedEvents = mutatedRelevantEvents;\n if (!(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bX)(interaction, hit.dateProfile, receivingContext)) {\n isInvalid = true;\n mutation = null;\n mutatedRelevantEvents = null;\n interaction.mutatedEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)();\n }\n }\n }\n else {\n receivingContext = null;\n }\n }\n this.displayDrag(receivingContext, interaction);\n if (!isInvalid) {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.au)();\n }\n else {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.av)();\n }\n if (!isFinal) {\n if (initialContext === receivingContext && // TODO: write test for this\n isHitsEqual(initialHit, hit)) {\n mutation = null;\n }\n this.dragging.setMirrorNeedsRevert(!mutation);\n // render the mirror if no already-rendered mirror\n // TODO: wish we could somehow wait for dispatch to guarantee render\n this.dragging.setMirrorIsVisible(!hit || !this.subjectEl.getRootNode().querySelector('.fc-event-mirror'));\n // assign states based on new hit\n this.receivingContext = receivingContext;\n this.validMutation = mutation;\n this.mutatedRelevantEvents = mutatedRelevantEvents;\n }\n };\n this.handlePointerUp = () => {\n if (!this.isDragging) {\n this.cleanup(); // because handleDragEnd won't fire\n }\n };\n this.handleDragEnd = (ev) => {\n if (this.isDragging) {\n let initialContext = this.component.context;\n let initialView = initialContext.viewApi;\n let { receivingContext, validMutation } = this;\n let eventDef = this.eventRange.def;\n let eventInstance = this.eventRange.instance;\n let eventApi = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(initialContext, eventDef, eventInstance);\n let relevantEvents = this.relevantEvents;\n let mutatedRelevantEvents = this.mutatedRelevantEvents;\n let { finalHit } = this.hitDragging;\n this.clearDrag(); // must happen after revert animation\n initialContext.emitter.trigger('eventDragStop', {\n el: this.subjectEl,\n event: eventApi,\n jsEvent: ev.origEvent,\n view: initialView,\n });\n if (validMutation) {\n // dropped within same calendar\n if (receivingContext === initialContext) {\n let updatedEventApi = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);\n initialContext.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: mutatedRelevantEvents,\n });\n let eventChangeArg = {\n oldEvent: eventApi,\n event: updatedEventApi,\n relatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.w)(mutatedRelevantEvents, initialContext, eventInstance),\n revert() {\n initialContext.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: relevantEvents, // the pre-change data\n });\n },\n };\n let transformed = {};\n for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {\n Object.assign(transformed, transformer(validMutation, initialContext));\n }\n initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView }));\n initialContext.emitter.trigger('eventChange', eventChangeArg);\n // dropped in different calendar\n }\n else if (receivingContext) {\n let eventRemoveArg = {\n event: eventApi,\n relatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.w)(relevantEvents, initialContext, eventInstance),\n revert() {\n initialContext.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: relevantEvents,\n });\n },\n };\n initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView }));\n initialContext.dispatch({\n type: 'REMOVE_EVENTS',\n eventStore: relevantEvents,\n });\n initialContext.emitter.trigger('eventRemove', eventRemoveArg);\n let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];\n let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];\n let addedEventApi = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(receivingContext, addedEventDef, addedEventInstance);\n receivingContext.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: mutatedRelevantEvents,\n });\n let eventAddArg = {\n event: addedEventApi,\n relatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.w)(mutatedRelevantEvents, receivingContext, addedEventInstance),\n revert() {\n receivingContext.dispatch({\n type: 'REMOVE_EVENTS',\n eventStore: mutatedRelevantEvents,\n });\n },\n };\n receivingContext.emitter.trigger('eventAdd', eventAddArg);\n if (ev.isTouch) {\n receivingContext.dispatch({\n type: 'SELECT_EVENT',\n eventInstanceId: eventInstance.instanceId,\n });\n }\n receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi }));\n receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi }));\n }\n }\n else {\n initialContext.emitter.trigger('_noEventDrop');\n }\n }\n this.cleanup();\n };\n let { component } = this;\n let { options } = component.context;\n let dragging = this.dragging = new FeaturefulElementDragging(settings.el);\n dragging.pointer.selector = EventDragging.SELECTOR;\n dragging.touchScrollAllowed = false;\n dragging.autoScroller.isEnabled = options.dragScroll;\n let hitDragging = this.hitDragging = new HitDragging(this.dragging, _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.a5);\n hitDragging.useSubjectCenter = settings.useEventCenter;\n hitDragging.emitter.on('pointerdown', this.handlePointerDown);\n hitDragging.emitter.on('dragstart', this.handleDragStart);\n hitDragging.emitter.on('hitupdate', this.handleHitUpdate);\n hitDragging.emitter.on('pointerup', this.handlePointerUp);\n hitDragging.emitter.on('dragend', this.handleDragEnd);\n }\n destroy() {\n this.dragging.destroy();\n }\n // render a drag state on the next receivingCalendar\n displayDrag(nextContext, state) {\n let initialContext = this.component.context;\n let prevContext = this.receivingContext;\n // does the previous calendar need to be cleared?\n if (prevContext && prevContext !== nextContext) {\n // does the initial calendar need to be cleared?\n // if so, don't clear all the way. we still need to to hide the affectedEvents\n if (prevContext === initialContext) {\n prevContext.dispatch({\n type: 'SET_EVENT_DRAG',\n state: {\n affectedEvents: state.affectedEvents,\n mutatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)(),\n isEvent: true,\n },\n });\n // completely clear the old calendar if it wasn't the initial\n }\n else {\n prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });\n }\n }\n if (nextContext) {\n nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });\n }\n }\n clearDrag() {\n let initialCalendar = this.component.context;\n let { receivingContext } = this;\n if (receivingContext) {\n receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });\n }\n // the initial calendar might have an dummy drag state from displayDrag\n if (initialCalendar !== receivingContext) {\n initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });\n }\n }\n cleanup() {\n this.subjectSeg = null;\n this.isDragging = false;\n this.eventRange = null;\n this.relevantEvents = null;\n this.receivingContext = null;\n this.validMutation = null;\n this.mutatedRelevantEvents = null;\n }\n}\n// TODO: test this in IE11\n// QUESTION: why do we need it on the resizable???\nEventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';\nfunction computeEventMutation(hit0, hit1, eventInstanceStart, massagers) {\n let dateSpan0 = hit0.dateSpan;\n let dateSpan1 = hit1.dateSpan;\n let date0 = dateSpan0.range.start;\n let date1 = dateSpan1.range.start;\n let standardProps = {};\n if (dateSpan0.allDay !== dateSpan1.allDay) {\n standardProps.allDay = dateSpan1.allDay;\n standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;\n if (dateSpan1.allDay) {\n // means date1 is already start-of-day,\n // but date0 needs to be converted\n date0 = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.q)(eventInstanceStart);\n }\n else {\n // Moving from allDate->timed\n // Doesn't matter where on the event the drag began, mutate the event's start-date to date1\n date0 = eventInstanceStart;\n }\n }\n let delta = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ay)(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?\n hit0.largeUnit :\n null);\n if (delta.milliseconds) { // has hours/minutes/seconds\n standardProps.allDay = false;\n }\n let mutation = {\n datesDelta: delta,\n standardProps,\n };\n for (let massager of massagers) {\n massager(mutation, hit0, hit1);\n }\n return mutation;\n}\nfunction getComponentTouchDelay(component) {\n let { options } = component.context;\n let delay = options.eventLongPressDelay;\n if (delay == null) {\n delay = options.longPressDelay;\n }\n return delay;\n}\n\nclass EventResizing extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.X {\n constructor(settings) {\n super(settings);\n // internal state\n this.draggingSegEl = null;\n this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?\n this.eventRange = null;\n this.relevantEvents = null;\n this.validMutation = null;\n this.mutatedRelevantEvents = null;\n this.handlePointerDown = (ev) => {\n let { component } = this;\n let segEl = this.querySegEl(ev);\n let seg = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Y)(segEl);\n let eventRange = this.eventRange = seg.eventRange;\n this.dragging.minDistance = component.context.options.eventDragMinDistance;\n // if touch, need to be working with a selected event\n this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||\n (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));\n };\n this.handleDragStart = (ev) => {\n let { context } = this.component;\n let eventRange = this.eventRange;\n this.relevantEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aT)(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);\n let segEl = this.querySegEl(ev);\n this.draggingSegEl = segEl;\n this.draggingSeg = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Y)(segEl);\n context.calendarApi.unselect();\n context.emitter.trigger('eventResizeStart', {\n el: segEl,\n event: new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(context, eventRange.def, eventRange.instance),\n jsEvent: ev.origEvent,\n view: context.viewApi,\n });\n };\n this.handleHitUpdate = (hit, isFinal, ev) => {\n let { context } = this.component;\n let relevantEvents = this.relevantEvents;\n let initialHit = this.hitDragging.initialHit;\n let eventInstance = this.eventRange.instance;\n let mutation = null;\n let mutatedRelevantEvents = null;\n let isInvalid = false;\n let interaction = {\n affectedEvents: relevantEvents,\n mutatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)(),\n isEvent: true,\n };\n if (hit) {\n let disallowed = hit.componentId === initialHit.componentId\n && this.isHitComboAllowed\n && !this.isHitComboAllowed(initialHit, hit);\n if (!disallowed) {\n mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);\n }\n }\n if (mutation) {\n mutatedRelevantEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bV)(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);\n interaction.mutatedEvents = mutatedRelevantEvents;\n if (!(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bX)(interaction, hit.dateProfile, context)) {\n isInvalid = true;\n mutation = null;\n mutatedRelevantEvents = null;\n interaction.mutatedEvents = null;\n }\n }\n if (mutatedRelevantEvents) {\n context.dispatch({\n type: 'SET_EVENT_RESIZE',\n state: interaction,\n });\n }\n else {\n context.dispatch({ type: 'UNSET_EVENT_RESIZE' });\n }\n if (!isInvalid) {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.au)();\n }\n else {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.av)();\n }\n if (!isFinal) {\n if (mutation && isHitsEqual(initialHit, hit)) {\n mutation = null;\n }\n this.validMutation = mutation;\n this.mutatedRelevantEvents = mutatedRelevantEvents;\n }\n };\n this.handleDragEnd = (ev) => {\n let { context } = this.component;\n let eventDef = this.eventRange.def;\n let eventInstance = this.eventRange.instance;\n let eventApi = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(context, eventDef, eventInstance);\n let relevantEvents = this.relevantEvents;\n let mutatedRelevantEvents = this.mutatedRelevantEvents;\n context.emitter.trigger('eventResizeStop', {\n el: this.draggingSegEl,\n event: eventApi,\n jsEvent: ev.origEvent,\n view: context.viewApi,\n });\n if (this.validMutation) {\n let updatedEventApi = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);\n context.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: mutatedRelevantEvents,\n });\n let eventChangeArg = {\n oldEvent: eventApi,\n event: updatedEventApi,\n relatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.w)(mutatedRelevantEvents, context, eventInstance),\n revert() {\n context.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: relevantEvents, // the pre-change events\n });\n },\n };\n context.emitter.trigger('eventResize', Object.assign(Object.assign({}, eventChangeArg), { el: this.draggingSegEl, startDelta: this.validMutation.startDelta || (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.d)(0), endDelta: this.validMutation.endDelta || (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.d)(0), jsEvent: ev.origEvent, view: context.viewApi }));\n context.emitter.trigger('eventChange', eventChangeArg);\n }\n else {\n context.emitter.trigger('_noEventResize');\n }\n // reset all internal state\n this.draggingSeg = null;\n this.relevantEvents = null;\n this.validMutation = null;\n // okay to keep eventInstance around. useful to set it in handlePointerDown\n };\n let { component } = settings;\n let dragging = this.dragging = new FeaturefulElementDragging(settings.el);\n dragging.pointer.selector = '.fc-event-resizer';\n dragging.touchScrollAllowed = false;\n dragging.autoScroller.isEnabled = component.context.options.dragScroll;\n let hitDragging = this.hitDragging = new HitDragging(this.dragging, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bE)(settings));\n hitDragging.emitter.on('pointerdown', this.handlePointerDown);\n hitDragging.emitter.on('dragstart', this.handleDragStart);\n hitDragging.emitter.on('hitupdate', this.handleHitUpdate);\n hitDragging.emitter.on('dragend', this.handleDragEnd);\n }\n destroy() {\n this.dragging.destroy();\n }\n querySegEl(ev) {\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(ev.subjectEl, '.fc-event');\n }\n}\nfunction computeMutation(hit0, hit1, isFromStart, instanceRange) {\n let dateEnv = hit0.context.dateEnv;\n let date0 = hit0.dateSpan.range.start;\n let date1 = hit1.dateSpan.range.start;\n let delta = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ay)(date0, date1, dateEnv, hit0.largeUnit);\n if (isFromStart) {\n if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {\n return { startDelta: delta };\n }\n }\n else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {\n return { endDelta: delta };\n }\n return null;\n}\n\nclass UnselectAuto {\n constructor(context) {\n this.context = context;\n this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system\n this.matchesCancel = false;\n this.matchesEvent = false;\n this.onSelect = (selectInfo) => {\n if (selectInfo.jsEvent) {\n this.isRecentPointerDateSelect = true;\n }\n };\n this.onDocumentPointerDown = (pev) => {\n let unselectCancel = this.context.options.unselectCancel;\n let downEl = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aP)(pev.origEvent);\n this.matchesCancel = !!(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(downEl, unselectCancel);\n this.matchesEvent = !!(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.Z)(downEl, EventDragging.SELECTOR); // interaction started on an event?\n };\n this.onDocumentPointerUp = (pev) => {\n let { context } = this;\n let { documentPointer } = this;\n let calendarState = context.getCurrentData();\n // touch-scrolling should never unfocus any type of selection\n if (!documentPointer.wasTouchScroll) {\n if (calendarState.dateSelection && // an existing date selection?\n !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?\n ) {\n let unselectAuto = context.options.unselectAuto;\n if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {\n context.calendarApi.unselect(pev);\n }\n }\n if (calendarState.eventSelection && // an existing event selected?\n !this.matchesEvent // interaction DIDN'T start on an event\n ) {\n context.dispatch({ type: 'UNSELECT_EVENT' });\n }\n }\n this.isRecentPointerDateSelect = false;\n };\n let documentPointer = this.documentPointer = new PointerDragging(document);\n documentPointer.shouldIgnoreMove = true;\n documentPointer.shouldWatchScroll = false;\n documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);\n documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);\n /*\n TODO: better way to know about whether there was a selection with the pointer\n */\n context.emitter.on('select', this.onSelect);\n }\n destroy() {\n this.context.emitter.off('select', this.onSelect);\n this.documentPointer.destroy();\n }\n}\n\nconst OPTION_REFINERS = {\n fixedMirrorParent: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n};\nconst LISTENER_REFINERS = {\n dateClick: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventDragStart: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventDragStop: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventDrop: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventResizeStart: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventResizeStop: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventResize: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n drop: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventReceive: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n eventLeave: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.n,\n};\n\n/*\nGiven an already instantiated draggable object for one-or-more elements,\nInterprets any dragging as an attempt to drag an events that lives outside\nof a calendar onto a calendar.\n*/\nclass ExternalElementDragging {\n constructor(dragging, suppliedDragMeta) {\n this.receivingContext = null;\n this.droppableEvent = null; // will exist for all drags, even if create:false\n this.suppliedDragMeta = null;\n this.dragMeta = null;\n this.handleDragStart = (ev) => {\n this.dragMeta = this.buildDragMeta(ev.subjectEl);\n };\n this.handleHitUpdate = (hit, isFinal, ev) => {\n let { dragging } = this.hitDragging;\n let receivingContext = null;\n let droppableEvent = null;\n let isInvalid = false;\n let interaction = {\n affectedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)(),\n mutatedEvents: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)(),\n isEvent: this.dragMeta.create,\n };\n if (hit) {\n receivingContext = hit.context;\n if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {\n droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);\n interaction.mutatedEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aU)(droppableEvent);\n isInvalid = !(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bX)(interaction, hit.dateProfile, receivingContext);\n if (isInvalid) {\n interaction.mutatedEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.H)();\n droppableEvent = null;\n }\n }\n }\n this.displayDrag(receivingContext, interaction);\n // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)\n // TODO: wish we could somehow wait for dispatch to guarantee render\n dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));\n if (!isInvalid) {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.au)();\n }\n else {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.av)();\n }\n if (!isFinal) {\n dragging.setMirrorNeedsRevert(!droppableEvent);\n this.receivingContext = receivingContext;\n this.droppableEvent = droppableEvent;\n }\n };\n this.handleDragEnd = (pev) => {\n let { receivingContext, droppableEvent } = this;\n this.clearDrag();\n if (receivingContext && droppableEvent) {\n let finalHit = this.hitDragging.finalHit;\n let finalView = finalHit.context.viewApi;\n let dragMeta = this.dragMeta;\n receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }));\n if (dragMeta.create) {\n let addingEvents = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aU)(droppableEvent);\n receivingContext.dispatch({\n type: 'MERGE_EVENTS',\n eventStore: addingEvents,\n });\n if (pev.isTouch) {\n receivingContext.dispatch({\n type: 'SELECT_EVENT',\n eventInstanceId: droppableEvent.instance.instanceId,\n });\n }\n // signal that an external event landed\n receivingContext.emitter.trigger('eventReceive', {\n event: new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__._(receivingContext, droppableEvent.def, droppableEvent.instance),\n relatedEvents: [],\n revert() {\n receivingContext.dispatch({\n type: 'REMOVE_EVENTS',\n eventStore: addingEvents,\n });\n },\n draggedEl: pev.subjectEl,\n view: finalView,\n });\n }\n }\n this.receivingContext = null;\n this.droppableEvent = null;\n };\n let hitDragging = this.hitDragging = new HitDragging(dragging, _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.a5);\n hitDragging.requireInitial = false; // will start outside of a component\n hitDragging.emitter.on('dragstart', this.handleDragStart);\n hitDragging.emitter.on('hitupdate', this.handleHitUpdate);\n hitDragging.emitter.on('dragend', this.handleDragEnd);\n this.suppliedDragMeta = suppliedDragMeta;\n }\n buildDragMeta(subjectEl) {\n if (typeof this.suppliedDragMeta === 'object') {\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bH)(this.suppliedDragMeta);\n }\n if (typeof this.suppliedDragMeta === 'function') {\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bH)(this.suppliedDragMeta(subjectEl));\n }\n return getDragMetaFromEl(subjectEl);\n }\n displayDrag(nextContext, state) {\n let prevContext = this.receivingContext;\n if (prevContext && prevContext !== nextContext) {\n prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });\n }\n if (nextContext) {\n nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });\n }\n }\n clearDrag() {\n if (this.receivingContext) {\n this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });\n }\n }\n canDropElOnCalendar(el, receivingContext) {\n let dropAccept = receivingContext.options.dropAccept;\n if (typeof dropAccept === 'function') {\n return dropAccept.call(receivingContext.calendarApi, el);\n }\n if (typeof dropAccept === 'string' && dropAccept) {\n return Boolean((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aO)(el, dropAccept));\n }\n return true;\n }\n}\n// Utils for computing event store from the DragMeta\n// ----------------------------------------------------------------------------------------------------\nfunction computeEventForDateSpan(dateSpan, dragMeta, context) {\n let defProps = Object.assign({}, dragMeta.leftoverProps);\n for (let transform of context.pluginHooks.externalDefTransforms) {\n Object.assign(defProps, transform(dateSpan, dragMeta));\n }\n let { refined, extra } = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.aj)(defProps, context);\n let def = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ai)(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd\n context);\n let start = dateSpan.range.start;\n // only rely on time info if drop zone is all-day,\n // otherwise, we already know the time\n if (dateSpan.allDay && dragMeta.startTime) {\n start = context.dateEnv.add(start, dragMeta.startTime);\n }\n let end = dragMeta.duration ?\n context.dateEnv.add(start, dragMeta.duration) :\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.cs)(dateSpan.allDay, start, context);\n let instance = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.ah)(def.defId, { start, end });\n return { def, instance };\n}\n// Utils for extracting data from element\n// ----------------------------------------------------------------------------------------------------\nfunction getDragMetaFromEl(el) {\n let str = getEmbeddedElData(el, 'event');\n let obj = str ?\n JSON.parse(str) :\n { create: false }; // if no embedded data, assume no event creation\n return (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bH)(obj);\n}\n_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bG.dataAttrPrefix = '';\nfunction getEmbeddedElData(el, name) {\n let prefix = _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bG.dataAttrPrefix;\n let prefixedName = (prefix ? prefix + '-' : '') + name;\n return el.getAttribute('data-' + prefixedName) || '';\n}\n\n/*\nMakes an element (that is *external* to any calendar) draggable.\nCan pass in data that determines how an event will be created when dropped onto a calendar.\nLeverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.\n*/\nclass ExternalDraggable {\n constructor(el, settings = {}) {\n this.handlePointerDown = (ev) => {\n let { dragging } = this;\n let { minDistance, longPressDelay } = this.settings;\n dragging.minDistance =\n minDistance != null ?\n minDistance :\n (ev.isTouch ? 0 : _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.e.eventDragMinDistance);\n dragging.delay =\n ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv\n (longPressDelay != null ? longPressDelay : _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.e.longPressDelay) :\n 0;\n };\n this.handleDragStart = (ev) => {\n if (ev.isTouch &&\n this.dragging.delay &&\n ev.subjectEl.classList.contains('fc-event')) {\n this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');\n }\n };\n this.settings = settings;\n let dragging = this.dragging = new FeaturefulElementDragging(el);\n dragging.touchScrollAllowed = false;\n if (settings.itemSelector != null) {\n dragging.pointer.selector = settings.itemSelector;\n }\n if (settings.appendTo != null) {\n dragging.mirror.parentNode = settings.appendTo; // TODO: write tests\n }\n dragging.emitter.on('pointerdown', this.handlePointerDown);\n dragging.emitter.on('dragstart', this.handleDragStart);\n new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new\n }\n destroy() {\n this.dragging.destroy();\n }\n}\n\n/*\nDetects when a *THIRD-PARTY* drag-n-drop system interacts with elements.\nThe third-party system is responsible for drawing the visuals effects of the drag.\nThis class simply monitors for pointer movements and fires events.\nIt also has the ability to hide the moving element (the \"mirror\") during the drag.\n*/\nclass InferredElementDragging extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_1__.bF {\n constructor(containerEl) {\n super(containerEl);\n this.shouldIgnoreMove = false;\n this.mirrorSelector = '';\n this.currentMirrorEl = null;\n this.handlePointerDown = (ev) => {\n this.emitter.trigger('pointerdown', ev);\n if (!this.shouldIgnoreMove) {\n // fire dragstart right away. does not support delay or min-distance\n this.emitter.trigger('dragstart', ev);\n }\n };\n this.handlePointerMove = (ev) => {\n if (!this.shouldIgnoreMove) {\n this.emitter.trigger('dragmove', ev);\n }\n };\n this.handlePointerUp = (ev) => {\n this.emitter.trigger('pointerup', ev);\n if (!this.shouldIgnoreMove) {\n // fire dragend right away. does not support a revert animation\n this.emitter.trigger('dragend', ev);\n }\n };\n let pointer = this.pointer = new PointerDragging(containerEl);\n pointer.emitter.on('pointerdown', this.handlePointerDown);\n pointer.emitter.on('pointermove', this.handlePointerMove);\n pointer.emitter.on('pointerup', this.handlePointerUp);\n }\n destroy() {\n this.pointer.destroy();\n }\n setIgnoreMove(bool) {\n this.shouldIgnoreMove = bool;\n }\n setMirrorIsVisible(bool) {\n if (bool) {\n // restore a previously hidden element.\n // use the reference in case the selector class has already been removed.\n if (this.currentMirrorEl) {\n this.currentMirrorEl.style.visibility = '';\n this.currentMirrorEl = null;\n }\n }\n else {\n let mirrorEl = this.mirrorSelector\n // TODO: somehow query FullCalendars WITHIN shadow-roots\n ? document.querySelector(this.mirrorSelector)\n : null;\n if (mirrorEl) {\n this.currentMirrorEl = mirrorEl;\n mirrorEl.style.visibility = 'hidden';\n }\n }\n }\n}\n\n/*\nBridges third-party drag-n-drop systems with FullCalendar.\nMust be instantiated and destroyed by caller.\n*/\nclass ThirdPartyDraggable {\n constructor(containerOrSettings, settings) {\n let containerEl = document;\n if (\n // wish we could just test instanceof EventTarget, but doesn't work in IE11\n containerOrSettings === document ||\n containerOrSettings instanceof Element) {\n containerEl = containerOrSettings;\n settings = settings || {};\n }\n else {\n settings = (containerOrSettings || {});\n }\n let dragging = this.dragging = new InferredElementDragging(containerEl);\n if (typeof settings.itemSelector === 'string') {\n dragging.pointer.selector = settings.itemSelector;\n }\n else if (containerEl === document) {\n dragging.pointer.selector = '[data-event]';\n }\n if (typeof settings.mirrorSelector === 'string') {\n dragging.mirrorSelector = settings.mirrorSelector;\n }\n let externalDragging = new ExternalElementDragging(dragging, settings.eventData);\n // The hit-detection system requires that the dnd-mirror-element be pointer-events:none,\n // but this can't be guaranteed for third-party draggables, so disable\n externalDragging.hitDragging.disablePointCheck = true;\n }\n destroy() {\n this.dragging.destroy();\n }\n}\n\nvar index = (0,_fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__.createPlugin)({\n name: '@fullcalendar/interaction',\n componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],\n calendarInteractions: [UnselectAuto],\n elementDraggingImpl: FeaturefulElementDragging,\n optionRefiners: OPTION_REFINERS,\n listenerRefiners: LISTENER_REFINERS,\n});\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxZQUFZLHlFQUFZO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRWdGIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vYXJjaGl0ZWN0dWktaHRtbC1mcmVlLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvaW50ZXJhY3Rpb24vaW5kZXguanM/ZGQ3YyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVQbHVnaW4gfSBmcm9tICdAZnVsbGNhbGVuZGFyL2NvcmUvaW5kZXguanMnO1xuaW1wb3J0IHsgY29uZmlnLCBFbWl0dGVyLCBlbGVtZW50Q2xvc2VzdCwgYXBwbHlTdHlsZSwgd2hlblRyYW5zaXRpb25Eb25lLCByZW1vdmVFbGVtZW50LCBTY3JvbGxDb250cm9sbGVyLCBFbGVtZW50U2Nyb2xsQ29udHJvbGxlciwgY29tcHV0ZUlubmVyUmVjdCwgV2luZG93U2Nyb2xsQ29udHJvbGxlciwgRWxlbWVudERyYWdnaW5nLCBwcmV2ZW50U2VsZWN0aW9uLCBwcmV2ZW50Q29udGV4dE1lbnUsIGFsbG93U2VsZWN0aW9uLCBhbGxvd0NvbnRleHRNZW51LCBjb21wdXRlUmVjdCwgZ2V0Q2xpcHBpbmdQYXJlbnRzLCBwb2ludEluc2lkZVJlY3QsIGNvbnN0cmFpblBvaW50LCBpbnRlcnNlY3RSZWN0cywgZ2V0UmVjdENlbnRlciwgZGlmZlBvaW50cywgbWFwSGFzaCwgcmFuZ2VDb250YWluc1JhbmdlLCBpc0RhdGVTcGFuc0VxdWFsLCBJbnRlcmFjdGlvbiwgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUsIGlzRGF0ZVNlbGVjdGlvblZhbGlkLCBlbmFibGVDdXJzb3IsIGRpc2FibGVDdXJzb3IsIHRyaWdnZXJEYXRlU2VsZWN0LCBjb21wYXJlTnVtYmVycywgZ2V0RWxTZWcsIGdldFJlbGV2YW50RXZlbnRzLCBFdmVudEltcGwsIGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSwgYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZSwgaXNJbnRlcmFjdGlvblZhbGlkLCBidWlsZEV2ZW50QXBpcywgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlLCBzdGFydE9mRGF5LCBkaWZmRGF0ZXMsIGNyZWF0ZUR1cmF0aW9uLCBnZXRFdmVudFRhcmdldFZpYVJvb3QsIGlkZW50aXR5LCBldmVudFR1cGxlVG9TdG9yZSwgcGFyc2VEcmFnTWV0YSwgZWxlbWVudE1hdGNoZXMsIHJlZmluZUV2ZW50RGVmLCBwYXJzZUV2ZW50RGVmLCBnZXREZWZhdWx0RXZlbnRFbmQsIGNyZWF0ZUV2ZW50SW5zdGFuY2UsIEJBU0VfT1BUSU9OX0RFRkFVTFRTIH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9jb3JlL2ludGVybmFsLmpzJztcblxuY29uZmlnLnRvdWNoTW91c2VJZ25vcmVXYWl0ID0gNTAwO1xubGV0IGlnbm9yZU1vdXNlRGVwdGggPSAwO1xubGV0IGxpc3RlbmVyQ250ID0gMDtcbmxldCBpc1dpbmRvd1RvdWNoTW92ZUNhbmNlbGxlZCA9IGZhbHNlO1xuLypcblVzZXMgYSBcInBvaW50ZXJcIiBhYnN0cmFjdGlvbiwgd2hpY2ggbW9uaXRvcnMgVUkgZXZlbnRzIGZvciBib3RoIG1vdXNlIGFuZCB0b3VjaC5cblRyYWNrcyB3aGVuIHRoZSBwb2ludGVyIFwiZHJhZ3NcIiBvbiBhIGNlcnRhaW4gZWxlbWVudCwgbWVhbmluZyBkb3duK21vdmUrdXAuXG5cbkFsc28sIHRyYWNrcyBpZiB0aGVyZSB3YXMgdG91Y2gtc2Nyb2xsaW5nLlxuQWxzbywgY2FuIHByZXZlbnQgdG91Y2gtc2Nyb2xsaW5nIGZyb20gaGFwcGVuaW5nLlxuQWxzbywgY2FuIGZpcmUgcG9pbnRlcm1vdmUgZXZlbnRzIHdoZW4gc2Nyb2xsaW5nIGhhcHBlbnMgdW5kZXJuZWF0aCwgZXZlbiB3aGVuIG5vIHJlYWwgcG9pbnRlciBtb3ZlbWVudC5cblxuZW1pdHM6XG4tIHBvaW50ZXJkb3duXG4tIHBvaW50ZXJtb3ZlXG4tIHBvaW50ZXJ1cFxuKi9cbmNsYXNzIFBvaW50ZXJEcmFnZ2luZyB7XG4gICAgY29uc3RydWN0b3IoY29udGFpbmVyRWwpIHtcbiAgICAgICAgdGhpcy5zdWJqZWN0RWwgPSBudWxsO1xuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIGRpcmVjdGx5IGFzc2lnbmVkIGJ5IGNhbGxlclxuICAgICAgICB0aGlzLnNlbGVjdG9yID0gJyc7IC8vIHdpbGwgY2F1c2Ugc3ViamVjdEVsIGluIGFsbCBlbWl0dGVkIGV2ZW50cyB0byBiZSB0aGlzIGVsZW1lbnRcbiAgICAgICAgdGhpcy5oYW5kbGVTZWxlY3RvciA9ICcnO1xuICAgICAgICB0aGlzLnNob3VsZElnbm9yZU1vdmUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zaG91bGRXYXRjaFNjcm9sbCA9IHRydWU7IC8vIGZvciBzaW11bGF0aW5nIHBvaW50ZXJtb3ZlIG9uIHNjcm9sbFxuICAgICAgICAvLyBpbnRlcm5hbCBzdGF0ZXNcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNUb3VjaERyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMud2FzVG91Y2hTY3JvbGwgPSBmYWxzZTtcbiAgICAgICAgLy8gTW91c2VcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNob3VsZElnbm9yZU1vdXNlKCkgJiZcbiAgICAgICAgICAgICAgICBpc1ByaW1hcnlNb3VzZUJ1dHRvbihldikgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnRyeVN0YXJ0KGV2KSkge1xuICAgICAgICAgICAgICAgIGxldCBwZXYgPSB0aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2LCB0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcmRvd24nLCBwZXYpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFNjcm9sbFdhdGNoKHBldik7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5oYW5kbGVNb3VzZU1vdmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5oYW5kbGVNb3VzZVVwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVNb3VzZU1vdmUgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGxldCBwZXYgPSB0aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2KTtcbiAgICAgICAgICAgIHRoaXMucmVjb3JkQ29vcmRzKHBldik7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcm1vdmUnLCBwZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlVXAgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuaGFuZGxlTW91c2VNb3ZlKTtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLmhhbmRsZU1vdXNlVXApO1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJ1cCcsIHRoaXMuY3JlYXRlRXZlbnRGcm9tTW91c2UoZXYpKTtcbiAgICAgICAgICAgIHRoaXMuY2xlYW51cCgpOyAvLyBjYWxsIGxhc3Qgc28gdGhhdCBwb2ludGVydXAgaGFzIGFjY2VzcyB0byBwcm9wc1xuICAgICAgICB9O1xuICAgICAgICAvLyBUb3VjaFxuICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIHRoaXMuaGFuZGxlVG91Y2hTdGFydCA9IChldikgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMudHJ5U3RhcnQoZXYpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc1RvdWNoRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGxldCBwZXYgPSB0aGlzLmNyZWF0ZUV2ZW50RnJvbVRvdWNoKGV2LCB0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcmRvd24nLCBwZXYpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFNjcm9sbFdhdGNoKHBldik7XG4gICAgICAgICAgICAgICAgLy8gdW5saWtlIG1vdXNlLCBuZWVkIHRvIGF0dGFjaCB0byB0YXJnZXQsIG5vdCBkb2N1bWVudFxuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS80NTc2MDAxNFxuICAgICAgICAgICAgICAgIGxldCB0YXJnZXRFbCA9IGV2LnRhcmdldDtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2hvdWxkSWdub3JlTW92ZSkge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXRFbC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLmhhbmRsZVRvdWNoTW92ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRhcmdldEVsLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWwuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCB0aGlzLmhhbmRsZVRvdWNoRW5kKTsgLy8gdHJlYXQgaXQgYXMgYSB0b3VjaCBlbmRcbiAgICAgICAgICAgICAgICAvLyBhdHRhY2ggYSBoYW5kbGVyIHRvIGdldCBjYWxsZWQgd2hlbiBBTlkgc2Nyb2xsIGFjdGlvbiBoYXBwZW5zIG9uIHRoZSBwYWdlLlxuICAgICAgICAgICAgICAgIC8vIHRoaXMgd2FzIGltcG9zc2libGUgdG8gZG8gd2l0aCBub3JtYWwgb24vb2ZmIGJlY2F1c2UgJ3Njcm9sbCcgZG9lc24ndCBidWJibGUuXG4gICAgICAgICAgICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzI5NTQ1NjUvOTYzNDJcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVUb3VjaFNjcm9sbCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlVG91Y2hNb3ZlID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgcGV2ID0gdGhpcy5jcmVhdGVFdmVudEZyb21Ub3VjaChldik7XG4gICAgICAgICAgICB0aGlzLnJlY29yZENvb3JkcyhwZXYpO1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJtb3ZlJywgcGV2KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVUb3VjaEVuZCA9IChldikgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcmFnZ2luZykgeyAvLyBkb25lIHRvIGd1YXJkIGFnYWluc3QgdG91Y2hlbmQgZm9sbG93ZWQgYnkgdG91Y2hjYW5jZWxcbiAgICAgICAgICAgICAgICBsZXQgdGFyZ2V0RWwgPSBldi50YXJnZXQ7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWwucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5oYW5kbGVUb3VjaE1vdmUpO1xuICAgICAgICAgICAgICAgIHRhcmdldEVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWwucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCB0aGlzLmhhbmRsZVRvdWNoRW5kKTtcbiAgICAgICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVUb3VjaFNjcm9sbCwgdHJ1ZSk7IC8vIHVzZUNhcHR1cmVkPXRydWVcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgdGhpcy5jcmVhdGVFdmVudEZyb21Ub3VjaChldikpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xlYW51cCgpOyAvLyBjYWxsIGxhc3Qgc28gdGhhdCBwb2ludGVydXAgaGFzIGFjY2VzcyB0byBwcm9wc1xuICAgICAgICAgICAgICAgIHRoaXMuaXNUb3VjaERyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhcnRJZ25vcmluZ01vdXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlVG91Y2hTY3JvbGwgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLndhc1RvdWNoU2Nyb2xsID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGwgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgbGV0IHBhZ2VYID0gKHdpbmRvdy5zY3JvbGxYIC0gdGhpcy5wcmV2U2Nyb2xsWCkgKyB0aGlzLnByZXZQYWdlWDtcbiAgICAgICAgICAgICAgICBsZXQgcGFnZVkgPSAod2luZG93LnNjcm9sbFkgLSB0aGlzLnByZXZTY3JvbGxZKSArIHRoaXMucHJldlBhZ2VZO1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIHtcbiAgICAgICAgICAgICAgICAgICAgb3JpZ0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgaXNUb3VjaDogdGhpcy5pc1RvdWNoRHJhZ2dpbmcsXG4gICAgICAgICAgICAgICAgICAgIHN1YmplY3RFbDogdGhpcy5zdWJqZWN0RWwsXG4gICAgICAgICAgICAgICAgICAgIHBhZ2VYLFxuICAgICAgICAgICAgICAgICAgICBwYWdlWSxcbiAgICAgICAgICAgICAgICAgICAgZGVsdGFYOiBwYWdlWCAtIHRoaXMub3JpZ1BhZ2VYLFxuICAgICAgICAgICAgICAgICAgICBkZWx0YVk6IHBhZ2VZIC0gdGhpcy5vcmlnUGFnZVksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwgPSBjb250YWluZXJFbDtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcbiAgICAgICAgY29udGFpbmVyRWwuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5oYW5kbGVNb3VzZURvd24pO1xuICAgICAgICBjb250YWluZXJFbC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5oYW5kbGVUb3VjaFN0YXJ0LCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gICAgICAgIGxpc3RlbmVyQ3JlYXRlZCgpO1xuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuaGFuZGxlTW91c2VEb3duKTtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5oYW5kbGVUb3VjaFN0YXJ0LCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gICAgICAgIGxpc3RlbmVyRGVzdHJveWVkKCk7XG4gICAgfVxuICAgIHRyeVN0YXJ0KGV2KSB7XG4gICAgICAgIGxldCBzdWJqZWN0RWwgPSB0aGlzLnF1ZXJ5U3ViamVjdEVsKGV2KTtcbiAgICAgICAgbGV0IGRvd25FbCA9IGV2LnRhcmdldDtcbiAgICAgICAgaWYgKHN1YmplY3RFbCAmJlxuICAgICAgICAgICAgKCF0aGlzLmhhbmRsZVNlbGVjdG9yIHx8IGVsZW1lbnRDbG9zZXN0KGRvd25FbCwgdGhpcy5oYW5kbGVTZWxlY3RvcikpKSB7XG4gICAgICAgICAgICB0aGlzLnN1YmplY3RFbCA9IHN1YmplY3RFbDtcbiAgICAgICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7IC8vIGRvIHRoaXMgZmlyc3Qgc28gY2FuY2VsVG91Y2hTY3JvbGwgd2lsbCB3b3JrXG4gICAgICAgICAgICB0aGlzLndhc1RvdWNoU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNsZWFudXAoKSB7XG4gICAgICAgIGlzV2luZG93VG91Y2hNb3ZlQ2FuY2VsbGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnN1YmplY3RFbCA9IG51bGw7XG4gICAgICAgIC8vIGtlZXAgd2FzVG91Y2hTY3JvbGwgYXJvdW5kIGZvciBsYXRlciBhY2Nlc3NcbiAgICAgICAgdGhpcy5kZXN0cm95U2Nyb2xsV2F0Y2goKTtcbiAgICB9XG4gICAgcXVlcnlTdWJqZWN0RWwoZXYpIHtcbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50Q2xvc2VzdChldi50YXJnZXQsIHRoaXMuc2VsZWN0b3IpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lckVsO1xuICAgIH1cbiAgICBzaG91bGRJZ25vcmVNb3VzZSgpIHtcbiAgICAgICAgcmV0dXJuIGlnbm9yZU1vdXNlRGVwdGggfHwgdGhpcy5pc1RvdWNoRHJhZ2dpbmc7XG4gICAgfVxuICAgIC8vIGNhbiBiZSBjYWxsZWQgYnkgdXNlciBvZiB0aGlzIGNsYXNzLCB0byBjYW5jZWwgdG91Y2gtYmFzZWQgc2Nyb2xsaW5nIGZvciB0aGUgY3VycmVudCBkcmFnXG4gICAgY2FuY2VsVG91Y2hTY3JvbGwoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIGlzV2luZG93VG91Y2hNb3ZlQ2FuY2VsbGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBTY3JvbGxpbmcgdGhhdCBzaW11bGF0ZXMgcG9pbnRlcm1vdmVzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGluaXRTY3JvbGxXYXRjaChldikge1xuICAgICAgICBpZiAodGhpcy5zaG91bGRXYXRjaFNjcm9sbCkge1xuICAgICAgICAgICAgdGhpcy5yZWNvcmRDb29yZHMoZXYpO1xuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsLCB0cnVlKTsgLy8gdXNlQ2FwdHVyZT10cnVlXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVjb3JkQ29vcmRzKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZFdhdGNoU2Nyb2xsKSB7XG4gICAgICAgICAgICB0aGlzLnByZXZQYWdlWCA9IGV2LnBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5wcmV2UGFnZVkgPSBldi5wYWdlWTtcbiAgICAgICAgICAgIHRoaXMucHJldlNjcm9sbFggPSB3aW5kb3cuc2Nyb2xsWDtcbiAgICAgICAgICAgIHRoaXMucHJldlNjcm9sbFkgPSB3aW5kb3cuc2Nyb2xsWTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZXN0cm95U2Nyb2xsV2F0Y2goKSB7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZFdhdGNoU2Nyb2xsKSB7XG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVTY3JvbGwsIHRydWUpOyAvLyB1c2VDYXB0dXJlZD10cnVlXG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gRXZlbnQgTm9ybWFsaXphdGlvblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjcmVhdGVFdmVudEZyb21Nb3VzZShldiwgaXNGaXJzdCkge1xuICAgICAgICBsZXQgZGVsdGFYID0gMDtcbiAgICAgICAgbGV0IGRlbHRhWSA9IDA7XG4gICAgICAgIC8vIFRPRE86IHJlcGVhdCBjb2RlXG4gICAgICAgIGlmIChpc0ZpcnN0KSB7XG4gICAgICAgICAgICB0aGlzLm9yaWdQYWdlWCA9IGV2LnBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5vcmlnUGFnZVkgPSBldi5wYWdlWTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlbHRhWCA9IGV2LnBhZ2VYIC0gdGhpcy5vcmlnUGFnZVg7XG4gICAgICAgICAgICBkZWx0YVkgPSBldi5wYWdlWSAtIHRoaXMub3JpZ1BhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBvcmlnRXZlbnQ6IGV2LFxuICAgICAgICAgICAgaXNUb3VjaDogZmFsc2UsXG4gICAgICAgICAgICBzdWJqZWN0RWw6IHRoaXMuc3ViamVjdEVsLFxuICAgICAgICAgICAgcGFnZVg6IGV2LnBhZ2VYLFxuICAgICAgICAgICAgcGFnZVk6IGV2LnBhZ2VZLFxuICAgICAgICAgICAgZGVsdGFYLFxuICAgICAgICAgICAgZGVsdGFZLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBjcmVhdGVFdmVudEZyb21Ub3VjaChldiwgaXNGaXJzdCkge1xuICAgICAgICBsZXQgdG91Y2hlcyA9IGV2LnRvdWNoZXM7XG4gICAgICAgIGxldCBwYWdlWDtcbiAgICAgICAgbGV0IHBhZ2VZO1xuICAgICAgICBsZXQgZGVsdGFYID0gMDtcbiAgICAgICAgbGV0IGRlbHRhWSA9IDA7XG4gICAgICAgIC8vIGlmIHRvdWNoIGNvb3JkcyBhdmFpbGFibGUsIHByZWZlcixcbiAgICAgICAgLy8gYmVjYXVzZSBGRiB3b3VsZCBnaXZlIGJhZCBldi5wYWdlWCBldi5wYWdlWVxuICAgICAgICBpZiAodG91Y2hlcyAmJiB0b3VjaGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgcGFnZVggPSB0b3VjaGVzWzBdLnBhZ2VYO1xuICAgICAgICAgICAgcGFnZVkgPSB0b3VjaGVzWzBdLnBhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcGFnZVggPSBldi5wYWdlWDtcbiAgICAgICAgICAgIHBhZ2VZID0gZXYucGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogcmVwZWF0IGNvZGVcbiAgICAgICAgaWYgKGlzRmlyc3QpIHtcbiAgICAgICAgICAgIHRoaXMub3JpZ1BhZ2VYID0gcGFnZVg7XG4gICAgICAgICAgICB0aGlzLm9yaWdQYWdlWSA9IHBhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZGVsdGFYID0gcGFnZVggLSB0aGlzLm9yaWdQYWdlWDtcbiAgICAgICAgICAgIGRlbHRhWSA9IHBhZ2VZIC0gdGhpcy5vcmlnUGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG9yaWdFdmVudDogZXYsXG4gICAgICAgICAgICBpc1RvdWNoOiB0cnVlLFxuICAgICAgICAgICAgc3ViamVjdEVsOiB0aGlzLnN1YmplY3RFbCxcbiAgICAgICAgICAgIHBhZ2VYLFxuICAgICAgICAgICAgcGFnZVksXG4gICAgICAgICAgICBkZWx0YVgsXG4gICAgICAgICAgICBkZWx0YVksXG4gICAgICAgIH07XG4gICAgfVxufVxuLy8gUmV0dXJucyBhIGJvb2xlYW4gd2hldGhlciB0aGlzIHdhcyBhIGxlZnQgbW91c2UgY2xpY2sgYW5kIG5vIGN0cmwga2V5ICh3aGljaCBtZWFucyByaWdodCBjbGljayBvbiBNYWMpXG5mdW5jdGlvbiBpc1ByaW1hcnlNb3VzZUJ1dHRvbihldikge1xuICAgIHJldHVybiBldi5idXR0b24gPT09IDAgJiYgIWV2LmN0cmxLZXk7XG59XG4vLyBJZ25vcmluZyBmYWtlIG1vdXNlIGV2ZW50cyBnZW5lcmF0ZWQgYnkgdG91Y2hcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIHN0YXJ0SWdub3JpbmdNb3VzZSgpIHtcbiAgICBpZ25vcmVNb3VzZURlcHRoICs9IDE7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGlnbm9yZU1vdXNlRGVwdGggLT0gMTtcbiAgICB9LCBjb25maWcudG91Y2hNb3VzZUlnbm9yZVdhaXQpO1xufVxuLy8gV2Ugd2FudCB0byBhdHRhY2ggdG91Y2htb3ZlIGFzIGVhcmx5IGFzIHBvc3NpYmxlIGZvciBTYWZhcmlcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGxpc3RlbmVyQ3JlYXRlZCgpIHtcbiAgICBsaXN0ZW5lckNudCArPSAxO1xuICAgIGlmIChsaXN0ZW5lckNudCA9PT0gMSkge1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb25XaW5kb3dUb3VjaE1vdmUsIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gbGlzdGVuZXJEZXN0cm95ZWQoKSB7XG4gICAgbGlzdGVuZXJDbnQgLT0gMTtcbiAgICBpZiAoIWxpc3RlbmVyQ250KSB7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBvbldpbmRvd1RvdWNoTW92ZSwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICB9XG59XG5mdW5jdGlvbiBvbldpbmRvd1RvdWNoTW92ZShldikge1xuICAgIGlmIChpc1dpbmRvd1RvdWNoTW92ZUNhbmNlbGxlZCkge1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cblxuLypcbkFuIGVmZmVjdCBpbiB3aGljaCBhbiBlbGVtZW50IGZvbGxvd3MgdGhlIG1vdmVtZW50IG9mIGEgcG9pbnRlciBhY3Jvc3MgdGhlIHNjcmVlbi5cblRoZSBtb3ZpbmcgZWxlbWVudCBpcyBhIGNsb25lIG9mIHNvbWUgb3RoZXIgZWxlbWVudC5cbk11c3QgY2FsbCBzdGFydCArIGhhbmRsZU1vdmUgKyBzdG9wLlxuKi9cbmNsYXNzIEVsZW1lbnRNaXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlOyAvLyBtdXN0IGJlIGV4cGxpY2l0bHkgZW5hYmxlZFxuICAgICAgICB0aGlzLnNvdXJjZUVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5taXJyb3JFbCA9IG51bGw7XG4gICAgICAgIHRoaXMuc291cmNlRWxSZWN0ID0gbnVsbDsgLy8gc2NyZWVuIGNvb3JkcyByZWxhdGl2ZSB0byB2aWV3cG9ydFxuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIHNldCBkaXJlY3RseSBieSBjYWxsZXJcbiAgICAgICAgdGhpcy5wYXJlbnROb2RlID0gZG9jdW1lbnQuYm9keTsgLy8gSElHSExZIFNVR0dFU1RFRCB0byBzZXQgdGhpcyB0byBzaWRlc3RlcCBTaGFkb3dET00gaXNzdWVzXG4gICAgICAgIHRoaXMuekluZGV4ID0gOTk5OTtcbiAgICAgICAgdGhpcy5yZXZlcnREdXJhdGlvbiA9IDA7XG4gICAgfVxuICAgIHN0YXJ0KHNvdXJjZUVsLCBwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgdGhpcy5zb3VyY2VFbCA9IHNvdXJjZUVsO1xuICAgICAgICB0aGlzLnNvdXJjZUVsUmVjdCA9IHRoaXMuc291cmNlRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHRoaXMub3JpZ1NjcmVlblggPSBwYWdlWCAtIHdpbmRvdy5zY3JvbGxYO1xuICAgICAgICB0aGlzLm9yaWdTY3JlZW5ZID0gcGFnZVkgLSB3aW5kb3cuc2Nyb2xsWTtcbiAgICAgICAgdGhpcy5kZWx0YVggPSAwO1xuICAgICAgICB0aGlzLmRlbHRhWSA9IDA7XG4gICAgICAgIHRoaXMudXBkYXRlRWxQb3NpdGlvbigpO1xuICAgIH1cbiAgICBoYW5kbGVNb3ZlKHBhZ2VYLCBwYWdlWSkge1xuICAgICAgICB0aGlzLmRlbHRhWCA9IChwYWdlWCAtIHdpbmRvdy5zY3JvbGxYKSAtIHRoaXMub3JpZ1NjcmVlblg7XG4gICAgICAgIHRoaXMuZGVsdGFZID0gKHBhZ2VZIC0gd2luZG93LnNjcm9sbFkpIC0gdGhpcy5vcmlnU2NyZWVuWTtcbiAgICAgICAgdGhpcy51cGRhdGVFbFBvc2l0aW9uKCk7XG4gICAgfVxuICAgIC8vIGNhbiBiZSBjYWxsZWQgYmVmb3JlIHN0YXJ0XG4gICAgc2V0SXNWaXNpYmxlKGJvb2wpIHtcbiAgICAgICAgaWYgKGJvb2wpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5taXJyb3JFbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pcnJvckVsLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5pc1Zpc2libGUgPSBib29sOyAvLyBuZWVkcyB0byBoYXBwZW4gYmVmb3JlIHVwZGF0ZUVsUG9zaXRpb25cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVsUG9zaXRpb24oKTsgLy8gYmVjYXVzZSB3YXMgbm90IHVwZGF0aW5nIHRoZSBwb3NpdGlvbiB3aGlsZSBpbnZpc2libGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMubWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvckVsLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGJvb2w7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gYWx3YXlzIGFzeW5jXG4gICAgc3RvcChuZWVkc1JldmVydEFuaW1hdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgbGV0IGRvbmUgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsZWFudXAoKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH07XG4gICAgICAgIGlmIChuZWVkc1JldmVydEFuaW1hdGlvbiAmJlxuICAgICAgICAgICAgdGhpcy5taXJyb3JFbCAmJlxuICAgICAgICAgICAgdGhpcy5pc1Zpc2libGUgJiZcbiAgICAgICAgICAgIHRoaXMucmV2ZXJ0RHVyYXRpb24gJiYgLy8gaWYgMCwgdHJhbnNpdGlvbiB3b24ndCB3b3JrXG4gICAgICAgICAgICAodGhpcy5kZWx0YVggfHwgdGhpcy5kZWx0YVkpIC8vIGlmIHNhbWUgY29vcmRzLCB0cmFuc2l0aW9uIHdvbid0IHdvcmtcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmRvUmV2ZXJ0QW5pbWF0aW9uKGRvbmUsIHRoaXMucmV2ZXJ0RHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2V0VGltZW91dChkb25lLCAwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkb1JldmVydEFuaW1hdGlvbihjYWxsYmFjaywgcmV2ZXJ0RHVyYXRpb24pIHtcbiAgICAgICAgbGV0IG1pcnJvckVsID0gdGhpcy5taXJyb3JFbDtcbiAgICAgICAgbGV0IGZpbmFsU291cmNlRWxSZWN0ID0gdGhpcy5zb3VyY2VFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgLy8gYmVjYXVzZSBhdXRvc2Nyb2xsaW5nIG1pZ2h0IGhhdmUgaGFwcGVuZWRcbiAgICAgICAgbWlycm9yRWwuc3R5bGUudHJhbnNpdGlvbiA9XG4gICAgICAgICAgICAndG9wICcgKyByZXZlcnREdXJhdGlvbiArICdtcywnICtcbiAgICAgICAgICAgICAgICAnbGVmdCAnICsgcmV2ZXJ0RHVyYXRpb24gKyAnbXMnO1xuICAgICAgICBhcHBseVN0eWxlKG1pcnJvckVsLCB7XG4gICAgICAgICAgICBsZWZ0OiBmaW5hbFNvdXJjZUVsUmVjdC5sZWZ0LFxuICAgICAgICAgICAgdG9wOiBmaW5hbFNvdXJjZUVsUmVjdC50b3AsXG4gICAgICAgIH0pO1xuICAgICAgICB3aGVuVHJhbnNpdGlvbkRvbmUobWlycm9yRWwsICgpID0+IHtcbiAgICAgICAgICAgIG1pcnJvckVsLnN0eWxlLnRyYW5zaXRpb24gPSAnJztcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjbGVhbnVwKCkge1xuICAgICAgICBpZiAodGhpcy5taXJyb3JFbCkge1xuICAgICAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLm1pcnJvckVsKTtcbiAgICAgICAgICAgIHRoaXMubWlycm9yRWwgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc291cmNlRWwgPSBudWxsO1xuICAgIH1cbiAgICB1cGRhdGVFbFBvc2l0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VFbCAmJiB0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmdldE1pcnJvckVsKCksIHtcbiAgICAgICAgICAgICAgICBsZWZ0OiB0aGlzLnNvdXJjZUVsUmVjdC5sZWZ0ICsgdGhpcy5kZWx0YVgsXG4gICAgICAgICAgICAgICAgdG9wOiB0aGlzLnNvdXJjZUVsUmVjdC50b3AgKyB0aGlzLmRlbHRhWSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldE1pcnJvckVsKCkge1xuICAgICAgICBsZXQgc291cmNlRWxSZWN0ID0gdGhpcy5zb3VyY2VFbFJlY3Q7XG4gICAgICAgIGxldCBtaXJyb3JFbCA9IHRoaXMubWlycm9yRWw7XG4gICAgICAgIGlmICghbWlycm9yRWwpIHtcbiAgICAgICAgICAgIG1pcnJvckVsID0gdGhpcy5taXJyb3JFbCA9IHRoaXMuc291cmNlRWwuY2xvbmVOb2RlKHRydWUpOyAvLyBjbG9uZUNoaWxkcmVuPXRydWVcbiAgICAgICAgICAgIC8vIHdlIGRvbid0IHdhbnQgbG9uZyB0YXBzIG9yIGFueSBtb3VzZSBpbnRlcmFjdGlvbiBjYXVzaW5nIHNlbGVjdGlvbi9tZW51cy5cbiAgICAgICAgICAgIC8vIHdvdWxkIHVzZSBwcmV2ZW50U2VsZWN0aW9uKCksIGJ1dCB0aGF0IHByZXZlbnRzIHNlbGVjdHN0YXJ0LCBjYXVzaW5nIHByb2JsZW1zLlxuICAgICAgICAgICAgbWlycm9yRWwuc3R5bGUudXNlclNlbGVjdCA9ICdub25lJztcbiAgICAgICAgICAgIG1pcnJvckVsLnN0eWxlLndlYmtpdFVzZXJTZWxlY3QgPSAnbm9uZSc7XG4gICAgICAgICAgICBtaXJyb3JFbC5zdHlsZS5wb2ludGVyRXZlbnRzID0gJ25vbmUnO1xuICAgICAgICAgICAgbWlycm9yRWwuY2xhc3NMaXN0LmFkZCgnZmMtZXZlbnQtZHJhZ2dpbmcnKTtcbiAgICAgICAgICAgIGFwcGx5U3R5bGUobWlycm9yRWwsIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogJ2ZpeGVkJyxcbiAgICAgICAgICAgICAgICB6SW5kZXg6IHRoaXMuekluZGV4LFxuICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6ICcnLFxuICAgICAgICAgICAgICAgIGJveFNpemluZzogJ2JvcmRlci1ib3gnLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBzb3VyY2VFbFJlY3QucmlnaHQgLSBzb3VyY2VFbFJlY3QubGVmdCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHNvdXJjZUVsUmVjdC5ib3R0b20gLSBzb3VyY2VFbFJlY3QudG9wLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiAnYXV0bycsXG4gICAgICAgICAgICAgICAgYm90dG9tOiAnYXV0bycsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiAwLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobWlycm9yRWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtaXJyb3JFbDtcbiAgICB9XG59XG5cbi8qXG5JcyBhIGNhY2hlIGZvciBhIGdpdmVuIGVsZW1lbnQncyBzY3JvbGwgaW5mb3JtYXRpb24gKGFsbCB0aGUgaW5mbyB0aGF0IFNjcm9sbENvbnRyb2xsZXIgc3RvcmVzKVxuaW4gYWRkaXRpb24gdGhlIFwiY2xpZW50IHJlY3RhbmdsZVwiIG9mIHRoZSBlbGVtZW50Li4gdGhlIGFyZWEgd2l0aGluIHRoZSBzY3JvbGxiYXJzLlxuXG5UaGUgY2FjaGUgY2FuIGJlIGluIG9uZSBvZiB0d28gbW9kZXM6XG4tIGRvZXNMaXN0ZW5pbmc6ZmFsc2UgLSBpZ25vcmVzIHdoZW4gdGhlIGNvbnRhaW5lciBpcyBzY3JvbGxlZCBieSBzb21lb25lIGVsc2Vcbi0gZG9lc0xpc3RlbmluZzp0cnVlIC0gd2F0Y2ggZm9yIHNjcm9sbGluZyBhbmQgdXBkYXRlIHRoZSBjYWNoZVxuKi9cbmNsYXNzIFNjcm9sbEdlb21DYWNoZSBleHRlbmRzIFNjcm9sbENvbnRyb2xsZXIge1xuICAgIGNvbnN0cnVjdG9yKHNjcm9sbENvbnRyb2xsZXIsIGRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGwgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsQ29udHJvbGxlci5nZXRTY3JvbGxUb3AoKTtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsTGVmdCA9IHRoaXMuc2Nyb2xsQ29udHJvbGxlci5nZXRTY3JvbGxMZWZ0KCk7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVNjcm9sbENoYW5nZSgpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNjcm9sbENvbnRyb2xsZXIgPSBzY3JvbGxDb250cm9sbGVyO1xuICAgICAgICB0aGlzLmRvZXNMaXN0ZW5pbmcgPSBkb2VzTGlzdGVuaW5nO1xuICAgICAgICB0aGlzLnNjcm9sbFRvcCA9IHRoaXMub3JpZ1Njcm9sbFRvcCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsVG9wKCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsTGVmdCA9IHRoaXMub3JpZ1Njcm9sbExlZnQgPSBzY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbExlZnQoKTtcbiAgICAgICAgdGhpcy5zY3JvbGxXaWR0aCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsV2lkdGgoKTtcbiAgICAgICAgdGhpcy5zY3JvbGxIZWlnaHQgPSBzY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbEhlaWdodCgpO1xuICAgICAgICB0aGlzLmNsaWVudFdpZHRoID0gc2Nyb2xsQ29udHJvbGxlci5nZXRDbGllbnRXaWR0aCgpO1xuICAgICAgICB0aGlzLmNsaWVudEhlaWdodCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0Q2xpZW50SGVpZ2h0KCk7XG4gICAgICAgIHRoaXMuY2xpZW50UmVjdCA9IHRoaXMuY29tcHV0ZUNsaWVudFJlY3QoKTsgLy8gZG8gbGFzdCBpbiBjYXNlIGl0IG5lZWRzIGNhY2hlZCB2YWx1ZXNcbiAgICAgICAgaWYgKHRoaXMuZG9lc0xpc3RlbmluZykge1xuICAgICAgICAgICAgdGhpcy5nZXRFdmVudFRhcmdldCgpLmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5kb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmdldEV2ZW50VGFyZ2V0KCkucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVTY3JvbGwpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldFNjcm9sbFRvcCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsVG9wO1xuICAgIH1cbiAgICBnZXRTY3JvbGxMZWZ0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxMZWZ0O1xuICAgIH1cbiAgICBzZXRTY3JvbGxUb3AodG9wKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udHJvbGxlci5zZXRTY3JvbGxUb3AodG9wKTtcbiAgICAgICAgaWYgKCF0aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSBub3QgcmVseWluZyBvbiB0aGUgZWxlbWVudCB0byBub3JtYWxpemUgb3V0LW9mLWJvdW5kcyBzY3JvbGwgdmFsdWVzXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIHNhbml0aXplIG91cnNlbHZlc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxUb3AgPSBNYXRoLm1heChNYXRoLm1pbih0b3AsIHRoaXMuZ2V0TWF4U2Nyb2xsVG9wKCkpLCAwKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0U2Nyb2xsTGVmdCh0b3ApIHtcbiAgICAgICAgdGhpcy5zY3JvbGxDb250cm9sbGVyLnNldFNjcm9sbExlZnQodG9wKTtcbiAgICAgICAgaWYgKCF0aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSBub3QgcmVseWluZyBvbiB0aGUgZWxlbWVudCB0byBub3JtYWxpemUgb3V0LW9mLWJvdW5kcyBzY3JvbGwgdmFsdWVzXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIHNhbml0aXplIG91cnNlbHZlc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxMZWZ0ID0gTWF0aC5tYXgoTWF0aC5taW4odG9wLCB0aGlzLmdldE1heFNjcm9sbExlZnQoKSksIDApO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGxDaGFuZ2UoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRDbGllbnRXaWR0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50V2lkdGg7XG4gICAgfVxuICAgIGdldENsaWVudEhlaWdodCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50SGVpZ2h0O1xuICAgIH1cbiAgICBnZXRTY3JvbGxXaWR0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsV2lkdGg7XG4gICAgfVxuICAgIGdldFNjcm9sbEhlaWdodCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsSGVpZ2h0O1xuICAgIH1cbiAgICBoYW5kbGVTY3JvbGxDaGFuZ2UoKSB7XG4gICAgfVxufVxuXG5jbGFzcyBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlIGV4dGVuZHMgU2Nyb2xsR2VvbUNhY2hlIHtcbiAgICBjb25zdHJ1Y3RvcihlbCwgZG9lc0xpc3RlbmluZykge1xuICAgICAgICBzdXBlcihuZXcgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIoZWwpLCBkb2VzTGlzdGVuaW5nKTtcbiAgICB9XG4gICAgZ2V0RXZlbnRUYXJnZXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbENvbnRyb2xsZXIuZWw7XG4gICAgfVxuICAgIGNvbXB1dGVDbGllbnRSZWN0KCkge1xuICAgICAgICByZXR1cm4gY29tcHV0ZUlubmVyUmVjdCh0aGlzLnNjcm9sbENvbnRyb2xsZXIuZWwpO1xuICAgIH1cbn1cblxuY2xhc3MgV2luZG93U2Nyb2xsR2VvbUNhY2hlIGV4dGVuZHMgU2Nyb2xsR2VvbUNhY2hlIHtcbiAgICBjb25zdHJ1Y3Rvcihkb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgIHN1cGVyKG5ldyBXaW5kb3dTY3JvbGxDb250cm9sbGVyKCksIGRvZXNMaXN0ZW5pbmcpO1xuICAgIH1cbiAgICBnZXRFdmVudFRhcmdldCgpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdztcbiAgICB9XG4gICAgY29tcHV0ZUNsaWVudFJlY3QoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsZWZ0OiB0aGlzLnNjcm9sbExlZnQsXG4gICAgICAgICAgICByaWdodDogdGhpcy5zY3JvbGxMZWZ0ICsgdGhpcy5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgIHRvcDogdGhpcy5zY3JvbGxUb3AsXG4gICAgICAgICAgICBib3R0b206IHRoaXMuc2Nyb2xsVG9wICsgdGhpcy5jbGllbnRIZWlnaHQsXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8vIHRoZSB3aW5kb3cgaXMgdGhlIG9ubHkgc2Nyb2xsIG9iamVjdCB0aGF0IGNoYW5nZXMgaXQncyByZWN0YW5nbGUgcmVsYXRpdmVcbiAgICAvLyB0byB0aGUgZG9jdW1lbnQncyB0b3BsZWZ0IGFzIGl0IHNjcm9sbHNcbiAgICBoYW5kbGVTY3JvbGxDaGFuZ2UoKSB7XG4gICAgICAgIHRoaXMuY2xpZW50UmVjdCA9IHRoaXMuY29tcHV0ZUNsaWVudFJlY3QoKTtcbiAgICB9XG59XG5cbi8vIElmIGF2YWlsYWJsZSB3ZSBhcmUgdXNpbmcgbmF0aXZlIFwicGVyZm9ybWFuY2VcIiBBUEkgaW5zdGVhZCBvZiBcIkRhdGVcIlxuLy8gUmVhZCBtb3JlIGFib3V0IGl0IG9uIE1ETjpcbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9QZXJmb3JtYW5jZVxuY29uc3QgZ2V0VGltZSA9IHR5cGVvZiBwZXJmb3JtYW5jZSA9PT0gJ2Z1bmN0aW9uJyA/IHBlcmZvcm1hbmNlLm5vdyA6IERhdGUubm93O1xuLypcbkZvciBhIHBvaW50ZXIgaW50ZXJhY3Rpb24sIGF1dG9tYXRpY2FsbHkgc2Nyb2xscyBjZXJ0YWluIHNjcm9sbCBjb250YWluZXJzIHdoZW4gdGhlIHBvaW50ZXJcbmFwcHJvYWNoZXMgdGhlIGVkZ2UuXG5cblRoZSBjYWxsZXIgbXVzdCBjYWxsIHN0YXJ0ICsgaGFuZGxlTW92ZSArIHN0b3AuXG4qL1xuY2xhc3MgQXV0b1Njcm9sbGVyIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgLy8gb3B0aW9ucyB0aGF0IGNhbiBiZSBzZXQgYnkgY2FsbGVyXG4gICAgICAgIHRoaXMuaXNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zY3JvbGxRdWVyeSA9IFt3aW5kb3csICcuZmMtc2Nyb2xsZXInXTtcbiAgICAgICAgdGhpcy5lZGdlVGhyZXNob2xkID0gNTA7IC8vIHBpeGVsc1xuICAgICAgICB0aGlzLm1heFZlbG9jaXR5ID0gMzAwOyAvLyBwaXhlbHMgcGVyIHNlY29uZFxuICAgICAgICAvLyBpbnRlcm5hbCBzdGF0ZVxuICAgICAgICB0aGlzLnBvaW50ZXJTY3JlZW5YID0gbnVsbDtcbiAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWSA9IG51bGw7XG4gICAgICAgIHRoaXMuaXNBbmltYXRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSBudWxsO1xuICAgICAgICAvLyBwcm90ZWN0IGFnYWluc3QgdGhlIGluaXRpYWwgcG9pbnRlcmRvd24gYmVpbmcgdG9vIGNsb3NlIHRvIGFuIGVkZ2UgYW5kIHN0YXJ0aW5nIHRoZSBzY3JvbGxcbiAgICAgICAgdGhpcy5ldmVyTW92ZWRVcCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmV2ZXJNb3ZlZERvd24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVyTW92ZWRMZWZ0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlck1vdmVkUmlnaHQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hbmltYXRlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNBbmltYXRpbmcpIHsgLy8gd2Fzbid0IGNhbmNlbGxlZCBiZXR3ZWVuIGFuaW1hdGlvbiBjYWxsc1xuICAgICAgICAgICAgICAgIGxldCBlZGdlID0gdGhpcy5jb21wdXRlQmVzdEVkZ2UodGhpcy5wb2ludGVyU2NyZWVuWCArIHdpbmRvdy5zY3JvbGxYLCB0aGlzLnBvaW50ZXJTY3JlZW5ZICsgd2luZG93LnNjcm9sbFkpO1xuICAgICAgICAgICAgICAgIGlmIChlZGdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBub3cgPSBnZXRUaW1lKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlU2lkZShlZGdlLCAobm93IC0gdGhpcy5tc1NpbmNlUmVxdWVzdCkgLyAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0QW5pbWF0aW9uKG5vdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7IC8vIHdpbGwgc3RvcCBhbmltYXRpb25cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIHN0YXJ0KHBhZ2VYLCBwYWdlWSwgc2Nyb2xsU3RhcnRFbCkge1xuICAgICAgICBpZiAodGhpcy5pc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ2FjaGVzID0gdGhpcy5idWlsZENhY2hlcyhzY3JvbGxTdGFydEVsKTtcbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblggPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFVwID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZERvd24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZXZlck1vdmVkTGVmdCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRSaWdodCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVNb3ZlKHBhZ2VYLCBwYWdlWSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaGFuZGxlTW92ZShwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICBsZXQgcG9pbnRlclNjcmVlblggPSBwYWdlWCAtIHdpbmRvdy5zY3JvbGxYO1xuICAgICAgICAgICAgbGV0IHBvaW50ZXJTY3JlZW5ZID0gcGFnZVkgLSB3aW5kb3cuc2Nyb2xsWTtcbiAgICAgICAgICAgIGxldCB5RGVsdGEgPSB0aGlzLnBvaW50ZXJTY3JlZW5ZID09PSBudWxsID8gMCA6IHBvaW50ZXJTY3JlZW5ZIC0gdGhpcy5wb2ludGVyU2NyZWVuWTtcbiAgICAgICAgICAgIGxldCB4RGVsdGEgPSB0aGlzLnBvaW50ZXJTY3JlZW5YID09PSBudWxsID8gMCA6IHBvaW50ZXJTY3JlZW5YIC0gdGhpcy5wb2ludGVyU2NyZWVuWDtcbiAgICAgICAgICAgIGlmICh5RGVsdGEgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh5RGVsdGEgPiAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWREb3duID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh4RGVsdGEgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRMZWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHhEZWx0YSA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFJpZ2h0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblggPSBwb2ludGVyU2NyZWVuWDtcbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblkgPSBwb2ludGVyU2NyZWVuWTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0FuaW1hdGluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNBbmltYXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEFuaW1hdGlvbihnZXRUaW1lKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHN0b3AoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5pc0FuaW1hdGluZyA9IGZhbHNlOyAvLyB3aWxsIHN0b3AgYW5pbWF0aW9uXG4gICAgICAgICAgICBmb3IgKGxldCBzY3JvbGxDYWNoZSBvZiB0aGlzLnNjcm9sbENhY2hlcykge1xuICAgICAgICAgICAgICAgIHNjcm9sbENhY2hlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ2FjaGVzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXF1ZXN0QW5pbWF0aW9uKG5vdykge1xuICAgICAgICB0aGlzLm1zU2luY2VSZXF1ZXN0ID0gbm93O1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRlKTtcbiAgICB9XG4gICAgaGFuZGxlU2lkZShlZGdlLCBzZWNvbmRzKSB7XG4gICAgICAgIGxldCB7IHNjcm9sbENhY2hlIH0gPSBlZGdlO1xuICAgICAgICBsZXQgeyBlZGdlVGhyZXNob2xkIH0gPSB0aGlzO1xuICAgICAgICBsZXQgaW52RGlzdGFuY2UgPSBlZGdlVGhyZXNob2xkIC0gZWRnZS5kaXN0YW5jZTtcbiAgICAgICAgbGV0IHZlbG9jaXR5ID0gLy8gdGhlIGNsb3NlciB0byB0aGUgZWRnZSwgdGhlIGZhc3RlciB3ZSBzY3JvbGxcbiAgICAgICAgICgoaW52RGlzdGFuY2UgKiBpbnZEaXN0YW5jZSkgLyAoZWRnZVRocmVzaG9sZCAqIGVkZ2VUaHJlc2hvbGQpKSAqIC8vIHF1YWRyYXRpY1xuICAgICAgICAgICAgdGhpcy5tYXhWZWxvY2l0eSAqIHNlY29uZHM7XG4gICAgICAgIGxldCBzaWduID0gMTtcbiAgICAgICAgc3dpdGNoIChlZGdlLm5hbWUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICAgICAgICAgIHNpZ24gPSAtMTtcbiAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgICAgICAgICBzY3JvbGxDYWNoZS5zZXRTY3JvbGxMZWZ0KHNjcm9sbENhY2hlLmdldFNjcm9sbExlZnQoKSArIHZlbG9jaXR5ICogc2lnbik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgICAgICAgIHNpZ24gPSAtMTtcbiAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuc2V0U2Nyb2xsVG9wKHNjcm9sbENhY2hlLmdldFNjcm9sbFRvcCgpICsgdmVsb2NpdHkgKiBzaWduKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBsZWZ0L3RvcCBhcmUgcmVsYXRpdmUgdG8gZG9jdW1lbnQgdG9wbGVmdFxuICAgIGNvbXB1dGVCZXN0RWRnZShsZWZ0LCB0b3ApIHtcbiAgICAgICAgbGV0IHsgZWRnZVRocmVzaG9sZCB9ID0gdGhpcztcbiAgICAgICAgbGV0IGJlc3RTaWRlID0gbnVsbDtcbiAgICAgICAgbGV0IHNjcm9sbENhY2hlcyA9IHRoaXMuc2Nyb2xsQ2FjaGVzIHx8IFtdO1xuICAgICAgICBmb3IgKGxldCBzY3JvbGxDYWNoZSBvZiBzY3JvbGxDYWNoZXMpIHtcbiAgICAgICAgICAgIGxldCByZWN0ID0gc2Nyb2xsQ2FjaGUuY2xpZW50UmVjdDtcbiAgICAgICAgICAgIGxldCBsZWZ0RGlzdCA9IGxlZnQgLSByZWN0LmxlZnQ7XG4gICAgICAgICAgICBsZXQgcmlnaHREaXN0ID0gcmVjdC5yaWdodCAtIGxlZnQ7XG4gICAgICAgICAgICBsZXQgdG9wRGlzdCA9IHRvcCAtIHJlY3QudG9wO1xuICAgICAgICAgICAgbGV0IGJvdHRvbURpc3QgPSByZWN0LmJvdHRvbSAtIHRvcDtcbiAgICAgICAgICAgIC8vIGNvbXBsZXRlbHkgd2l0aGluIHRoZSByZWN0P1xuICAgICAgICAgICAgaWYgKGxlZnREaXN0ID49IDAgJiYgcmlnaHREaXN0ID49IDAgJiYgdG9wRGlzdCA+PSAwICYmIGJvdHRvbURpc3QgPj0gMCkge1xuICAgICAgICAgICAgICAgIGlmICh0b3BEaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRVcCAmJiBzY3JvbGxDYWNoZS5jYW5TY3JvbGxVcCgpICYmXG4gICAgICAgICAgICAgICAgICAgICghYmVzdFNpZGUgfHwgYmVzdFNpZGUuZGlzdGFuY2UgPiB0b3BEaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGUsIG5hbWU6ICd0b3AnLCBkaXN0YW5jZTogdG9wRGlzdCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYm90dG9tRGlzdCA8PSBlZGdlVGhyZXNob2xkICYmIHRoaXMuZXZlck1vdmVkRG93biAmJiBzY3JvbGxDYWNoZS5jYW5TY3JvbGxEb3duKCkgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFiZXN0U2lkZSB8fCBiZXN0U2lkZS5kaXN0YW5jZSA+IGJvdHRvbURpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RTaWRlID0geyBzY3JvbGxDYWNoZSwgbmFtZTogJ2JvdHRvbScsIGRpc3RhbmNlOiBib3R0b21EaXN0IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgVE9ETzogZml4IGJyb2tlbiBSVEwgc2Nyb2xsaW5nLiBjYW5TY3JvbGxMZWZ0IGFsd2F5cyByZXR1cm5pbmcgZmFsc2VcbiAgICAgICAgICAgICAgICBodHRwczovL2dpdGh1Yi5jb20vZnVsbGNhbGVuZGFyL2Z1bGxjYWxlbmRhci9pc3N1ZXMvNDgzN1xuICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgaWYgKGxlZnREaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRMZWZ0ICYmIHNjcm9sbENhY2hlLmNhblNjcm9sbExlZnQoKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIWJlc3RTaWRlIHx8IGJlc3RTaWRlLmRpc3RhbmNlID4gbGVmdERpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RTaWRlID0geyBzY3JvbGxDYWNoZSwgbmFtZTogJ2xlZnQnLCBkaXN0YW5jZTogbGVmdERpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJpZ2h0RGlzdCA8PSBlZGdlVGhyZXNob2xkICYmIHRoaXMuZXZlck1vdmVkUmlnaHQgJiYgc2Nyb2xsQ2FjaGUuY2FuU2Nyb2xsUmlnaHQoKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIWJlc3RTaWRlIHx8IGJlc3RTaWRlLmRpc3RhbmNlID4gcmlnaHREaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGUsIG5hbWU6ICdyaWdodCcsIGRpc3RhbmNlOiByaWdodERpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJlc3RTaWRlO1xuICAgIH1cbiAgICBidWlsZENhY2hlcyhzY3JvbGxTdGFydEVsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnF1ZXJ5U2Nyb2xsRWxzKHNjcm9sbFN0YXJ0RWwpLm1hcCgoZWwpID0+IHtcbiAgICAgICAgICAgIGlmIChlbCA9PT0gd2luZG93KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUoZmFsc2UpOyAvLyBmYWxzZSA9IGRvbid0IGxpc3RlbiB0byB1c2VyLWdlbmVyYXRlZCBzY3JvbGxzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUoZWwsIGZhbHNlKTsgLy8gZmFsc2UgPSBkb24ndCBsaXN0ZW4gdG8gdXNlci1nZW5lcmF0ZWQgc2Nyb2xsc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcXVlcnlTY3JvbGxFbHMoc2Nyb2xsU3RhcnRFbCkge1xuICAgICAgICBsZXQgZWxzID0gW107XG4gICAgICAgIGZvciAobGV0IHF1ZXJ5IG9mIHRoaXMuc2Nyb2xsUXVlcnkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcXVlcnkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgZWxzLnB1c2gocXVlcnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICBUT0RPOiBpbiB0aGUgZnV0dXJlLCBhbHdheXMgaGF2ZSBhdXRvLXNjcm9sbCBoYXBwZW4gb24gZWxlbWVudCB3aGVyZSBjdXJyZW50IEhpdCBjYW1lIGZyb21cbiAgICAgICAgICAgICAgICBUaWNrZXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9mdWxsY2FsZW5kYXIvZnVsbGNhbGVuZGFyL2lzc3Vlcy80NTkzXG4gICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBlbHMucHVzaCguLi5BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChzY3JvbGxTdGFydEVsLmdldFJvb3ROb2RlKCkucXVlcnlTZWxlY3RvckFsbChxdWVyeSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxzO1xuICAgIH1cbn1cblxuLypcbk1vbml0b3JzIGRyYWdnaW5nIG9uIGFuIGVsZW1lbnQuIEhhcyBhIG51bWJlciBvZiBoaWdoLWxldmVsIGZlYXR1cmVzOlxuLSBtaW5pbXVtIGRpc3RhbmNlIHJlcXVpcmVkIGJlZm9yZSBkcmFnZ2luZ1xuLSBtaW5pbXVtIHdhaXQgdGltZSAoXCJkZWxheVwiKSBiZWZvcmUgZHJhZ2dpbmdcbi0gYSBtaXJyb3IgZWxlbWVudCB0aGF0IGZvbGxvd3MgdGhlIHBvaW50ZXJcbiovXG5jbGFzcyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nIGV4dGVuZHMgRWxlbWVudERyYWdnaW5nIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250YWluZXJFbCwgc2VsZWN0b3IpIHtcbiAgICAgICAgc3VwZXIoY29udGFpbmVyRWwpO1xuICAgICAgICB0aGlzLmNvbnRhaW5lckVsID0gY29udGFpbmVyRWw7XG4gICAgICAgIC8vIG9wdGlvbnMgdGhhdCBjYW4gYmUgZGlyZWN0bHkgc2V0IGJ5IGNhbGxlclxuICAgICAgICAvLyB0aGUgY2FsbGVyIGNhbiBhbHNvIHNldCB0aGUgUG9pbnRlckRyYWdnaW5nJ3Mgb3B0aW9ucyBhcyB3ZWxsXG4gICAgICAgIHRoaXMuZGVsYXkgPSBudWxsO1xuICAgICAgICB0aGlzLm1pbkRpc3RhbmNlID0gMDtcbiAgICAgICAgdGhpcy50b3VjaFNjcm9sbEFsbG93ZWQgPSB0cnVlOyAvLyBwcmV2ZW50cyBkcmFnIGZyb20gc3RhcnRpbmcgYW5kIGJsb2NrcyBzY3JvbGxpbmcgZHVyaW5nIGRyYWdcbiAgICAgICAgdGhpcy5taXJyb3JOZWVkc1JldmVydCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzSW50ZXJhY3RpbmcgPSBmYWxzZTsgLy8gaXMgdGhlIHVzZXIgdmFsaWRseSBtb3ZpbmcgdGhlIHBvaW50ZXI/IGxhc3RzIHVudGlsIHBvaW50ZXJ1cFxuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTsgLy8gaXMgaXQgSU5URU5URlVMTFkgZHJhZ2dpbmc/IGxhc3RzIHVudGlsIGFmdGVyIHJldmVydCBhbmltYXRpb25cbiAgICAgICAgdGhpcy5pc0RlbGF5RW5kZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0Rpc3RhbmNlU3VycGFzc2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZGVsYXlUaW1lb3V0SWQgPSBudWxsO1xuICAgICAgICB0aGlzLm9uUG9pbnRlckRvd24gPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0RyYWdnaW5nKSB7IC8vIHNvIG5ldyBkcmFnIGRvZXNuJ3QgaGFwcGVuIHdoaWxlIHJldmVydCBhbmltYXRpb24gaXMgZ29pbmdcbiAgICAgICAgICAgICAgICB0aGlzLmlzSW50ZXJhY3RpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuaXNEZWxheUVuZGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0Rpc3RhbmNlU3VycGFzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcHJldmVudFNlbGVjdGlvbihkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgICAgICAgICBwcmV2ZW50Q29udGV4dE1lbnUoZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgLy8gcHJldmVudCBsaW5rcyBmcm9tIGJlaW5nIHZpc2l0ZWQgaWYgdGhlcmUncyBhbiBldmVudHVhbCBkcmFnLlxuICAgICAgICAgICAgICAgIC8vIGFsc28gcHJldmVudHMgc2VsZWN0aW9uIGluIG9sZGVyIGJyb3dzZXJzIChtYXliZT8pLlxuICAgICAgICAgICAgICAgIC8vIG5vdCBuZWNlc3NhcnkgZm9yIHRvdWNoLCBiZXNpZGVzLCBicm93c2VyIHdvdWxkIGNvbXBsYWluIGFib3V0IHBhc3NpdmVuZXNzLlxuICAgICAgICAgICAgICAgIGlmICghZXYuaXNUb3VjaCkge1xuICAgICAgICAgICAgICAgICAgICBldi5vcmlnRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgZXYpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzSW50ZXJhY3RpbmcgJiYgLy8gbm90IGRlc3Ryb3llZCB2aWEgcG9pbnRlcmRvd24gaGFuZGxlclxuICAgICAgICAgICAgICAgICAgICAhdGhpcy5wb2ludGVyLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYWN0aW9ucyByZWxhdGVkIHRvIGluaXRpYXRpbmcgZHJhZ3N0YXJ0K2RyYWdtb3ZlK2RyYWdlbmQuLi5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5taXJyb3Iuc2V0SXNWaXNpYmxlKGZhbHNlKTsgLy8gcmVzZXQuIGNhbGxlciBtdXN0IHNldC12aXNpYmxlXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWlycm9yLnN0YXJ0KGV2LnN1YmplY3RFbCwgZXYucGFnZVgsIGV2LnBhZ2VZKTsgLy8gbXVzdCBoYXBwZW4gb24gZmlyc3QgcG9pbnRlciBkb3duXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhcnREZWxheShldik7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5taW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVEaXN0YW5jZVN1cnBhc3NlZChldik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMub25Qb2ludGVyTW92ZSA9IChldikgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNJbnRlcmFjdGluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIGV2KTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbWluRGlzdGFuY2UgPSB0aGlzLm1pbkRpc3RhbmNlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZGlzdGFuY2VTcTsgLy8gY3VycmVudCBkaXN0YW5jZSBmcm9tIHRoZSBvcmlnaW4sIHNxdWFyZWRcbiAgICAgICAgICAgICAgICAgICAgbGV0IHsgZGVsdGFYLCBkZWx0YVkgfSA9IGV2O1xuICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZVNxID0gZGVsdGFYICogZGVsdGFYICsgZGVsdGFZICogZGVsdGFZO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGlzdGFuY2VTcSA+PSBtaW5EaXN0YW5jZSAqIG1pbkRpc3RhbmNlKSB7IC8vIHVzZSBweXRoYWdvcmVhbiB0aGVvcmVtXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZURpc3RhbmNlU3VycGFzc2VkKGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGEgcmVhbCBwb2ludGVyIG1vdmU/IChub3Qgb25lIHNpbXVsYXRlZCBieSBzY3JvbGxpbmcpXG4gICAgICAgICAgICAgICAgICAgIGlmIChldi5vcmlnRXZlbnQudHlwZSAhPT0gJ3Njcm9sbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWlycm9yLmhhbmRsZU1vdmUoZXYucGFnZVgsIGV2LnBhZ2VZKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXV0b1Njcm9sbGVyLmhhbmRsZU1vdmUoZXYucGFnZVgsIGV2LnBhZ2VZKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ21vdmUnLCBldik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLm9uUG9pbnRlclVwID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0ludGVyYWN0aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0ludGVyYWN0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYWxsb3dTZWxlY3Rpb24oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgYWxsb3dDb250ZXh0TWVudShkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgZXYpOyAvLyBjYW4gcG90ZW50aWFsbHkgc2V0IG1pcnJvck5lZWRzUmV2ZXJ0XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmF1dG9TY3JvbGxlci5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHJ5U3RvcERyYWcoZXYpOyAvLyB3aGljaCB3aWxsIHN0b3AgdGhlIG1pcnJvclxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kZWxheVRpbWVvdXRJZCkge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5kZWxheVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVsYXlUaW1lb3V0SWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgbGV0IHBvaW50ZXIgPSB0aGlzLnBvaW50ZXIgPSBuZXcgUG9pbnRlckRyYWdnaW5nKGNvbnRhaW5lckVsKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMub25Qb2ludGVyRG93bik7XG4gICAgICAgIHBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcm1vdmUnLCB0aGlzLm9uUG9pbnRlck1vdmUpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIHRoaXMub25Qb2ludGVyVXApO1xuICAgICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICAgIHBvaW50ZXIuc2VsZWN0b3IgPSBzZWxlY3RvcjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1pcnJvciA9IG5ldyBFbGVtZW50TWlycm9yKCk7XG4gICAgICAgIHRoaXMuYXV0b1Njcm9sbGVyID0gbmV3IEF1dG9TY3JvbGxlcigpO1xuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLnBvaW50ZXIuZGVzdHJveSgpO1xuICAgICAgICAvLyBIQUNLOiBzaW11bGF0ZSBhIHBvaW50ZXItdXAgdG8gZW5kIHRoZSBjdXJyZW50IGRyYWdcbiAgICAgICAgLy8gVE9ETzogZmlyZSAnZHJhZ2VuZCcgZGlyZWN0bHkgYW5kIHN0b3AgaW50ZXJhY3Rpb24uIGRpc2NvdXJhZ2UgdXNlIG9mIHBvaW50ZXJ1cCBldmVudCAoYi9jIG1pZ2h0IG5vdCBmaXJlKVxuICAgICAgICB0aGlzLm9uUG9pbnRlclVwKHt9KTtcbiAgICB9XG4gICAgc3RhcnREZWxheShldikge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZGVsYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF5VGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5kZWxheVRpbWVvdXRJZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVEZWxheUVuZChldik7XG4gICAgICAgICAgICB9LCB0aGlzLmRlbGF5KTsgLy8gbm90IGFzc2lnbmFibGUgdG8gbnVtYmVyIVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEZWxheUVuZChldik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaGFuZGxlRGVsYXlFbmQoZXYpIHtcbiAgICAgICAgdGhpcy5pc0RlbGF5RW5kZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnRyeVN0YXJ0RHJhZyhldik7XG4gICAgfVxuICAgIGhhbmRsZURpc3RhbmNlU3VycGFzc2VkKGV2KSB7XG4gICAgICAgIHRoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCA9IHRydWU7XG4gICAgICAgIHRoaXMudHJ5U3RhcnREcmFnKGV2KTtcbiAgICB9XG4gICAgdHJ5U3RhcnREcmFnKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLmlzRGVsYXlFbmRlZCAmJiB0aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5wb2ludGVyLndhc1RvdWNoU2Nyb2xsIHx8IHRoaXMudG91Y2hTY3JvbGxBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvck5lZWRzUmV2ZXJ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvU2Nyb2xsZXIuc3RhcnQoZXYucGFnZVgsIGV2LnBhZ2VZLCB0aGlzLmNvbnRhaW5lckVsKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ3N0YXJ0JywgZXYpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRvdWNoU2Nyb2xsQWxsb3dlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wb2ludGVyLmNhbmNlbFRvdWNoU2Nyb2xsKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHRyeVN0b3BEcmFnKGV2KSB7XG4gICAgICAgIC8vIC5zdG9wKCkgaXMgQUxXQVlTIGFzeW5jaHJvbm91cywgd2hpY2ggd2UgTkVFRCBiZWNhdXNlIHdlIHdhbnQgYWxsIHBvaW50ZXJ1cCBldmVudHNcbiAgICAgICAgLy8gdGhhdCBjb21lIGZyb20gdGhlIGRvY3VtZW50IHRvIGZpcmUgYmVmb3JlaGFuZC4gbXVjaCBtb3JlIGNvbnZlbmllbnQgdGhpcyB3YXkuXG4gICAgICAgIHRoaXMubWlycm9yLnN0b3AodGhpcy5taXJyb3JOZWVkc1JldmVydCwgdGhpcy5zdG9wRHJhZy5iaW5kKHRoaXMsIGV2KSk7XG4gICAgfVxuICAgIHN0b3BEcmFnKGV2KSB7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ2VuZCcsIGV2KTtcbiAgICB9XG4gICAgLy8gZmlsbCBpbiB0aGUgaW1wbGVtZW50YXRpb25zLi4uXG4gICAgc2V0SWdub3JlTW92ZShib29sKSB7XG4gICAgICAgIHRoaXMucG9pbnRlci5zaG91bGRJZ25vcmVNb3ZlID0gYm9vbDtcbiAgICB9XG4gICAgc2V0TWlycm9ySXNWaXNpYmxlKGJvb2wpIHtcbiAgICAgICAgdGhpcy5taXJyb3Iuc2V0SXNWaXNpYmxlKGJvb2wpO1xuICAgIH1cbiAgICBzZXRNaXJyb3JOZWVkc1JldmVydChib29sKSB7XG4gICAgICAgIHRoaXMubWlycm9yTmVlZHNSZXZlcnQgPSBib29sO1xuICAgIH1cbiAgICBzZXRBdXRvU2Nyb2xsRW5hYmxlZChib29sKSB7XG4gICAgICAgIHRoaXMuYXV0b1Njcm9sbGVyLmlzRW5hYmxlZCA9IGJvb2w7XG4gICAgfVxufVxuXG4vKlxuV2hlbiB0aGlzIGNsYXNzIGlzIGluc3RhbnRpYXRlZCwgaXQgcmVjb3JkcyB0aGUgb2Zmc2V0IG9mIGFuIGVsZW1lbnQgKHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0b3BsZWZ0KSxcbmFuZCBjb250aW51ZXMgdG8gbW9uaXRvciBzY3JvbGxpbmcsIHVwZGF0aW5nIHRoZSBjYWNoZWQgY29vcmRpbmF0ZXMgaWYgaXQgbmVlZHMgdG8uXG5Eb2VzIG5vdCBhY2Nlc3MgdGhlIERPTSBhZnRlciBpbnN0YW50aWF0aW9uLCBzbyBoaWdobHkgcGVyZm9ybWFudC5cblxuQWxzbyBrZWVwcyB0cmFjayBvZiBhbGwgc2Nyb2xsaW5nL292ZXJmbG93OmhpZGRlbiBjb250YWluZXJzIHRoYXQgYXJlIHBhcmVudHMgb2YgdGhlIGdpdmVuIGVsZW1lbnRcbmFuZCBhbiBkZXRlcm1pbmUgaWYgYSBnaXZlbiBwb2ludCBpcyBpbnNpZGUgdGhlIGNvbWJpbmVkIGNsaXBwaW5nIHJlY3RhbmdsZS5cbiovXG5jbGFzcyBPZmZzZXRUcmFja2VyIHtcbiAgICBjb25zdHJ1Y3RvcihlbCkge1xuICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgICAgIHRoaXMub3JpZ1JlY3QgPSBjb21wdXRlUmVjdChlbCk7XG4gICAgICAgIC8vIHdpbGwgd29yayBmaW5lIGZvciBkaXZzIHRoYXQgaGF2ZSBvdmVyZmxvdzpoaWRkZW5cbiAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSBnZXRDbGlwcGluZ1BhcmVudHMoZWwpLm1hcCgoc2Nyb2xsRWwpID0+IG5ldyBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlKHNjcm9sbEVsLCB0cnVlKSk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIGZvciAobGV0IHNjcm9sbENhY2hlIG9mIHRoaXMuc2Nyb2xsQ2FjaGVzKSB7XG4gICAgICAgICAgICBzY3JvbGxDYWNoZS5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29tcHV0ZUxlZnQoKSB7XG4gICAgICAgIGxldCBsZWZ0ID0gdGhpcy5vcmlnUmVjdC5sZWZ0O1xuICAgICAgICBmb3IgKGxldCBzY3JvbGxDYWNoZSBvZiB0aGlzLnNjcm9sbENhY2hlcykge1xuICAgICAgICAgICAgbGVmdCArPSBzY3JvbGxDYWNoZS5vcmlnU2Nyb2xsTGVmdCAtIHNjcm9sbENhY2hlLmdldFNjcm9sbExlZnQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGVmdDtcbiAgICB9XG4gICAgY29tcHV0ZVRvcCgpIHtcbiAgICAgICAgbGV0IHRvcCA9IHRoaXMub3JpZ1JlY3QudG9wO1xuICAgICAgICBmb3IgKGxldCBzY3JvbGxDYWNoZSBvZiB0aGlzLnNjcm9sbENhY2hlcykge1xuICAgICAgICAgICAgdG9wICs9IHNjcm9sbENhY2hlLm9yaWdTY3JvbGxUb3AgLSBzY3JvbGxDYWNoZS5nZXRTY3JvbGxUb3AoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9wO1xuICAgIH1cbiAgICBpc1dpdGhpbkNsaXBwaW5nKHBhZ2VYLCBwYWdlWSkge1xuICAgICAgICBsZXQgcG9pbnQgPSB7IGxlZnQ6IHBhZ2VYLCB0b3A6IHBhZ2VZIH07XG4gICAgICAgIGZvciAobGV0IHNjcm9sbENhY2hlIG9mIHRoaXMuc2Nyb2xsQ2FjaGVzKSB7XG4gICAgICAgICAgICBpZiAoIWlzSWdub3JlZENsaXBwaW5nKHNjcm9sbENhY2hlLmdldEV2ZW50VGFyZ2V0KCkpICYmXG4gICAgICAgICAgICAgICAgIXBvaW50SW5zaWRlUmVjdChwb2ludCwgc2Nyb2xsQ2FjaGUuY2xpZW50UmVjdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuLy8gY2VydGFpbiBjbGlwcGluZyBjb250YWluZXJzIHNob3VsZCBuZXZlciBjb25zdHJhaW4gaW50ZXJhY3Rpb25zLCBsaWtlIDxodG1sPiBhbmQgPGJvZHk+XG4vLyBodHRwczovL2dpdGh1Yi5jb20vZnVsbGNhbGVuZGFyL2Z1bGxjYWxlbmRhci9pc3N1ZXMvMzYxNVxuZnVuY3Rpb24gaXNJZ25vcmVkQ2xpcHBpbmcobm9kZSkge1xuICAgIGxldCB0YWdOYW1lID0gbm9kZS50YWdOYW1lO1xuICAgIHJldHVybiB0YWdOYW1lID09PSAnSFRNTCcgfHwgdGFnTmFtZSA9PT0gJ0JPRFknO1xufVxuXG4vKlxuVHJhY2tzIG1vdmVtZW50IG92ZXIgbXVsdGlwbGUgZHJvcHBhYmxlIGFyZWFzIChha2EgXCJoaXRzXCIpXG50aGF0IGV4aXN0IGluIG9uZSBvciBtb3JlIERhdGVDb21wb25lbnRzLlxuUmVsaWVzIG9uIGFuIGV4aXN0aW5nIGRyYWdnYWJsZS5cblxuZW1pdHM6XG4tIHBvaW50ZXJkb3duXG4tIGRyYWdzdGFydFxuLSBoaXRjaGFuZ2UgLSBmaXJlcyBpbml0aWFsbHksIGV2ZW4gaWYgbm90IG92ZXIgYSBoaXRcbi0gcG9pbnRlcnVwXG4tIChoaXRjaGFuZ2UgLSBhZ2FpbiwgdG8gbnVsbCwgaWYgZW5kZWQgb3ZlciBhIGhpdClcbi0gZHJhZ2VuZFxuKi9cbmNsYXNzIEhpdERyYWdnaW5nIHtcbiAgICBjb25zdHJ1Y3RvcihkcmFnZ2luZywgZHJvcHBhYmxlU3RvcmUpIHtcbiAgICAgICAgLy8gb3B0aW9ucyB0aGF0IGNhbiBiZSBzZXQgYnkgY2FsbGVyXG4gICAgICAgIHRoaXMudXNlU3ViamVjdENlbnRlciA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlcXVpcmVJbml0aWFsID0gdHJ1ZTsgLy8gaWYgZG9lc24ndCBzdGFydCBvdXQgb24gYSBoaXQsIHdvbid0IGVtaXQgYW55IGV2ZW50c1xuICAgICAgICB0aGlzLmRpc2FibGVQb2ludENoZWNrID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaW5pdGlhbEhpdCA9IG51bGw7XG4gICAgICAgIHRoaXMubW92aW5nSGl0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5maW5hbEhpdCA9IG51bGw7IC8vIHdvbid0IGV2ZXIgYmUgcG9wdWxhdGVkIGlmIHNob3VsZElnbm9yZU1vdmVcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IHsgZHJhZ2dpbmcgfSA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxIaXQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5tb3ZpbmdIaXQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5maW5hbEhpdCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnByZXBhcmVIaXRzKCk7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NGaXJzdENvb3JkKGV2KTtcbiAgICAgICAgICAgIGlmICh0aGlzLmluaXRpYWxIaXQgfHwgIXRoaXMucmVxdWlyZUluaXRpYWwpIHtcbiAgICAgICAgICAgICAgICBkcmFnZ2luZy5zZXRJZ25vcmVNb3ZlKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBmaXJlIHRoaXMgYmVmb3JlIGNvbXB1dGluZyBwcm9jZXNzRmlyc3RDb29yZCwgc28gbGlzdGVuZXJzIGNhbiBjYW5jZWwuIHRoaXMgZ2V0cyBmaXJlZCBieSBhbG1vc3QgZXZlcnkgaGFuZGxlciA6KFxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gKGV2KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ3N0YXJ0JywgZXYpO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVNb3ZlKGV2LCB0cnVlKTsgLy8gZm9yY2UgPSBmaXJlIGV2ZW4gaWYgaW5pdGlhbGx5IG51bGxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVEcmFnTW92ZSA9IChldikgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdtb3ZlJywgZXYpO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVNb3ZlKGV2KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyVXAgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVsZWFzZUhpdHMoKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVydXAnLCBldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IChldikgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMubW92aW5nSGl0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2hpdHVwZGF0ZScsIG51bGwsIHRydWUsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZmluYWxIaXQgPSB0aGlzLm1vdmluZ0hpdDtcbiAgICAgICAgICAgIHRoaXMubW92aW5nSGl0ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnZW5kJywgZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmRyb3BwYWJsZVN0b3JlID0gZHJvcHBhYmxlU3RvcmU7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ21vdmUnLCB0aGlzLmhhbmRsZURyYWdNb3ZlKTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcnVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnZW5kJywgdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgdGhpcy5kcmFnZ2luZyA9IGRyYWdnaW5nO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuICAgIH1cbiAgICAvLyBzZXRzIGluaXRpYWxIaXRcbiAgICAvLyBzZXRzIGNvb3JkQWRqdXN0XG4gICAgcHJvY2Vzc0ZpcnN0Q29vcmQoZXYpIHtcbiAgICAgICAgbGV0IG9yaWdQb2ludCA9IHsgbGVmdDogZXYucGFnZVgsIHRvcDogZXYucGFnZVkgfTtcbiAgICAgICAgbGV0IGFkanVzdGVkUG9pbnQgPSBvcmlnUG9pbnQ7XG4gICAgICAgIGxldCBzdWJqZWN0RWwgPSBldi5zdWJqZWN0RWw7XG4gICAgICAgIGxldCBzdWJqZWN0UmVjdDtcbiAgICAgICAgaWYgKHN1YmplY3RFbCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7IC8vIGkuZS4gbm90IGEgRG9jdW1lbnQvU2hhZG93Um9vdFxuICAgICAgICAgICAgc3ViamVjdFJlY3QgPSBjb21wdXRlUmVjdChzdWJqZWN0RWwpO1xuICAgICAgICAgICAgYWRqdXN0ZWRQb2ludCA9IGNvbnN0cmFpblBvaW50KGFkanVzdGVkUG9pbnQsIHN1YmplY3RSZWN0KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaW5pdGlhbEhpdCA9IHRoaXMuaW5pdGlhbEhpdCA9IHRoaXMucXVlcnlIaXRGb3JPZmZzZXQoYWRqdXN0ZWRQb2ludC5sZWZ0LCBhZGp1c3RlZFBvaW50LnRvcCk7XG4gICAgICAgIGlmIChpbml0aWFsSGl0KSB7XG4gICAgICAgICAgICBpZiAodGhpcy51c2VTdWJqZWN0Q2VudGVyICYmIHN1YmplY3RSZWN0KSB7XG4gICAgICAgICAgICAgICAgbGV0IHNsaWNlZFN1YmplY3RSZWN0ID0gaW50ZXJzZWN0UmVjdHMoc3ViamVjdFJlY3QsIGluaXRpYWxIaXQucmVjdCk7XG4gICAgICAgICAgICAgICAgaWYgKHNsaWNlZFN1YmplY3RSZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGFkanVzdGVkUG9pbnQgPSBnZXRSZWN0Q2VudGVyKHNsaWNlZFN1YmplY3RSZWN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNvb3JkQWRqdXN0ID0gZGlmZlBvaW50cyhhZGp1c3RlZFBvaW50LCBvcmlnUG9pbnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jb29yZEFkanVzdCA9IHsgbGVmdDogMCwgdG9wOiAwIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgaGFuZGxlTW92ZShldiwgZm9yY2VIYW5kbGUpIHtcbiAgICAgICAgbGV0IGhpdCA9IHRoaXMucXVlcnlIaXRGb3JPZmZzZXQoZXYucGFnZVggKyB0aGlzLmNvb3JkQWRqdXN0LmxlZnQsIGV2LnBhZ2VZICsgdGhpcy5jb29yZEFkanVzdC50b3ApO1xuICAgICAgICBpZiAoZm9yY2VIYW5kbGUgfHwgIWlzSGl0c0VxdWFsKHRoaXMubW92aW5nSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICB0aGlzLm1vdmluZ0hpdCA9IGhpdDtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdoaXR1cGRhdGUnLCBoaXQsIGZhbHNlLCBldik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHJlcGFyZUhpdHMoKSB7XG4gICAgICAgIHRoaXMub2Zmc2V0VHJhY2tlcnMgPSBtYXBIYXNoKHRoaXMuZHJvcHBhYmxlU3RvcmUsIChpbnRlcmFjdGlvblNldHRpbmdzKSA9PiB7XG4gICAgICAgICAgICBpbnRlcmFjdGlvblNldHRpbmdzLmNvbXBvbmVudC5wcmVwYXJlSGl0cygpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBPZmZzZXRUcmFja2VyKGludGVyYWN0aW9uU2V0dGluZ3MuZWwpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmVsZWFzZUhpdHMoKSB7XG4gICAgICAgIGxldCB7IG9mZnNldFRyYWNrZXJzIH0gPSB0aGlzO1xuICAgICAgICBmb3IgKGxldCBpZCBpbiBvZmZzZXRUcmFja2Vycykge1xuICAgICAgICAgICAgb2Zmc2V0VHJhY2tlcnNbaWRdLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9mZnNldFRyYWNrZXJzID0ge307XG4gICAgfVxuICAgIHF1ZXJ5SGl0Rm9yT2Zmc2V0KG9mZnNldExlZnQsIG9mZnNldFRvcCkge1xuICAgICAgICBsZXQgeyBkcm9wcGFibGVTdG9yZSwgb2Zmc2V0VHJhY2tlcnMgfSA9IHRoaXM7XG4gICAgICAgIGxldCBiZXN0SGl0ID0gbnVsbDtcbiAgICAgICAgZm9yIChsZXQgaWQgaW4gZHJvcHBhYmxlU3RvcmUpIHtcbiAgICAgICAgICAgIGxldCBjb21wb25lbnQgPSBkcm9wcGFibGVTdG9yZVtpZF0uY29tcG9uZW50O1xuICAgICAgICAgICAgbGV0IG9mZnNldFRyYWNrZXIgPSBvZmZzZXRUcmFja2Vyc1tpZF07XG4gICAgICAgICAgICBpZiAob2Zmc2V0VHJhY2tlciAmJiAvLyB3YXNuJ3QgZGVzdHJveWVkIG1pZC1kcmFnXG4gICAgICAgICAgICAgICAgb2Zmc2V0VHJhY2tlci5pc1dpdGhpbkNsaXBwaW5nKG9mZnNldExlZnQsIG9mZnNldFRvcCkpIHtcbiAgICAgICAgICAgICAgICBsZXQgb3JpZ2luTGVmdCA9IG9mZnNldFRyYWNrZXIuY29tcHV0ZUxlZnQoKTtcbiAgICAgICAgICAgICAgICBsZXQgb3JpZ2luVG9wID0gb2Zmc2V0VHJhY2tlci5jb21wdXRlVG9wKCk7XG4gICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uTGVmdCA9IG9mZnNldExlZnQgLSBvcmlnaW5MZWZ0O1xuICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvblRvcCA9IG9mZnNldFRvcCAtIG9yaWdpblRvcDtcbiAgICAgICAgICAgICAgICBsZXQgeyBvcmlnUmVjdCB9ID0gb2Zmc2V0VHJhY2tlcjtcbiAgICAgICAgICAgICAgICBsZXQgd2lkdGggPSBvcmlnUmVjdC5yaWdodCAtIG9yaWdSZWN0LmxlZnQ7XG4gICAgICAgICAgICAgICAgbGV0IGhlaWdodCA9IG9yaWdSZWN0LmJvdHRvbSAtIG9yaWdSZWN0LnRvcDtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgLy8gbXVzdCBiZSB3aXRoaW4gdGhlIGVsZW1lbnQncyBib3VuZHNcbiAgICAgICAgICAgICAgICBwb3NpdGlvbkxlZnQgPj0gMCAmJiBwb3NpdGlvbkxlZnQgPCB3aWR0aCAmJlxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvblRvcCA+PSAwICYmIHBvc2l0aW9uVG9wIDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBoaXQgPSBjb21wb25lbnQucXVlcnlIaXQocG9zaXRpb25MZWZ0LCBwb3NpdGlvblRvcCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoaXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAvLyBtYWtlIHN1cmUgdGhlIGhpdCBpcyB3aXRoaW4gYWN0aXZlUmFuZ2UsIG1lYW5pbmcgaXQncyBub3QgYSBkZWFkIGNlbGxcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VDb250YWluc1JhbmdlKGhpdC5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgaGl0LmRhdGVTcGFuLnJhbmdlKSkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVuc3VyZSB0aGUgY29tcG9uZW50IHdlIGFyZSBxdWVyeWluZyBmb3IgdGhlIGhpdCBpcyBhY2Nlc3NpYmx5IG15IHRoZSBwb2ludGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQcmV2ZW50cyBvYnNjdXJlZCBjYWxlbmRhcnMgKGV4OiB1bmRlciBhIG1vZGFsIGRpYWxvZykgZnJvbSBhY2NlcHRpbmcgaGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZnVsbGNhbGVuZGFyL2Z1bGxjYWxlbmRhci9pc3N1ZXMvNTAyNlxuICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMuZGlzYWJsZVBvaW50Q2hlY2sgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRUcmFja2VyLmVsLmNvbnRhaW5zKG9mZnNldFRyYWNrZXIuZWwuZ2V0Um9vdE5vZGUoKS5lbGVtZW50RnJvbVBvaW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZC1iYWNrIG9yaWdpbnMgdG8gZ2V0IGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdG9wLWxlZnQgb2Ygd2luZG93IHZpZXdwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25MZWZ0ICsgb3JpZ2luTGVmdCAtIHdpbmRvdy5zY3JvbGxYLCBwb3NpdGlvblRvcCArIG9yaWdpblRvcCAtIHdpbmRvdy5zY3JvbGxZKSkpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoIWJlc3RIaXQgfHwgaGl0LmxheWVyID4gYmVzdEhpdC5sYXllcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpdC5jb21wb25lbnRJZCA9IGlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LmNvbnRleHQgPSBjb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGJldHRlciB3YXkgdG8gcmUtb3JpZW50IHJlY3RhbmdsZVxuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QubGVmdCArPSBvcmlnaW5MZWZ0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QucmlnaHQgKz0gb3JpZ2luTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpdC5yZWN0LnRvcCArPSBvcmlnaW5Ub3A7XG4gICAgICAgICAgICAgICAgICAgICAgICBoaXQucmVjdC5ib3R0b20gKz0gb3JpZ2luVG9wO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVzdEhpdCA9IGhpdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmVzdEhpdDtcbiAgICB9XG59XG5mdW5jdGlvbiBpc0hpdHNFcXVhbChoaXQwLCBoaXQxKSB7XG4gICAgaWYgKCFoaXQwICYmICFoaXQxKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoQm9vbGVhbihoaXQwKSAhPT0gQm9vbGVhbihoaXQxKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBpc0RhdGVTcGFuc0VxdWFsKGhpdDAuZGF0ZVNwYW4sIGhpdDEuZGF0ZVNwYW4pO1xufVxuXG5mdW5jdGlvbiBidWlsZERhdGVQb2ludEFwaVdpdGhDb250ZXh0KGRhdGVTcGFuLCBjb250ZXh0KSB7XG4gICAgbGV0IHByb3BzID0ge307XG4gICAgZm9yIChsZXQgdHJhbnNmb3JtIG9mIGNvbnRleHQucGx1Z2luSG9va3MuZGF0ZVBvaW50VHJhbnNmb3Jtcykge1xuICAgICAgICBPYmplY3QuYXNzaWduKHByb3BzLCB0cmFuc2Zvcm0oZGF0ZVNwYW4sIGNvbnRleHQpKTtcbiAgICB9XG4gICAgT2JqZWN0LmFzc2lnbihwcm9wcywgYnVpbGREYXRlUG9pbnRBcGkoZGF0ZVNwYW4sIGNvbnRleHQuZGF0ZUVudikpO1xuICAgIHJldHVybiBwcm9wcztcbn1cbmZ1bmN0aW9uIGJ1aWxkRGF0ZVBvaW50QXBpKHNwYW4sIGRhdGVFbnYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkYXRlOiBkYXRlRW52LnRvRGF0ZShzcGFuLnJhbmdlLnN0YXJ0KSxcbiAgICAgICAgZGF0ZVN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5zdGFydCwgeyBvbWl0VGltZTogc3Bhbi5hbGxEYXkgfSksXG4gICAgICAgIGFsbERheTogc3Bhbi5hbGxEYXksXG4gICAgfTtcbn1cblxuLypcbk1vbml0b3JzIHdoZW4gdGhlIHVzZXIgY2xpY2tzIG9uIGEgc3BlY2lmaWMgZGF0ZS90aW1lIG9mIGEgY29tcG9uZW50LlxuQSBwb2ludGVyZG93bitwb2ludGVydXAgb24gdGhlIHNhbWUgXCJoaXRcIiBjb25zdGl0dXRlcyBhIGNsaWNrLlxuKi9cbmNsYXNzIERhdGVDbGlja2luZyBleHRlbmRzIEludGVyYWN0aW9uIHtcbiAgICBjb25zdHJ1Y3RvcihzZXR0aW5ncykge1xuICAgICAgICBzdXBlcihzZXR0aW5ncyk7XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlckRvd24gPSAocGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBkcmFnZ2luZyB9ID0gdGhpcztcbiAgICAgICAgICAgIGxldCBkb3duRWwgPSBwZXYub3JpZ0V2ZW50LnRhcmdldDtcbiAgICAgICAgICAgIC8vIGRvIHRoaXMgaW4gcG9pbnRlcmRvd24gKG5vdCBkcmFnZW5kKSBiZWNhdXNlIERPTSBtaWdodCBiZSBtdXRhdGVkIGJ5IHRoZSB0aW1lIGRyYWdlbmQgaXMgZmlyZWRcbiAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoIXRoaXMuY29tcG9uZW50LmlzVmFsaWREYXRlRG93bkVsKGRvd25FbCkpO1xuICAgICAgICB9O1xuICAgICAgICAvLyB3b24ndCBldmVuIGZpcmUgaWYgbW92aW5nIHdhcyBpZ25vcmVkXG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IHsgY29tcG9uZW50IH0gPSB0aGlzO1xuICAgICAgICAgICAgbGV0IHsgcG9pbnRlciB9ID0gdGhpcy5kcmFnZ2luZztcbiAgICAgICAgICAgIGlmICghcG9pbnRlci53YXNUb3VjaFNjcm9sbCkge1xuICAgICAgICAgICAgICAgIGxldCB7IGluaXRpYWxIaXQsIGZpbmFsSGl0IH0gPSB0aGlzLmhpdERyYWdnaW5nO1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsSGl0ICYmIGZpbmFsSGl0ICYmIGlzSGl0c0VxdWFsKGluaXRpYWxIaXQsIGZpbmFsSGl0KSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgeyBjb250ZXh0IH0gPSBjb21wb25lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGxldCBhcmcgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJ1aWxkRGF0ZVBvaW50QXBpV2l0aENvbnRleHQoaW5pdGlhbEhpdC5kYXRlU3BhbiwgY29udGV4dCkpLCB7IGRheUVsOiBpbml0aWFsSGl0LmRheUVsLCBqc0V2ZW50OiBldi5vcmlnRXZlbnQsIHZpZXc6IGNvbnRleHQudmlld0FwaSB8fCBjb250ZXh0LmNhbGVuZGFyQXBpLnZpZXcgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdkYXRlQ2xpY2snLCBhcmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLy8gd2UgRE8gd2FudCB0byB3YXRjaCBwb2ludGVyIG1vdmVzIGJlY2F1c2Ugb3RoZXJ3aXNlIGZpbmFsSGl0IHdvbid0IGdldCBwb3B1bGF0ZWRcbiAgICAgICAgdGhpcy5kcmFnZ2luZyA9IG5ldyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nKHNldHRpbmdzLmVsKTtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gZmFsc2U7XG4gICAgICAgIGxldCBoaXREcmFnZ2luZyA9IHRoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcodGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIHRoaXMuaGFuZGxlRHJhZ0VuZCk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH1cbn1cblxuLypcblRyYWNrcyB3aGVuIHRoZSB1c2VyIHNlbGVjdHMgYSBwb3J0aW9uIG9mIHRpbWUgb2YgYSBjb21wb25lbnQsXG5jb25zdGl0dXRlZCBieSBhIGRyYWcgb3ZlciBkYXRlIGNlbGxzLCB3aXRoIGEgcG9zc2libGUgZGVsYXkgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgZHJhZy5cbiovXG5jbGFzcyBEYXRlU2VsZWN0aW5nIGV4dGVuZHMgSW50ZXJhY3Rpb24ge1xuICAgIGNvbnN0cnVjdG9yKHNldHRpbmdzKSB7XG4gICAgICAgIHN1cGVyKHNldHRpbmdzKTtcbiAgICAgICAgdGhpcy5kcmFnU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IHsgY29tcG9uZW50LCBkcmFnZ2luZyB9ID0gdGhpcztcbiAgICAgICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICAgICAgbGV0IGNhblNlbGVjdCA9IG9wdGlvbnMuc2VsZWN0YWJsZSAmJlxuICAgICAgICAgICAgICAgIGNvbXBvbmVudC5pc1ZhbGlkRGF0ZURvd25FbChldi5vcmlnRXZlbnQudGFyZ2V0KTtcbiAgICAgICAgICAgIC8vIGRvbid0IGJvdGhlciB0byB3YXRjaCBleHBlbnNpdmUgbW92ZXMgaWYgY29tcG9uZW50IHdvbid0IGRvIHNlbGVjdGlvblxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZSghY2FuU2VsZWN0KTtcbiAgICAgICAgICAgIC8vIGlmIHRvdWNoLCByZXF1aXJlIHVzZXIgdG8gaG9sZCBkb3duXG4gICAgICAgICAgICBkcmFnZ2luZy5kZWxheSA9IGV2LmlzVG91Y2ggPyBnZXRDb21wb25lbnRUb3VjaERlbGF5JDEoY29tcG9uZW50KSA6IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gKGV2KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyQXBpLnVuc2VsZWN0KGV2KTsgLy8gdW5zZWxlY3QgcHJldmlvdXMgc2VsZWN0aW9uc1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZUhpdFVwZGF0ZSA9IChoaXQsIGlzRmluYWwpID0+IHtcbiAgICAgICAgICAgIGxldCB7IGNvbnRleHQgfSA9IHRoaXMuY29tcG9uZW50O1xuICAgICAgICAgICAgbGV0IGRyYWdTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICAgICAgbGV0IGlzSW52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGhpdCkge1xuICAgICAgICAgICAgICAgIGxldCBpbml0aWFsSGl0ID0gdGhpcy5oaXREcmFnZ2luZy5pbml0aWFsSGl0O1xuICAgICAgICAgICAgICAgIGxldCBkaXNhbGxvd2VkID0gaGl0LmNvbXBvbmVudElkID09PSBpbml0aWFsSGl0LmNvbXBvbmVudElkXG4gICAgICAgICAgICAgICAgICAgICYmIHRoaXMuaXNIaXRDb21ib0FsbG93ZWRcbiAgICAgICAgICAgICAgICAgICAgJiYgIXRoaXMuaXNIaXRDb21ib0FsbG93ZWQoaW5pdGlhbEhpdCwgaGl0KTtcbiAgICAgICAgICAgICAgICBpZiAoIWRpc2FsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ1NlbGVjdGlvbiA9IGpvaW5IaXRzSW50b1NlbGVjdGlvbihpbml0aWFsSGl0LCBoaXQsIGNvbnRleHQucGx1Z2luSG9va3MuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghZHJhZ1NlbGVjdGlvbiB8fCAhaXNEYXRlU2VsZWN0aW9uVmFsaWQoZHJhZ1NlbGVjdGlvbiwgaGl0LmRhdGVQcm9maWxlLCBjb250ZXh0KSkge1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBkcmFnU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZHJhZ1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2goeyB0eXBlOiAnU0VMRUNUX0RBVEVTJywgc2VsZWN0aW9uOiBkcmFnU2VsZWN0aW9uIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoIWlzRmluYWwpIHsgLy8gb25seSB1bnNlbGVjdCBpZiBtb3ZlZCBhd2F5IHdoaWxlIGRyYWdnaW5nXG4gICAgICAgICAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9EQVRFUycgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnU2VsZWN0aW9uID0gZHJhZ1NlbGVjdGlvbjsgLy8gb25seSBjbGVhciBpZiBtb3ZlZCBhd2F5IGZyb20gYWxsIGhpdHMgd2hpbGUgZHJhZ2dpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyVXAgPSAocGV2KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5kcmFnU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gc2VsZWN0aW9uIGlzIGFscmVhZHkgcmVuZGVyZWQsIHNvIGp1c3QgbmVlZCB0byByZXBvcnQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgdHJpZ2dlckRhdGVTZWxlY3QodGhpcy5kcmFnU2VsZWN0aW9uLCBwZXYsIHRoaXMuY29tcG9uZW50LmNvbnRleHQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhZ1NlbGVjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGxldCB7IGNvbXBvbmVudCB9ID0gc2V0dGluZ3M7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICBsZXQgZHJhZ2dpbmcgPSB0aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoc2V0dGluZ3MuZWwpO1xuICAgICAgICBkcmFnZ2luZy50b3VjaFNjcm9sbEFsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgZHJhZ2dpbmcubWluRGlzdGFuY2UgPSBvcHRpb25zLnNlbGVjdE1pbkRpc3RhbmNlIHx8IDA7XG4gICAgICAgIGRyYWdnaW5nLmF1dG9TY3JvbGxlci5pc0VuYWJsZWQgPSBvcHRpb25zLmRyYWdTY3JvbGw7XG4gICAgICAgIGxldCBoaXREcmFnZ2luZyA9IHRoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcodGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgdGhpcy5oYW5kbGVEcmFnU3RhcnQpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdoaXR1cGRhdGUnLCB0aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIHRoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0Q29tcG9uZW50VG91Y2hEZWxheSQxKGNvbXBvbmVudCkge1xuICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbXBvbmVudC5jb250ZXh0O1xuICAgIGxldCBkZWxheSA9IG9wdGlvbnMuc2VsZWN0TG9uZ1ByZXNzRGVsYXk7XG4gICAgaWYgKGRlbGF5ID09IG51bGwpIHtcbiAgICAgICAgZGVsYXkgPSBvcHRpb25zLmxvbmdQcmVzc0RlbGF5O1xuICAgIH1cbiAgICByZXR1cm4gZGVsYXk7XG59XG5mdW5jdGlvbiBqb2luSGl0c0ludG9TZWxlY3Rpb24oaGl0MCwgaGl0MSwgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycykge1xuICAgIGxldCBkYXRlU3BhbjAgPSBoaXQwLmRhdGVTcGFuO1xuICAgIGxldCBkYXRlU3BhbjEgPSBoaXQxLmRhdGVTcGFuO1xuICAgIGxldCBtcyA9IFtcbiAgICAgICAgZGF0ZVNwYW4wLnJhbmdlLnN0YXJ0LFxuICAgICAgICBkYXRlU3BhbjAucmFuZ2UuZW5kLFxuICAgICAgICBkYXRlU3BhbjEucmFuZ2Uuc3RhcnQsXG4gICAgICAgIGRhdGVTcGFuMS5yYW5nZS5lbmQsXG4gICAgXTtcbiAgICBtcy5zb3J0KGNvbXBhcmVOdW1iZXJzKTtcbiAgICBsZXQgcHJvcHMgPSB7fTtcbiAgICBmb3IgKGxldCB0cmFuc2Zvcm1lciBvZiBkYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzKSB7XG4gICAgICAgIGxldCByZXMgPSB0cmFuc2Zvcm1lcihoaXQwLCBoaXQxKTtcbiAgICAgICAgaWYgKHJlcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXMpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24ocHJvcHMsIHJlcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHJvcHMucmFuZ2UgPSB7IHN0YXJ0OiBtc1swXSwgZW5kOiBtc1szXSB9O1xuICAgIHByb3BzLmFsbERheSA9IGRhdGVTcGFuMC5hbGxEYXk7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuXG5jbGFzcyBFdmVudERyYWdnaW5nIGV4dGVuZHMgSW50ZXJhY3Rpb24ge1xuICAgIGNvbnN0cnVjdG9yKHNldHRpbmdzKSB7XG4gICAgICAgIHN1cGVyKHNldHRpbmdzKTtcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgdGhpcy5zdWJqZWN0RWwgPSBudWxsO1xuICAgICAgICB0aGlzLnN1YmplY3RTZWcgPSBudWxsOyAvLyB0aGUgc2VnIGJlaW5nIHNlbGVjdGVkL2RyYWdnZWRcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlbnRSYW5nZSA9IG51bGw7XG4gICAgICAgIHRoaXMucmVsZXZhbnRFdmVudHMgPSBudWxsOyAvLyB0aGUgZXZlbnRzIGJlaW5nIGRyYWdnZWRcbiAgICAgICAgdGhpcy5yZWNlaXZpbmdDb250ZXh0ID0gbnVsbDtcbiAgICAgICAgdGhpcy52YWxpZE11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgb3JpZ1RhcmdldCA9IGV2Lm9yaWdFdmVudC50YXJnZXQ7XG4gICAgICAgICAgICBsZXQgeyBjb21wb25lbnQsIGRyYWdnaW5nIH0gPSB0aGlzO1xuICAgICAgICAgICAgbGV0IHsgbWlycm9yIH0gPSBkcmFnZ2luZztcbiAgICAgICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICAgICAgbGV0IGluaXRpYWxDb250ZXh0ID0gY29tcG9uZW50LmNvbnRleHQ7XG4gICAgICAgICAgICB0aGlzLnN1YmplY3RFbCA9IGV2LnN1YmplY3RFbDtcbiAgICAgICAgICAgIGxldCBzdWJqZWN0U2VnID0gdGhpcy5zdWJqZWN0U2VnID0gZ2V0RWxTZWcoZXYuc3ViamVjdEVsKTtcbiAgICAgICAgICAgIGxldCBldmVudFJhbmdlID0gdGhpcy5ldmVudFJhbmdlID0gc3ViamVjdFNlZy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgbGV0IGV2ZW50SW5zdGFuY2VJZCA9IGV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZDtcbiAgICAgICAgICAgIHRoaXMucmVsZXZhbnRFdmVudHMgPSBnZXRSZWxldmFudEV2ZW50cyhpbml0aWFsQ29udGV4dC5nZXRDdXJyZW50RGF0YSgpLmV2ZW50U3RvcmUsIGV2ZW50SW5zdGFuY2VJZCk7XG4gICAgICAgICAgICBkcmFnZ2luZy5taW5EaXN0YW5jZSA9IGV2LmlzVG91Y2ggPyAwIDogb3B0aW9ucy5ldmVudERyYWdNaW5EaXN0YW5jZTtcbiAgICAgICAgICAgIGRyYWdnaW5nLmRlbGF5ID1cbiAgICAgICAgICAgICAgICAvLyBvbmx5IGRvIGEgdG91Y2ggZGVsYXkgaWYgdG91Y2ggYW5kIHRoaXMgZXZlbnQgaGFzbid0IGJlZW4gc2VsZWN0ZWQgeWV0XG4gICAgICAgICAgICAgICAgKGV2LmlzVG91Y2ggJiYgZXZlbnRJbnN0YW5jZUlkICE9PSBjb21wb25lbnQucHJvcHMuZXZlbnRTZWxlY3Rpb24pID9cbiAgICAgICAgICAgICAgICAgICAgZ2V0Q29tcG9uZW50VG91Y2hEZWxheShjb21wb25lbnQpIDpcbiAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmZpeGVkTWlycm9yUGFyZW50KSB7XG4gICAgICAgICAgICAgICAgbWlycm9yLnBhcmVudE5vZGUgPSBvcHRpb25zLmZpeGVkTWlycm9yUGFyZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbWlycm9yLnBhcmVudE5vZGUgPSBlbGVtZW50Q2xvc2VzdChvcmlnVGFyZ2V0LCAnLmZjJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtaXJyb3IucmV2ZXJ0RHVyYXRpb24gPSBvcHRpb25zLmRyYWdSZXZlcnREdXJhdGlvbjtcbiAgICAgICAgICAgIGxldCBpc1ZhbGlkID0gY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwob3JpZ1RhcmdldCkgJiZcbiAgICAgICAgICAgICAgICAhZWxlbWVudENsb3Nlc3Qob3JpZ1RhcmdldCwgJy5mYy1ldmVudC1yZXNpemVyJyk7IC8vIE5PVCBvbiBhIHJlc2l6ZXJcbiAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoIWlzVmFsaWQpO1xuICAgICAgICAgICAgLy8gZGlzYWJsZSBkcmFnZ2luZyBmb3IgZWxlbWVudHMgdGhhdCBhcmUgcmVzaXphYmxlIChpZSwgc2VsZWN0YWJsZSlcbiAgICAgICAgICAgIC8vIGJ1dCBhcmUgbm90IGRyYWdnYWJsZVxuICAgICAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gaXNWYWxpZCAmJlxuICAgICAgICAgICAgICAgIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLWV2ZW50LWRyYWdnYWJsZScpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdTdGFydCA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IGluaXRpYWxDb250ZXh0ID0gdGhpcy5jb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgICAgIGxldCBldmVudFJhbmdlID0gdGhpcy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgbGV0IGV2ZW50SW5zdGFuY2VJZCA9IGV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZDtcbiAgICAgICAgICAgIGlmIChldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgLy8gbmVlZCB0byBzZWxlY3QgYSBkaWZmZXJlbnQgZXZlbnQ/XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50SW5zdGFuY2VJZCAhPT0gdGhpcy5jb21wb25lbnQucHJvcHMuZXZlbnRTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuZGlzcGF0Y2goeyB0eXBlOiAnU0VMRUNUX0VWRU5UJywgZXZlbnRJbnN0YW5jZUlkIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vdyB1c2luZyBtb3VzZSwgYnV0IHdhcyBwcmV2aW91cyB0b3VjaCBpbnRlcmFjdGlvbiwgY2xlYXIgc2VsZWN0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBpbml0aWFsQ29udGV4dC5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9FVkVOVCcgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuY2FsZW5kYXJBcGkudW5zZWxlY3QoZXYpOyAvLyB1bnNlbGVjdCAqZGF0ZSogc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudERyYWdTdGFydCcsIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IHRoaXMuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50SW1wbChpbml0aWFsQ29udGV4dCwgZXZlbnRSYW5nZS5kZWYsIGV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IGluaXRpYWxDb250ZXh0LnZpZXdBcGksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlSGl0VXBkYXRlID0gKGhpdCwgaXNGaW5hbCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVsZXZhbnRFdmVudHMgPSB0aGlzLnJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgbGV0IGluaXRpYWxIaXQgPSB0aGlzLmhpdERyYWdnaW5nLmluaXRpYWxIaXQ7XG4gICAgICAgICAgICBsZXQgaW5pdGlhbENvbnRleHQgPSB0aGlzLmNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICAgICAgLy8gc3RhdGVzIGJhc2VkIG9uIG5ldyBoaXRcbiAgICAgICAgICAgIGxldCByZWNlaXZpbmdDb250ZXh0ID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICBsZXQgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogcmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoaGl0KSB7XG4gICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dCA9IGhpdC5jb250ZXh0O1xuICAgICAgICAgICAgICAgIGxldCByZWNlaXZpbmdPcHRpb25zID0gcmVjZWl2aW5nQ29udGV4dC5vcHRpb25zO1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsQ29udGV4dCA9PT0gcmVjZWl2aW5nQ29udGV4dCB8fFxuICAgICAgICAgICAgICAgICAgICAocmVjZWl2aW5nT3B0aW9ucy5lZGl0YWJsZSAmJiByZWNlaXZpbmdPcHRpb25zLmRyb3BwYWJsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRpb24gPSBjb21wdXRlRXZlbnRNdXRhdGlvbihpbml0aWFsSGl0LCBoaXQsIHRoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZS5yYW5nZS5zdGFydCwgcmVjZWl2aW5nQ29udGV4dC5nZXRDdXJyZW50RGF0YSgpLnBsdWdpbkhvb2tzLmV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG11dGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlKHJlbGV2YW50RXZlbnRzLCByZWNlaXZpbmdDb250ZXh0LmdldEN1cnJlbnREYXRhKCkuZXZlbnRVaUJhc2VzLCBtdXRhdGlvbiwgcmVjZWl2aW5nQ29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzID0gbXV0YXRlZFJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0ludGVyYWN0aW9uVmFsaWQoaW50ZXJhY3Rpb24sIGhpdC5kYXRlUHJvZmlsZSwgcmVjZWl2aW5nQ29udGV4dCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kaXNwbGF5RHJhZyhyZWNlaXZpbmdDb250ZXh0LCBpbnRlcmFjdGlvbik7XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGluaXRpYWxDb250ZXh0ID09PSByZWNlaXZpbmdDb250ZXh0ICYmIC8vIFRPRE86IHdyaXRlIHRlc3QgZm9yIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgaXNIaXRzRXF1YWwoaW5pdGlhbEhpdCwgaGl0KSkge1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZHJhZ2dpbmcuc2V0TWlycm9yTmVlZHNSZXZlcnQoIW11dGF0aW9uKTtcbiAgICAgICAgICAgICAgICAvLyByZW5kZXIgdGhlIG1pcnJvciBpZiBubyBhbHJlYWR5LXJlbmRlcmVkIG1pcnJvclxuICAgICAgICAgICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgc29tZWhvdyB3YWl0IGZvciBkaXNwYXRjaCB0byBndWFyYW50ZWUgcmVuZGVyXG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnZ2luZy5zZXRNaXJyb3JJc1Zpc2libGUoIWhpdCB8fCAhdGhpcy5zdWJqZWN0RWwuZ2V0Um9vdE5vZGUoKS5xdWVyeVNlbGVjdG9yKCcuZmMtZXZlbnQtbWlycm9yJykpO1xuICAgICAgICAgICAgICAgIC8vIGFzc2lnbiBzdGF0ZXMgYmFzZWQgb24gbmV3IGhpdFxuICAgICAgICAgICAgICAgIHRoaXMucmVjZWl2aW5nQ29udGV4dCA9IHJlY2VpdmluZ0NvbnRleHQ7XG4gICAgICAgICAgICAgICAgdGhpcy52YWxpZE11dGF0aW9uID0gbXV0YXRpb247XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBtdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlclVwID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFudXAoKTsgLy8gYmVjYXVzZSBoYW5kbGVEcmFnRW5kIHdvbid0IGZpcmVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVEcmFnRW5kID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgbGV0IGluaXRpYWxDb250ZXh0ID0gdGhpcy5jb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgICAgICAgICBsZXQgaW5pdGlhbFZpZXcgPSBpbml0aWFsQ29udGV4dC52aWV3QXBpO1xuICAgICAgICAgICAgICAgIGxldCB7IHJlY2VpdmluZ0NvbnRleHQsIHZhbGlkTXV0YXRpb24gfSA9IHRoaXM7XG4gICAgICAgICAgICAgICAgbGV0IGV2ZW50RGVmID0gdGhpcy5ldmVudFJhbmdlLmRlZjtcbiAgICAgICAgICAgICAgICBsZXQgZXZlbnRJbnN0YW5jZSA9IHRoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZTtcbiAgICAgICAgICAgICAgICBsZXQgZXZlbnRBcGkgPSBuZXcgRXZlbnRJbXBsKGluaXRpYWxDb250ZXh0LCBldmVudERlZiwgZXZlbnRJbnN0YW5jZSk7XG4gICAgICAgICAgICAgICAgbGV0IHJlbGV2YW50RXZlbnRzID0gdGhpcy5yZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgICAgICBsZXQgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgbGV0IHsgZmluYWxIaXQgfSA9IHRoaXMuaGl0RHJhZ2dpbmc7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhckRyYWcoKTsgLy8gbXVzdCBoYXBwZW4gYWZ0ZXIgcmV2ZXJ0IGFuaW1hdGlvblxuICAgICAgICAgICAgICAgIGluaXRpYWxDb250ZXh0LmVtaXR0ZXIudHJpZ2dlcignZXZlbnREcmFnU3RvcCcsIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IHRoaXMuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogaW5pdGlhbFZpZXcsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbGlkTXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZHJvcHBlZCB3aXRoaW4gc2FtZSBjYWxlbmRhclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVjZWl2aW5nQ29udGV4dCA9PT0gaW5pdGlhbENvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB1cGRhdGVkRXZlbnRBcGkgPSBuZXcgRXZlbnRJbXBsKGluaXRpYWxDb250ZXh0LCBtdXRhdGVkUmVsZXZhbnRFdmVudHMuZGVmc1tldmVudERlZi5kZWZJZF0sIGV2ZW50SW5zdGFuY2UgPyBtdXRhdGVkUmVsZXZhbnRFdmVudHMuaW5zdGFuY2VzW2V2ZW50SW5zdGFuY2UuaW5zdGFuY2VJZF0gOiBudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBtdXRhdGVkUmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBldmVudENoYW5nZUFyZyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRFdmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IHVwZGF0ZWRFdmVudEFwaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxhdGVkRXZlbnRzOiBidWlsZEV2ZW50QXBpcyhtdXRhdGVkUmVsZXZhbnRFdmVudHMsIGluaXRpYWxDb250ZXh0LCBldmVudEluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZlcnQoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogcmVsZXZhbnRFdmVudHMsIC8vIHRoZSBwcmUtY2hhbmdlIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdHJhbnNmb3JtZWQgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHRyYW5zZm9ybWVyIG9mIGluaXRpYWxDb250ZXh0LmdldEN1cnJlbnREYXRhKCkucGx1Z2luSG9va3MuZXZlbnREcm9wVHJhbnNmb3JtZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbih0cmFuc2Zvcm1lZCwgdHJhbnNmb3JtZXIodmFsaWRNdXRhdGlvbiwgaW5pdGlhbENvbnRleHQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDb250ZXh0LmVtaXR0ZXIudHJpZ2dlcignZXZlbnREcm9wJywgT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGV2ZW50Q2hhbmdlQXJnKSwgdHJhbnNmb3JtZWQpLCB7IGVsOiBldi5zdWJqZWN0RWwsIGRlbHRhOiB2YWxpZE11dGF0aW9uLmRhdGVzRGVsdGEsIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCwgdmlldzogaW5pdGlhbFZpZXcgfSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudENoYW5nZScsIGV2ZW50Q2hhbmdlQXJnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRyb3BwZWQgaW4gZGlmZmVyZW50IGNhbGVuZGFyXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAocmVjZWl2aW5nQ29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGV2ZW50UmVtb3ZlQXJnID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBldmVudEFwaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxhdGVkRXZlbnRzOiBidWlsZEV2ZW50QXBpcyhyZWxldmFudEV2ZW50cywgaW5pdGlhbENvbnRleHQsIGV2ZW50SW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldmVydCgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiByZWxldmFudEV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2V2ZW50TGVhdmUnLCBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGV2ZW50UmVtb3ZlQXJnKSwgeyBkcmFnZ2VkRWw6IGV2LnN1YmplY3RFbCwgdmlldzogaW5pdGlhbFZpZXcgfSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiByZWxldmFudEV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudFJlbW92ZScsIGV2ZW50UmVtb3ZlQXJnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhZGRlZEV2ZW50RGVmID0gbXV0YXRlZFJlbGV2YW50RXZlbnRzLmRlZnNbZXZlbnREZWYuZGVmSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFkZGVkRXZlbnRJbnN0YW5jZSA9IG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhZGRlZEV2ZW50QXBpID0gbmV3IEV2ZW50SW1wbChyZWNlaXZpbmdDb250ZXh0LCBhZGRlZEV2ZW50RGVmLCBhZGRlZEV2ZW50SW5zdGFuY2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogbXV0YXRlZFJlbGV2YW50RXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXZlbnRBZGRBcmcgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGFkZGVkRXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRlZEV2ZW50czogYnVpbGRFdmVudEFwaXMobXV0YXRlZFJlbGV2YW50RXZlbnRzLCByZWNlaXZpbmdDb250ZXh0LCBhZGRlZEV2ZW50SW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldmVydCgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnUkVNT1ZFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBtdXRhdGVkUmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2V2ZW50QWRkJywgZXZlbnRBZGRBcmcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2LmlzVG91Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFTEVDVF9FVkVOVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50SW5zdGFuY2VJZDogZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2Ryb3AnLCBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJ1aWxkRGF0ZVBvaW50QXBpV2l0aENvbnRleHQoZmluYWxIaXQuZGF0ZVNwYW4sIHJlY2VpdmluZ0NvbnRleHQpKSwgeyBkcmFnZ2VkRWw6IGV2LnN1YmplY3RFbCwganNFdmVudDogZXYub3JpZ0V2ZW50LCB2aWV3OiBmaW5hbEhpdC5jb250ZXh0LnZpZXdBcGkgfSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2V2ZW50UmVjZWl2ZScsIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnRBZGRBcmcpLCB7IGRyYWdnZWRFbDogZXYuc3ViamVjdEVsLCB2aWV3OiBmaW5hbEhpdC5jb250ZXh0LnZpZXdBcGkgfSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ19ub0V2ZW50RHJvcCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY2xlYW51cCgpO1xuICAgICAgICB9O1xuICAgICAgICBsZXQgeyBjb21wb25lbnQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICBsZXQgZHJhZ2dpbmcgPSB0aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoc2V0dGluZ3MuZWwpO1xuICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gRXZlbnREcmFnZ2luZy5TRUxFQ1RPUjtcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGRyYWdnaW5nLmF1dG9TY3JvbGxlci5pc0VuYWJsZWQgPSBvcHRpb25zLmRyYWdTY3JvbGw7XG4gICAgICAgIGxldCBoaXREcmFnZ2luZyA9IHRoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcodGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcudXNlU3ViamVjdENlbnRlciA9IHNldHRpbmdzLnVzZUV2ZW50Q2VudGVyO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIHRoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcnVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnZW5kJywgdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfVxuICAgIC8vIHJlbmRlciBhIGRyYWcgc3RhdGUgb24gdGhlIG5leHQgcmVjZWl2aW5nQ2FsZW5kYXJcbiAgICBkaXNwbGF5RHJhZyhuZXh0Q29udGV4dCwgc3RhdGUpIHtcbiAgICAgICAgbGV0IGluaXRpYWxDb250ZXh0ID0gdGhpcy5jb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgbGV0IHByZXZDb250ZXh0ID0gdGhpcy5yZWNlaXZpbmdDb250ZXh0O1xuICAgICAgICAvLyBkb2VzIHRoZSBwcmV2aW91cyBjYWxlbmRhciBuZWVkIHRvIGJlIGNsZWFyZWQ/XG4gICAgICAgIGlmIChwcmV2Q29udGV4dCAmJiBwcmV2Q29udGV4dCAhPT0gbmV4dENvbnRleHQpIHtcbiAgICAgICAgICAgIC8vIGRvZXMgdGhlIGluaXRpYWwgY2FsZW5kYXIgbmVlZCB0byBiZSBjbGVhcmVkP1xuICAgICAgICAgICAgLy8gaWYgc28sIGRvbid0IGNsZWFyIGFsbCB0aGUgd2F5LiB3ZSBzdGlsbCBuZWVkIHRvIHRvIGhpZGUgdGhlIGFmZmVjdGVkRXZlbnRzXG4gICAgICAgICAgICBpZiAocHJldkNvbnRleHQgPT09IGluaXRpYWxDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgcHJldkNvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX0VWRU5UX0RSQUcnLFxuICAgICAgICAgICAgICAgICAgICBzdGF0ZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IHN0YXRlLmFmZmVjdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0V2ZW50OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIGNvbXBsZXRlbHkgY2xlYXIgdGhlIG9sZCBjYWxlbmRhciBpZiBpdCB3YXNuJ3QgdGhlIGluaXRpYWxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHByZXZDb250ZXh0LmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0Q29udGV4dCkge1xuICAgICAgICAgICAgbmV4dENvbnRleHQuZGlzcGF0Y2goeyB0eXBlOiAnU0VUX0VWRU5UX0RSQUcnLCBzdGF0ZSB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjbGVhckRyYWcoKSB7XG4gICAgICAgIGxldCBpbml0aWFsQ2FsZW5kYXIgPSB0aGlzLmNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICBsZXQgeyByZWNlaXZpbmdDb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBpZiAocmVjZWl2aW5nQ29udGV4dCkge1xuICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGUgaW5pdGlhbCBjYWxlbmRhciBtaWdodCBoYXZlIGFuIGR1bW15IGRyYWcgc3RhdGUgZnJvbSBkaXNwbGF5RHJhZ1xuICAgICAgICBpZiAoaW5pdGlhbENhbGVuZGFyICE9PSByZWNlaXZpbmdDb250ZXh0KSB7XG4gICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfRFJBRycgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY2xlYW51cCgpIHtcbiAgICAgICAgdGhpcy5zdWJqZWN0U2VnID0gbnVsbDtcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlbnRSYW5nZSA9IG51bGw7XG4gICAgICAgIHRoaXMucmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICB0aGlzLnJlY2VpdmluZ0NvbnRleHQgPSBudWxsO1xuICAgICAgICB0aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgfVxufVxuLy8gVE9ETzogdGVzdCB0aGlzIGluIElFMTFcbi8vIFFVRVNUSU9OOiB3aHkgZG8gd2UgbmVlZCBpdCBvbiB0aGUgcmVzaXphYmxlPz8/XG5FdmVudERyYWdnaW5nLlNFTEVDVE9SID0gJy5mYy1ldmVudC1kcmFnZ2FibGUsIC5mYy1ldmVudC1yZXNpemFibGUnO1xuZnVuY3Rpb24gY29tcHV0ZUV2ZW50TXV0YXRpb24oaGl0MCwgaGl0MSwgZXZlbnRJbnN0YW5jZVN0YXJ0LCBtYXNzYWdlcnMpIHtcbiAgICBsZXQgZGF0ZVNwYW4wID0gaGl0MC5kYXRlU3BhbjtcbiAgICBsZXQgZGF0ZVNwYW4xID0gaGl0MS5kYXRlU3BhbjtcbiAgICBsZXQgZGF0ZTAgPSBkYXRlU3BhbjAucmFuZ2Uuc3RhcnQ7XG4gICAgbGV0IGRhdGUxID0gZGF0ZVNwYW4xLnJhbmdlLnN0YXJ0O1xuICAgIGxldCBzdGFuZGFyZFByb3BzID0ge307XG4gICAgaWYgKGRhdGVTcGFuMC5hbGxEYXkgIT09IGRhdGVTcGFuMS5hbGxEYXkpIHtcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5hbGxEYXkgPSBkYXRlU3BhbjEuYWxsRGF5O1xuICAgICAgICBzdGFuZGFyZFByb3BzLmhhc0VuZCA9IGhpdDEuY29udGV4dC5vcHRpb25zLmFsbERheU1haW50YWluRHVyYXRpb247XG4gICAgICAgIGlmIChkYXRlU3BhbjEuYWxsRGF5KSB7XG4gICAgICAgICAgICAvLyBtZWFucyBkYXRlMSBpcyBhbHJlYWR5IHN0YXJ0LW9mLWRheSxcbiAgICAgICAgICAgIC8vIGJ1dCBkYXRlMCBuZWVkcyB0byBiZSBjb252ZXJ0ZWRcbiAgICAgICAgICAgIGRhdGUwID0gc3RhcnRPZkRheShldmVudEluc3RhbmNlU3RhcnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gTW92aW5nIGZyb20gYWxsRGF0ZS0+dGltZWRcbiAgICAgICAgICAgIC8vIERvZXNuJ3QgbWF0dGVyIHdoZXJlIG9uIHRoZSBldmVudCB0aGUgZHJhZyBiZWdhbiwgbXV0YXRlIHRoZSBldmVudCdzIHN0YXJ0LWRhdGUgdG8gZGF0ZTFcbiAgICAgICAgICAgIGRhdGUwID0gZXZlbnRJbnN0YW5jZVN0YXJ0O1xuICAgICAgICB9XG4gICAgfVxuICAgIGxldCBkZWx0YSA9IGRpZmZEYXRlcyhkYXRlMCwgZGF0ZTEsIGhpdDAuY29udGV4dC5kYXRlRW52LCBoaXQwLmNvbXBvbmVudElkID09PSBoaXQxLmNvbXBvbmVudElkID9cbiAgICAgICAgaGl0MC5sYXJnZVVuaXQgOlxuICAgICAgICBudWxsKTtcbiAgICBpZiAoZGVsdGEubWlsbGlzZWNvbmRzKSB7IC8vIGhhcyBob3Vycy9taW51dGVzL3NlY29uZHNcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5hbGxEYXkgPSBmYWxzZTtcbiAgICB9XG4gICAgbGV0IG11dGF0aW9uID0ge1xuICAgICAgICBkYXRlc0RlbHRhOiBkZWx0YSxcbiAgICAgICAgc3RhbmRhcmRQcm9wcyxcbiAgICB9O1xuICAgIGZvciAobGV0IG1hc3NhZ2VyIG9mIG1hc3NhZ2Vycykge1xuICAgICAgICBtYXNzYWdlcihtdXRhdGlvbiwgaGl0MCwgaGl0MSk7XG4gICAgfVxuICAgIHJldHVybiBtdXRhdGlvbjtcbn1cbmZ1bmN0aW9uIGdldENvbXBvbmVudFRvdWNoRGVsYXkoY29tcG9uZW50KSB7XG4gICAgbGV0IHsgb3B0aW9ucyB9ID0gY29tcG9uZW50LmNvbnRleHQ7XG4gICAgbGV0IGRlbGF5ID0gb3B0aW9ucy5ldmVudExvbmdQcmVzc0RlbGF5O1xuICAgIGlmIChkZWxheSA9PSBudWxsKSB7XG4gICAgICAgIGRlbGF5ID0gb3B0aW9ucy5sb25nUHJlc3NEZWxheTtcbiAgICB9XG4gICAgcmV0dXJuIGRlbGF5O1xufVxuXG5jbGFzcyBFdmVudFJlc2l6aW5nIGV4dGVuZHMgSW50ZXJhY3Rpb24ge1xuICAgIGNvbnN0cnVjdG9yKHNldHRpbmdzKSB7XG4gICAgICAgIHN1cGVyKHNldHRpbmdzKTtcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgdGhpcy5kcmFnZ2luZ1NlZ0VsID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnZ2luZ1NlZyA9IG51bGw7IC8vIFRPRE86IHJlbmFtZSB0byByZXNpemluZ1NlZz8gc3ViamVjdFNlZz9cbiAgICAgICAgdGhpcy5ldmVudFJhbmdlID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIHRoaXMudmFsaWRNdXRhdGlvbiA9IG51bGw7XG4gICAgICAgIHRoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IHsgY29tcG9uZW50IH0gPSB0aGlzO1xuICAgICAgICAgICAgbGV0IHNlZ0VsID0gdGhpcy5xdWVyeVNlZ0VsKGV2KTtcbiAgICAgICAgICAgIGxldCBzZWcgPSBnZXRFbFNlZyhzZWdFbCk7XG4gICAgICAgICAgICBsZXQgZXZlbnRSYW5nZSA9IHRoaXMuZXZlbnRSYW5nZSA9IHNlZy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgdGhpcy5kcmFnZ2luZy5taW5EaXN0YW5jZSA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnMuZXZlbnREcmFnTWluRGlzdGFuY2U7XG4gICAgICAgICAgICAvLyBpZiB0b3VjaCwgbmVlZCB0byBiZSB3b3JraW5nIHdpdGggYSBzZWxlY3RlZCBldmVudFxuICAgICAgICAgICAgdGhpcy5kcmFnZ2luZy5zZXRJZ25vcmVNb3ZlKCF0aGlzLmNvbXBvbmVudC5pc1ZhbGlkU2VnRG93bkVsKGV2Lm9yaWdFdmVudC50YXJnZXQpIHx8XG4gICAgICAgICAgICAgICAgKGV2LmlzVG91Y2ggJiYgdGhpcy5jb21wb25lbnQucHJvcHMuZXZlbnRTZWxlY3Rpb24gIT09IGV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZCkpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdTdGFydCA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IHsgY29udGV4dCB9ID0gdGhpcy5jb21wb25lbnQ7XG4gICAgICAgICAgICBsZXQgZXZlbnRSYW5nZSA9IHRoaXMuZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIHRoaXMucmVsZXZhbnRFdmVudHMgPSBnZXRSZWxldmFudEV2ZW50cyhjb250ZXh0LmdldEN1cnJlbnREYXRhKCkuZXZlbnRTdG9yZSwgdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWQpO1xuICAgICAgICAgICAgbGV0IHNlZ0VsID0gdGhpcy5xdWVyeVNlZ0VsKGV2KTtcbiAgICAgICAgICAgIHRoaXMuZHJhZ2dpbmdTZWdFbCA9IHNlZ0VsO1xuICAgICAgICAgICAgdGhpcy5kcmFnZ2luZ1NlZyA9IGdldEVsU2VnKHNlZ0VsKTtcbiAgICAgICAgICAgIGNvbnRleHQuY2FsZW5kYXJBcGkudW5zZWxlY3QoKTtcbiAgICAgICAgICAgIGNvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudFJlc2l6ZVN0YXJ0Jywge1xuICAgICAgICAgICAgICAgIGVsOiBzZWdFbCxcbiAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50SW1wbChjb250ZXh0LCBldmVudFJhbmdlLmRlZiwgZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICAgICAganNFdmVudDogZXYub3JpZ0V2ZW50LFxuICAgICAgICAgICAgICAgIHZpZXc6IGNvbnRleHQudmlld0FwaSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZUhpdFVwZGF0ZSA9IChoaXQsIGlzRmluYWwsIGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBjb250ZXh0IH0gPSB0aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIGxldCByZWxldmFudEV2ZW50cyA9IHRoaXMucmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICBsZXQgaW5pdGlhbEhpdCA9IHRoaXMuaGl0RHJhZ2dpbmcuaW5pdGlhbEhpdDtcbiAgICAgICAgICAgIGxldCBldmVudEluc3RhbmNlID0gdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICAgICAgbGV0IG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgbGV0IGlzSW52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGludGVyYWN0aW9uID0ge1xuICAgICAgICAgICAgICAgIGFmZmVjdGVkRXZlbnRzOiByZWxldmFudEV2ZW50cyxcbiAgICAgICAgICAgICAgICBtdXRhdGVkRXZlbnRzOiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKSxcbiAgICAgICAgICAgICAgICBpc0V2ZW50OiB0cnVlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChoaXQpIHtcbiAgICAgICAgICAgICAgICBsZXQgZGlzYWxsb3dlZCA9IGhpdC5jb21wb25lbnRJZCA9PT0gaW5pdGlhbEhpdC5jb21wb25lbnRJZFxuICAgICAgICAgICAgICAgICAgICAmJiB0aGlzLmlzSGl0Q29tYm9BbGxvd2VkXG4gICAgICAgICAgICAgICAgICAgICYmICF0aGlzLmlzSGl0Q29tYm9BbGxvd2VkKGluaXRpYWxIaXQsIGhpdCk7XG4gICAgICAgICAgICAgICAgaWYgKCFkaXNhbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gY29tcHV0ZU11dGF0aW9uKGluaXRpYWxIaXQsIGhpdCwgZXYuc3ViamVjdEVsLmNsYXNzTGlzdC5jb250YWlucygnZmMtZXZlbnQtcmVzaXplci1zdGFydCcpLCBldmVudEluc3RhbmNlLnJhbmdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlKHJlbGV2YW50RXZlbnRzLCBjb250ZXh0LmdldEN1cnJlbnREYXRhKCkuZXZlbnRVaUJhc2VzLCBtdXRhdGlvbiwgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgICAgICBpZiAoIWlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbiwgaGl0LmRhdGVQcm9maWxlLCBjb250ZXh0KSkge1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtdXRhdGVkUmVsZXZhbnRFdmVudHMpIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9FVkVOVF9SRVNJWkUnLFxuICAgICAgICAgICAgICAgICAgICBzdGF0ZTogaW50ZXJhY3Rpb24sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX1JFU0laRScgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKG11dGF0aW9uICYmIGlzSGl0c0VxdWFsKGluaXRpYWxIaXQsIGhpdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRpb24gPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnZhbGlkTXV0YXRpb24gPSBtdXRhdGlvbjtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVEcmFnRW5kID0gKGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBjb250ZXh0IH0gPSB0aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIGxldCBldmVudERlZiA9IHRoaXMuZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgICAgICBsZXQgZXZlbnRJbnN0YW5jZSA9IHRoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZTtcbiAgICAgICAgICAgIGxldCBldmVudEFwaSA9IG5ldyBFdmVudEltcGwoY29udGV4dCwgZXZlbnREZWYsIGV2ZW50SW5zdGFuY2UpO1xuICAgICAgICAgICAgbGV0IHJlbGV2YW50RXZlbnRzID0gdGhpcy5yZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIGxldCBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSB0aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIGNvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudFJlc2l6ZVN0b3AnLCB7XG4gICAgICAgICAgICAgICAgZWw6IHRoaXMuZHJhZ2dpbmdTZWdFbCxcbiAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAganNFdmVudDogZXYub3JpZ0V2ZW50LFxuICAgICAgICAgICAgICAgIHZpZXc6IGNvbnRleHQudmlld0FwaSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMudmFsaWRNdXRhdGlvbikge1xuICAgICAgICAgICAgICAgIGxldCB1cGRhdGVkRXZlbnRBcGkgPSBuZXcgRXZlbnRJbXBsKGNvbnRleHQsIG11dGF0ZWRSZWxldmFudEV2ZW50cy5kZWZzW2V2ZW50RGVmLmRlZklkXSwgZXZlbnRJbnN0YW5jZSA/IG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSA6IG51bGwpO1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogbXV0YXRlZFJlbGV2YW50RXZlbnRzLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGxldCBldmVudENoYW5nZUFyZyA9IHtcbiAgICAgICAgICAgICAgICAgICAgb2xkRXZlbnQ6IGV2ZW50QXBpLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogdXBkYXRlZEV2ZW50QXBpLFxuICAgICAgICAgICAgICAgICAgICByZWxhdGVkRXZlbnRzOiBidWlsZEV2ZW50QXBpcyhtdXRhdGVkUmVsZXZhbnRFdmVudHMsIGNvbnRleHQsIGV2ZW50SW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICByZXZlcnQoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiByZWxldmFudEV2ZW50cywgLy8gdGhlIHByZS1jaGFuZ2UgZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZW1pdHRlci50cmlnZ2VyKCdldmVudFJlc2l6ZScsIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnRDaGFuZ2VBcmcpLCB7IGVsOiB0aGlzLmRyYWdnaW5nU2VnRWwsIHN0YXJ0RGVsdGE6IHRoaXMudmFsaWRNdXRhdGlvbi5zdGFydERlbHRhIHx8IGNyZWF0ZUR1cmF0aW9uKDApLCBlbmREZWx0YTogdGhpcy52YWxpZE11dGF0aW9uLmVuZERlbHRhIHx8IGNyZWF0ZUR1cmF0aW9uKDApLCBqc0V2ZW50OiBldi5vcmlnRXZlbnQsIHZpZXc6IGNvbnRleHQudmlld0FwaSB9KSk7XG4gICAgICAgICAgICAgICAgY29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2V2ZW50Q2hhbmdlJywgZXZlbnRDaGFuZ2VBcmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ19ub0V2ZW50UmVzaXplJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByZXNldCBhbGwgaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgICAgIHRoaXMuZHJhZ2dpbmdTZWcgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICAgICAgLy8gb2theSB0byBrZWVwIGV2ZW50SW5zdGFuY2UgYXJvdW5kLiB1c2VmdWwgdG8gc2V0IGl0IGluIGhhbmRsZVBvaW50ZXJEb3duXG4gICAgICAgIH07XG4gICAgICAgIGxldCB7IGNvbXBvbmVudCB9ID0gc2V0dGluZ3M7XG4gICAgICAgIGxldCBkcmFnZ2luZyA9IHRoaXMuZHJhZ2dpbmcgPSBuZXcgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhzZXR0aW5ncy5lbCk7XG4gICAgICAgIGRyYWdnaW5nLnBvaW50ZXIuc2VsZWN0b3IgPSAnLmZjLWV2ZW50LXJlc2l6ZXInO1xuICAgICAgICBkcmFnZ2luZy50b3VjaFNjcm9sbEFsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgZHJhZ2dpbmcuYXV0b1Njcm9sbGVyLmlzRW5hYmxlZCA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnMuZHJhZ1Njcm9sbDtcbiAgICAgICAgbGV0IGhpdERyYWdnaW5nID0gdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyh0aGlzLmRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIHRoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIHRoaXMuaGFuZGxlRHJhZ0VuZCk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH1cbiAgICBxdWVyeVNlZ0VsKGV2KSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50Q2xvc2VzdChldi5zdWJqZWN0RWwsICcuZmMtZXZlbnQnKTtcbiAgICB9XG59XG5mdW5jdGlvbiBjb21wdXRlTXV0YXRpb24oaGl0MCwgaGl0MSwgaXNGcm9tU3RhcnQsIGluc3RhbmNlUmFuZ2UpIHtcbiAgICBsZXQgZGF0ZUVudiA9IGhpdDAuY29udGV4dC5kYXRlRW52O1xuICAgIGxldCBkYXRlMCA9IGhpdDAuZGF0ZVNwYW4ucmFuZ2Uuc3RhcnQ7XG4gICAgbGV0IGRhdGUxID0gaGl0MS5kYXRlU3Bhbi5yYW5nZS5zdGFydDtcbiAgICBsZXQgZGVsdGEgPSBkaWZmRGF0ZXMoZGF0ZTAsIGRhdGUxLCBkYXRlRW52LCBoaXQwLmxhcmdlVW5pdCk7XG4gICAgaWYgKGlzRnJvbVN0YXJ0KSB7XG4gICAgICAgIGlmIChkYXRlRW52LmFkZChpbnN0YW5jZVJhbmdlLnN0YXJ0LCBkZWx0YSkgPCBpbnN0YW5jZVJhbmdlLmVuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3RhcnREZWx0YTogZGVsdGEgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmIChkYXRlRW52LmFkZChpbnN0YW5jZVJhbmdlLmVuZCwgZGVsdGEpID4gaW5zdGFuY2VSYW5nZS5zdGFydCkge1xuICAgICAgICByZXR1cm4geyBlbmREZWx0YTogZGVsdGEgfTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmNsYXNzIFVuc2VsZWN0QXV0byB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCkge1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB0aGlzLmlzUmVjZW50UG9pbnRlckRhdGVTZWxlY3QgPSBmYWxzZTsgLy8gd2lzaCB3ZSBjb3VsZCB1c2UgYSBzZWxlY3RvciB0byBkZXRlY3QgZGF0ZSBzZWxlY3Rpb24sIGJ1dCB1c2VzIGhpdCBzeXN0ZW1cbiAgICAgICAgdGhpcy5tYXRjaGVzQ2FuY2VsID0gZmFsc2U7XG4gICAgICAgIHRoaXMubWF0Y2hlc0V2ZW50ID0gZmFsc2U7XG4gICAgICAgIHRoaXMub25TZWxlY3QgPSAoc2VsZWN0SW5mbykgPT4ge1xuICAgICAgICAgICAgaWYgKHNlbGVjdEluZm8uanNFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNSZWNlbnRQb2ludGVyRGF0ZVNlbGVjdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMub25Eb2N1bWVudFBvaW50ZXJEb3duID0gKHBldikgPT4ge1xuICAgICAgICAgICAgbGV0IHVuc2VsZWN0Q2FuY2VsID0gdGhpcy5jb250ZXh0Lm9wdGlvbnMudW5zZWxlY3RDYW5jZWw7XG4gICAgICAgICAgICBsZXQgZG93bkVsID0gZ2V0RXZlbnRUYXJnZXRWaWFSb290KHBldi5vcmlnRXZlbnQpO1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzQ2FuY2VsID0gISFlbGVtZW50Q2xvc2VzdChkb3duRWwsIHVuc2VsZWN0Q2FuY2VsKTtcbiAgICAgICAgICAgIHRoaXMubWF0Y2hlc0V2ZW50ID0gISFlbGVtZW50Q2xvc2VzdChkb3duRWwsIEV2ZW50RHJhZ2dpbmcuU0VMRUNUT1IpOyAvLyBpbnRlcmFjdGlvbiBzdGFydGVkIG9uIGFuIGV2ZW50P1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLm9uRG9jdW1lbnRQb2ludGVyVXAgPSAocGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICAgICAgbGV0IHsgZG9jdW1lbnRQb2ludGVyIH0gPSB0aGlzO1xuICAgICAgICAgICAgbGV0IGNhbGVuZGFyU3RhdGUgPSBjb250ZXh0LmdldEN1cnJlbnREYXRhKCk7XG4gICAgICAgICAgICAvLyB0b3VjaC1zY3JvbGxpbmcgc2hvdWxkIG5ldmVyIHVuZm9jdXMgYW55IHR5cGUgb2Ygc2VsZWN0aW9uXG4gICAgICAgICAgICBpZiAoIWRvY3VtZW50UG9pbnRlci53YXNUb3VjaFNjcm9sbCkge1xuICAgICAgICAgICAgICAgIGlmIChjYWxlbmRhclN0YXRlLmRhdGVTZWxlY3Rpb24gJiYgLy8gYW4gZXhpc3RpbmcgZGF0ZSBzZWxlY3Rpb24/XG4gICAgICAgICAgICAgICAgICAgICF0aGlzLmlzUmVjZW50UG9pbnRlckRhdGVTZWxlY3QgLy8gYSBuZXcgcG9pbnRlci1pbml0aWF0ZWQgZGF0ZSBzZWxlY3Rpb24gc2luY2UgbGFzdCBvbkRvY3VtZW50UG9pbnRlclVwP1xuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgdW5zZWxlY3RBdXRvID0gY29udGV4dC5vcHRpb25zLnVuc2VsZWN0QXV0bztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVuc2VsZWN0QXV0byAmJiAoIXVuc2VsZWN0QXV0byB8fCAhdGhpcy5tYXRjaGVzQ2FuY2VsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC5jYWxlbmRhckFwaS51bnNlbGVjdChwZXYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjYWxlbmRhclN0YXRlLmV2ZW50U2VsZWN0aW9uICYmIC8vIGFuIGV4aXN0aW5nIGV2ZW50IHNlbGVjdGVkP1xuICAgICAgICAgICAgICAgICAgICAhdGhpcy5tYXRjaGVzRXZlbnQgLy8gaW50ZXJhY3Rpb24gRElETidUIHN0YXJ0IG9uIGFuIGV2ZW50XG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRUxFQ1RfRVZFTlQnIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaXNSZWNlbnRQb2ludGVyRGF0ZVNlbGVjdCA9IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICBsZXQgZG9jdW1lbnRQb2ludGVyID0gdGhpcy5kb2N1bWVudFBvaW50ZXIgPSBuZXcgUG9pbnRlckRyYWdnaW5nKGRvY3VtZW50KTtcbiAgICAgICAgZG9jdW1lbnRQb2ludGVyLnNob3VsZElnbm9yZU1vdmUgPSB0cnVlO1xuICAgICAgICBkb2N1bWVudFBvaW50ZXIuc2hvdWxkV2F0Y2hTY3JvbGwgPSBmYWxzZTtcbiAgICAgICAgZG9jdW1lbnRQb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgdGhpcy5vbkRvY3VtZW50UG9pbnRlckRvd24pO1xuICAgICAgICBkb2N1bWVudFBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcnVwJywgdGhpcy5vbkRvY3VtZW50UG9pbnRlclVwKTtcbiAgICAgICAgLypcbiAgICAgICAgVE9ETzogYmV0dGVyIHdheSB0byBrbm93IGFib3V0IHdoZXRoZXIgdGhlcmUgd2FzIGEgc2VsZWN0aW9uIHdpdGggdGhlIHBvaW50ZXJcbiAgICAgICAgKi9cbiAgICAgICAgY29udGV4dC5lbWl0dGVyLm9uKCdzZWxlY3QnLCB0aGlzLm9uU2VsZWN0KTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0LmVtaXR0ZXIub2ZmKCdzZWxlY3QnLCB0aGlzLm9uU2VsZWN0KTtcbiAgICAgICAgdGhpcy5kb2N1bWVudFBvaW50ZXIuZGVzdHJveSgpO1xuICAgIH1cbn1cblxuY29uc3QgT1BUSU9OX1JFRklORVJTID0ge1xuICAgIGZpeGVkTWlycm9yUGFyZW50OiBpZGVudGl0eSxcbn07XG5jb25zdCBMSVNURU5FUl9SRUZJTkVSUyA9IHtcbiAgICBkYXRlQ2xpY2s6IGlkZW50aXR5LFxuICAgIGV2ZW50RHJhZ1N0YXJ0OiBpZGVudGl0eSxcbiAgICBldmVudERyYWdTdG9wOiBpZGVudGl0eSxcbiAgICBldmVudERyb3A6IGlkZW50aXR5LFxuICAgIGV2ZW50UmVzaXplU3RhcnQ6IGlkZW50aXR5LFxuICAgIGV2ZW50UmVzaXplU3RvcDogaWRlbnRpdHksXG4gICAgZXZlbnRSZXNpemU6IGlkZW50aXR5LFxuICAgIGRyb3A6IGlkZW50aXR5LFxuICAgIGV2ZW50UmVjZWl2ZTogaWRlbnRpdHksXG4gICAgZXZlbnRMZWF2ZTogaWRlbnRpdHksXG59O1xuXG4vKlxuR2l2ZW4gYW4gYWxyZWFkeSBpbnN0YW50aWF0ZWQgZHJhZ2dhYmxlIG9iamVjdCBmb3Igb25lLW9yLW1vcmUgZWxlbWVudHMsXG5JbnRlcnByZXRzIGFueSBkcmFnZ2luZyBhcyBhbiBhdHRlbXB0IHRvIGRyYWcgYW4gZXZlbnRzIHRoYXQgbGl2ZXMgb3V0c2lkZVxub2YgYSBjYWxlbmRhciBvbnRvIGEgY2FsZW5kYXIuXG4qL1xuY2xhc3MgRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcge1xuICAgIGNvbnN0cnVjdG9yKGRyYWdnaW5nLCBzdXBwbGllZERyYWdNZXRhKSB7XG4gICAgICAgIHRoaXMucmVjZWl2aW5nQ29udGV4dCA9IG51bGw7XG4gICAgICAgIHRoaXMuZHJvcHBhYmxlRXZlbnQgPSBudWxsOyAvLyB3aWxsIGV4aXN0IGZvciBhbGwgZHJhZ3MsIGV2ZW4gaWYgY3JlYXRlOmZhbHNlXG4gICAgICAgIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9IG51bGw7XG4gICAgICAgIHRoaXMuZHJhZ01ldGEgPSBudWxsO1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdTdGFydCA9IChldikgPT4ge1xuICAgICAgICAgICAgdGhpcy5kcmFnTWV0YSA9IHRoaXMuYnVpbGREcmFnTWV0YShldi5zdWJqZWN0RWwpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZUhpdFVwZGF0ZSA9IChoaXQsIGlzRmluYWwsIGV2KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBkcmFnZ2luZyB9ID0gdGhpcy5oaXREcmFnZ2luZztcbiAgICAgICAgICAgIGxldCByZWNlaXZpbmdDb250ZXh0ID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBkcm9wcGFibGVFdmVudCA9IG51bGw7XG4gICAgICAgICAgICBsZXQgaXNJbnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgaW50ZXJhY3Rpb24gPSB7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IHRoaXMuZHJhZ01ldGEuY3JlYXRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChoaXQpIHtcbiAgICAgICAgICAgICAgICByZWNlaXZpbmdDb250ZXh0ID0gaGl0LmNvbnRleHQ7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY2FuRHJvcEVsT25DYWxlbmRhcihldi5zdWJqZWN0RWwsIHJlY2VpdmluZ0NvbnRleHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyb3BwYWJsZUV2ZW50ID0gY29tcHV0ZUV2ZW50Rm9yRGF0ZVNwYW4oaGl0LmRhdGVTcGFuLCB0aGlzLmRyYWdNZXRhLCByZWNlaXZpbmdDb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IGV2ZW50VHVwbGVUb1N0b3JlKGRyb3BwYWJsZUV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkID0gIWlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbiwgaGl0LmRhdGVQcm9maWxlLCByZWNlaXZpbmdDb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZHJvcHBhYmxlRXZlbnQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kaXNwbGF5RHJhZyhyZWNlaXZpbmdDb250ZXh0LCBpbnRlcmFjdGlvbik7XG4gICAgICAgICAgICAvLyBzaG93IG1pcnJvciBpZiBubyBhbHJlYWR5LXJlbmRlcmVkIG1pcnJvciBlbGVtZW50IE9SIGlmIHdlIGFyZSBzaHV0dGluZyBkb3duIHRoZSBtaXJyb3IgKD8pXG4gICAgICAgICAgICAvLyBUT0RPOiB3aXNoIHdlIGNvdWxkIHNvbWVob3cgd2FpdCBmb3IgZGlzcGF0Y2ggdG8gZ3VhcmFudGVlIHJlbmRlclxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0TWlycm9ySXNWaXNpYmxlKGlzRmluYWwgfHwgIWRyb3BwYWJsZUV2ZW50IHx8ICFkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuZmMtZXZlbnQtbWlycm9yJykpO1xuICAgICAgICAgICAgaWYgKCFpc0ludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBlbmFibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpc2FibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNGaW5hbCkge1xuICAgICAgICAgICAgICAgIGRyYWdnaW5nLnNldE1pcnJvck5lZWRzUmV2ZXJ0KCFkcm9wcGFibGVFdmVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWNlaXZpbmdDb250ZXh0ID0gcmVjZWl2aW5nQ29udGV4dDtcbiAgICAgICAgICAgICAgICB0aGlzLmRyb3BwYWJsZUV2ZW50ID0gZHJvcHBhYmxlRXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IChwZXYpID0+IHtcbiAgICAgICAgICAgIGxldCB7IHJlY2VpdmluZ0NvbnRleHQsIGRyb3BwYWJsZUV2ZW50IH0gPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5jbGVhckRyYWcoKTtcbiAgICAgICAgICAgIGlmIChyZWNlaXZpbmdDb250ZXh0ICYmIGRyb3BwYWJsZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgbGV0IGZpbmFsSGl0ID0gdGhpcy5oaXREcmFnZ2luZy5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICBsZXQgZmluYWxWaWV3ID0gZmluYWxIaXQuY29udGV4dC52aWV3QXBpO1xuICAgICAgICAgICAgICAgIGxldCBkcmFnTWV0YSA9IHRoaXMuZHJhZ01ldGE7XG4gICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2Ryb3AnLCBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJ1aWxkRGF0ZVBvaW50QXBpV2l0aENvbnRleHQoZmluYWxIaXQuZGF0ZVNwYW4sIHJlY2VpdmluZ0NvbnRleHQpKSwgeyBkcmFnZ2VkRWw6IHBldi5zdWJqZWN0RWwsIGpzRXZlbnQ6IHBldi5vcmlnRXZlbnQsIHZpZXc6IGZpbmFsVmlldyB9KSk7XG4gICAgICAgICAgICAgICAgaWYgKGRyYWdNZXRhLmNyZWF0ZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgYWRkaW5nRXZlbnRzID0gZXZlbnRUdXBsZVRvU3RvcmUoZHJvcHBhYmxlRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogYWRkaW5nRXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VMRUNUX0VWRU5UJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudEluc3RhbmNlSWQ6IGRyb3BwYWJsZUV2ZW50Lmluc3RhbmNlLmluc3RhbmNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBzaWduYWwgdGhhdCBhbiBleHRlcm5hbCBldmVudCBsYW5kZWRcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5lbWl0dGVyLnRyaWdnZXIoJ2V2ZW50UmVjZWl2ZScsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRJbXBsKHJlY2VpdmluZ0NvbnRleHQsIGRyb3BwYWJsZUV2ZW50LmRlZiwgZHJvcHBhYmxlRXZlbnQuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRlZEV2ZW50czogW10sXG4gICAgICAgICAgICAgICAgICAgICAgICByZXZlcnQoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogYWRkaW5nRXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRFbDogcGV2LnN1YmplY3RFbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGZpbmFsVmlldyxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZWNlaXZpbmdDb250ZXh0ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuZHJvcHBhYmxlRXZlbnQgPSBudWxsO1xuICAgICAgICB9O1xuICAgICAgICBsZXQgaGl0RHJhZ2dpbmcgPSB0aGlzLmhpdERyYWdnaW5nID0gbmV3IEhpdERyYWdnaW5nKGRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUpO1xuICAgICAgICBoaXREcmFnZ2luZy5yZXF1aXJlSW5pdGlhbCA9IGZhbHNlOyAvLyB3aWxsIHN0YXJ0IG91dHNpZGUgb2YgYSBjb21wb25lbnRcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgdGhpcy5oYW5kbGVEcmFnU3RhcnQpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdoaXR1cGRhdGUnLCB0aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdlbmQnLCB0aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICB0aGlzLnN1cHBsaWVkRHJhZ01ldGEgPSBzdXBwbGllZERyYWdNZXRhO1xuICAgIH1cbiAgICBidWlsZERyYWdNZXRhKHN1YmplY3RFbCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZURyYWdNZXRhKHRoaXMuc3VwcGxpZWREcmFnTWV0YSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnN1cHBsaWVkRHJhZ01ldGEgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZURyYWdNZXRhKHRoaXMuc3VwcGxpZWREcmFnTWV0YShzdWJqZWN0RWwpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ2V0RHJhZ01ldGFGcm9tRWwoc3ViamVjdEVsKTtcbiAgICB9XG4gICAgZGlzcGxheURyYWcobmV4dENvbnRleHQsIHN0YXRlKSB7XG4gICAgICAgIGxldCBwcmV2Q29udGV4dCA9IHRoaXMucmVjZWl2aW5nQ29udGV4dDtcbiAgICAgICAgaWYgKHByZXZDb250ZXh0ICYmIHByZXZDb250ZXh0ICE9PSBuZXh0Q29udGV4dCkge1xuICAgICAgICAgICAgcHJldkNvbnRleHQuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfRFJBRycgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5leHRDb250ZXh0KSB7XG4gICAgICAgICAgICBuZXh0Q29udGV4dC5kaXNwYXRjaCh7IHR5cGU6ICdTRVRfRVZFTlRfRFJBRycsIHN0YXRlIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNsZWFyRHJhZygpIHtcbiAgICAgICAgaWYgKHRoaXMucmVjZWl2aW5nQ29udGV4dCkge1xuICAgICAgICAgICAgdGhpcy5yZWNlaXZpbmdDb250ZXh0LmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNhbkRyb3BFbE9uQ2FsZW5kYXIoZWwsIHJlY2VpdmluZ0NvbnRleHQpIHtcbiAgICAgICAgbGV0IGRyb3BBY2NlcHQgPSByZWNlaXZpbmdDb250ZXh0Lm9wdGlvbnMuZHJvcEFjY2VwdDtcbiAgICAgICAgaWYgKHR5cGVvZiBkcm9wQWNjZXB0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gZHJvcEFjY2VwdC5jYWxsKHJlY2VpdmluZ0NvbnRleHQuY2FsZW5kYXJBcGksIGVsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGRyb3BBY2NlcHQgPT09ICdzdHJpbmcnICYmIGRyb3BBY2NlcHQpIHtcbiAgICAgICAgICAgIHJldHVybiBCb29sZWFuKGVsZW1lbnRNYXRjaGVzKGVsLCBkcm9wQWNjZXB0KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuLy8gVXRpbHMgZm9yIGNvbXB1dGluZyBldmVudCBzdG9yZSBmcm9tIHRoZSBEcmFnTWV0YVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gY29tcHV0ZUV2ZW50Rm9yRGF0ZVNwYW4oZGF0ZVNwYW4sIGRyYWdNZXRhLCBjb250ZXh0KSB7XG4gICAgbGV0IGRlZlByb3BzID0gT2JqZWN0LmFzc2lnbih7fSwgZHJhZ01ldGEubGVmdG92ZXJQcm9wcyk7XG4gICAgZm9yIChsZXQgdHJhbnNmb3JtIG9mIGNvbnRleHQucGx1Z2luSG9va3MuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zKSB7XG4gICAgICAgIE9iamVjdC5hc3NpZ24oZGVmUHJvcHMsIHRyYW5zZm9ybShkYXRlU3BhbiwgZHJhZ01ldGEpKTtcbiAgICB9XG4gICAgbGV0IHsgcmVmaW5lZCwgZXh0cmEgfSA9IHJlZmluZUV2ZW50RGVmKGRlZlByb3BzLCBjb250ZXh0KTtcbiAgICBsZXQgZGVmID0gcGFyc2VFdmVudERlZihyZWZpbmVkLCBleHRyYSwgZHJhZ01ldGEuc291cmNlSWQsIGRhdGVTcGFuLmFsbERheSwgY29udGV4dC5vcHRpb25zLmZvcmNlRXZlbnREdXJhdGlvbiB8fCBCb29sZWFuKGRyYWdNZXRhLmR1cmF0aW9uKSwgLy8gaGFzRW5kXG4gICAgY29udGV4dCk7XG4gICAgbGV0IHN0YXJ0ID0gZGF0ZVNwYW4ucmFuZ2Uuc3RhcnQ7XG4gICAgLy8gb25seSByZWx5IG9uIHRpbWUgaW5mbyBpZiBkcm9wIHpvbmUgaXMgYWxsLWRheSxcbiAgICAvLyBvdGhlcndpc2UsIHdlIGFscmVhZHkga25vdyB0aGUgdGltZVxuICAgIGlmIChkYXRlU3Bhbi5hbGxEYXkgJiYgZHJhZ01ldGEuc3RhcnRUaW1lKSB7XG4gICAgICAgIHN0YXJ0ID0gY29udGV4dC5kYXRlRW52LmFkZChzdGFydCwgZHJhZ01ldGEuc3RhcnRUaW1lKTtcbiAgICB9XG4gICAgbGV0IGVuZCA9IGRyYWdNZXRhLmR1cmF0aW9uID9cbiAgICAgICAgY29udGV4dC5kYXRlRW52LmFkZChzdGFydCwgZHJhZ01ldGEuZHVyYXRpb24pIDpcbiAgICAgICAgZ2V0RGVmYXVsdEV2ZW50RW5kKGRhdGVTcGFuLmFsbERheSwgc3RhcnQsIGNvbnRleHQpO1xuICAgIGxldCBpbnN0YW5jZSA9IGNyZWF0ZUV2ZW50SW5zdGFuY2UoZGVmLmRlZklkLCB7IHN0YXJ0LCBlbmQgfSk7XG4gICAgcmV0dXJuIHsgZGVmLCBpbnN0YW5jZSB9O1xufVxuLy8gVXRpbHMgZm9yIGV4dHJhY3RpbmcgZGF0YSBmcm9tIGVsZW1lbnRcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGdldERyYWdNZXRhRnJvbUVsKGVsKSB7XG4gICAgbGV0IHN0ciA9IGdldEVtYmVkZGVkRWxEYXRhKGVsLCAnZXZlbnQnKTtcbiAgICBsZXQgb2JqID0gc3RyID9cbiAgICAgICAgSlNPTi5wYXJzZShzdHIpIDpcbiAgICAgICAgeyBjcmVhdGU6IGZhbHNlIH07IC8vIGlmIG5vIGVtYmVkZGVkIGRhdGEsIGFzc3VtZSBubyBldmVudCBjcmVhdGlvblxuICAgIHJldHVybiBwYXJzZURyYWdNZXRhKG9iaik7XG59XG5jb25maWcuZGF0YUF0dHJQcmVmaXggPSAnJztcbmZ1bmN0aW9uIGdldEVtYmVkZGVkRWxEYXRhKGVsLCBuYW1lKSB7XG4gICAgbGV0IHByZWZpeCA9IGNvbmZpZy5kYXRhQXR0clByZWZpeDtcbiAgICBsZXQgcHJlZml4ZWROYW1lID0gKHByZWZpeCA/IHByZWZpeCArICctJyA6ICcnKSArIG5hbWU7XG4gICAgcmV0dXJuIGVsLmdldEF0dHJpYnV0ZSgnZGF0YS0nICsgcHJlZml4ZWROYW1lKSB8fCAnJztcbn1cblxuLypcbk1ha2VzIGFuIGVsZW1lbnQgKHRoYXQgaXMgKmV4dGVybmFsKiB0byBhbnkgY2FsZW5kYXIpIGRyYWdnYWJsZS5cbkNhbiBwYXNzIGluIGRhdGEgdGhhdCBkZXRlcm1pbmVzIGhvdyBhbiBldmVudCB3aWxsIGJlIGNyZWF0ZWQgd2hlbiBkcm9wcGVkIG9udG8gYSBjYWxlbmRhci5cbkxldmVyYWdlcyBGdWxsQ2FsZW5kYXIncyBpbnRlcm5hbCBkcmFnLW4tZHJvcCBmdW5jdGlvbmFsaXR5IFdJVEhPVVQgYSB0aGlyZC1wYXJ0eSBkcmFnIHN5c3RlbS5cbiovXG5jbGFzcyBFeHRlcm5hbERyYWdnYWJsZSB7XG4gICAgY29uc3RydWN0b3IoZWwsIHNldHRpbmdzID0ge30pIHtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgbGV0IHsgZHJhZ2dpbmcgfSA9IHRoaXM7XG4gICAgICAgICAgICBsZXQgeyBtaW5EaXN0YW5jZSwgbG9uZ1ByZXNzRGVsYXkgfSA9IHRoaXMuc2V0dGluZ3M7XG4gICAgICAgICAgICBkcmFnZ2luZy5taW5EaXN0YW5jZSA9XG4gICAgICAgICAgICAgICAgbWluRGlzdGFuY2UgIT0gbnVsbCA/XG4gICAgICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlIDpcbiAgICAgICAgICAgICAgICAgICAgKGV2LmlzVG91Y2ggPyAwIDogQkFTRV9PUFRJT05fREVGQVVMVFMuZXZlbnREcmFnTWluRGlzdGFuY2UpO1xuICAgICAgICAgICAgZHJhZ2dpbmcuZGVsYXkgPVxuICAgICAgICAgICAgICAgIGV2LmlzVG91Y2ggPyAvLyBUT0RPOiBldmVudHVhbGx5IHJlYWQgZXZlbnRMb25nUHJlc3NEZWxheSBpbnN0ZWFkIHZ2dlxuICAgICAgICAgICAgICAgICAgICAobG9uZ1ByZXNzRGVsYXkgIT0gbnVsbCA/IGxvbmdQcmVzc0RlbGF5IDogQkFTRV9PUFRJT05fREVGQVVMVFMubG9uZ1ByZXNzRGVsYXkpIDpcbiAgICAgICAgICAgICAgICAgICAgMDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVEcmFnU3RhcnQgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGlmIChldi5pc1RvdWNoICYmXG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnZ2luZy5kZWxheSAmJlxuICAgICAgICAgICAgICAgIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLWV2ZW50JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWdnaW5nLm1pcnJvci5nZXRNaXJyb3JFbCgpLmNsYXNzTGlzdC5hZGQoJ2ZjLWV2ZW50LXNlbGVjdGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcbiAgICAgICAgbGV0IGRyYWdnaW5nID0gdGhpcy5kcmFnZ2luZyA9IG5ldyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nKGVsKTtcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGlmIChzZXR0aW5ncy5pdGVtU2VsZWN0b3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9IHNldHRpbmdzLml0ZW1TZWxlY3RvcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2V0dGluZ3MuYXBwZW5kVG8gIT0gbnVsbCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcubWlycm9yLnBhcmVudE5vZGUgPSBzZXR0aW5ncy5hcHBlbmRUbzsgLy8gVE9ETzogd3JpdGUgdGVzdHNcbiAgICAgICAgfVxuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIG5ldyBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyhkcmFnZ2luZywgc2V0dGluZ3MuZXZlbnREYXRhKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1uZXdcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfVxufVxuXG4vKlxuRGV0ZWN0cyB3aGVuIGEgKlRISVJELVBBUlRZKiBkcmFnLW4tZHJvcCBzeXN0ZW0gaW50ZXJhY3RzIHdpdGggZWxlbWVudHMuXG5UaGUgdGhpcmQtcGFydHkgc3lzdGVtIGlzIHJlc3BvbnNpYmxlIGZvciBkcmF3aW5nIHRoZSB2aXN1YWxzIGVmZmVjdHMgb2YgdGhlIGRyYWcuXG5UaGlzIGNsYXNzIHNpbXBseSBtb25pdG9ycyBmb3IgcG9pbnRlciBtb3ZlbWVudHMgYW5kIGZpcmVzIGV2ZW50cy5cbkl0IGFsc28gaGFzIHRoZSBhYmlsaXR5IHRvIGhpZGUgdGhlIG1vdmluZyBlbGVtZW50ICh0aGUgXCJtaXJyb3JcIikgZHVyaW5nIHRoZSBkcmFnLlxuKi9cbmNsYXNzIEluZmVycmVkRWxlbWVudERyYWdnaW5nIGV4dGVuZHMgRWxlbWVudERyYWdnaW5nIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250YWluZXJFbCkge1xuICAgICAgICBzdXBlcihjb250YWluZXJFbCk7XG4gICAgICAgIHRoaXMuc2hvdWxkSWdub3JlTW92ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLm1pcnJvclNlbGVjdG9yID0gJyc7XG4gICAgICAgIHRoaXMuY3VycmVudE1pcnJvckVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IChldikgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgZXYpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAvLyBmaXJlIGRyYWdzdGFydCByaWdodCBhd2F5LiBkb2VzIG5vdCBzdXBwb3J0IGRlbGF5IG9yIG1pbi1kaXN0YW5jZVxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnc3RhcnQnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlck1vdmUgPSAoZXYpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdtb3ZlJywgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJVcCA9IChldikgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJ1cCcsIGV2KTtcbiAgICAgICAgICAgIGlmICghdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgLy8gZmlyZSBkcmFnZW5kIHJpZ2h0IGF3YXkuIGRvZXMgbm90IHN1cHBvcnQgYSByZXZlcnQgYW5pbWF0aW9uXG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdlbmQnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGxldCBwb2ludGVyID0gdGhpcy5wb2ludGVyID0gbmV3IFBvaW50ZXJEcmFnZ2luZyhjb250YWluZXJFbCk7XG4gICAgICAgIHBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVybW92ZScsIHRoaXMuaGFuZGxlUG9pbnRlck1vdmUpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIHRoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5wb2ludGVyLmRlc3Ryb3koKTtcbiAgICB9XG4gICAgc2V0SWdub3JlTW92ZShib29sKSB7XG4gICAgICAgIHRoaXMuc2hvdWxkSWdub3JlTW92ZSA9IGJvb2w7XG4gICAgfVxuICAgIHNldE1pcnJvcklzVmlzaWJsZShib29sKSB7XG4gICAgICAgIGlmIChib29sKSB7XG4gICAgICAgICAgICAvLyByZXN0b3JlIGEgcHJldmlvdXNseSBoaWRkZW4gZWxlbWVudC5cbiAgICAgICAgICAgIC8vIHVzZSB0aGUgcmVmZXJlbmNlIGluIGNhc2UgdGhlIHNlbGVjdG9yIGNsYXNzIGhhcyBhbHJlYWR5IGJlZW4gcmVtb3ZlZC5cbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRNaXJyb3JFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudE1pcnJvckVsLnN0eWxlLnZpc2liaWxpdHkgPSAnJztcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZXQgbWlycm9yRWwgPSB0aGlzLm1pcnJvclNlbGVjdG9yXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogc29tZWhvdyBxdWVyeSBGdWxsQ2FsZW5kYXJzIFdJVEhJTiBzaGFkb3ctcm9vdHNcbiAgICAgICAgICAgICAgICA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5taXJyb3JTZWxlY3RvcilcbiAgICAgICAgICAgICAgICA6IG51bGw7XG4gICAgICAgICAgICBpZiAobWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG1pcnJvckVsO1xuICAgICAgICAgICAgICAgIG1pcnJvckVsLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuLypcbkJyaWRnZXMgdGhpcmQtcGFydHkgZHJhZy1uLWRyb3Agc3lzdGVtcyB3aXRoIEZ1bGxDYWxlbmRhci5cbk11c3QgYmUgaW5zdGFudGlhdGVkIGFuZCBkZXN0cm95ZWQgYnkgY2FsbGVyLlxuKi9cbmNsYXNzIFRoaXJkUGFydHlEcmFnZ2FibGUge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRhaW5lck9yU2V0dGluZ3MsIHNldHRpbmdzKSB7XG4gICAgICAgIGxldCBjb250YWluZXJFbCA9IGRvY3VtZW50O1xuICAgICAgICBpZiAoXG4gICAgICAgIC8vIHdpc2ggd2UgY291bGQganVzdCB0ZXN0IGluc3RhbmNlb2YgRXZlbnRUYXJnZXQsIGJ1dCBkb2Vzbid0IHdvcmsgaW4gSUUxMVxuICAgICAgICBjb250YWluZXJPclNldHRpbmdzID09PSBkb2N1bWVudCB8fFxuICAgICAgICAgICAgY29udGFpbmVyT3JTZXR0aW5ncyBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lckVsID0gY29udGFpbmVyT3JTZXR0aW5ncztcbiAgICAgICAgICAgIHNldHRpbmdzID0gc2V0dGluZ3MgfHwge307XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzZXR0aW5ncyA9IChjb250YWluZXJPclNldHRpbmdzIHx8IHt9KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZHJhZ2dpbmcgPSB0aGlzLmRyYWdnaW5nID0gbmV3IEluZmVycmVkRWxlbWVudERyYWdnaW5nKGNvbnRhaW5lckVsKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy5pdGVtU2VsZWN0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gc2V0dGluZ3MuaXRlbVNlbGVjdG9yO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbnRhaW5lckVsID09PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9ICdbZGF0YS1ldmVudF0nO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0dGluZ3MubWlycm9yU2VsZWN0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkcmFnZ2luZy5taXJyb3JTZWxlY3RvciA9IHNldHRpbmdzLm1pcnJvclNlbGVjdG9yO1xuICAgICAgICB9XG4gICAgICAgIGxldCBleHRlcm5hbERyYWdnaW5nID0gbmV3IEV4dGVybmFsRWxlbWVudERyYWdnaW5nKGRyYWdnaW5nLCBzZXR0aW5ncy5ldmVudERhdGEpO1xuICAgICAgICAvLyBUaGUgaGl0LWRldGVjdGlvbiBzeXN0ZW0gcmVxdWlyZXMgdGhhdCB0aGUgZG5kLW1pcnJvci1lbGVtZW50IGJlIHBvaW50ZXItZXZlbnRzOm5vbmUsXG4gICAgICAgIC8vIGJ1dCB0aGlzIGNhbid0IGJlIGd1YXJhbnRlZWQgZm9yIHRoaXJkLXBhcnR5IGRyYWdnYWJsZXMsIHNvIGRpc2FibGVcbiAgICAgICAgZXh0ZXJuYWxEcmFnZ2luZy5oaXREcmFnZ2luZy5kaXNhYmxlUG9pbnRDaGVjayA9IHRydWU7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH1cbn1cblxudmFyIGluZGV4ID0gY3JlYXRlUGx1Z2luKHtcbiAgICBuYW1lOiAnQGZ1bGxjYWxlbmRhci9pbnRlcmFjdGlvbicsXG4gICAgY29tcG9uZW50SW50ZXJhY3Rpb25zOiBbRGF0ZUNsaWNraW5nLCBEYXRlU2VsZWN0aW5nLCBFdmVudERyYWdnaW5nLCBFdmVudFJlc2l6aW5nXSxcbiAgICBjYWxlbmRhckludGVyYWN0aW9uczogW1Vuc2VsZWN0QXV0b10sXG4gICAgZWxlbWVudERyYWdnaW5nSW1wbDogRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyxcbiAgICBvcHRpb25SZWZpbmVyczogT1BUSU9OX1JFRklORVJTLFxuICAgIGxpc3RlbmVyUmVmaW5lcnM6IExJU1RFTkVSX1JFRklORVJTLFxufSk7XG5cbmV4cG9ydCB7IEV4dGVybmFsRHJhZ2dhYmxlIGFzIERyYWdnYWJsZSwgVGhpcmRQYXJ0eURyYWdnYWJsZSwgaW5kZXggYXMgZGVmYXVsdCB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///117\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 118:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ index)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(112);\n/* harmony import */ var _internal_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(119);\n\n\n\n\n\nvar index = (0,_fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__.createPlugin)({\n name: '@fullcalendar/daygrid',\n initialView: 'dayGridMonth',\n views: {\n dayGrid: {\n component: _internal_js__WEBPACK_IMPORTED_MODULE_1__.DayGridView,\n dateProfileGeneratorClass: _internal_js__WEBPACK_IMPORTED_MODULE_1__.TableDateProfileGenerator,\n },\n dayGridDay: {\n type: 'dayGrid',\n duration: { days: 1 },\n },\n dayGridWeek: {\n type: 'dayGrid',\n duration: { weeks: 1 },\n },\n dayGridMonth: {\n type: 'dayGrid',\n duration: { months: 1 },\n fixedWeekCount: true,\n },\n dayGridYear: {\n type: 'dayGrid',\n duration: { years: 1 },\n },\n },\n});\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTE4LmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUEyRDtBQUM0QjtBQUMvQztBQUNGOztBQUV0QyxZQUFZLHlFQUFZO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHFEQUFZO0FBQ25DLHVDQUF1QyxtRUFBeUI7QUFDaEUsU0FBUztBQUNUO0FBQ0E7QUFDQSx3QkFBd0IsU0FBUztBQUNqQyxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHdCQUF3QixVQUFVO0FBQ2xDLFNBQVM7QUFDVDtBQUNBO0FBQ0Esd0JBQXdCLFdBQVc7QUFDbkM7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHdCQUF3QixVQUFVO0FBQ2xDLFNBQVM7QUFDVCxLQUFLO0FBQ0wsQ0FBQzs7QUFFMkIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcmNoaXRlY3R1aS1odG1sLWZyZWUvLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9kYXlncmlkL2luZGV4LmpzP2IwNDQiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlUGx1Z2luIH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9jb3JlL2luZGV4LmpzJztcbmltcG9ydCB7IERheUdyaWRWaWV3IGFzIERheVRhYmxlVmlldywgVGFibGVEYXRlUHJvZmlsZUdlbmVyYXRvciB9IGZyb20gJy4vaW50ZXJuYWwuanMnO1xuaW1wb3J0ICdAZnVsbGNhbGVuZGFyL2NvcmUvaW50ZXJuYWwuanMnO1xuaW1wb3J0ICdAZnVsbGNhbGVuZGFyL2NvcmUvcHJlYWN0LmpzJztcblxudmFyIGluZGV4ID0gY3JlYXRlUGx1Z2luKHtcbiAgICBuYW1lOiAnQGZ1bGxjYWxlbmRhci9kYXlncmlkJyxcbiAgICBpbml0aWFsVmlldzogJ2RheUdyaWRNb250aCcsXG4gICAgdmlld3M6IHtcbiAgICAgICAgZGF5R3JpZDoge1xuICAgICAgICAgICAgY29tcG9uZW50OiBEYXlUYWJsZVZpZXcsXG4gICAgICAgICAgICBkYXRlUHJvZmlsZUdlbmVyYXRvckNsYXNzOiBUYWJsZURhdGVQcm9maWxlR2VuZXJhdG9yLFxuICAgICAgICB9LFxuICAgICAgICBkYXlHcmlkRGF5OiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyBkYXlzOiAxIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGRheUdyaWRXZWVrOiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyB3ZWVrczogMSB9LFxuICAgICAgICB9LFxuICAgICAgICBkYXlHcmlkTW9udGg6IHtcbiAgICAgICAgICAgIHR5cGU6ICdkYXlHcmlkJyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB7IG1vbnRoczogMSB9LFxuICAgICAgICAgICAgZml4ZWRXZWVrQ291bnQ6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIGRheUdyaWRZZWFyOiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyB5ZWFyczogMSB9LFxuICAgICAgICB9LFxuICAgIH0sXG59KTtcblxuZXhwb3J0IHsgaW5kZXggYXMgZGVmYXVsdCB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///118\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 119:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DayGridView: () => (/* binding */ DayTableView),\n/* harmony export */ DayTable: () => (/* binding */ DayTable),\n/* harmony export */ DayTableSlicer: () => (/* binding */ DayTableSlicer),\n/* harmony export */ Table: () => (/* binding */ Table),\n/* harmony export */ TableDateProfileGenerator: () => (/* binding */ TableDateProfileGenerator),\n/* harmony export */ TableRows: () => (/* binding */ TableRows),\n/* harmony export */ TableView: () => (/* binding */ TableView),\n/* harmony export */ buildDayTableModel: () => (/* binding */ buildDayTableModel),\n/* harmony export */ buildDayTableRenderRange: () => (/* binding */ buildDayTableRenderRange)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113);\n/* harmony import */ var _fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(114);\n\n\n\n/* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.\n----------------------------------------------------------------------------------------------------------------------*/\n// It is a manager for a Table subcomponent, which does most of the heavy lifting.\n// It is responsible for managing width/height.\nclass TableView extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.headerElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n }\n renderSimpleLayout(headerRowContent, bodyContent) {\n let { props, context } = this;\n let sections = [];\n let stickyHeaderDates = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ca)(context.options);\n if (headerRowContent) {\n sections.push({\n type: 'header',\n key: 'header',\n isSticky: stickyHeaderDates,\n chunk: {\n elRef: this.headerElRef,\n tableClassName: 'fc-col-header',\n rowContent: headerRowContent,\n },\n });\n }\n sections.push({\n type: 'body',\n key: 'body',\n liquid: true,\n chunk: { content: bodyContent },\n });\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cq, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bZ, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));\n }\n renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {\n let ScrollGrid = this.context.pluginHooks.scrollGridImpl;\n if (!ScrollGrid) {\n throw new Error('No ScrollGrid implementation');\n }\n let { props, context } = this;\n let stickyHeaderDates = !props.forPrint && (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ca)(context.options);\n let stickyFooterScrollbar = !props.forPrint && (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.c9)(context.options);\n let sections = [];\n if (headerRowContent) {\n sections.push({\n type: 'header',\n key: 'header',\n isSticky: stickyHeaderDates,\n chunks: [{\n key: 'main',\n elRef: this.headerElRef,\n tableClassName: 'fc-col-header',\n rowContent: headerRowContent,\n }],\n });\n }\n sections.push({\n type: 'body',\n key: 'body',\n liquid: true,\n chunks: [{\n key: 'main',\n content: bodyContent,\n }],\n });\n if (stickyFooterScrollbar) {\n sections.push({\n type: 'footer',\n key: 'footer',\n isSticky: true,\n chunks: [{\n key: 'main',\n content: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.c8,\n }],\n });\n }\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cq, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));\n }\n}\n\nfunction splitSegsByRow(segs, rowCnt) {\n let byRow = [];\n for (let i = 0; i < rowCnt; i += 1) {\n byRow[i] = [];\n }\n for (let seg of segs) {\n byRow[seg.row].push(seg);\n }\n return byRow;\n}\nfunction splitSegsByFirstCol(segs, colCnt) {\n let byCol = [];\n for (let i = 0; i < colCnt; i += 1) {\n byCol[i] = [];\n }\n for (let seg of segs) {\n byCol[seg.firstCol].push(seg);\n }\n return byCol;\n}\nfunction splitInteractionByRow(ui, rowCnt) {\n let byRow = [];\n if (!ui) {\n for (let i = 0; i < rowCnt; i += 1) {\n byRow[i] = null;\n }\n }\n else {\n for (let i = 0; i < rowCnt; i += 1) {\n byRow[i] = {\n affectedInstances: ui.affectedInstances,\n isEvent: ui.isEvent,\n segs: [],\n };\n }\n for (let seg of ui.segs) {\n byRow[seg.row].segs.push(seg);\n }\n }\n return byRow;\n}\n\nconst DEFAULT_TABLE_EVENT_TIME_FORMAT = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)({\n hour: 'numeric',\n minute: '2-digit',\n omitZeroMinute: true,\n meridiem: 'narrow',\n});\nfunction hasListItemDisplay(seg) {\n let { display } = seg.eventRange.ui;\n return display === 'list-item' || (display === 'auto' &&\n !seg.eventRange.def.allDay &&\n seg.firstCol === seg.lastCol && // can't be multi-day\n seg.isStart && // \"\n seg.isEnd // \"\n );\n}\n\nclass TableBlockEvent extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let { props } = this;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cg, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));\n }\n}\n\nclass TableListItemEvent extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let { props, context } = this;\n let { options } = context;\n let { seg } = props;\n let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;\n let timeText = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bO)(seg, timeFormat, context, true, props.defaultDisplayEventEnd);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ck, Object.assign({}, props, { elTag: \"a\", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bS)(props.seg, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));\n }\n}\nfunction renderInnerContent(renderProps) {\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-event-dot\", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),\n renderProps.timeText && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-event-time\" }, renderProps.timeText)),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-event-title\" }, renderProps.event.title || (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, \"\\u00A0\"))));\n}\n\nclass TableCellMoreLink extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n constructor() {\n super(...arguments);\n this.compileSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(compileSegs);\n }\n render() {\n let { props } = this;\n let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.co, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {\n let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||\n (props.eventResize ? props.eventResize.affectedInstances : null) ||\n {};\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, allSegs.map((seg) => {\n let instanceId = seg.eventRange.instance.instanceId;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-event-harness\", key: instanceId, style: {\n visibility: isForcedInvisible[instanceId] ? 'hidden' : '',\n } }, hasListItemDisplay(seg) ? ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, props.todayRange)))) : ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, props.todayRange))))));\n })));\n } }));\n }\n}\nfunction compileSegs(singlePlacements) {\n let allSegs = [];\n let invisibleSegs = [];\n for (let placement of singlePlacements) {\n allSegs.push(placement.seg);\n if (!placement.isVisible) {\n invisibleSegs.push(placement.seg);\n }\n }\n return { allSegs, invisibleSegs };\n}\n\nconst DEFAULT_WEEK_NUM_FORMAT = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)({ week: 'narrow' });\nclass TableCell extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.rootElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.state = {\n dayNumberId: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a3)(),\n };\n this.handleRootEl = (el) => {\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.W)(this.rootElRef, el);\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.W)(this.props.elRef, el);\n };\n }\n render() {\n let { context, props, state, rootElRef } = this;\n let { options, dateEnv } = context;\n let { date, dateProfile } = props;\n // TODO: memoize this?\n const isMonthStart = props.showDayNumber &&\n shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ci, { elTag: \"td\", elRef: this.handleRootEl, elClasses: [\n 'fc-daygrid-day',\n ...(props.extraClassNames || []),\n ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { ref: props.innerElRef, className: \"fc-daygrid-day-frame fc-scrollgrid-sync-inner\", style: { minHeight: props.minHeight } },\n props.showWeekNumber && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cn, { elTag: \"a\", elClasses: ['fc-daygrid-week-number'], elAttrs: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a_)(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })),\n !renderProps.isDisabled &&\n (props.showDayNumber || (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cj)(options) || props.forceDayTop) ? ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-day-top\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"a\", elClasses: [\n 'fc-daygrid-day-number',\n isMonthStart && 'fc-daygrid-month-start',\n ], elAttrs: Object.assign(Object.assign({}, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a_)(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (\n // for creating correct amount of space (see issue #7162)\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-day-top\", style: { visibility: 'hidden' } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"a\", { className: \"fc-daygrid-day-number\" }, \"\\u00A0\"))) : undefined,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-day-events\", ref: props.fgContentElRef },\n props.fgContent,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-day-bottom\", style: { marginTop: props.moreMarginTop } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-daygrid-day-bg\" }, props.bgContent)))));\n }\n}\nfunction renderTopInner(props) {\n return props.dayNumberText || (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, \"\\u00A0\");\n}\nfunction shouldDisplayMonthStart(date, currentRange, dateEnv) {\n const { start: currentStart, end: currentEnd } = currentRange;\n const currentEndIncl = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.be)(currentEnd, -1);\n const currentFirstYear = dateEnv.getYear(currentStart);\n const currentFirstMonth = dateEnv.getMonth(currentStart);\n const currentLastYear = dateEnv.getYear(currentEndIncl);\n const currentLastMonth = dateEnv.getMonth(currentEndIncl);\n // spans more than one month?\n return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&\n Boolean(\n // first date in current view?\n date.valueOf() === currentStart.valueOf() ||\n // a month-start that's within the current range?\n (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));\n}\n\nfunction generateSegKey(seg) {\n return seg.eventRange.instance.instanceId + ':' + seg.firstCol;\n}\nfunction generateSegUid(seg) {\n return generateSegKey(seg) + ':' + seg.lastCol;\n}\nfunction computeFgSegPlacement(segs, // assumed already sorted\ndayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {\n let hierarchy = new DayGridSegHierarchy((segEntry) => {\n // TODO: more DRY with generateSegUid\n let segUid = segs[segEntry.index].eventRange.instance.instanceId +\n ':' + segEntry.span.start +\n ':' + (segEntry.span.end - 1);\n // if no thickness known, assume 1 (if 0, so small it always fits)\n return segHeights[segUid] || 1;\n });\n hierarchy.allowReslicing = true;\n hierarchy.strictOrder = strictOrder;\n if (dayMaxEvents === true || dayMaxEventRows === true) {\n hierarchy.maxCoord = maxContentHeight;\n hierarchy.hiddenConsumes = true;\n }\n else if (typeof dayMaxEvents === 'number') {\n hierarchy.maxStackCnt = dayMaxEvents;\n }\n else if (typeof dayMaxEventRows === 'number') {\n hierarchy.maxStackCnt = dayMaxEventRows;\n hierarchy.hiddenConsumes = true;\n }\n // create segInputs only for segs with known heights\n let segInputs = [];\n let unknownHeightSegs = [];\n for (let i = 0; i < segs.length; i += 1) {\n let seg = segs[i];\n let segUid = generateSegUid(seg);\n let eventHeight = segHeights[segUid];\n if (eventHeight != null) {\n segInputs.push({\n index: i,\n span: {\n start: seg.firstCol,\n end: seg.lastCol + 1,\n },\n });\n }\n else {\n unknownHeightSegs.push(seg);\n }\n }\n let hiddenEntries = hierarchy.addSegs(segInputs);\n let segRects = hierarchy.toRects();\n let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);\n let moreCnts = [];\n let moreMarginTops = [];\n // add segs with unknown heights\n for (let seg of unknownHeightSegs) {\n multiColPlacements[seg.firstCol].push({\n seg,\n isVisible: false,\n isAbsolute: true,\n absoluteTop: 0,\n marginTop: 0,\n });\n for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {\n singleColPlacements[col].push({\n seg: resliceSeg(seg, col, col + 1, cells),\n isVisible: false,\n isAbsolute: false,\n absoluteTop: 0,\n marginTop: 0,\n });\n }\n }\n // add the hidden entries\n for (let col = 0; col < cells.length; col += 1) {\n moreCnts.push(0);\n }\n for (let hiddenEntry of hiddenEntries) {\n let seg = segs[hiddenEntry.index];\n let hiddenSpan = hiddenEntry.span;\n multiColPlacements[hiddenSpan.start].push({\n seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),\n isVisible: false,\n isAbsolute: true,\n absoluteTop: 0,\n marginTop: 0,\n });\n for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {\n moreCnts[col] += 1;\n singleColPlacements[col].push({\n seg: resliceSeg(seg, col, col + 1, cells),\n isVisible: false,\n isAbsolute: false,\n absoluteTop: 0,\n marginTop: 0,\n });\n }\n }\n // deal with leftover margins\n for (let col = 0; col < cells.length; col += 1) {\n moreMarginTops.push(leftoverMargins[col]);\n }\n return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };\n}\n// rects ordered by top coord, then left\nfunction placeRects(allRects, segs, cells) {\n let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);\n let singleColPlacements = [];\n let multiColPlacements = [];\n let leftoverMargins = [];\n for (let col = 0; col < cells.length; col += 1) {\n let rects = rectsByEachCol[col];\n // compute all static segs in singlePlacements\n let singlePlacements = [];\n let currentHeight = 0;\n let currentMarginTop = 0;\n for (let rect of rects) {\n let seg = segs[rect.index];\n singlePlacements.push({\n seg: resliceSeg(seg, col, col + 1, cells),\n isVisible: true,\n isAbsolute: false,\n absoluteTop: rect.levelCoord,\n marginTop: rect.levelCoord - currentHeight,\n });\n currentHeight = rect.levelCoord + rect.thickness;\n }\n // compute mixed static/absolute segs in multiPlacements\n let multiPlacements = [];\n currentHeight = 0;\n currentMarginTop = 0;\n for (let rect of rects) {\n let seg = segs[rect.index];\n let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?\n let isFirstCol = rect.span.start === col;\n currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg\n currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg\n if (isAbsolute) {\n currentMarginTop += rect.thickness;\n if (isFirstCol) {\n multiPlacements.push({\n seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),\n isVisible: true,\n isAbsolute: true,\n absoluteTop: rect.levelCoord,\n marginTop: 0,\n });\n }\n }\n else if (isFirstCol) {\n multiPlacements.push({\n seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),\n isVisible: true,\n isAbsolute: false,\n absoluteTop: rect.levelCoord,\n marginTop: currentMarginTop, // claim the margin\n });\n currentMarginTop = 0;\n }\n }\n singleColPlacements.push(singlePlacements);\n multiColPlacements.push(multiPlacements);\n leftoverMargins.push(currentMarginTop);\n }\n return { singleColPlacements, multiColPlacements, leftoverMargins };\n}\nfunction groupRectsByEachCol(rects, colCnt) {\n let rectsByEachCol = [];\n for (let col = 0; col < colCnt; col += 1) {\n rectsByEachCol.push([]);\n }\n for (let rect of rects) {\n for (let col = rect.span.start; col < rect.span.end; col += 1) {\n rectsByEachCol[col].push(rect);\n }\n }\n return rectsByEachCol;\n}\nfunction resliceSeg(seg, spanStart, spanEnd, cells) {\n if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {\n return seg;\n }\n let eventRange = seg.eventRange;\n let origRange = eventRange.range;\n let slicedRange = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.o)(origRange, {\n start: cells[spanStart].date,\n end: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.t)(cells[spanEnd - 1].date, 1),\n });\n return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {\n def: eventRange.def,\n ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),\n instance: eventRange.instance,\n range: slicedRange,\n }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });\n}\nclass DayGridSegHierarchy extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.by {\n constructor() {\n super(...arguments);\n // config\n this.hiddenConsumes = false;\n // allows us to keep hidden entries in the hierarchy so they take up space\n this.forceHidden = {};\n }\n addSegs(segInputs) {\n const hiddenSegs = super.addSegs(segInputs);\n const { entriesByLevel } = this;\n const excludeHidden = (entry) => !this.forceHidden[(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bz)(entry)];\n // remove the forced-hidden segs\n for (let level = 0; level < entriesByLevel.length; level += 1) {\n entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);\n }\n return hiddenSegs;\n }\n handleInvalidInsertion(insertion, entry, hiddenEntries) {\n const { entriesByLevel, forceHidden } = this;\n const { touchingEntry, touchingLevel, touchingLateral } = insertion;\n // the entry that the new insertion is touching must be hidden\n if (this.hiddenConsumes && touchingEntry) {\n const touchingEntryId = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bz)(touchingEntry);\n if (!forceHidden[touchingEntryId]) {\n if (this.allowReslicing) {\n // split up the touchingEntry, reinsert it\n const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bD)(touchingEntry.span, entry.span) });\n // reinsert the area that turned into a \"more\" link (so no other entries try to\n // occupy the space) but mark it forced-hidden\n const hiddenEntryId = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bz)(hiddenEntry);\n forceHidden[hiddenEntryId] = true;\n entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;\n hiddenEntries.push(hiddenEntry);\n this.splitEntry(touchingEntry, entry, hiddenEntries);\n }\n else {\n forceHidden[touchingEntryId] = true;\n hiddenEntries.push(touchingEntry);\n }\n }\n }\n // will try to reslice...\n super.handleInvalidInsertion(insertion, entry, hiddenEntries);\n }\n}\n\nclass TableRow extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.cellElRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd(); // the <td>\n this.frameElRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd(); // the fc-daygrid-day-frame\n this.fgElRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd(); // the fc-daygrid-day-events\n this.segHarnessRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd(); // indexed by \"instanceId:firstCol\"\n this.rootElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.state = {\n framePositions: null,\n maxContentHeight: null,\n segHeights: {},\n };\n this.handleResize = (isForced) => {\n if (isForced) {\n this.updateSizing(true); // isExternal=true\n }\n };\n }\n render() {\n let { props, state, context } = this;\n let { options } = context;\n let colCnt = props.cells.length;\n let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);\n let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);\n let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);\n let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);\n let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bP)(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);\n let isForcedInvisible = // TODO: messy way to compute this\n (props.eventDrag && props.eventDrag.affectedInstances) ||\n (props.eventResize && props.eventResize.affectedInstances) ||\n {};\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { ref: this.rootElRef, role: \"row\" },\n props.renderIntro && props.renderIntro(),\n props.cells.map((cell, col) => {\n let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);\n let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, normalFgNodes),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n this.renderFillSegs(highlightSegsByCol[col], 'highlight'),\n this.renderFillSegs(businessHoursByCol[col], 'non-business'),\n this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));\n })));\n }\n componentDidMount() {\n this.updateSizing(true);\n this.context.addResizeHandler(this.handleResize);\n }\n componentDidUpdate(prevProps, prevState) {\n let currentProps = this.props;\n this.updateSizing(!(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.E)(prevProps, currentProps));\n }\n componentWillUnmount() {\n this.context.removeResizeHandler(this.handleResize);\n }\n getHighlightSegs() {\n let { props } = this;\n if (props.eventDrag && props.eventDrag.segs.length) { // messy check\n return props.eventDrag.segs;\n }\n if (props.eventResize && props.eventResize.segs.length) { // messy check\n return props.eventResize.segs;\n }\n return props.dateSelectionSegs;\n }\n getMirrorSegs() {\n let { props } = this;\n if (props.eventResize && props.eventResize.segs.length) { // messy check\n return props.eventResize.segs;\n }\n return [];\n }\n renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {\n let { context } = this;\n let { eventSelection } = this.props;\n let { framePositions } = this.state;\n let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1\n let isMirror = isDragging || isResizing || isDateSelecting;\n let nodes = [];\n if (framePositions) {\n for (let placement of segPlacements) {\n let { seg } = placement;\n let { instanceId } = seg.eventRange.instance;\n let isVisible = placement.isVisible && !isForcedInvisible[instanceId];\n let isAbsolute = placement.isAbsolute;\n let left = '';\n let right = '';\n if (isAbsolute) {\n if (context.isRtl) {\n right = 0;\n left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];\n }\n else {\n left = 0;\n right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];\n }\n }\n /*\n known bug: events that are force to be list-item but span multiple days still take up space in later columns\n todo: in print view, for multi-day events, don't display title within non-start/end segs\n */\n nodes.push((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {\n visibility: isVisible ? '' : 'hidden',\n marginTop: isAbsolute ? '' : placement.marginTop,\n top: isAbsolute ? placement.absoluteTop : '',\n left,\n right,\n } }, hasListItemDisplay(seg) ? ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, todayRange)))) : ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, todayRange))))));\n }\n }\n return nodes;\n }\n renderFillSegs(segs, fillType) {\n let { isRtl } = this.context;\n let { todayRange } = this.props;\n let { framePositions } = this.state;\n let nodes = [];\n if (framePositions) {\n for (let seg of segs) {\n let leftRightCss = isRtl ? {\n right: 0,\n left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],\n } : {\n left: 0,\n right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],\n };\n nodes.push((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { key: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bR)(seg.eventRange), className: \"fc-daygrid-bg-harness\", style: leftRightCss }, fillType === 'bg-event' ?\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cm, Object.assign({ seg: seg }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, todayRange))) :\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cl)(fillType)));\n }\n }\n return (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, {}, ...nodes);\n }\n updateSizing(isExternalSizingChange) {\n let { props, state, frameElRefs } = this;\n if (!props.forPrint &&\n props.clientWidth !== null // positioning ready?\n ) {\n if (isExternalSizingChange) {\n let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);\n if (frameEls.length) {\n let originEl = this.rootElRef.current;\n let newPositionCache = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.b8(originEl, frameEls, true, // isHorizontal\n false);\n if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {\n this.setState({\n framePositions: new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.b8(originEl, frameEls, true, // isHorizontal\n false),\n });\n }\n }\n }\n const oldSegHeights = this.state.segHeights;\n const newSegHeights = this.querySegHeights();\n const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;\n this.safeSetState({\n // HACK to prevent oscillations of events being shown/hidden from max-event-rows\n // Essentially, once you compute an element's height, never null-out.\n // TODO: always display all events, as visibility:hidden?\n segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),\n maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,\n });\n }\n }\n querySegHeights() {\n let segElMap = this.segHarnessRefs.currentMap;\n let segHeights = {};\n // get the max height amongst instance segs\n for (let segUid in segElMap) {\n let height = Math.round(segElMap[segUid].getBoundingClientRect().height);\n segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);\n }\n return segHeights;\n }\n computeMaxContentHeight() {\n let firstKey = this.props.cells[0].key;\n let cellEl = this.cellElRefs.currentMap[firstKey];\n let fcContainerEl = this.fgElRefs.currentMap[firstKey];\n return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;\n }\n getCellEls() {\n let elMap = this.cellElRefs.currentMap;\n return this.props.cells.map((cell) => elMap[cell.key]);\n }\n}\nTableRow.addStateEquality({\n segHeights: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.E,\n});\nfunction buildMirrorPlacements(mirrorSegs, colPlacements) {\n if (!mirrorSegs.length) {\n return [];\n }\n let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?\n return mirrorSegs.map((seg) => ({\n seg,\n isVisible: true,\n isAbsolute: true,\n absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],\n marginTop: 0,\n }));\n}\nfunction buildAbsoluteTopHash(colPlacements) {\n let topsByInstanceId = {};\n for (let placements of colPlacements) {\n for (let placement of placements) {\n topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;\n }\n }\n return topsByInstanceId;\n}\n\nclass TableRows extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.splitBusinessHourSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByRow);\n this.splitBgEventSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitAllDaySegsByRow);\n this.splitFgEventSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByRow);\n this.splitDateSelectionSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByRow);\n this.splitEventDrag = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitInteractionByRow);\n this.splitEventResize = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitInteractionByRow);\n this.rowRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd();\n }\n render() {\n let { props, context } = this;\n let rowCnt = props.cells.length;\n let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);\n let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);\n let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);\n let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);\n let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);\n let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);\n // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished\n // choose 7 because a month view will have max 6 rows\n let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?\n props.clientWidth / context.options.aspectRatio / 6 :\n null;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a6, { unit: \"day\" }, (nowDate, todayRange) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, props.cells.map((cells, row) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length\n ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */\n : row // in case there are no cells (like when resource view is loading)\n , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row], fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));\n }\n componentDidMount() {\n this.registerInteractiveComponent();\n }\n componentDidUpdate() {\n // for if started with zero cells\n this.registerInteractiveComponent();\n }\n registerInteractiveComponent() {\n if (!this.rootEl) {\n // HACK: need a daygrid wrapper parent to do positioning\n // NOTE: a daygrid resource view w/o resources can have zero cells\n const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];\n const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;\n if (rootEl) {\n this.rootEl = rootEl;\n this.context.registerInteractiveComponent(this, {\n el: rootEl,\n isHitComboAllowed: this.props.isHitComboAllowed,\n });\n }\n }\n }\n componentWillUnmount() {\n if (this.rootEl) {\n this.context.unregisterInteractiveComponent(this);\n this.rootEl = null;\n }\n }\n // Hit System\n // ----------------------------------------------------------------------------------------------------\n prepareHits() {\n this.rowPositions = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.b8(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal\n false, true);\n this.colPositions = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.b8(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row\n true, // horizontal\n false);\n }\n queryHit(positionLeft, positionTop) {\n let { colPositions, rowPositions } = this;\n let col = colPositions.leftToIndex(positionLeft);\n let row = rowPositions.topToIndex(positionTop);\n if (row != null && col != null) {\n let cell = this.props.cells[row][col];\n return {\n dateProfile: this.props.dateProfile,\n dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),\n dayEl: this.getCellEl(row, col),\n rect: {\n left: colPositions.lefts[col],\n right: colPositions.rights[col],\n top: rowPositions.tops[row],\n bottom: rowPositions.bottoms[row],\n },\n layer: 0,\n };\n }\n return null;\n }\n getCellEl(row, col) {\n return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal\n }\n getCellRange(row, col) {\n let start = this.props.cells[row][col].date;\n let end = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.t)(start, 1);\n return { start, end };\n }\n}\nfunction splitAllDaySegsByRow(segs, rowCnt) {\n return splitSegsByRow(segs.filter(isSegAllDay), rowCnt);\n}\nfunction isSegAllDay(seg) {\n return seg.eventRange.def.allDay;\n}\n\nclass Table extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.elRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.needsScrollReset = false;\n }\n render() {\n let { props } = this;\n let { dayMaxEventRows, dayMaxEvents, expandRows } = props;\n let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;\n // if rows can't expand to fill fixed height, can't do balanced-height event limit\n // TODO: best place to normalize these options?\n if (limitViaBalanced && !expandRows) {\n limitViaBalanced = false;\n dayMaxEventRows = null;\n dayMaxEvents = null;\n }\n let classNames = [\n 'fc-daygrid-body',\n limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',\n expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?\n ];\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { ref: this.elRef, className: classNames.join(' '), style: {\n // these props are important to give this wrapper correct dimensions for interactions\n // TODO: if we set it here, can we avoid giving to inner tables?\n width: props.clientWidth,\n minWidth: props.tableMinWidth,\n } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"table\", { role: \"presentation\", className: \"fc-scrollgrid-sync-table\", style: {\n width: props.clientWidth,\n minWidth: props.tableMinWidth,\n height: expandRows ? props.clientHeight : '',\n } },\n props.colGroupNode,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tbody\", { role: \"presentation\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));\n }\n componentDidMount() {\n this.requestScrollReset();\n }\n componentDidUpdate(prevProps) {\n if (prevProps.dateProfile !== this.props.dateProfile) {\n this.requestScrollReset();\n }\n else {\n this.flushScrollReset();\n }\n }\n requestScrollReset() {\n this.needsScrollReset = true;\n this.flushScrollReset();\n }\n flushScrollReset() {\n if (this.needsScrollReset &&\n this.props.clientWidth // sizes computed?\n ) {\n const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);\n if (subjectEl) {\n const originEl = subjectEl.closest('.fc-daygrid-body');\n const scrollEl = originEl.closest('.fc-scroller');\n const scrollTop = subjectEl.getBoundingClientRect().top -\n originEl.getBoundingClientRect().top;\n scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border\n }\n this.needsScrollReset = false;\n }\n }\n}\nfunction getScrollSubjectEl(containerEl, dateProfile) {\n let el;\n if (dateProfile.currentRangeUnit.match(/year|month/)) {\n el = containerEl.querySelector(`[data-date=\"${(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bv)(dateProfile.currentDate)}-01\"]`);\n // even if view is month-based, first-of-month might be hidden...\n }\n if (!el) {\n el = containerEl.querySelector(`[data-date=\"${(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bt)(dateProfile.currentDate)}\"]`);\n // could still be hidden if an interior-view hidden day\n }\n return el;\n}\n\nclass DayTableSlicer extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bU {\n constructor() {\n super(...arguments);\n this.forceDayIfListItem = true;\n }\n sliceRange(dateRange, dayTableModel) {\n return dayTableModel.sliceRange(dateRange);\n }\n}\n\nclass DayTable extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.slicer = new DayTableSlicer();\n this.tableRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n }\n render() {\n let { props, context } = this;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));\n }\n}\n\nclass DayTableView extends TableView {\n constructor() {\n super(...arguments);\n this.buildDayTableModel = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildDayTableModel);\n this.headerRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.tableRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n // can't override any lifecycle methods from parent\n }\n render() {\n let { options, dateProfileGenerator } = this.context;\n let { props } = this;\n let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);\n let headerContent = options.dayHeaders && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bI, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));\n let bodyContent = (contentArg) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));\n return options.dayMinWidth\n ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)\n : this.renderSimpleLayout(headerContent, bodyContent);\n }\n}\nfunction buildDayTableModel(dateProfile, dateProfileGenerator) {\n let daySeries = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bM(dateProfile.renderRange, dateProfileGenerator);\n return new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bT(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));\n}\n\nclass TableDateProfileGenerator extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.R {\n // Computes the date range that will be rendered\n buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {\n let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);\n let { props } = this;\n return buildDayTableRenderRange({\n currentRange: renderRange,\n snapToWeek: /^(year|month)$/.test(currentRangeUnit),\n fixedWeekCount: props.fixedWeekCount,\n dateEnv: props.dateEnv,\n });\n }\n}\nfunction buildDayTableRenderRange(props) {\n let { dateEnv, currentRange } = props;\n let { start, end } = currentRange;\n let endOfWeek;\n // year and month views should be aligned with weeks. this is already done for week\n if (props.snapToWeek) {\n start = dateEnv.startOfWeek(start);\n // make end-of-week if not already\n endOfWeek = dateEnv.startOfWeek(end);\n if (endOfWeek.valueOf() !== end.valueOf()) {\n end = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bf)(endOfWeek, 1);\n }\n }\n // ensure 6 weeks\n if (props.fixedWeekCount) {\n // TODO: instead of these date-math gymnastics (for multimonth view),\n // compute dateprofiles of all months, then use start of first and end of last.\n let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.t)(currentRange.end, -1)));\n let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bg)(lastMonthRenderStart, end));\n end = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bf)(end, 6 - rowCnt);\n }\n return { start, end };\n}\n\nvar css_248z = \":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\\\"\\\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\\\"\\\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}\";\n(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ct)(css_248z);\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QW9DLFVBQVUscUNBQXFDLFVBQVUsc0JBQXNCLGVBQWUsVUFBVSxzQ0FBc0MsVUFBVSwyQkFBMkIsZ0JBQWdCLGFBQWEsbUVBQW1FLFdBQVcsYUFBYSxjQUFjLDBCQUEwQixrQkFBa0IsZUFBZSxjQUFjLGVBQWUsZUFBZSxnQkFBZ0IsWUFBWSxrQkFBa0IsbUJBQW1CLFVBQVUsZ0NBQWdDLGdDQUFnQyw0QkFBNEIsNENBQTRDLG1DQUFtQyxnQkFBZ0IsWUFBWSxrQkFBa0Isa0JBQWtCLE1BQU0sVUFBVSxzQ0FBc0MsZ0JBQWdCLGFBQWEsb0dBQW9HLGdCQUFnQixvR0FBb0csaUJBQWlCLHdDQUF3QyxXQUFXLDBDQUEwQyx3QkFBd0IsT0FBTyx3Q0FBd0MsWUFBWSwwQ0FBMEMsd0JBQXdCLFFBQVEsc0NBQXNDLGdCQUFnQixrQkFBa0Isa0JBQWtCLG9DQUFvQyxrQkFBa0IsbUJBQW1CLHVDQUF1QyxnQkFBZ0IsK0VBQStFLFlBQVksc0JBQXNCLG1CQUFtQixhQUFhLGNBQWMsc0NBQXNDLFlBQVksY0FBYyxnQkFBZ0IsWUFBWSxnQkFBZ0Isa0VBQWtFLDBCQUEwQiwrQ0FBK0MsYUFBYSxVQUFVLHNCQUFzQixvRkFBb0Ysd0RBQXdELHVCQUF1QixTQUFTLGFBQWEsUUFBUSxtREFBbUQsaUJBQWlCLG1EQUFtRCxnQkFBZ0I7QUFDcDlHLGtFQUFZOztBQUUySiIsInNvdXJjZXMiOlsid2VicGFjazovL2FyY2hpdGVjdHVpLWh0bWwtZnJlZS8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2RheWdyaWQvaW50ZXJuYWwuanM/OTNjMCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEYXRlQ29tcG9uZW50LCBnZXRTdGlja3lIZWFkZXJEYXRlcywgVmlld0NvbnRhaW5lciwgU2ltcGxlU2Nyb2xsR3JpZCwgZ2V0U3RpY2t5Rm9vdGVyU2Nyb2xsYmFyLCByZW5kZXJTY3JvbGxTaGltLCBjcmVhdGVGb3JtYXR0ZXIsIEJhc2VDb21wb25lbnQsIFN0YW5kYXJkRXZlbnQsIGJ1aWxkU2VnVGltZVRleHQsIEV2ZW50Q29udGFpbmVyLCBnZXRTZWdBbmNob3JBdHRycywgbWVtb2l6ZSwgTW9yZUxpbmtDb250YWluZXIsIGdldFNlZ01ldGEsIGdldFVuaXF1ZURvbUlkLCBzZXRSZWYsIERheUNlbGxDb250YWluZXIsIFdlZWtOdW1iZXJDb250YWluZXIsIGJ1aWxkTmF2TGlua0F0dHJzLCBoYXNDdXN0b21EYXlDZWxsQ29udGVudCwgYWRkTXMsIGludGVyc2VjdFJhbmdlcywgYWRkRGF5cywgU2VnSGllcmFyY2h5LCBidWlsZEVudHJ5S2V5LCBpbnRlcnNlY3RTcGFucywgUmVmTWFwLCBzb3J0RXZlbnRTZWdzLCBpc1Byb3BzRXF1YWwsIGJ1aWxkRXZlbnRSYW5nZUtleSwgQmdFdmVudCwgcmVuZGVyRmlsbCwgUG9zaXRpb25DYWNoZSwgTm93VGltZXIsIGZvcm1hdElzb01vbnRoU3RyLCBmb3JtYXREYXlTdHJpbmcsIFNsaWNlciwgRGF5SGVhZGVyLCBEYXlTZXJpZXNNb2RlbCwgRGF5VGFibGVNb2RlbCwgRGF0ZVByb2ZpbGVHZW5lcmF0b3IsIGFkZFdlZWtzLCBkaWZmV2Vla3MsIGluamVjdFN0eWxlcyB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZS9pbnRlcm5hbC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVSZWYsIGNyZWF0ZUVsZW1lbnQsIEZyYWdtZW50IH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9jb3JlL3ByZWFjdC5qcyc7XG5cbi8qIEFuIGFic3RyYWN0IGNsYXNzIGZvciB0aGUgZGF5Z3JpZCB2aWV3cywgYXMgd2VsbCBhcyBtb250aCB2aWV3LiBSZW5kZXJzIG9uZSBvciBtb3JlIHJvd3Mgb2YgZGF5IGNlbGxzLlxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4vLyBJdCBpcyBhIG1hbmFnZXIgZm9yIGEgVGFibGUgc3ViY29tcG9uZW50LCB3aGljaCBkb2VzIG1vc3Qgb2YgdGhlIGhlYXZ5IGxpZnRpbmcuXG4vLyBJdCBpcyByZXNwb25zaWJsZSBmb3IgbWFuYWdpbmcgd2lkdGgvaGVpZ2h0LlxuY2xhc3MgVGFibGVWaWV3IGV4dGVuZHMgRGF0ZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuaGVhZGVyRWxSZWYgPSBjcmVhdGVSZWYoKTtcbiAgICB9XG4gICAgcmVuZGVyU2ltcGxlTGF5b3V0KGhlYWRlclJvd0NvbnRlbnQsIGJvZHlDb250ZW50KSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBsZXQgc2VjdGlvbnMgPSBbXTtcbiAgICAgICAgbGV0IHN0aWNreUhlYWRlckRhdGVzID0gZ2V0U3RpY2t5SGVhZGVyRGF0ZXMoY29udGV4dC5vcHRpb25zKTtcbiAgICAgICAgaWYgKGhlYWRlclJvd0NvbnRlbnQpIHtcbiAgICAgICAgICAgIHNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdoZWFkZXInLFxuICAgICAgICAgICAgICAgIGtleTogJ2hlYWRlcicsXG4gICAgICAgICAgICAgICAgaXNTdGlja3k6IHN0aWNreUhlYWRlckRhdGVzLFxuICAgICAgICAgICAgICAgIGNodW5rOiB7XG4gICAgICAgICAgICAgICAgICAgIGVsUmVmOiB0aGlzLmhlYWRlckVsUmVmLFxuICAgICAgICAgICAgICAgICAgICB0YWJsZUNsYXNzTmFtZTogJ2ZjLWNvbC1oZWFkZXInLFxuICAgICAgICAgICAgICAgICAgICByb3dDb250ZW50OiBoZWFkZXJSb3dDb250ZW50LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBzZWN0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdib2R5JyxcbiAgICAgICAgICAgIGtleTogJ2JvZHknLFxuICAgICAgICAgICAgbGlxdWlkOiB0cnVlLFxuICAgICAgICAgICAgY2h1bms6IHsgY29udGVudDogYm9keUNvbnRlbnQgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChWaWV3Q29udGFpbmVyLCB7IGVsQ2xhc3NlczogWydmYy1kYXlncmlkJ10sIHZpZXdTcGVjOiBjb250ZXh0LnZpZXdTcGVjIH0sXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFNpbXBsZVNjcm9sbEdyaWQsIHsgbGlxdWlkOiAhcHJvcHMuaXNIZWlnaHRBdXRvICYmICFwcm9wcy5mb3JQcmludCwgY29sbGFwc2libGVXaWR0aDogcHJvcHMuZm9yUHJpbnQsIGNvbHM6IFtdIC8qIFRPRE86IG1ha2Ugb3B0aW9uYWw/ICovLCBzZWN0aW9uczogc2VjdGlvbnMgfSkpKTtcbiAgICB9XG4gICAgcmVuZGVySFNjcm9sbExheW91dChoZWFkZXJSb3dDb250ZW50LCBib2R5Q29udGVudCwgY29sQ250LCBkYXlNaW5XaWR0aCkge1xuICAgICAgICBsZXQgU2Nyb2xsR3JpZCA9IHRoaXMuY29udGV4dC5wbHVnaW5Ib29rcy5zY3JvbGxHcmlkSW1wbDtcbiAgICAgICAgaWYgKCFTY3JvbGxHcmlkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIFNjcm9sbEdyaWQgaW1wbGVtZW50YXRpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgeyBwcm9wcywgY29udGV4dCB9ID0gdGhpcztcbiAgICAgICAgbGV0IHN0aWNreUhlYWRlckRhdGVzID0gIXByb3BzLmZvclByaW50ICYmIGdldFN0aWNreUhlYWRlckRhdGVzKGNvbnRleHQub3B0aW9ucyk7XG4gICAgICAgIGxldCBzdGlja3lGb290ZXJTY3JvbGxiYXIgPSAhcHJvcHMuZm9yUHJpbnQgJiYgZ2V0U3RpY2t5Rm9vdGVyU2Nyb2xsYmFyKGNvbnRleHQub3B0aW9ucyk7XG4gICAgICAgIGxldCBzZWN0aW9ucyA9IFtdO1xuICAgICAgICBpZiAoaGVhZGVyUm93Q29udGVudCkge1xuICAgICAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2hlYWRlcicsXG4gICAgICAgICAgICAgICAga2V5OiAnaGVhZGVyJyxcbiAgICAgICAgICAgICAgICBpc1N0aWNreTogc3RpY2t5SGVhZGVyRGF0ZXMsXG4gICAgICAgICAgICAgICAgY2h1bmtzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5OiAnbWFpbicsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbFJlZjogdGhpcy5oZWFkZXJFbFJlZixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhYmxlQ2xhc3NOYW1lOiAnZmMtY29sLWhlYWRlcicsXG4gICAgICAgICAgICAgICAgICAgICAgICByb3dDb250ZW50OiBoZWFkZXJSb3dDb250ZW50LFxuICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogJ2JvZHknLFxuICAgICAgICAgICAga2V5OiAnYm9keScsXG4gICAgICAgICAgICBsaXF1aWQ6IHRydWUsXG4gICAgICAgICAgICBjaHVua3M6IFt7XG4gICAgICAgICAgICAgICAgICAgIGtleTogJ21haW4nLFxuICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBib2R5Q29udGVudCxcbiAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChzdGlja3lGb290ZXJTY3JvbGxiYXIpIHtcbiAgICAgICAgICAgIHNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdmb290ZXInLFxuICAgICAgICAgICAgICAgIGtleTogJ2Zvb3RlcicsXG4gICAgICAgICAgICAgICAgaXNTdGlja3k6IHRydWUsXG4gICAgICAgICAgICAgICAgY2h1bmtzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5OiAnbWFpbicsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiByZW5kZXJTY3JvbGxTaGltLFxuICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChWaWV3Q29udGFpbmVyLCB7IGVsQ2xhc3NlczogWydmYy1kYXlncmlkJ10sIHZpZXdTcGVjOiBjb250ZXh0LnZpZXdTcGVjIH0sXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFNjcm9sbEdyaWQsIHsgbGlxdWlkOiAhcHJvcHMuaXNIZWlnaHRBdXRvICYmICFwcm9wcy5mb3JQcmludCwgZm9yUHJpbnQ6IHByb3BzLmZvclByaW50LCBjb2xsYXBzaWJsZVdpZHRoOiBwcm9wcy5mb3JQcmludCwgY29sR3JvdXBzOiBbeyBjb2xzOiBbeyBzcGFuOiBjb2xDbnQsIG1pbldpZHRoOiBkYXlNaW5XaWR0aCB9XSB9XSwgc2VjdGlvbnM6IHNlY3Rpb25zIH0pKSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzcGxpdFNlZ3NCeVJvdyhzZWdzLCByb3dDbnQpIHtcbiAgICBsZXQgYnlSb3cgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvd0NudDsgaSArPSAxKSB7XG4gICAgICAgIGJ5Um93W2ldID0gW107XG4gICAgfVxuICAgIGZvciAobGV0IHNlZyBvZiBzZWdzKSB7XG4gICAgICAgIGJ5Um93W3NlZy5yb3ddLnB1c2goc2VnKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ5Um93O1xufVxuZnVuY3Rpb24gc3BsaXRTZWdzQnlGaXJzdENvbChzZWdzLCBjb2xDbnQpIHtcbiAgICBsZXQgYnlDb2wgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbENudDsgaSArPSAxKSB7XG4gICAgICAgIGJ5Q29sW2ldID0gW107XG4gICAgfVxuICAgIGZvciAobGV0IHNlZyBvZiBzZWdzKSB7XG4gICAgICAgIGJ5Q29sW3NlZy5maXJzdENvbF0ucHVzaChzZWcpO1xuICAgIH1cbiAgICByZXR1cm4gYnlDb2w7XG59XG5mdW5jdGlvbiBzcGxpdEludGVyYWN0aW9uQnlSb3codWksIHJvd0NudCkge1xuICAgIGxldCBieVJvdyA9IFtdO1xuICAgIGlmICghdWkpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByb3dDbnQ7IGkgKz0gMSkge1xuICAgICAgICAgICAgYnlSb3dbaV0gPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvd0NudDsgaSArPSAxKSB7XG4gICAgICAgICAgICBieVJvd1tpXSA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEluc3RhbmNlczogdWkuYWZmZWN0ZWRJbnN0YW5jZXMsXG4gICAgICAgICAgICAgICAgaXNFdmVudDogdWkuaXNFdmVudCxcbiAgICAgICAgICAgICAgICBzZWdzOiBbXSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgc2VnIG9mIHVpLnNlZ3MpIHtcbiAgICAgICAgICAgIGJ5Um93W3NlZy5yb3ddLnNlZ3MucHVzaChzZWcpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBieVJvdztcbn1cblxuY29uc3QgREVGQVVMVF9UQUJMRV9FVkVOVF9USU1FX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7XG4gICAgaG91cjogJ251bWVyaWMnLFxuICAgIG1pbnV0ZTogJzItZGlnaXQnLFxuICAgIG9taXRaZXJvTWludXRlOiB0cnVlLFxuICAgIG1lcmlkaWVtOiAnbmFycm93Jyxcbn0pO1xuZnVuY3Rpb24gaGFzTGlzdEl0ZW1EaXNwbGF5KHNlZykge1xuICAgIGxldCB7IGRpc3BsYXkgfSA9IHNlZy5ldmVudFJhbmdlLnVpO1xuICAgIHJldHVybiBkaXNwbGF5ID09PSAnbGlzdC1pdGVtJyB8fCAoZGlzcGxheSA9PT0gJ2F1dG8nICYmXG4gICAgICAgICFzZWcuZXZlbnRSYW5nZS5kZWYuYWxsRGF5ICYmXG4gICAgICAgIHNlZy5maXJzdENvbCA9PT0gc2VnLmxhc3RDb2wgJiYgLy8gY2FuJ3QgYmUgbXVsdGktZGF5XG4gICAgICAgIHNlZy5pc1N0YXJ0ICYmIC8vIFwiXG4gICAgICAgIHNlZy5pc0VuZCAvLyBcIlxuICAgICk7XG59XG5cbmNsYXNzIFRhYmxlQmxvY2tFdmVudCBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChTdGFuZGFyZEV2ZW50LCBPYmplY3QuYXNzaWduKHt9LCBwcm9wcywgeyBlbENsYXNzZXM6IFsnZmMtZGF5Z3JpZC1ldmVudCcsICdmYy1kYXlncmlkLWJsb2NrLWV2ZW50JywgJ2ZjLWgtZXZlbnQnXSwgZGVmYXVsdFRpbWVGb3JtYXQ6IERFRkFVTFRfVEFCTEVfRVZFTlRfVElNRV9GT1JNQVQsIGRlZmF1bHREaXNwbGF5RXZlbnRFbmQ6IHByb3BzLmRlZmF1bHREaXNwbGF5RXZlbnRFbmQsIGRpc2FibGVSZXNpemluZzogIXByb3BzLnNlZy5ldmVudFJhbmdlLmRlZi5hbGxEYXkgfSkpKTtcbiAgICB9XG59XG5cbmNsYXNzIFRhYmxlTGlzdEl0ZW1FdmVudCBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgICAgIGxldCB7IHNlZyB9ID0gcHJvcHM7XG4gICAgICAgIGxldCB0aW1lRm9ybWF0ID0gb3B0aW9ucy5ldmVudFRpbWVGb3JtYXQgfHwgREVGQVVMVF9UQUJMRV9FVkVOVF9USU1FX0ZPUk1BVDtcbiAgICAgICAgbGV0IHRpbWVUZXh0ID0gYnVpbGRTZWdUaW1lVGV4dChzZWcsIHRpbWVGb3JtYXQsIGNvbnRleHQsIHRydWUsIHByb3BzLmRlZmF1bHREaXNwbGF5RXZlbnRFbmQpO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoRXZlbnRDb250YWluZXIsIE9iamVjdC5hc3NpZ24oe30sIHByb3BzLCB7IGVsVGFnOiBcImFcIiwgZWxDbGFzc2VzOiBbJ2ZjLWRheWdyaWQtZXZlbnQnLCAnZmMtZGF5Z3JpZC1kb3QtZXZlbnQnXSwgZWxBdHRyczogZ2V0U2VnQW5jaG9yQXR0cnMocHJvcHMuc2VnLCBjb250ZXh0KSwgZGVmYXVsdEdlbmVyYXRvcjogcmVuZGVySW5uZXJDb250ZW50LCB0aW1lVGV4dDogdGltZVRleHQsIGlzUmVzaXppbmc6IGZhbHNlLCBpc0RhdGVTZWxlY3Rpbmc6IGZhbHNlIH0pKSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVuZGVySW5uZXJDb250ZW50KHJlbmRlclByb3BzKSB7XG4gICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLFxuICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWRheWdyaWQtZXZlbnQtZG90XCIsIHN0eWxlOiB7IGJvcmRlckNvbG9yOiByZW5kZXJQcm9wcy5ib3JkZXJDb2xvciB8fCByZW5kZXJQcm9wcy5iYWNrZ3JvdW5kQ29sb3IgfSB9KSxcbiAgICAgICAgcmVuZGVyUHJvcHMudGltZVRleHQgJiYgKGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtZXZlbnQtdGltZVwiIH0sIHJlbmRlclByb3BzLnRpbWVUZXh0KSksXG4gICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtZXZlbnQtdGl0bGVcIiB9LCByZW5kZXJQcm9wcy5ldmVudC50aXRsZSB8fCBjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLCBcIlxcdTAwQTBcIikpKSk7XG59XG5cbmNsYXNzIFRhYmxlQ2VsbE1vcmVMaW5rIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuY29tcGlsZVNlZ3MgPSBtZW1vaXplKGNvbXBpbGVTZWdzKTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgYWxsU2VncywgaW52aXNpYmxlU2VncyB9ID0gdGhpcy5jb21waWxlU2Vncyhwcm9wcy5zaW5nbGVQbGFjZW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KE1vcmVMaW5rQ29udGFpbmVyLCB7IGVsQ2xhc3NlczogWydmYy1kYXlncmlkLW1vcmUtbGluayddLCBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2U6IHByb3BzLnRvZGF5UmFuZ2UsIGFsbERheURhdGU6IHByb3BzLmFsbERheURhdGUsIG1vcmVDbnQ6IHByb3BzLm1vcmVDbnQsIGFsbFNlZ3M6IGFsbFNlZ3MsIGhpZGRlblNlZ3M6IGludmlzaWJsZVNlZ3MsIGFsaWdubWVudEVsUmVmOiBwcm9wcy5hbGlnbm1lbnRFbFJlZiwgYWxpZ25HcmlkVG9wOiBwcm9wcy5hbGlnbkdyaWRUb3AsIGV4dHJhRGF0ZVNwYW46IHByb3BzLmV4dHJhRGF0ZVNwYW4sIHBvcG92ZXJDb250ZW50OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGlzRm9yY2VkSW52aXNpYmxlID0gKHByb3BzLmV2ZW50RHJhZyA/IHByb3BzLmV2ZW50RHJhZy5hZmZlY3RlZEluc3RhbmNlcyA6IG51bGwpIHx8XG4gICAgICAgICAgICAgICAgICAgIChwcm9wcy5ldmVudFJlc2l6ZSA/IHByb3BzLmV2ZW50UmVzaXplLmFmZmVjdGVkSW5zdGFuY2VzIDogbnVsbCkgfHxcbiAgICAgICAgICAgICAgICAgICAge307XG4gICAgICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLCBhbGxTZWdzLm1hcCgoc2VnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpbnN0YW5jZUlkID0gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWRheWdyaWQtZXZlbnQtaGFybmVzc1wiLCBrZXk6IGluc3RhbmNlSWQsIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogaXNGb3JjZWRJbnZpc2libGVbaW5zdGFuY2VJZF0gPyAnaGlkZGVuJyA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSB9LCBoYXNMaXN0SXRlbURpc3BsYXkoc2VnKSA/IChjcmVhdGVFbGVtZW50KFRhYmxlTGlzdEl0ZW1FdmVudCwgT2JqZWN0LmFzc2lnbih7IHNlZzogc2VnLCBpc0RyYWdnaW5nOiBmYWxzZSwgaXNTZWxlY3RlZDogaW5zdGFuY2VJZCA9PT0gcHJvcHMuZXZlbnRTZWxlY3Rpb24sIGRlZmF1bHREaXNwbGF5RXZlbnRFbmQ6IGZhbHNlIH0sIGdldFNlZ01ldGEoc2VnLCBwcm9wcy50b2RheVJhbmdlKSkpKSA6IChjcmVhdGVFbGVtZW50KFRhYmxlQmxvY2tFdmVudCwgT2JqZWN0LmFzc2lnbih7IHNlZzogc2VnLCBpc0RyYWdnaW5nOiBmYWxzZSwgaXNSZXNpemluZzogZmFsc2UsIGlzRGF0ZVNlbGVjdGluZzogZmFsc2UsIGlzU2VsZWN0ZWQ6IGluc3RhbmNlSWQgPT09IHByb3BzLmV2ZW50U2VsZWN0aW9uLCBkZWZhdWx0RGlzcGxheUV2ZW50RW5kOiBmYWxzZSB9LCBnZXRTZWdNZXRhKHNlZywgcHJvcHMudG9kYXlSYW5nZSkpKSkpKTtcbiAgICAgICAgICAgICAgICB9KSkpO1xuICAgICAgICAgICAgfSB9KSk7XG4gICAgfVxufVxuZnVuY3Rpb24gY29tcGlsZVNlZ3Moc2luZ2xlUGxhY2VtZW50cykge1xuICAgIGxldCBhbGxTZWdzID0gW107XG4gICAgbGV0IGludmlzaWJsZVNlZ3MgPSBbXTtcbiAgICBmb3IgKGxldCBwbGFjZW1lbnQgb2Ygc2luZ2xlUGxhY2VtZW50cykge1xuICAgICAgICBhbGxTZWdzLnB1c2gocGxhY2VtZW50LnNlZyk7XG4gICAgICAgIGlmICghcGxhY2VtZW50LmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgaW52aXNpYmxlU2Vncy5wdXNoKHBsYWNlbWVudC5zZWcpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGFsbFNlZ3MsIGludmlzaWJsZVNlZ3MgfTtcbn1cblxuY29uc3QgREVGQVVMVF9XRUVLX05VTV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrOiAnbmFycm93JyB9KTtcbmNsYXNzIFRhYmxlQ2VsbCBleHRlbmRzIERhdGVDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLnJvb3RFbFJlZiA9IGNyZWF0ZVJlZigpO1xuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgZGF5TnVtYmVySWQ6IGdldFVuaXF1ZURvbUlkKCksXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUm9vdEVsID0gKGVsKSA9PiB7XG4gICAgICAgICAgICBzZXRSZWYodGhpcy5yb290RWxSZWYsIGVsKTtcbiAgICAgICAgICAgIHNldFJlZih0aGlzLnByb3BzLmVsUmVmLCBlbCk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgY29udGV4dCwgcHJvcHMsIHN0YXRlLCByb290RWxSZWYgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMsIGRhdGVFbnYgfSA9IGNvbnRleHQ7XG4gICAgICAgIGxldCB7IGRhdGUsIGRhdGVQcm9maWxlIH0gPSBwcm9wcztcbiAgICAgICAgLy8gVE9ETzogbWVtb2l6ZSB0aGlzP1xuICAgICAgICBjb25zdCBpc01vbnRoU3RhcnQgPSBwcm9wcy5zaG93RGF5TnVtYmVyICYmXG4gICAgICAgICAgICBzaG91bGREaXNwbGF5TW9udGhTdGFydChkYXRlLCBkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2UsIGRhdGVFbnYpO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoRGF5Q2VsbENvbnRhaW5lciwgeyBlbFRhZzogXCJ0ZFwiLCBlbFJlZjogdGhpcy5oYW5kbGVSb290RWwsIGVsQ2xhc3NlczogW1xuICAgICAgICAgICAgICAgICdmYy1kYXlncmlkLWRheScsXG4gICAgICAgICAgICAgICAgLi4uKHByb3BzLmV4dHJhQ2xhc3NOYW1lcyB8fCBbXSksXG4gICAgICAgICAgICBdLCBlbEF0dHJzOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJvcHMuZXh0cmFEYXRhQXR0cnMpLCAocHJvcHMuc2hvd0RheU51bWJlciA/IHsgJ2FyaWEtbGFiZWxsZWRieSc6IHN0YXRlLmRheU51bWJlcklkIH0gOiB7fSkpLCB7IHJvbGU6ICdncmlkY2VsbCcgfSksIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlclRvcElubmVyLCBkYXRlOiBkYXRlLCBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2U6IHByb3BzLnRvZGF5UmFuZ2UsIHNob3dEYXlOdW1iZXI6IHByb3BzLnNob3dEYXlOdW1iZXIsIGlzTW9udGhTdGFydDogaXNNb250aFN0YXJ0LCBleHRyYVJlbmRlclByb3BzOiBwcm9wcy5leHRyYVJlbmRlclByb3BzIH0sIChJbm5lckNvbnRlbnQsIHJlbmRlclByb3BzKSA9PiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IHJlZjogcHJvcHMuaW5uZXJFbFJlZiwgY2xhc3NOYW1lOiBcImZjLWRheWdyaWQtZGF5LWZyYW1lIGZjLXNjcm9sbGdyaWQtc3luYy1pbm5lclwiLCBzdHlsZTogeyBtaW5IZWlnaHQ6IHByb3BzLm1pbkhlaWdodCB9IH0sXG4gICAgICAgICAgICBwcm9wcy5zaG93V2Vla051bWJlciAmJiAoY3JlYXRlRWxlbWVudChXZWVrTnVtYmVyQ29udGFpbmVyLCB7IGVsVGFnOiBcImFcIiwgZWxDbGFzc2VzOiBbJ2ZjLWRheWdyaWQtd2Vlay1udW1iZXInXSwgZWxBdHRyczogYnVpbGROYXZMaW5rQXR0cnMoY29udGV4dCwgZGF0ZSwgJ3dlZWsnKSwgZGF0ZTogZGF0ZSwgZGVmYXVsdEZvcm1hdDogREVGQVVMVF9XRUVLX05VTV9GT1JNQVQgfSkpLFxuICAgICAgICAgICAgIXJlbmRlclByb3BzLmlzRGlzYWJsZWQgJiZcbiAgICAgICAgICAgICAgICAocHJvcHMuc2hvd0RheU51bWJlciB8fCBoYXNDdXN0b21EYXlDZWxsQ29udGVudChvcHRpb25zKSB8fCBwcm9wcy5mb3JjZURheVRvcCkgPyAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy1kYXlncmlkLWRheS10b3BcIiB9LFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoSW5uZXJDb250ZW50LCB7IGVsVGFnOiBcImFcIiwgZWxDbGFzc2VzOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAnZmMtZGF5Z3JpZC1kYXktbnVtYmVyJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzTW9udGhTdGFydCAmJiAnZmMtZGF5Z3JpZC1tb250aC1zdGFydCcsXG4gICAgICAgICAgICAgICAgICAgIF0sIGVsQXR0cnM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgYnVpbGROYXZMaW5rQXR0cnMoY29udGV4dCwgZGF0ZSkpLCB7IGlkOiBzdGF0ZS5kYXlOdW1iZXJJZCB9KSB9KSkpIDogcHJvcHMuc2hvd0RheU51bWJlciA/IChcbiAgICAgICAgICAgIC8vIGZvciBjcmVhdGluZyBjb3JyZWN0IGFtb3VudCBvZiBzcGFjZSAoc2VlIGlzc3VlICM3MTYyKVxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy1kYXlncmlkLWRheS10b3BcIiwgc3R5bGU6IHsgdmlzaWJpbGl0eTogJ2hpZGRlbicgfSB9LFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJhXCIsIHsgY2xhc3NOYW1lOiBcImZjLWRheWdyaWQtZGF5LW51bWJlclwiIH0sIFwiXFx1MDBBMFwiKSkpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy1kYXlncmlkLWRheS1ldmVudHNcIiwgcmVmOiBwcm9wcy5mZ0NvbnRlbnRFbFJlZiB9LFxuICAgICAgICAgICAgICAgIHByb3BzLmZnQ29udGVudCxcbiAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWRheWdyaWQtZGF5LWJvdHRvbVwiLCBzdHlsZTogeyBtYXJnaW5Ub3A6IHByb3BzLm1vcmVNYXJnaW5Ub3AgfSB9LFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFRhYmxlQ2VsbE1vcmVMaW5rLCB7IGFsbERheURhdGU6IGRhdGUsIHNpbmdsZVBsYWNlbWVudHM6IHByb3BzLnNpbmdsZVBsYWNlbWVudHMsIG1vcmVDbnQ6IHByb3BzLm1vcmVDbnQsIGFsaWdubWVudEVsUmVmOiByb290RWxSZWYsIGFsaWduR3JpZFRvcDogIXByb3BzLnNob3dEYXlOdW1iZXIsIGV4dHJhRGF0ZVNwYW46IHByb3BzLmV4dHJhRGF0ZVNwYW4sIGRhdGVQcm9maWxlOiBwcm9wcy5kYXRlUHJvZmlsZSwgZXZlbnRTZWxlY3Rpb246IHByb3BzLmV2ZW50U2VsZWN0aW9uLCBldmVudERyYWc6IHByb3BzLmV2ZW50RHJhZywgZXZlbnRSZXNpemU6IHByb3BzLmV2ZW50UmVzaXplLCB0b2RheVJhbmdlOiBwcm9wcy50b2RheVJhbmdlIH0pKSksXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLWRheWdyaWQtZGF5LWJnXCIgfSwgcHJvcHMuYmdDb250ZW50KSkpKSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVuZGVyVG9wSW5uZXIocHJvcHMpIHtcbiAgICByZXR1cm4gcHJvcHMuZGF5TnVtYmVyVGV4dCB8fCBjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLCBcIlxcdTAwQTBcIik7XG59XG5mdW5jdGlvbiBzaG91bGREaXNwbGF5TW9udGhTdGFydChkYXRlLCBjdXJyZW50UmFuZ2UsIGRhdGVFbnYpIHtcbiAgICBjb25zdCB7IHN0YXJ0OiBjdXJyZW50U3RhcnQsIGVuZDogY3VycmVudEVuZCB9ID0gY3VycmVudFJhbmdlO1xuICAgIGNvbnN0IGN1cnJlbnRFbmRJbmNsID0gYWRkTXMoY3VycmVudEVuZCwgLTEpO1xuICAgIGNvbnN0IGN1cnJlbnRGaXJzdFllYXIgPSBkYXRlRW52LmdldFllYXIoY3VycmVudFN0YXJ0KTtcbiAgICBjb25zdCBjdXJyZW50Rmlyc3RNb250aCA9IGRhdGVFbnYuZ2V0TW9udGgoY3VycmVudFN0YXJ0KTtcbiAgICBjb25zdCBjdXJyZW50TGFzdFllYXIgPSBkYXRlRW52LmdldFllYXIoY3VycmVudEVuZEluY2wpO1xuICAgIGNvbnN0IGN1cnJlbnRMYXN0TW9udGggPSBkYXRlRW52LmdldE1vbnRoKGN1cnJlbnRFbmRJbmNsKTtcbiAgICAvLyBzcGFucyBtb3JlIHRoYW4gb25lIG1vbnRoP1xuICAgIHJldHVybiAhKGN1cnJlbnRGaXJzdFllYXIgPT09IGN1cnJlbnRMYXN0WWVhciAmJiBjdXJyZW50Rmlyc3RNb250aCA9PT0gY3VycmVudExhc3RNb250aCkgJiZcbiAgICAgICAgQm9vbGVhbihcbiAgICAgICAgLy8gZmlyc3QgZGF0ZSBpbiBjdXJyZW50IHZpZXc/XG4gICAgICAgIGRhdGUudmFsdWVPZigpID09PSBjdXJyZW50U3RhcnQudmFsdWVPZigpIHx8XG4gICAgICAgICAgICAvLyBhIG1vbnRoLXN0YXJ0IHRoYXQncyB3aXRoaW4gdGhlIGN1cnJlbnQgcmFuZ2U/XG4gICAgICAgICAgICAoZGF0ZUVudi5nZXREYXkoZGF0ZSkgPT09IDEgJiYgZGF0ZS52YWx1ZU9mKCkgPCBjdXJyZW50RW5kLnZhbHVlT2YoKSkpO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZVNlZ0tleShzZWcpIHtcbiAgICByZXR1cm4gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZCArICc6JyArIHNlZy5maXJzdENvbDtcbn1cbmZ1bmN0aW9uIGdlbmVyYXRlU2VnVWlkKHNlZykge1xuICAgIHJldHVybiBnZW5lcmF0ZVNlZ0tleShzZWcpICsgJzonICsgc2VnLmxhc3RDb2w7XG59XG5mdW5jdGlvbiBjb21wdXRlRmdTZWdQbGFjZW1lbnQoc2VncywgLy8gYXNzdW1lZCBhbHJlYWR5IHNvcnRlZFxuZGF5TWF4RXZlbnRzLCBkYXlNYXhFdmVudFJvd3MsIHN0cmljdE9yZGVyLCBzZWdIZWlnaHRzLCBtYXhDb250ZW50SGVpZ2h0LCBjZWxscykge1xuICAgIGxldCBoaWVyYXJjaHkgPSBuZXcgRGF5R3JpZFNlZ0hpZXJhcmNoeSgoc2VnRW50cnkpID0+IHtcbiAgICAgICAgLy8gVE9ETzogbW9yZSBEUlkgd2l0aCBnZW5lcmF0ZVNlZ1VpZFxuICAgICAgICBsZXQgc2VnVWlkID0gc2Vnc1tzZWdFbnRyeS5pbmRleF0uZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkICtcbiAgICAgICAgICAgICc6JyArIHNlZ0VudHJ5LnNwYW4uc3RhcnQgK1xuICAgICAgICAgICAgJzonICsgKHNlZ0VudHJ5LnNwYW4uZW5kIC0gMSk7XG4gICAgICAgIC8vIGlmIG5vIHRoaWNrbmVzcyBrbm93biwgYXNzdW1lIDEgKGlmIDAsIHNvIHNtYWxsIGl0IGFsd2F5cyBmaXRzKVxuICAgICAgICByZXR1cm4gc2VnSGVpZ2h0c1tzZWdVaWRdIHx8IDE7XG4gICAgfSk7XG4gICAgaGllcmFyY2h5LmFsbG93UmVzbGljaW5nID0gdHJ1ZTtcbiAgICBoaWVyYXJjaHkuc3RyaWN0T3JkZXIgPSBzdHJpY3RPcmRlcjtcbiAgICBpZiAoZGF5TWF4RXZlbnRzID09PSB0cnVlIHx8IGRheU1heEV2ZW50Um93cyA9PT0gdHJ1ZSkge1xuICAgICAgICBoaWVyYXJjaHkubWF4Q29vcmQgPSBtYXhDb250ZW50SGVpZ2h0O1xuICAgICAgICBoaWVyYXJjaHkuaGlkZGVuQ29uc3VtZXMgPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGF5TWF4RXZlbnRzID09PSAnbnVtYmVyJykge1xuICAgICAgICBoaWVyYXJjaHkubWF4U3RhY2tDbnQgPSBkYXlNYXhFdmVudHM7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkYXlNYXhFdmVudFJvd3MgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGhpZXJhcmNoeS5tYXhTdGFja0NudCA9IGRheU1heEV2ZW50Um93cztcbiAgICAgICAgaGllcmFyY2h5LmhpZGRlbkNvbnN1bWVzID0gdHJ1ZTtcbiAgICB9XG4gICAgLy8gY3JlYXRlIHNlZ0lucHV0cyBvbmx5IGZvciBzZWdzIHdpdGgga25vd24gaGVpZ2h0c1xuICAgIGxldCBzZWdJbnB1dHMgPSBbXTtcbiAgICBsZXQgdW5rbm93bkhlaWdodFNlZ3MgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgbGV0IHNlZyA9IHNlZ3NbaV07XG4gICAgICAgIGxldCBzZWdVaWQgPSBnZW5lcmF0ZVNlZ1VpZChzZWcpO1xuICAgICAgICBsZXQgZXZlbnRIZWlnaHQgPSBzZWdIZWlnaHRzW3NlZ1VpZF07XG4gICAgICAgIGlmIChldmVudEhlaWdodCAhPSBudWxsKSB7XG4gICAgICAgICAgICBzZWdJbnB1dHMucHVzaCh7XG4gICAgICAgICAgICAgICAgaW5kZXg6IGksXG4gICAgICAgICAgICAgICAgc3Bhbjoge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogc2VnLmZpcnN0Q29sLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IHNlZy5sYXN0Q29sICsgMSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB1bmtub3duSGVpZ2h0U2Vncy5wdXNoKHNlZyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgbGV0IGhpZGRlbkVudHJpZXMgPSBoaWVyYXJjaHkuYWRkU2VncyhzZWdJbnB1dHMpO1xuICAgIGxldCBzZWdSZWN0cyA9IGhpZXJhcmNoeS50b1JlY3RzKCk7XG4gICAgbGV0IHsgc2luZ2xlQ29sUGxhY2VtZW50cywgbXVsdGlDb2xQbGFjZW1lbnRzLCBsZWZ0b3Zlck1hcmdpbnMgfSA9IHBsYWNlUmVjdHMoc2VnUmVjdHMsIHNlZ3MsIGNlbGxzKTtcbiAgICBsZXQgbW9yZUNudHMgPSBbXTtcbiAgICBsZXQgbW9yZU1hcmdpblRvcHMgPSBbXTtcbiAgICAvLyBhZGQgc2VncyB3aXRoIHVua25vd24gaGVpZ2h0c1xuICAgIGZvciAobGV0IHNlZyBvZiB1bmtub3duSGVpZ2h0U2Vncykge1xuICAgICAgICBtdWx0aUNvbFBsYWNlbWVudHNbc2VnLmZpcnN0Q29sXS5wdXNoKHtcbiAgICAgICAgICAgIHNlZyxcbiAgICAgICAgICAgIGlzVmlzaWJsZTogZmFsc2UsXG4gICAgICAgICAgICBpc0Fic29sdXRlOiB0cnVlLFxuICAgICAgICAgICAgYWJzb2x1dGVUb3A6IDAsXG4gICAgICAgICAgICBtYXJnaW5Ub3A6IDAsXG4gICAgICAgIH0pO1xuICAgICAgICBmb3IgKGxldCBjb2wgPSBzZWcuZmlyc3RDb2w7IGNvbCA8PSBzZWcubGFzdENvbDsgY29sICs9IDEpIHtcbiAgICAgICAgICAgIHNpbmdsZUNvbFBsYWNlbWVudHNbY29sXS5wdXNoKHtcbiAgICAgICAgICAgICAgICBzZWc6IHJlc2xpY2VTZWcoc2VnLCBjb2wsIGNvbCArIDEsIGNlbGxzKSxcbiAgICAgICAgICAgICAgICBpc1Zpc2libGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGlzQWJzb2x1dGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGFic29sdXRlVG9wOiAwLFxuICAgICAgICAgICAgICAgIG1hcmdpblRvcDogMCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGFkZCB0aGUgaGlkZGVuIGVudHJpZXNcbiAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCBjZWxscy5sZW5ndGg7IGNvbCArPSAxKSB7XG4gICAgICAgIG1vcmVDbnRzLnB1c2goMCk7XG4gICAgfVxuICAgIGZvciAobGV0IGhpZGRlbkVudHJ5IG9mIGhpZGRlbkVudHJpZXMpIHtcbiAgICAgICAgbGV0IHNlZyA9IHNlZ3NbaGlkZGVuRW50cnkuaW5kZXhdO1xuICAgICAgICBsZXQgaGlkZGVuU3BhbiA9IGhpZGRlbkVudHJ5LnNwYW47XG4gICAgICAgIG11bHRpQ29sUGxhY2VtZW50c1toaWRkZW5TcGFuLnN0YXJ0XS5wdXNoKHtcbiAgICAgICAgICAgIHNlZzogcmVzbGljZVNlZyhzZWcsIGhpZGRlblNwYW4uc3RhcnQsIGhpZGRlblNwYW4uZW5kLCBjZWxscyksXG4gICAgICAgICAgICBpc1Zpc2libGU6IGZhbHNlLFxuICAgICAgICAgICAgaXNBYnNvbHV0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGFic29sdXRlVG9wOiAwLFxuICAgICAgICAgICAgbWFyZ2luVG9wOiAwLFxuICAgICAgICB9KTtcbiAgICAgICAgZm9yIChsZXQgY29sID0gaGlkZGVuU3Bhbi5zdGFydDsgY29sIDwgaGlkZGVuU3Bhbi5lbmQ7IGNvbCArPSAxKSB7XG4gICAgICAgICAgICBtb3JlQ250c1tjb2xdICs9IDE7XG4gICAgICAgICAgICBzaW5nbGVDb2xQbGFjZW1lbnRzW2NvbF0ucHVzaCh7XG4gICAgICAgICAgICAgICAgc2VnOiByZXNsaWNlU2VnKHNlZywgY29sLCBjb2wgKyAxLCBjZWxscyksXG4gICAgICAgICAgICAgICAgaXNWaXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc0Fic29sdXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhYnNvbHV0ZVRvcDogMCxcbiAgICAgICAgICAgICAgICBtYXJnaW5Ub3A6IDAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBkZWFsIHdpdGggbGVmdG92ZXIgbWFyZ2luc1xuICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IGNlbGxzLmxlbmd0aDsgY29sICs9IDEpIHtcbiAgICAgICAgbW9yZU1hcmdpblRvcHMucHVzaChsZWZ0b3Zlck1hcmdpbnNbY29sXSk7XG4gICAgfVxuICAgIHJldHVybiB7IHNpbmdsZUNvbFBsYWNlbWVudHMsIG11bHRpQ29sUGxhY2VtZW50cywgbW9yZUNudHMsIG1vcmVNYXJnaW5Ub3BzIH07XG59XG4vLyByZWN0cyBvcmRlcmVkIGJ5IHRvcCBjb29yZCwgdGhlbiBsZWZ0XG5mdW5jdGlvbiBwbGFjZVJlY3RzKGFsbFJlY3RzLCBzZWdzLCBjZWxscykge1xuICAgIGxldCByZWN0c0J5RWFjaENvbCA9IGdyb3VwUmVjdHNCeUVhY2hDb2woYWxsUmVjdHMsIGNlbGxzLmxlbmd0aCk7XG4gICAgbGV0IHNpbmdsZUNvbFBsYWNlbWVudHMgPSBbXTtcbiAgICBsZXQgbXVsdGlDb2xQbGFjZW1lbnRzID0gW107XG4gICAgbGV0IGxlZnRvdmVyTWFyZ2lucyA9IFtdO1xuICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IGNlbGxzLmxlbmd0aDsgY29sICs9IDEpIHtcbiAgICAgICAgbGV0IHJlY3RzID0gcmVjdHNCeUVhY2hDb2xbY29sXTtcbiAgICAgICAgLy8gY29tcHV0ZSBhbGwgc3RhdGljIHNlZ3MgaW4gc2luZ2xlUGxhY2VtZW50c1xuICAgICAgICBsZXQgc2luZ2xlUGxhY2VtZW50cyA9IFtdO1xuICAgICAgICBsZXQgY3VycmVudEhlaWdodCA9IDA7XG4gICAgICAgIGxldCBjdXJyZW50TWFyZ2luVG9wID0gMDtcbiAgICAgICAgZm9yIChsZXQgcmVjdCBvZiByZWN0cykge1xuICAgICAgICAgICAgbGV0IHNlZyA9IHNlZ3NbcmVjdC5pbmRleF07XG4gICAgICAgICAgICBzaW5nbGVQbGFjZW1lbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgIHNlZzogcmVzbGljZVNlZyhzZWcsIGNvbCwgY29sICsgMSwgY2VsbHMpLFxuICAgICAgICAgICAgICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpc0Fic29sdXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhYnNvbHV0ZVRvcDogcmVjdC5sZXZlbENvb3JkLFxuICAgICAgICAgICAgICAgIG1hcmdpblRvcDogcmVjdC5sZXZlbENvb3JkIC0gY3VycmVudEhlaWdodCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY3VycmVudEhlaWdodCA9IHJlY3QubGV2ZWxDb29yZCArIHJlY3QudGhpY2tuZXNzO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbXB1dGUgbWl4ZWQgc3RhdGljL2Fic29sdXRlIHNlZ3MgaW4gbXVsdGlQbGFjZW1lbnRzXG4gICAgICAgIGxldCBtdWx0aVBsYWNlbWVudHMgPSBbXTtcbiAgICAgICAgY3VycmVudEhlaWdodCA9IDA7XG4gICAgICAgIGN1cnJlbnRNYXJnaW5Ub3AgPSAwO1xuICAgICAgICBmb3IgKGxldCByZWN0IG9mIHJlY3RzKSB7XG4gICAgICAgICAgICBsZXQgc2VnID0gc2Vnc1tyZWN0LmluZGV4XTtcbiAgICAgICAgICAgIGxldCBpc0Fic29sdXRlID0gcmVjdC5zcGFuLmVuZCAtIHJlY3Quc3Bhbi5zdGFydCA+IDE7IC8vIG11bHRpLWNvbHVtbj9cbiAgICAgICAgICAgIGxldCBpc0ZpcnN0Q29sID0gcmVjdC5zcGFuLnN0YXJ0ID09PSBjb2w7XG4gICAgICAgICAgICBjdXJyZW50TWFyZ2luVG9wICs9IHJlY3QubGV2ZWxDb29yZCAtIGN1cnJlbnRIZWlnaHQ7IC8vIGFtb3VudCBvZiBzcGFjZSBzaW5jZSBib3R0b20gb2YgcHJldmlvdXMgc2VnXG4gICAgICAgICAgICBjdXJyZW50SGVpZ2h0ID0gcmVjdC5sZXZlbENvb3JkICsgcmVjdC50aGlja25lc3M7IC8vIGhlaWdodCB3aWxsIG5vdyBiZSBib3R0b20gb2YgY3VycmVudCBzZWdcbiAgICAgICAgICAgIGlmIChpc0Fic29sdXRlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudE1hcmdpblRvcCArPSByZWN0LnRoaWNrbmVzcztcbiAgICAgICAgICAgICAgICBpZiAoaXNGaXJzdENvbCkge1xuICAgICAgICAgICAgICAgICAgICBtdWx0aVBsYWNlbWVudHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWc6IHJlc2xpY2VTZWcoc2VnLCByZWN0LnNwYW4uc3RhcnQsIHJlY3Quc3Bhbi5lbmQsIGNlbGxzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzQWJzb2x1dGU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBhYnNvbHV0ZVRvcDogcmVjdC5sZXZlbENvb3JkLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luVG9wOiAwLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpc0ZpcnN0Q29sKSB7XG4gICAgICAgICAgICAgICAgbXVsdGlQbGFjZW1lbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzZWc6IHJlc2xpY2VTZWcoc2VnLCByZWN0LnNwYW4uc3RhcnQsIHJlY3Quc3Bhbi5lbmQsIGNlbGxzKSxcbiAgICAgICAgICAgICAgICAgICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBpc0Fic29sdXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgYWJzb2x1dGVUb3A6IHJlY3QubGV2ZWxDb29yZCxcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2luVG9wOiBjdXJyZW50TWFyZ2luVG9wLCAvLyBjbGFpbSB0aGUgbWFyZ2luXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY3VycmVudE1hcmdpblRvcCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2luZ2xlQ29sUGxhY2VtZW50cy5wdXNoKHNpbmdsZVBsYWNlbWVudHMpO1xuICAgICAgICBtdWx0aUNvbFBsYWNlbWVudHMucHVzaChtdWx0aVBsYWNlbWVudHMpO1xuICAgICAgICBsZWZ0b3Zlck1hcmdpbnMucHVzaChjdXJyZW50TWFyZ2luVG9wKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgc2luZ2xlQ29sUGxhY2VtZW50cywgbXVsdGlDb2xQbGFjZW1lbnRzLCBsZWZ0b3Zlck1hcmdpbnMgfTtcbn1cbmZ1bmN0aW9uIGdyb3VwUmVjdHNCeUVhY2hDb2wocmVjdHMsIGNvbENudCkge1xuICAgIGxldCByZWN0c0J5RWFjaENvbCA9IFtdO1xuICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IGNvbENudDsgY29sICs9IDEpIHtcbiAgICAgICAgcmVjdHNCeUVhY2hDb2wucHVzaChbXSk7XG4gICAgfVxuICAgIGZvciAobGV0IHJlY3Qgb2YgcmVjdHMpIHtcbiAgICAgICAgZm9yIChsZXQgY29sID0gcmVjdC5zcGFuLnN0YXJ0OyBjb2wgPCByZWN0LnNwYW4uZW5kOyBjb2wgKz0gMSkge1xuICAgICAgICAgICAgcmVjdHNCeUVhY2hDb2xbY29sXS5wdXNoKHJlY3QpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWN0c0J5RWFjaENvbDtcbn1cbmZ1bmN0aW9uIHJlc2xpY2VTZWcoc2VnLCBzcGFuU3RhcnQsIHNwYW5FbmQsIGNlbGxzKSB7XG4gICAgaWYgKHNlZy5maXJzdENvbCA9PT0gc3BhblN0YXJ0ICYmIHNlZy5sYXN0Q29sID09PSBzcGFuRW5kIC0gMSkge1xuICAgICAgICByZXR1cm4gc2VnO1xuICAgIH1cbiAgICBsZXQgZXZlbnRSYW5nZSA9IHNlZy5ldmVudFJhbmdlO1xuICAgIGxldCBvcmlnUmFuZ2UgPSBldmVudFJhbmdlLnJhbmdlO1xuICAgIGxldCBzbGljZWRSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhvcmlnUmFuZ2UsIHtcbiAgICAgICAgc3RhcnQ6IGNlbGxzW3NwYW5TdGFydF0uZGF0ZSxcbiAgICAgICAgZW5kOiBhZGREYXlzKGNlbGxzW3NwYW5FbmQgLSAxXS5kYXRlLCAxKSxcbiAgICB9KTtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzZWcpLCB7IGZpcnN0Q29sOiBzcGFuU3RhcnQsIGxhc3RDb2w6IHNwYW5FbmQgLSAxLCBldmVudFJhbmdlOiB7XG4gICAgICAgICAgICBkZWY6IGV2ZW50UmFuZ2UuZGVmLFxuICAgICAgICAgICAgdWk6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZXZlbnRSYW5nZS51aSksIHsgZHVyYXRpb25FZGl0YWJsZTogZmFsc2UgfSksXG4gICAgICAgICAgICBpbnN0YW5jZTogZXZlbnRSYW5nZS5pbnN0YW5jZSxcbiAgICAgICAgICAgIHJhbmdlOiBzbGljZWRSYW5nZSxcbiAgICAgICAgfSwgaXNTdGFydDogc2VnLmlzU3RhcnQgJiYgc2xpY2VkUmFuZ2Uuc3RhcnQudmFsdWVPZigpID09PSBvcmlnUmFuZ2Uuc3RhcnQudmFsdWVPZigpLCBpc0VuZDogc2VnLmlzRW5kICYmIHNsaWNlZFJhbmdlLmVuZC52YWx1ZU9mKCkgPT09IG9yaWdSYW5nZS5lbmQudmFsdWVPZigpIH0pO1xufVxuY2xhc3MgRGF5R3JpZFNlZ0hpZXJhcmNoeSBleHRlbmRzIFNlZ0hpZXJhcmNoeSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIC8vIGNvbmZpZ1xuICAgICAgICB0aGlzLmhpZGRlbkNvbnN1bWVzID0gZmFsc2U7XG4gICAgICAgIC8vIGFsbG93cyB1cyB0byBrZWVwIGhpZGRlbiBlbnRyaWVzIGluIHRoZSBoaWVyYXJjaHkgc28gdGhleSB0YWtlIHVwIHNwYWNlXG4gICAgICAgIHRoaXMuZm9yY2VIaWRkZW4gPSB7fTtcbiAgICB9XG4gICAgYWRkU2VncyhzZWdJbnB1dHMpIHtcbiAgICAgICAgY29uc3QgaGlkZGVuU2VncyA9IHN1cGVyLmFkZFNlZ3Moc2VnSW5wdXRzKTtcbiAgICAgICAgY29uc3QgeyBlbnRyaWVzQnlMZXZlbCB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgZXhjbHVkZUhpZGRlbiA9IChlbnRyeSkgPT4gIXRoaXMuZm9yY2VIaWRkZW5bYnVpbGRFbnRyeUtleShlbnRyeSldO1xuICAgICAgICAvLyByZW1vdmUgdGhlIGZvcmNlZC1oaWRkZW4gc2Vnc1xuICAgICAgICBmb3IgKGxldCBsZXZlbCA9IDA7IGxldmVsIDwgZW50cmllc0J5TGV2ZWwubGVuZ3RoOyBsZXZlbCArPSAxKSB7XG4gICAgICAgICAgICBlbnRyaWVzQnlMZXZlbFtsZXZlbF0gPSBlbnRyaWVzQnlMZXZlbFtsZXZlbF0uZmlsdGVyKGV4Y2x1ZGVIaWRkZW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoaWRkZW5TZWdzO1xuICAgIH1cbiAgICBoYW5kbGVJbnZhbGlkSW5zZXJ0aW9uKGluc2VydGlvbiwgZW50cnksIGhpZGRlbkVudHJpZXMpIHtcbiAgICAgICAgY29uc3QgeyBlbnRyaWVzQnlMZXZlbCwgZm9yY2VIaWRkZW4gfSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHsgdG91Y2hpbmdFbnRyeSwgdG91Y2hpbmdMZXZlbCwgdG91Y2hpbmdMYXRlcmFsIH0gPSBpbnNlcnRpb247XG4gICAgICAgIC8vIHRoZSBlbnRyeSB0aGF0IHRoZSBuZXcgaW5zZXJ0aW9uIGlzIHRvdWNoaW5nIG11c3QgYmUgaGlkZGVuXG4gICAgICAgIGlmICh0aGlzLmhpZGRlbkNvbnN1bWVzICYmIHRvdWNoaW5nRW50cnkpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvdWNoaW5nRW50cnlJZCA9IGJ1aWxkRW50cnlLZXkodG91Y2hpbmdFbnRyeSk7XG4gICAgICAgICAgICBpZiAoIWZvcmNlSGlkZGVuW3RvdWNoaW5nRW50cnlJZF0pIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5hbGxvd1Jlc2xpY2luZykge1xuICAgICAgICAgICAgICAgICAgICAvLyBzcGxpdCB1cCB0aGUgdG91Y2hpbmdFbnRyeSwgcmVpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaGlkZGVuRW50cnkgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRvdWNoaW5nRW50cnkpLCB7IHNwYW46IGludGVyc2VjdFNwYW5zKHRvdWNoaW5nRW50cnkuc3BhbiwgZW50cnkuc3BhbikgfSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIHJlaW5zZXJ0IHRoZSBhcmVhIHRoYXQgdHVybmVkIGludG8gYSBcIm1vcmVcIiBsaW5rIChzbyBubyBvdGhlciBlbnRyaWVzIHRyeSB0b1xuICAgICAgICAgICAgICAgICAgICAvLyBvY2N1cHkgdGhlIHNwYWNlKSBidXQgbWFyayBpdCBmb3JjZWQtaGlkZGVuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGhpZGRlbkVudHJ5SWQgPSBidWlsZEVudHJ5S2V5KGhpZGRlbkVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgZm9yY2VIaWRkZW5baGlkZGVuRW50cnlJZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBlbnRyaWVzQnlMZXZlbFt0b3VjaGluZ0xldmVsXVt0b3VjaGluZ0xhdGVyYWxdID0gaGlkZGVuRW50cnk7XG4gICAgICAgICAgICAgICAgICAgIGhpZGRlbkVudHJpZXMucHVzaChoaWRkZW5FbnRyeSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRFbnRyeSh0b3VjaGluZ0VudHJ5LCBlbnRyeSwgaGlkZGVuRW50cmllcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3JjZUhpZGRlblt0b3VjaGluZ0VudHJ5SWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgaGlkZGVuRW50cmllcy5wdXNoKHRvdWNoaW5nRW50cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyB3aWxsIHRyeSB0byByZXNsaWNlLi4uXG4gICAgICAgIHN1cGVyLmhhbmRsZUludmFsaWRJbnNlcnRpb24oaW5zZXJ0aW9uLCBlbnRyeSwgaGlkZGVuRW50cmllcyk7XG4gICAgfVxufVxuXG5jbGFzcyBUYWJsZVJvdyBleHRlbmRzIERhdGVDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmNlbGxFbFJlZnMgPSBuZXcgUmVmTWFwKCk7IC8vIHRoZSA8dGQ+XG4gICAgICAgIHRoaXMuZnJhbWVFbFJlZnMgPSBuZXcgUmVmTWFwKCk7IC8vIHRoZSBmYy1kYXlncmlkLWRheS1mcmFtZVxuICAgICAgICB0aGlzLmZnRWxSZWZzID0gbmV3IFJlZk1hcCgpOyAvLyB0aGUgZmMtZGF5Z3JpZC1kYXktZXZlbnRzXG4gICAgICAgIHRoaXMuc2VnSGFybmVzc1JlZnMgPSBuZXcgUmVmTWFwKCk7IC8vIGluZGV4ZWQgYnkgXCJpbnN0YW5jZUlkOmZpcnN0Q29sXCJcbiAgICAgICAgdGhpcy5yb290RWxSZWYgPSBjcmVhdGVSZWYoKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIGZyYW1lUG9zaXRpb25zOiBudWxsLFxuICAgICAgICAgICAgbWF4Q29udGVudEhlaWdodDogbnVsbCxcbiAgICAgICAgICAgIHNlZ0hlaWdodHM6IHt9LFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVJlc2l6ZSA9IChpc0ZvcmNlZCkgPT4ge1xuICAgICAgICAgICAgaWYgKGlzRm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTaXppbmcodHJ1ZSk7IC8vIGlzRXh0ZXJuYWw9dHJ1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBzdGF0ZSwgY29udGV4dCB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICAgICAgbGV0IGNvbENudCA9IHByb3BzLmNlbGxzLmxlbmd0aDtcbiAgICAgICAgbGV0IGJ1c2luZXNzSG91cnNCeUNvbCA9IHNwbGl0U2Vnc0J5Rmlyc3RDb2wocHJvcHMuYnVzaW5lc3NIb3VyU2VncywgY29sQ250KTtcbiAgICAgICAgbGV0IGJnRXZlbnRTZWdzQnlDb2wgPSBzcGxpdFNlZ3NCeUZpcnN0Q29sKHByb3BzLmJnRXZlbnRTZWdzLCBjb2xDbnQpO1xuICAgICAgICBsZXQgaGlnaGxpZ2h0U2Vnc0J5Q29sID0gc3BsaXRTZWdzQnlGaXJzdENvbCh0aGlzLmdldEhpZ2hsaWdodFNlZ3MoKSwgY29sQ250KTtcbiAgICAgICAgbGV0IG1pcnJvclNlZ3NCeUNvbCA9IHNwbGl0U2Vnc0J5Rmlyc3RDb2wodGhpcy5nZXRNaXJyb3JTZWdzKCksIGNvbENudCk7XG4gICAgICAgIGxldCB7IHNpbmdsZUNvbFBsYWNlbWVudHMsIG11bHRpQ29sUGxhY2VtZW50cywgbW9yZUNudHMsIG1vcmVNYXJnaW5Ub3BzIH0gPSBjb21wdXRlRmdTZWdQbGFjZW1lbnQoc29ydEV2ZW50U2Vncyhwcm9wcy5mZ0V2ZW50U2Vncywgb3B0aW9ucy5ldmVudE9yZGVyKSwgcHJvcHMuZGF5TWF4RXZlbnRzLCBwcm9wcy5kYXlNYXhFdmVudFJvd3MsIG9wdGlvbnMuZXZlbnRPcmRlclN0cmljdCwgc3RhdGUuc2VnSGVpZ2h0cywgc3RhdGUubWF4Q29udGVudEhlaWdodCwgcHJvcHMuY2VsbHMpO1xuICAgICAgICBsZXQgaXNGb3JjZWRJbnZpc2libGUgPSAvLyBUT0RPOiBtZXNzeSB3YXkgdG8gY29tcHV0ZSB0aGlzXG4gICAgICAgICAocHJvcHMuZXZlbnREcmFnICYmIHByb3BzLmV2ZW50RHJhZy5hZmZlY3RlZEluc3RhbmNlcykgfHxcbiAgICAgICAgICAgIChwcm9wcy5ldmVudFJlc2l6ZSAmJiBwcm9wcy5ldmVudFJlc2l6ZS5hZmZlY3RlZEluc3RhbmNlcykgfHxcbiAgICAgICAgICAgIHt9O1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7IHJlZjogdGhpcy5yb290RWxSZWYsIHJvbGU6IFwicm93XCIgfSxcbiAgICAgICAgICAgIHByb3BzLnJlbmRlckludHJvICYmIHByb3BzLnJlbmRlckludHJvKCksXG4gICAgICAgICAgICBwcm9wcy5jZWxscy5tYXAoKGNlbGwsIGNvbCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBub3JtYWxGZ05vZGVzID0gdGhpcy5yZW5kZXJGZ1NlZ3MoY29sLCBwcm9wcy5mb3JQcmludCA/IHNpbmdsZUNvbFBsYWNlbWVudHNbY29sXSA6IG11bHRpQ29sUGxhY2VtZW50c1tjb2xdLCBwcm9wcy50b2RheVJhbmdlLCBpc0ZvcmNlZEludmlzaWJsZSk7XG4gICAgICAgICAgICAgICAgbGV0IG1pcnJvckZnTm9kZXMgPSB0aGlzLnJlbmRlckZnU2Vncyhjb2wsIGJ1aWxkTWlycm9yUGxhY2VtZW50cyhtaXJyb3JTZWdzQnlDb2xbY29sXSwgbXVsdGlDb2xQbGFjZW1lbnRzKSwgcHJvcHMudG9kYXlSYW5nZSwge30sIEJvb2xlYW4ocHJvcHMuZXZlbnREcmFnKSwgQm9vbGVhbihwcm9wcy5ldmVudFJlc2l6ZSksIGZhbHNlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoVGFibGVDZWxsLCB7IGtleTogY2VsbC5rZXksIGVsUmVmOiB0aGlzLmNlbGxFbFJlZnMuY3JlYXRlUmVmKGNlbGwua2V5KSwgaW5uZXJFbFJlZjogdGhpcy5mcmFtZUVsUmVmcy5jcmVhdGVSZWYoY2VsbC5rZXkpIC8qIEZGIDx0ZD4gcHJvYmxlbSwgYnV0IG9rYXkgdG8gdXNlIGZvciBsZWZ0L3JpZ2h0LiBUT0RPOiByZW5hbWUgcHJvcCAqLywgZGF0ZVByb2ZpbGU6IHByb3BzLmRhdGVQcm9maWxlLCBkYXRlOiBjZWxsLmRhdGUsIHNob3dEYXlOdW1iZXI6IHByb3BzLnNob3dEYXlOdW1iZXJzLCBzaG93V2Vla051bWJlcjogcHJvcHMuc2hvd1dlZWtOdW1iZXJzICYmIGNvbCA9PT0gMCwgZm9yY2VEYXlUb3A6IHByb3BzLnNob3dXZWVrTnVtYmVycyAvKiBldmVuIGRpc3BsYXlpbmcgd2Vla251bSBmb3Igcm93LCBub3QgbmVjZXNzYXJpbHkgZGF5ICovLCB0b2RheVJhbmdlOiBwcm9wcy50b2RheVJhbmdlLCBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb24sIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLCBldmVudFJlc2l6ZTogcHJvcHMuZXZlbnRSZXNpemUsIGV4dHJhUmVuZGVyUHJvcHM6IGNlbGwuZXh0cmFSZW5kZXJQcm9wcywgZXh0cmFEYXRhQXR0cnM6IGNlbGwuZXh0cmFEYXRhQXR0cnMsIGV4dHJhQ2xhc3NOYW1lczogY2VsbC5leHRyYUNsYXNzTmFtZXMsIGV4dHJhRGF0ZVNwYW46IGNlbGwuZXh0cmFEYXRlU3BhbiwgbW9yZUNudDogbW9yZUNudHNbY29sXSwgbW9yZU1hcmdpblRvcDogbW9yZU1hcmdpblRvcHNbY29sXSwgc2luZ2xlUGxhY2VtZW50czogc2luZ2xlQ29sUGxhY2VtZW50c1tjb2xdLCBmZ0NvbnRlbnRFbFJlZjogdGhpcy5mZ0VsUmVmcy5jcmVhdGVSZWYoY2VsbC5rZXkpLCBmZ0NvbnRlbnQ6ICggLy8gRnJhZ21lbnQgc2NvcGVzIHRoZSBrZXlzXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoRnJhZ21lbnQsIG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLCBub3JtYWxGZ05vZGVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoRnJhZ21lbnQsIG51bGwsIG1pcnJvckZnTm9kZXMpKSksIGJnQ29udGVudDogKCAvLyBGcmFnbWVudCBzY29wZXMgdGhlIGtleXNcbiAgICAgICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChGcmFnbWVudCwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyRmlsbFNlZ3MoaGlnaGxpZ2h0U2Vnc0J5Q29sW2NvbF0sICdoaWdobGlnaHQnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyRmlsbFNlZ3MoYnVzaW5lc3NIb3Vyc0J5Q29sW2NvbF0sICdub24tYnVzaW5lc3MnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyRmlsbFNlZ3MoYmdFdmVudFNlZ3NCeUNvbFtjb2xdLCAnYmctZXZlbnQnKSkpLCBtaW5IZWlnaHQ6IHByb3BzLmNlbGxNaW5IZWlnaHQgfSkpO1xuICAgICAgICAgICAgfSkpKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlU2l6aW5nKHRydWUpO1xuICAgICAgICB0aGlzLmNvbnRleHQuYWRkUmVzaXplSGFuZGxlcih0aGlzLmhhbmRsZVJlc2l6ZSk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHMsIHByZXZTdGF0ZSkge1xuICAgICAgICBsZXQgY3VycmVudFByb3BzID0gdGhpcy5wcm9wcztcbiAgICAgICAgdGhpcy51cGRhdGVTaXppbmcoIWlzUHJvcHNFcXVhbChwcmV2UHJvcHMsIGN1cnJlbnRQcm9wcykpO1xuICAgIH1cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0LnJlbW92ZVJlc2l6ZUhhbmRsZXIodGhpcy5oYW5kbGVSZXNpemUpO1xuICAgIH1cbiAgICBnZXRIaWdobGlnaHRTZWdzKCkge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgaWYgKHByb3BzLmV2ZW50RHJhZyAmJiBwcm9wcy5ldmVudERyYWcuc2Vncy5sZW5ndGgpIHsgLy8gbWVzc3kgY2hlY2tcbiAgICAgICAgICAgIHJldHVybiBwcm9wcy5ldmVudERyYWcuc2VncztcbiAgICAgICAgfVxuICAgICAgICBpZiAocHJvcHMuZXZlbnRSZXNpemUgJiYgcHJvcHMuZXZlbnRSZXNpemUuc2Vncy5sZW5ndGgpIHsgLy8gbWVzc3kgY2hlY2tcbiAgICAgICAgICAgIHJldHVybiBwcm9wcy5ldmVudFJlc2l6ZS5zZWdzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcm9wcy5kYXRlU2VsZWN0aW9uU2VncztcbiAgICB9XG4gICAgZ2V0TWlycm9yU2VncygpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGlmIChwcm9wcy5ldmVudFJlc2l6ZSAmJiBwcm9wcy5ldmVudFJlc2l6ZS5zZWdzLmxlbmd0aCkgeyAvLyBtZXNzeSBjaGVja1xuICAgICAgICAgICAgcmV0dXJuIHByb3BzLmV2ZW50UmVzaXplLnNlZ3M7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICByZW5kZXJGZ1NlZ3MoY29sLCBzZWdQbGFjZW1lbnRzLCB0b2RheVJhbmdlLCBpc0ZvcmNlZEludmlzaWJsZSwgaXNEcmFnZ2luZywgaXNSZXNpemluZywgaXNEYXRlU2VsZWN0aW5nKSB7XG4gICAgICAgIGxldCB7IGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IGV2ZW50U2VsZWN0aW9uIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBsZXQgeyBmcmFtZVBvc2l0aW9ucyB9ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgbGV0IGRlZmF1bHREaXNwbGF5RXZlbnRFbmQgPSB0aGlzLnByb3BzLmNlbGxzLmxlbmd0aCA9PT0gMTsgLy8gY29sQ250ID09PSAxXG4gICAgICAgIGxldCBpc01pcnJvciA9IGlzRHJhZ2dpbmcgfHwgaXNSZXNpemluZyB8fCBpc0RhdGVTZWxlY3Rpbmc7XG4gICAgICAgIGxldCBub2RlcyA9IFtdO1xuICAgICAgICBpZiAoZnJhbWVQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHBsYWNlbWVudCBvZiBzZWdQbGFjZW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgbGV0IHsgc2VnIH0gPSBwbGFjZW1lbnQ7XG4gICAgICAgICAgICAgICAgbGV0IHsgaW5zdGFuY2VJZCB9ID0gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgICAgICAgICAgbGV0IGlzVmlzaWJsZSA9IHBsYWNlbWVudC5pc1Zpc2libGUgJiYgIWlzRm9yY2VkSW52aXNpYmxlW2luc3RhbmNlSWRdO1xuICAgICAgICAgICAgICAgIGxldCBpc0Fic29sdXRlID0gcGxhY2VtZW50LmlzQWJzb2x1dGU7XG4gICAgICAgICAgICAgICAgbGV0IGxlZnQgPSAnJztcbiAgICAgICAgICAgICAgICBsZXQgcmlnaHQgPSAnJztcbiAgICAgICAgICAgICAgICBpZiAoaXNBYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29udGV4dC5pc1J0bCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGZyYW1lUG9zaXRpb25zLmxlZnRzW3NlZy5sYXN0Q29sXSAtIGZyYW1lUG9zaXRpb25zLmxlZnRzW3NlZy5maXJzdENvbF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gZnJhbWVQb3NpdGlvbnMucmlnaHRzW3NlZy5maXJzdENvbF0gLSBmcmFtZVBvc2l0aW9ucy5yaWdodHNbc2VnLmxhc3RDb2xdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAga25vd24gYnVnOiBldmVudHMgdGhhdCBhcmUgZm9yY2UgdG8gYmUgbGlzdC1pdGVtIGJ1dCBzcGFuIG11bHRpcGxlIGRheXMgc3RpbGwgdGFrZSB1cCBzcGFjZSBpbiBsYXRlciBjb2x1bW5zXG4gICAgICAgICAgICAgICAgdG9kbzogaW4gcHJpbnQgdmlldywgZm9yIG11bHRpLWRheSBldmVudHMsIGRvbid0IGRpc3BsYXkgdGl0bGUgd2l0aGluIG5vbi1zdGFydC9lbmQgc2Vnc1xuICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgbm9kZXMucHVzaChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiAnZmMtZGF5Z3JpZC1ldmVudC1oYXJuZXNzJyArIChpc0Fic29sdXRlID8gJyBmYy1kYXlncmlkLWV2ZW50LWhhcm5lc3MtYWJzJyA6ICcnKSwga2V5OiBnZW5lcmF0ZVNlZ0tleShzZWcpLCByZWY6IGlzTWlycm9yID8gbnVsbCA6IHRoaXMuc2VnSGFybmVzc1JlZnMuY3JlYXRlUmVmKGdlbmVyYXRlU2VnVWlkKHNlZykpLCBzdHlsZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogaXNWaXNpYmxlID8gJycgOiAnaGlkZGVuJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpblRvcDogaXNBYnNvbHV0ZSA/ICcnIDogcGxhY2VtZW50Lm1hcmdpblRvcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogaXNBYnNvbHV0ZSA/IHBsYWNlbWVudC5hYnNvbHV0ZVRvcCA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0LFxuICAgICAgICAgICAgICAgICAgICB9IH0sIGhhc0xpc3RJdGVtRGlzcGxheShzZWcpID8gKGNyZWF0ZUVsZW1lbnQoVGFibGVMaXN0SXRlbUV2ZW50LCBPYmplY3QuYXNzaWduKHsgc2VnOiBzZWcsIGlzRHJhZ2dpbmc6IGlzRHJhZ2dpbmcsIGlzU2VsZWN0ZWQ6IGluc3RhbmNlSWQgPT09IGV2ZW50U2VsZWN0aW9uLCBkZWZhdWx0RGlzcGxheUV2ZW50RW5kOiBkZWZhdWx0RGlzcGxheUV2ZW50RW5kIH0sIGdldFNlZ01ldGEoc2VnLCB0b2RheVJhbmdlKSkpKSA6IChjcmVhdGVFbGVtZW50KFRhYmxlQmxvY2tFdmVudCwgT2JqZWN0LmFzc2lnbih7IHNlZzogc2VnLCBpc0RyYWdnaW5nOiBpc0RyYWdnaW5nLCBpc1Jlc2l6aW5nOiBpc1Jlc2l6aW5nLCBpc0RhdGVTZWxlY3Rpbmc6IGlzRGF0ZVNlbGVjdGluZywgaXNTZWxlY3RlZDogaW5zdGFuY2VJZCA9PT0gZXZlbnRTZWxlY3Rpb24sIGRlZmF1bHREaXNwbGF5RXZlbnRFbmQ6IGRlZmF1bHREaXNwbGF5RXZlbnRFbmQgfSwgZ2V0U2VnTWV0YShzZWcsIHRvZGF5UmFuZ2UpKSkpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICByZW5kZXJGaWxsU2VncyhzZWdzLCBmaWxsVHlwZSkge1xuICAgICAgICBsZXQgeyBpc1J0bCB9ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBsZXQgeyB0b2RheVJhbmdlIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBsZXQgeyBmcmFtZVBvc2l0aW9ucyB9ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgbGV0IG5vZGVzID0gW107XG4gICAgICAgIGlmIChmcmFtZVBvc2l0aW9ucykge1xuICAgICAgICAgICAgZm9yIChsZXQgc2VnIG9mIHNlZ3MpIHtcbiAgICAgICAgICAgICAgICBsZXQgbGVmdFJpZ2h0Q3NzID0gaXNSdGwgPyB7XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiAwLFxuICAgICAgICAgICAgICAgICAgICBsZWZ0OiBmcmFtZVBvc2l0aW9ucy5sZWZ0c1tzZWcubGFzdENvbF0gLSBmcmFtZVBvc2l0aW9ucy5sZWZ0c1tzZWcuZmlyc3RDb2xdLFxuICAgICAgICAgICAgICAgIH0gOiB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBmcmFtZVBvc2l0aW9ucy5yaWdodHNbc2VnLmZpcnN0Q29sXSAtIGZyYW1lUG9zaXRpb25zLnJpZ2h0c1tzZWcubGFzdENvbF0sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBub2Rlcy5wdXNoKGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBrZXk6IGJ1aWxkRXZlbnRSYW5nZUtleShzZWcuZXZlbnRSYW5nZSksIGNsYXNzTmFtZTogXCJmYy1kYXlncmlkLWJnLWhhcm5lc3NcIiwgc3R5bGU6IGxlZnRSaWdodENzcyB9LCBmaWxsVHlwZSA9PT0gJ2JnLWV2ZW50JyA/XG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoQmdFdmVudCwgT2JqZWN0LmFzc2lnbih7IHNlZzogc2VnIH0sIGdldFNlZ01ldGEoc2VnLCB0b2RheVJhbmdlKSkpIDpcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyRmlsbChmaWxsVHlwZSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3JlYXRlRWxlbWVudChGcmFnbWVudCwge30sIC4uLm5vZGVzKTtcbiAgICB9XG4gICAgdXBkYXRlU2l6aW5nKGlzRXh0ZXJuYWxTaXppbmdDaGFuZ2UpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIHN0YXRlLCBmcmFtZUVsUmVmcyB9ID0gdGhpcztcbiAgICAgICAgaWYgKCFwcm9wcy5mb3JQcmludCAmJlxuICAgICAgICAgICAgcHJvcHMuY2xpZW50V2lkdGggIT09IG51bGwgLy8gcG9zaXRpb25pbmcgcmVhZHk/XG4gICAgICAgICkge1xuICAgICAgICAgICAgaWYgKGlzRXh0ZXJuYWxTaXppbmdDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICBsZXQgZnJhbWVFbHMgPSBwcm9wcy5jZWxscy5tYXAoKGNlbGwpID0+IGZyYW1lRWxSZWZzLmN1cnJlbnRNYXBbY2VsbC5rZXldKTtcbiAgICAgICAgICAgICAgICBpZiAoZnJhbWVFbHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcmlnaW5FbCA9IHRoaXMucm9vdEVsUmVmLmN1cnJlbnQ7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuZXdQb3NpdGlvbkNhY2hlID0gbmV3IFBvc2l0aW9uQ2FjaGUob3JpZ2luRWwsIGZyYW1lRWxzLCB0cnVlLCAvLyBpc0hvcml6b250YWxcbiAgICAgICAgICAgICAgICAgICAgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXN0YXRlLmZyYW1lUG9zaXRpb25zIHx8ICFzdGF0ZS5mcmFtZVBvc2l0aW9ucy5zaW1pbGFyVG8obmV3UG9zaXRpb25DYWNoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lUG9zaXRpb25zOiBuZXcgUG9zaXRpb25DYWNoZShvcmlnaW5FbCwgZnJhbWVFbHMsIHRydWUsIC8vIGlzSG9yaXpvbnRhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb2xkU2VnSGVpZ2h0cyA9IHRoaXMuc3RhdGUuc2VnSGVpZ2h0cztcbiAgICAgICAgICAgIGNvbnN0IG5ld1NlZ0hlaWdodHMgPSB0aGlzLnF1ZXJ5U2VnSGVpZ2h0cygpO1xuICAgICAgICAgICAgY29uc3QgbGltaXRCeUNvbnRlbnRIZWlnaHQgPSBwcm9wcy5kYXlNYXhFdmVudHMgPT09IHRydWUgfHwgcHJvcHMuZGF5TWF4RXZlbnRSb3dzID09PSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zYWZlU2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIC8vIEhBQ0sgdG8gcHJldmVudCBvc2NpbGxhdGlvbnMgb2YgZXZlbnRzIGJlaW5nIHNob3duL2hpZGRlbiBmcm9tIG1heC1ldmVudC1yb3dzXG4gICAgICAgICAgICAgICAgLy8gRXNzZW50aWFsbHksIG9uY2UgeW91IGNvbXB1dGUgYW4gZWxlbWVudCdzIGhlaWdodCwgbmV2ZXIgbnVsbC1vdXQuXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogYWx3YXlzIGRpc3BsYXkgYWxsIGV2ZW50cywgYXMgdmlzaWJpbGl0eTpoaWRkZW4/XG4gICAgICAgICAgICAgICAgc2VnSGVpZ2h0czogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBvbGRTZWdIZWlnaHRzKSwgbmV3U2VnSGVpZ2h0cyksXG4gICAgICAgICAgICAgICAgbWF4Q29udGVudEhlaWdodDogbGltaXRCeUNvbnRlbnRIZWlnaHQgPyB0aGlzLmNvbXB1dGVNYXhDb250ZW50SGVpZ2h0KCkgOiBudWxsLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVlcnlTZWdIZWlnaHRzKCkge1xuICAgICAgICBsZXQgc2VnRWxNYXAgPSB0aGlzLnNlZ0hhcm5lc3NSZWZzLmN1cnJlbnRNYXA7XG4gICAgICAgIGxldCBzZWdIZWlnaHRzID0ge307XG4gICAgICAgIC8vIGdldCB0aGUgbWF4IGhlaWdodCBhbW9uZ3N0IGluc3RhbmNlIHNlZ3NcbiAgICAgICAgZm9yIChsZXQgc2VnVWlkIGluIHNlZ0VsTWFwKSB7XG4gICAgICAgICAgICBsZXQgaGVpZ2h0ID0gTWF0aC5yb3VuZChzZWdFbE1hcFtzZWdVaWRdLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCk7XG4gICAgICAgICAgICBzZWdIZWlnaHRzW3NlZ1VpZF0gPSBNYXRoLm1heChzZWdIZWlnaHRzW3NlZ1VpZF0gfHwgMCwgaGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VnSGVpZ2h0cztcbiAgICB9XG4gICAgY29tcHV0ZU1heENvbnRlbnRIZWlnaHQoKSB7XG4gICAgICAgIGxldCBmaXJzdEtleSA9IHRoaXMucHJvcHMuY2VsbHNbMF0ua2V5O1xuICAgICAgICBsZXQgY2VsbEVsID0gdGhpcy5jZWxsRWxSZWZzLmN1cnJlbnRNYXBbZmlyc3RLZXldO1xuICAgICAgICBsZXQgZmNDb250YWluZXJFbCA9IHRoaXMuZmdFbFJlZnMuY3VycmVudE1hcFtmaXJzdEtleV07XG4gICAgICAgIHJldHVybiBjZWxsRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuYm90dG9tIC0gZmNDb250YWluZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3A7XG4gICAgfVxuICAgIGdldENlbGxFbHMoKSB7XG4gICAgICAgIGxldCBlbE1hcCA9IHRoaXMuY2VsbEVsUmVmcy5jdXJyZW50TWFwO1xuICAgICAgICByZXR1cm4gdGhpcy5wcm9wcy5jZWxscy5tYXAoKGNlbGwpID0+IGVsTWFwW2NlbGwua2V5XSk7XG4gICAgfVxufVxuVGFibGVSb3cuYWRkU3RhdGVFcXVhbGl0eSh7XG4gICAgc2VnSGVpZ2h0czogaXNQcm9wc0VxdWFsLFxufSk7XG5mdW5jdGlvbiBidWlsZE1pcnJvclBsYWNlbWVudHMobWlycm9yU2VncywgY29sUGxhY2VtZW50cykge1xuICAgIGlmICghbWlycm9yU2Vncy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBsZXQgdG9wc0J5SW5zdGFuY2VJZCA9IGJ1aWxkQWJzb2x1dGVUb3BIYXNoKGNvbFBsYWNlbWVudHMpOyAvLyBUT0RPOiBjYWNoZSB0aGlzIGF0IGZpcnN0IHJlbmRlcj9cbiAgICByZXR1cm4gbWlycm9yU2Vncy5tYXAoKHNlZykgPT4gKHtcbiAgICAgICAgc2VnLFxuICAgICAgICBpc1Zpc2libGU6IHRydWUsXG4gICAgICAgIGlzQWJzb2x1dGU6IHRydWUsXG4gICAgICAgIGFic29sdXRlVG9wOiB0b3BzQnlJbnN0YW5jZUlkW3NlZy5ldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWRdLFxuICAgICAgICBtYXJnaW5Ub3A6IDAsXG4gICAgfSkpO1xufVxuZnVuY3Rpb24gYnVpbGRBYnNvbHV0ZVRvcEhhc2goY29sUGxhY2VtZW50cykge1xuICAgIGxldCB0b3BzQnlJbnN0YW5jZUlkID0ge307XG4gICAgZm9yIChsZXQgcGxhY2VtZW50cyBvZiBjb2xQbGFjZW1lbnRzKSB7XG4gICAgICAgIGZvciAobGV0IHBsYWNlbWVudCBvZiBwbGFjZW1lbnRzKSB7XG4gICAgICAgICAgICB0b3BzQnlJbnN0YW5jZUlkW3BsYWNlbWVudC5zZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSA9IHBsYWNlbWVudC5hYnNvbHV0ZVRvcDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdG9wc0J5SW5zdGFuY2VJZDtcbn1cblxuY2xhc3MgVGFibGVSb3dzIGV4dGVuZHMgRGF0ZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc3BsaXRCdXNpbmVzc0hvdXJTZWdzID0gbWVtb2l6ZShzcGxpdFNlZ3NCeVJvdyk7XG4gICAgICAgIHRoaXMuc3BsaXRCZ0V2ZW50U2VncyA9IG1lbW9pemUoc3BsaXRBbGxEYXlTZWdzQnlSb3cpO1xuICAgICAgICB0aGlzLnNwbGl0RmdFdmVudFNlZ3MgPSBtZW1vaXplKHNwbGl0U2Vnc0J5Um93KTtcbiAgICAgICAgdGhpcy5zcGxpdERhdGVTZWxlY3Rpb25TZWdzID0gbWVtb2l6ZShzcGxpdFNlZ3NCeVJvdyk7XG4gICAgICAgIHRoaXMuc3BsaXRFdmVudERyYWcgPSBtZW1vaXplKHNwbGl0SW50ZXJhY3Rpb25CeVJvdyk7XG4gICAgICAgIHRoaXMuc3BsaXRFdmVudFJlc2l6ZSA9IG1lbW9pemUoc3BsaXRJbnRlcmFjdGlvbkJ5Um93KTtcbiAgICAgICAgdGhpcy5yb3dSZWZzID0gbmV3IFJlZk1hcCgpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBsZXQgcm93Q250ID0gcHJvcHMuY2VsbHMubGVuZ3RoO1xuICAgICAgICBsZXQgYnVzaW5lc3NIb3VyU2Vnc0J5Um93ID0gdGhpcy5zcGxpdEJ1c2luZXNzSG91clNlZ3MocHJvcHMuYnVzaW5lc3NIb3VyU2Vncywgcm93Q250KTtcbiAgICAgICAgbGV0IGJnRXZlbnRTZWdzQnlSb3cgPSB0aGlzLnNwbGl0QmdFdmVudFNlZ3MocHJvcHMuYmdFdmVudFNlZ3MsIHJvd0NudCk7XG4gICAgICAgIGxldCBmZ0V2ZW50U2Vnc0J5Um93ID0gdGhpcy5zcGxpdEZnRXZlbnRTZWdzKHByb3BzLmZnRXZlbnRTZWdzLCByb3dDbnQpO1xuICAgICAgICBsZXQgZGF0ZVNlbGVjdGlvblNlZ3NCeVJvdyA9IHRoaXMuc3BsaXREYXRlU2VsZWN0aW9uU2Vncyhwcm9wcy5kYXRlU2VsZWN0aW9uU2Vncywgcm93Q250KTtcbiAgICAgICAgbGV0IGV2ZW50RHJhZ0J5Um93ID0gdGhpcy5zcGxpdEV2ZW50RHJhZyhwcm9wcy5ldmVudERyYWcsIHJvd0NudCk7XG4gICAgICAgIGxldCBldmVudFJlc2l6ZUJ5Um93ID0gdGhpcy5zcGxpdEV2ZW50UmVzaXplKHByb3BzLmV2ZW50UmVzaXplLCByb3dDbnQpO1xuICAgICAgICAvLyBmb3IgRGF5R3JpZCB2aWV3IHdpdGggbWFueSByb3dzLCBmb3JjZSBhIG1pbi1oZWlnaHQgb24gY2VsbHMgc28gZG9lc24ndCBhcHBlYXIgc3F1aXNoZWRcbiAgICAgICAgLy8gY2hvb3NlIDcgYmVjYXVzZSBhIG1vbnRoIHZpZXcgd2lsbCBoYXZlIG1heCA2IHJvd3NcbiAgICAgICAgbGV0IGNlbGxNaW5IZWlnaHQgPSAocm93Q250ID49IDcgJiYgcHJvcHMuY2xpZW50V2lkdGgpID9cbiAgICAgICAgICAgIHByb3BzLmNsaWVudFdpZHRoIC8gY29udGV4dC5vcHRpb25zLmFzcGVjdFJhdGlvIC8gNiA6XG4gICAgICAgICAgICBudWxsO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoTm93VGltZXIsIHsgdW5pdDogXCJkYXlcIiB9LCAobm93RGF0ZSwgdG9kYXlSYW5nZSkgPT4gKGNyZWF0ZUVsZW1lbnQoRnJhZ21lbnQsIG51bGwsIHByb3BzLmNlbGxzLm1hcCgoY2VsbHMsIHJvdykgPT4gKGNyZWF0ZUVsZW1lbnQoVGFibGVSb3csIHsgcmVmOiB0aGlzLnJvd1JlZnMuY3JlYXRlUmVmKHJvdyksIGtleTogY2VsbHMubGVuZ3RoXG4gICAgICAgICAgICAgICAgPyBjZWxsc1swXS5kYXRlLnRvSVNPU3RyaW5nKCkgLyogYmVzdD8gb3IgcHV0IGtleSBvbiBjZWxsPyBvciB1c2UgZGlmZiBmb3JtYXR0ZXI/ICovXG4gICAgICAgICAgICAgICAgOiByb3cgLy8gaW4gY2FzZSB0aGVyZSBhcmUgbm8gY2VsbHMgKGxpa2Ugd2hlbiByZXNvdXJjZSB2aWV3IGlzIGxvYWRpbmcpXG4gICAgICAgICAgICAsIHNob3dEYXlOdW1iZXJzOiByb3dDbnQgPiAxLCBzaG93V2Vla051bWJlcnM6IHByb3BzLnNob3dXZWVrTnVtYmVycywgdG9kYXlSYW5nZTogdG9kYXlSYW5nZSwgZGF0ZVByb2ZpbGU6IHByb3BzLmRhdGVQcm9maWxlLCBjZWxsczogY2VsbHMsIHJlbmRlckludHJvOiBwcm9wcy5yZW5kZXJSb3dJbnRybywgYnVzaW5lc3NIb3VyU2VnczogYnVzaW5lc3NIb3VyU2Vnc0J5Um93W3Jvd10sIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvbiwgYmdFdmVudFNlZ3M6IGJnRXZlbnRTZWdzQnlSb3dbcm93XSwgZmdFdmVudFNlZ3M6IGZnRXZlbnRTZWdzQnlSb3dbcm93XSwgZGF0ZVNlbGVjdGlvblNlZ3M6IGRhdGVTZWxlY3Rpb25TZWdzQnlSb3dbcm93XSwgZXZlbnREcmFnOiBldmVudERyYWdCeVJvd1tyb3ddLCBldmVudFJlc2l6ZTogZXZlbnRSZXNpemVCeVJvd1tyb3ddLCBkYXlNYXhFdmVudHM6IHByb3BzLmRheU1heEV2ZW50cywgZGF5TWF4RXZlbnRSb3dzOiBwcm9wcy5kYXlNYXhFdmVudFJvd3MsIGNsaWVudFdpZHRoOiBwcm9wcy5jbGllbnRXaWR0aCwgY2xpZW50SGVpZ2h0OiBwcm9wcy5jbGllbnRIZWlnaHQsIGNlbGxNaW5IZWlnaHQ6IGNlbGxNaW5IZWlnaHQsIGZvclByaW50OiBwcm9wcy5mb3JQcmludCB9KSkpKSkpKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCgpO1xuICAgIH1cbiAgICBjb21wb25lbnREaWRVcGRhdGUoKSB7XG4gICAgICAgIC8vIGZvciBpZiBzdGFydGVkIHdpdGggemVybyBjZWxsc1xuICAgICAgICB0aGlzLnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQoKTtcbiAgICB9XG4gICAgcmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJvb3RFbCkge1xuICAgICAgICAgICAgLy8gSEFDSzogbmVlZCBhIGRheWdyaWQgd3JhcHBlciBwYXJlbnQgdG8gZG8gcG9zaXRpb25pbmdcbiAgICAgICAgICAgIC8vIE5PVEU6IGEgZGF5Z3JpZCByZXNvdXJjZSB2aWV3IHcvbyByZXNvdXJjZXMgY2FuIGhhdmUgemVybyBjZWxsc1xuICAgICAgICAgICAgY29uc3QgZmlyc3RDZWxsRWwgPSB0aGlzLnJvd1JlZnMuY3VycmVudE1hcFswXS5nZXRDZWxsRWxzKClbMF07XG4gICAgICAgICAgICBjb25zdCByb290RWwgPSBmaXJzdENlbGxFbCA/IGZpcnN0Q2VsbEVsLmNsb3Nlc3QoJy5mYy1kYXlncmlkLWJvZHknKSA6IG51bGw7XG4gICAgICAgICAgICBpZiAocm9vdEVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb290RWwgPSByb290RWw7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZXh0LnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBlbDogcm9vdEVsLFxuICAgICAgICAgICAgICAgICAgICBpc0hpdENvbWJvQWxsb3dlZDogdGhpcy5wcm9wcy5pc0hpdENvbWJvQWxsb3dlZCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgaWYgKHRoaXMucm9vdEVsKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRleHQudW5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5yb290RWwgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIEhpdCBTeXN0ZW1cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgcHJlcGFyZUhpdHMoKSB7XG4gICAgICAgIHRoaXMucm93UG9zaXRpb25zID0gbmV3IFBvc2l0aW9uQ2FjaGUodGhpcy5yb290RWwsIHRoaXMucm93UmVmcy5jb2xsZWN0KCkubWFwKChyb3dPYmopID0+IHJvd09iai5nZXRDZWxsRWxzKClbMF0pLCAvLyBmaXJzdCBjZWxsIGVsIGluIGVhY2ggcm93LiBUT0RPOiBub3Qgb3B0aW1hbFxuICAgICAgICBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuY29sUG9zaXRpb25zID0gbmV3IFBvc2l0aW9uQ2FjaGUodGhpcy5yb290RWwsIHRoaXMucm93UmVmcy5jdXJyZW50TWFwWzBdLmdldENlbGxFbHMoKSwgLy8gY2VsbCBlbHMgaW4gZmlyc3Qgcm93XG4gICAgICAgIHRydWUsIC8vIGhvcml6b250YWxcbiAgICAgICAgZmFsc2UpO1xuICAgIH1cbiAgICBxdWVyeUhpdChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wKSB7XG4gICAgICAgIGxldCB7IGNvbFBvc2l0aW9ucywgcm93UG9zaXRpb25zIH0gPSB0aGlzO1xuICAgICAgICBsZXQgY29sID0gY29sUG9zaXRpb25zLmxlZnRUb0luZGV4KHBvc2l0aW9uTGVmdCk7XG4gICAgICAgIGxldCByb3cgPSByb3dQb3NpdGlvbnMudG9wVG9JbmRleChwb3NpdGlvblRvcCk7XG4gICAgICAgIGlmIChyb3cgIT0gbnVsbCAmJiBjb2wgIT0gbnVsbCkge1xuICAgICAgICAgICAgbGV0IGNlbGwgPSB0aGlzLnByb3BzLmNlbGxzW3Jvd11bY29sXTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICAgICAgZGF0ZVNwYW46IE9iamVjdC5hc3NpZ24oeyByYW5nZTogdGhpcy5nZXRDZWxsUmFuZ2Uocm93LCBjb2wpLCBhbGxEYXk6IHRydWUgfSwgY2VsbC5leHRyYURhdGVTcGFuKSxcbiAgICAgICAgICAgICAgICBkYXlFbDogdGhpcy5nZXRDZWxsRWwocm93LCBjb2wpLFxuICAgICAgICAgICAgICAgIHJlY3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogY29sUG9zaXRpb25zLmxlZnRzW2NvbF0sXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBjb2xQb3NpdGlvbnMucmlnaHRzW2NvbF0sXG4gICAgICAgICAgICAgICAgICAgIHRvcDogcm93UG9zaXRpb25zLnRvcHNbcm93XSxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiByb3dQb3NpdGlvbnMuYm90dG9tc1tyb3ddLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbGF5ZXI6IDAsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBnZXRDZWxsRWwocm93LCBjb2wpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93UmVmcy5jdXJyZW50TWFwW3Jvd10uZ2V0Q2VsbEVscygpW2NvbF07IC8vIFRPRE86IG5vdCBvcHRpbWFsXG4gICAgfVxuICAgIGdldENlbGxSYW5nZShyb3csIGNvbCkge1xuICAgICAgICBsZXQgc3RhcnQgPSB0aGlzLnByb3BzLmNlbGxzW3Jvd11bY29sXS5kYXRlO1xuICAgICAgICBsZXQgZW5kID0gYWRkRGF5cyhzdGFydCwgMSk7XG4gICAgICAgIHJldHVybiB7IHN0YXJ0LCBlbmQgfTtcbiAgICB9XG59XG5mdW5jdGlvbiBzcGxpdEFsbERheVNlZ3NCeVJvdyhzZWdzLCByb3dDbnQpIHtcbiAgICByZXR1cm4gc3BsaXRTZWdzQnlSb3coc2Vncy5maWx0ZXIoaXNTZWdBbGxEYXkpLCByb3dDbnQpO1xufVxuZnVuY3Rpb24gaXNTZWdBbGxEYXkoc2VnKSB7XG4gICAgcmV0dXJuIHNlZy5ldmVudFJhbmdlLmRlZi5hbGxEYXk7XG59XG5cbmNsYXNzIFRhYmxlIGV4dGVuZHMgRGF0ZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuZWxSZWYgPSBjcmVhdGVSZWYoKTtcbiAgICAgICAgdGhpcy5uZWVkc1Njcm9sbFJlc2V0ID0gZmFsc2U7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IGRheU1heEV2ZW50Um93cywgZGF5TWF4RXZlbnRzLCBleHBhbmRSb3dzIH0gPSBwcm9wcztcbiAgICAgICAgbGV0IGxpbWl0VmlhQmFsYW5jZWQgPSBkYXlNYXhFdmVudHMgPT09IHRydWUgfHwgZGF5TWF4RXZlbnRSb3dzID09PSB0cnVlO1xuICAgICAgICAvLyBpZiByb3dzIGNhbid0IGV4cGFuZCB0byBmaWxsIGZpeGVkIGhlaWdodCwgY2FuJ3QgZG8gYmFsYW5jZWQtaGVpZ2h0IGV2ZW50IGxpbWl0XG4gICAgICAgIC8vIFRPRE86IGJlc3QgcGxhY2UgdG8gbm9ybWFsaXplIHRoZXNlIG9wdGlvbnM/XG4gICAgICAgIGlmIChsaW1pdFZpYUJhbGFuY2VkICYmICFleHBhbmRSb3dzKSB7XG4gICAgICAgICAgICBsaW1pdFZpYUJhbGFuY2VkID0gZmFsc2U7XG4gICAgICAgICAgICBkYXlNYXhFdmVudFJvd3MgPSBudWxsO1xuICAgICAgICAgICAgZGF5TWF4RXZlbnRzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgY2xhc3NOYW1lcyA9IFtcbiAgICAgICAgICAgICdmYy1kYXlncmlkLWJvZHknLFxuICAgICAgICAgICAgbGltaXRWaWFCYWxhbmNlZCA/ICdmYy1kYXlncmlkLWJvZHktYmFsYW5jZWQnIDogJ2ZjLWRheWdyaWQtYm9keS11bmJhbGFuY2VkJyxcbiAgICAgICAgICAgIGV4cGFuZFJvd3MgPyAnJyA6ICdmYy1kYXlncmlkLWJvZHktbmF0dXJhbCcsIC8vIHdpbGwgaGVpZ2h0IG9mIG9uZSByb3cgZGVwZW5kIG9uIHRoZSBvdGhlcnM/XG4gICAgICAgIF07XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IHJlZjogdGhpcy5lbFJlZiwgY2xhc3NOYW1lOiBjbGFzc05hbWVzLmpvaW4oJyAnKSwgc3R5bGU6IHtcbiAgICAgICAgICAgICAgICAvLyB0aGVzZSBwcm9wcyBhcmUgaW1wb3J0YW50IHRvIGdpdmUgdGhpcyB3cmFwcGVyIGNvcnJlY3QgZGltZW5zaW9ucyBmb3IgaW50ZXJhY3Rpb25zXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogaWYgd2Ugc2V0IGl0IGhlcmUsIGNhbiB3ZSBhdm9pZCBnaXZpbmcgdG8gaW5uZXIgdGFibGVzP1xuICAgICAgICAgICAgICAgIHdpZHRoOiBwcm9wcy5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgICAgICBtaW5XaWR0aDogcHJvcHMudGFibGVNaW5XaWR0aCxcbiAgICAgICAgICAgIH0gfSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJ0YWJsZVwiLCB7IHJvbGU6IFwicHJlc2VudGF0aW9uXCIsIGNsYXNzTmFtZTogXCJmYy1zY3JvbGxncmlkLXN5bmMtdGFibGVcIiwgc3R5bGU6IHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHByb3BzLmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBtaW5XaWR0aDogcHJvcHMudGFibGVNaW5XaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBleHBhbmRSb3dzID8gcHJvcHMuY2xpZW50SGVpZ2h0IDogJycsXG4gICAgICAgICAgICAgICAgfSB9LFxuICAgICAgICAgICAgICAgIHByb3BzLmNvbEdyb3VwTm9kZSxcbiAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwidGJvZHlcIiwgeyByb2xlOiBcInByZXNlbnRhdGlvblwiIH0sXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoVGFibGVSb3dzLCB7IGRhdGVQcm9maWxlOiBwcm9wcy5kYXRlUHJvZmlsZSwgY2VsbHM6IHByb3BzLmNlbGxzLCByZW5kZXJSb3dJbnRybzogcHJvcHMucmVuZGVyUm93SW50cm8sIHNob3dXZWVrTnVtYmVyczogcHJvcHMuc2hvd1dlZWtOdW1iZXJzLCBjbGllbnRXaWR0aDogcHJvcHMuY2xpZW50V2lkdGgsIGNsaWVudEhlaWdodDogcHJvcHMuY2xpZW50SGVpZ2h0LCBidXNpbmVzc0hvdXJTZWdzOiBwcm9wcy5idXNpbmVzc0hvdXJTZWdzLCBiZ0V2ZW50U2VnczogcHJvcHMuYmdFdmVudFNlZ3MsIGZnRXZlbnRTZWdzOiBwcm9wcy5mZ0V2ZW50U2VncywgZGF0ZVNlbGVjdGlvblNlZ3M6IHByb3BzLmRhdGVTZWxlY3Rpb25TZWdzLCBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb24sIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLCBldmVudFJlc2l6ZTogcHJvcHMuZXZlbnRSZXNpemUsIGRheU1heEV2ZW50czogZGF5TWF4RXZlbnRzLCBkYXlNYXhFdmVudFJvd3M6IGRheU1heEV2ZW50Um93cywgZm9yUHJpbnQ6IHByb3BzLmZvclByaW50LCBpc0hpdENvbWJvQWxsb3dlZDogcHJvcHMuaXNIaXRDb21ib0FsbG93ZWQgfSkpKSkpO1xuICAgIH1cbiAgICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgICAgdGhpcy5yZXF1ZXN0U2Nyb2xsUmVzZXQoKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkVXBkYXRlKHByZXZQcm9wcykge1xuICAgICAgICBpZiAocHJldlByb3BzLmRhdGVQcm9maWxlICE9PSB0aGlzLnByb3BzLmRhdGVQcm9maWxlKSB7XG4gICAgICAgICAgICB0aGlzLnJlcXVlc3RTY3JvbGxSZXNldCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5mbHVzaFNjcm9sbFJlc2V0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVxdWVzdFNjcm9sbFJlc2V0KCkge1xuICAgICAgICB0aGlzLm5lZWRzU2Nyb2xsUmVzZXQgPSB0cnVlO1xuICAgICAgICB0aGlzLmZsdXNoU2Nyb2xsUmVzZXQoKTtcbiAgICB9XG4gICAgZmx1c2hTY3JvbGxSZXNldCgpIHtcbiAgICAgICAgaWYgKHRoaXMubmVlZHNTY3JvbGxSZXNldCAmJlxuICAgICAgICAgICAgdGhpcy5wcm9wcy5jbGllbnRXaWR0aCAvLyBzaXplcyBjb21wdXRlZD9cbiAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBzdWJqZWN0RWwgPSBnZXRTY3JvbGxTdWJqZWN0RWwodGhpcy5lbFJlZi5jdXJyZW50LCB0aGlzLnByb3BzLmRhdGVQcm9maWxlKTtcbiAgICAgICAgICAgIGlmIChzdWJqZWN0RWwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvcmlnaW5FbCA9IHN1YmplY3RFbC5jbG9zZXN0KCcuZmMtZGF5Z3JpZC1ib2R5Jyk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2Nyb2xsRWwgPSBvcmlnaW5FbC5jbG9zZXN0KCcuZmMtc2Nyb2xsZXInKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzY3JvbGxUb3AgPSBzdWJqZWN0RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC1cbiAgICAgICAgICAgICAgICAgICAgb3JpZ2luRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuICAgICAgICAgICAgICAgIHNjcm9sbEVsLnNjcm9sbFRvcCA9IHNjcm9sbFRvcCA/IChzY3JvbGxUb3AgKyAxKSA6IDA7IC8vIG92ZXJjb21lIGJvcmRlclxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5uZWVkc1Njcm9sbFJlc2V0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBnZXRTY3JvbGxTdWJqZWN0RWwoY29udGFpbmVyRWwsIGRhdGVQcm9maWxlKSB7XG4gICAgbGV0IGVsO1xuICAgIGlmIChkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2VVbml0Lm1hdGNoKC95ZWFyfG1vbnRoLykpIHtcbiAgICAgICAgZWwgPSBjb250YWluZXJFbC5xdWVyeVNlbGVjdG9yKGBbZGF0YS1kYXRlPVwiJHtmb3JtYXRJc29Nb250aFN0cihkYXRlUHJvZmlsZS5jdXJyZW50RGF0ZSl9LTAxXCJdYCk7XG4gICAgICAgIC8vIGV2ZW4gaWYgdmlldyBpcyBtb250aC1iYXNlZCwgZmlyc3Qtb2YtbW9udGggbWlnaHQgYmUgaGlkZGVuLi4uXG4gICAgfVxuICAgIGlmICghZWwpIHtcbiAgICAgICAgZWwgPSBjb250YWluZXJFbC5xdWVyeVNlbGVjdG9yKGBbZGF0YS1kYXRlPVwiJHtmb3JtYXREYXlTdHJpbmcoZGF0ZVByb2ZpbGUuY3VycmVudERhdGUpfVwiXWApO1xuICAgICAgICAvLyBjb3VsZCBzdGlsbCBiZSBoaWRkZW4gaWYgYW4gaW50ZXJpb3ItdmlldyBoaWRkZW4gZGF5XG4gICAgfVxuICAgIHJldHVybiBlbDtcbn1cblxuY2xhc3MgRGF5VGFibGVTbGljZXIgZXh0ZW5kcyBTbGljZXIge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmZvcmNlRGF5SWZMaXN0SXRlbSA9IHRydWU7XG4gICAgfVxuICAgIHNsaWNlUmFuZ2UoZGF0ZVJhbmdlLCBkYXlUYWJsZU1vZGVsKSB7XG4gICAgICAgIHJldHVybiBkYXlUYWJsZU1vZGVsLnNsaWNlUmFuZ2UoZGF0ZVJhbmdlKTtcbiAgICB9XG59XG5cbmNsYXNzIERheVRhYmxlIGV4dGVuZHMgRGF0ZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc2xpY2VyID0gbmV3IERheVRhYmxlU2xpY2VyKCk7XG4gICAgICAgIHRoaXMudGFibGVSZWYgPSBjcmVhdGVSZWYoKTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcywgY29udGV4dCB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFRhYmxlLCBPYmplY3QuYXNzaWduKHsgcmVmOiB0aGlzLnRhYmxlUmVmIH0sIHRoaXMuc2xpY2VyLnNsaWNlUHJvcHMocHJvcHMsIHByb3BzLmRhdGVQcm9maWxlLCBwcm9wcy5uZXh0RGF5VGhyZXNob2xkLCBjb250ZXh0LCBwcm9wcy5kYXlUYWJsZU1vZGVsKSwgeyBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIGNlbGxzOiBwcm9wcy5kYXlUYWJsZU1vZGVsLmNlbGxzLCBjb2xHcm91cE5vZGU6IHByb3BzLmNvbEdyb3VwTm9kZSwgdGFibGVNaW5XaWR0aDogcHJvcHMudGFibGVNaW5XaWR0aCwgcmVuZGVyUm93SW50cm86IHByb3BzLnJlbmRlclJvd0ludHJvLCBkYXlNYXhFdmVudHM6IHByb3BzLmRheU1heEV2ZW50cywgZGF5TWF4RXZlbnRSb3dzOiBwcm9wcy5kYXlNYXhFdmVudFJvd3MsIHNob3dXZWVrTnVtYmVyczogcHJvcHMuc2hvd1dlZWtOdW1iZXJzLCBleHBhbmRSb3dzOiBwcm9wcy5leHBhbmRSb3dzLCBoZWFkZXJBbGlnbkVsUmVmOiBwcm9wcy5oZWFkZXJBbGlnbkVsUmVmLCBjbGllbnRXaWR0aDogcHJvcHMuY2xpZW50V2lkdGgsIGNsaWVudEhlaWdodDogcHJvcHMuY2xpZW50SGVpZ2h0LCBmb3JQcmludDogcHJvcHMuZm9yUHJpbnQgfSkpKTtcbiAgICB9XG59XG5cbmNsYXNzIERheVRhYmxlVmlldyBleHRlbmRzIFRhYmxlVmlldyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuYnVpbGREYXlUYWJsZU1vZGVsID0gbWVtb2l6ZShidWlsZERheVRhYmxlTW9kZWwpO1xuICAgICAgICB0aGlzLmhlYWRlclJlZiA9IGNyZWF0ZVJlZigpO1xuICAgICAgICB0aGlzLnRhYmxlUmVmID0gY3JlYXRlUmVmKCk7XG4gICAgICAgIC8vIGNhbid0IG92ZXJyaWRlIGFueSBsaWZlY3ljbGUgbWV0aG9kcyBmcm9tIHBhcmVudFxuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IG9wdGlvbnMsIGRhdGVQcm9maWxlR2VuZXJhdG9yIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgZGF5VGFibGVNb2RlbCA9IHRoaXMuYnVpbGREYXlUYWJsZU1vZGVsKHByb3BzLmRhdGVQcm9maWxlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcik7XG4gICAgICAgIGxldCBoZWFkZXJDb250ZW50ID0gb3B0aW9ucy5kYXlIZWFkZXJzICYmIChjcmVhdGVFbGVtZW50KERheUhlYWRlciwgeyByZWY6IHRoaXMuaGVhZGVyUmVmLCBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIGRhdGVzOiBkYXlUYWJsZU1vZGVsLmhlYWRlckRhdGVzLCBkYXRlc1JlcERpc3RpbmN0RGF5czogZGF5VGFibGVNb2RlbC5yb3dDbnQgPT09IDEgfSkpO1xuICAgICAgICBsZXQgYm9keUNvbnRlbnQgPSAoY29udGVudEFyZykgPT4gKGNyZWF0ZUVsZW1lbnQoRGF5VGFibGUsIHsgcmVmOiB0aGlzLnRhYmxlUmVmLCBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIGRheVRhYmxlTW9kZWw6IGRheVRhYmxlTW9kZWwsIGJ1c2luZXNzSG91cnM6IHByb3BzLmJ1c2luZXNzSG91cnMsIGRhdGVTZWxlY3Rpb246IHByb3BzLmRhdGVTZWxlY3Rpb24sIGV2ZW50U3RvcmU6IHByb3BzLmV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlczogcHJvcHMuZXZlbnRVaUJhc2VzLCBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb24sIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLCBldmVudFJlc2l6ZTogcHJvcHMuZXZlbnRSZXNpemUsIG5leHREYXlUaHJlc2hvbGQ6IG9wdGlvbnMubmV4dERheVRocmVzaG9sZCwgY29sR3JvdXBOb2RlOiBjb250ZW50QXJnLnRhYmxlQ29sR3JvdXBOb2RlLCB0YWJsZU1pbldpZHRoOiBjb250ZW50QXJnLnRhYmxlTWluV2lkdGgsIGRheU1heEV2ZW50czogb3B0aW9ucy5kYXlNYXhFdmVudHMsIGRheU1heEV2ZW50Um93czogb3B0aW9ucy5kYXlNYXhFdmVudFJvd3MsIHNob3dXZWVrTnVtYmVyczogb3B0aW9ucy53ZWVrTnVtYmVycywgZXhwYW5kUm93czogIXByb3BzLmlzSGVpZ2h0QXV0bywgaGVhZGVyQWxpZ25FbFJlZjogdGhpcy5oZWFkZXJFbFJlZiwgY2xpZW50V2lkdGg6IGNvbnRlbnRBcmcuY2xpZW50V2lkdGgsIGNsaWVudEhlaWdodDogY29udGVudEFyZy5jbGllbnRIZWlnaHQsIGZvclByaW50OiBwcm9wcy5mb3JQcmludCB9KSk7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmRheU1pbldpZHRoXG4gICAgICAgICAgICA/IHRoaXMucmVuZGVySFNjcm9sbExheW91dChoZWFkZXJDb250ZW50LCBib2R5Q29udGVudCwgZGF5VGFibGVNb2RlbC5jb2xDbnQsIG9wdGlvbnMuZGF5TWluV2lkdGgpXG4gICAgICAgICAgICA6IHRoaXMucmVuZGVyU2ltcGxlTGF5b3V0KGhlYWRlckNvbnRlbnQsIGJvZHlDb250ZW50KTtcbiAgICB9XG59XG5mdW5jdGlvbiBidWlsZERheVRhYmxlTW9kZWwoZGF0ZVByb2ZpbGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKSB7XG4gICAgbGV0IGRheVNlcmllcyA9IG5ldyBEYXlTZXJpZXNNb2RlbChkYXRlUHJvZmlsZS5yZW5kZXJSYW5nZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpO1xuICAgIHJldHVybiBuZXcgRGF5VGFibGVNb2RlbChkYXlTZXJpZXMsIC95ZWFyfG1vbnRofHdlZWsvLnRlc3QoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdCkpO1xufVxuXG5jbGFzcyBUYWJsZURhdGVQcm9maWxlR2VuZXJhdG9yIGV4dGVuZHMgRGF0ZVByb2ZpbGVHZW5lcmF0b3Ige1xuICAgIC8vIENvbXB1dGVzIHRoZSBkYXRlIHJhbmdlIHRoYXQgd2lsbCBiZSByZW5kZXJlZFxuICAgIGJ1aWxkUmVuZGVyUmFuZ2UoY3VycmVudFJhbmdlLCBjdXJyZW50UmFuZ2VVbml0LCBpc1JhbmdlQWxsRGF5KSB7XG4gICAgICAgIGxldCByZW5kZXJSYW5nZSA9IHN1cGVyLmJ1aWxkUmVuZGVyUmFuZ2UoY3VycmVudFJhbmdlLCBjdXJyZW50UmFuZ2VVbml0LCBpc1JhbmdlQWxsRGF5KTtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIHJldHVybiBidWlsZERheVRhYmxlUmVuZGVyUmFuZ2Uoe1xuICAgICAgICAgICAgY3VycmVudFJhbmdlOiByZW5kZXJSYW5nZSxcbiAgICAgICAgICAgIHNuYXBUb1dlZWs6IC9eKHllYXJ8bW9udGgpJC8udGVzdChjdXJyZW50UmFuZ2VVbml0KSxcbiAgICAgICAgICAgIGZpeGVkV2Vla0NvdW50OiBwcm9wcy5maXhlZFdlZWtDb3VudCxcbiAgICAgICAgICAgIGRhdGVFbnY6IHByb3BzLmRhdGVFbnYsXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGJ1aWxkRGF5VGFibGVSZW5kZXJSYW5nZShwcm9wcykge1xuICAgIGxldCB7IGRhdGVFbnYsIGN1cnJlbnRSYW5nZSB9ID0gcHJvcHM7XG4gICAgbGV0IHsgc3RhcnQsIGVuZCB9ID0gY3VycmVudFJhbmdlO1xuICAgIGxldCBlbmRPZldlZWs7XG4gICAgLy8geWVhciBhbmQgbW9udGggdmlld3Mgc2hvdWxkIGJlIGFsaWduZWQgd2l0aCB3ZWVrcy4gdGhpcyBpcyBhbHJlYWR5IGRvbmUgZm9yIHdlZWtcbiAgICBpZiAocHJvcHMuc25hcFRvV2Vlaykge1xuICAgICAgICBzdGFydCA9IGRhdGVFbnYuc3RhcnRPZldlZWsoc3RhcnQpO1xuICAgICAgICAvLyBtYWtlIGVuZC1vZi13ZWVrIGlmIG5vdCBhbHJlYWR5XG4gICAgICAgIGVuZE9mV2VlayA9IGRhdGVFbnYuc3RhcnRPZldlZWsoZW5kKTtcbiAgICAgICAgaWYgKGVuZE9mV2Vlay52YWx1ZU9mKCkgIT09IGVuZC52YWx1ZU9mKCkpIHtcbiAgICAgICAgICAgIGVuZCA9IGFkZFdlZWtzKGVuZE9mV2VlaywgMSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gZW5zdXJlIDYgd2Vla3NcbiAgICBpZiAocHJvcHMuZml4ZWRXZWVrQ291bnQpIHtcbiAgICAgICAgLy8gVE9ETzogaW5zdGVhZCBvZiB0aGVzZSBkYXRlLW1hdGggZ3ltbmFzdGljcyAoZm9yIG11bHRpbW9udGggdmlldyksXG4gICAgICAgIC8vIGNvbXB1dGUgZGF0ZXByb2ZpbGVzIG9mIGFsbCBtb250aHMsIHRoZW4gdXNlIHN0YXJ0IG9mIGZpcnN0IGFuZCBlbmQgb2YgbGFzdC5cbiAgICAgICAgbGV0IGxhc3RNb250aFJlbmRlclN0YXJ0ID0gZGF0ZUVudi5zdGFydE9mV2VlayhkYXRlRW52LnN0YXJ0T2ZNb250aChhZGREYXlzKGN1cnJlbnRSYW5nZS5lbmQsIC0xKSkpO1xuICAgICAgICBsZXQgcm93Q250ID0gTWF0aC5jZWlsKC8vIGNvdWxkIGJlIHBhcnRpYWwgd2Vla3MgZHVlIHRvIGhpZGRlbkRheXNcbiAgICAgICAgZGlmZldlZWtzKGxhc3RNb250aFJlbmRlclN0YXJ0LCBlbmQpKTtcbiAgICAgICAgZW5kID0gYWRkV2Vla3MoZW5kLCA2IC0gcm93Q250KTtcbiAgICB9XG4gICAgcmV0dXJuIHsgc3RhcnQsIGVuZCB9O1xufVxuXG52YXIgY3NzXzI0OHogPSBcIjpyb290ey0tZmMtZGF5Z3JpZC1ldmVudC1kb3Qtd2lkdGg6OHB4fS5mYy1kYXlncmlkLWRheS1ldmVudHM6YWZ0ZXIsLmZjLWRheWdyaWQtZGF5LWV2ZW50czpiZWZvcmUsLmZjLWRheWdyaWQtZGF5LWZyYW1lOmFmdGVyLC5mYy1kYXlncmlkLWRheS1mcmFtZTpiZWZvcmUsLmZjLWRheWdyaWQtZXZlbnQtaGFybmVzczphZnRlciwuZmMtZGF5Z3JpZC1ldmVudC1oYXJuZXNzOmJlZm9yZXtjbGVhcjpib3RoO2NvbnRlbnQ6XFxcIlxcXCI7ZGlzcGxheTp0YWJsZX0uZmMgLmZjLWRheWdyaWQtYm9keXtwb3NpdGlvbjpyZWxhdGl2ZTt6LWluZGV4OjF9LmZjIC5mYy1kYXlncmlkLWRheS5mYy1kYXktdG9kYXl7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1mYy10b2RheS1iZy1jb2xvcil9LmZjIC5mYy1kYXlncmlkLWRheS1mcmFtZXttaW4taGVpZ2h0OjEwMCU7cG9zaXRpb246cmVsYXRpdmV9LmZjIC5mYy1kYXlncmlkLWRheS10b3B7ZGlzcGxheTpmbGV4O2ZsZXgtZGlyZWN0aW9uOnJvdy1yZXZlcnNlfS5mYyAuZmMtZGF5LW90aGVyIC5mYy1kYXlncmlkLWRheS10b3B7b3BhY2l0eTouM30uZmMgLmZjLWRheWdyaWQtZGF5LW51bWJlcntwYWRkaW5nOjRweDtwb3NpdGlvbjpyZWxhdGl2ZTt6LWluZGV4OjR9LmZjIC5mYy1kYXlncmlkLW1vbnRoLXN0YXJ0e2ZvbnQtc2l6ZToxLjFlbTtmb250LXdlaWdodDo3MDB9LmZjIC5mYy1kYXlncmlkLWRheS1ldmVudHN7bWFyZ2luLXRvcDoxcHh9LmZjIC5mYy1kYXlncmlkLWJvZHktYmFsYW5jZWQgLmZjLWRheWdyaWQtZGF5LWV2ZW50c3tsZWZ0OjA7cG9zaXRpb246YWJzb2x1dGU7cmlnaHQ6MH0uZmMgLmZjLWRheWdyaWQtYm9keS11bmJhbGFuY2VkIC5mYy1kYXlncmlkLWRheS1ldmVudHN7bWluLWhlaWdodDoyZW07cG9zaXRpb246cmVsYXRpdmV9LmZjIC5mYy1kYXlncmlkLWJvZHktbmF0dXJhbCAuZmMtZGF5Z3JpZC1kYXktZXZlbnRze21hcmdpbi1ib3R0b206MWVtfS5mYyAuZmMtZGF5Z3JpZC1ldmVudC1oYXJuZXNze3Bvc2l0aW9uOnJlbGF0aXZlfS5mYyAuZmMtZGF5Z3JpZC1ldmVudC1oYXJuZXNzLWFic3tsZWZ0OjA7cG9zaXRpb246YWJzb2x1dGU7cmlnaHQ6MDt0b3A6MH0uZmMgLmZjLWRheWdyaWQtYmctaGFybmVzc3tib3R0b206MDtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MH0uZmMgLmZjLWRheWdyaWQtZGF5LWJnIC5mYy1ub24tYnVzaW5lc3N7ei1pbmRleDoxfS5mYyAuZmMtZGF5Z3JpZC1kYXktYmcgLmZjLWJnLWV2ZW50e3otaW5kZXg6Mn0uZmMgLmZjLWRheWdyaWQtZGF5LWJnIC5mYy1oaWdobGlnaHR7ei1pbmRleDozfS5mYyAuZmMtZGF5Z3JpZC1ldmVudHttYXJnaW4tdG9wOjFweDt6LWluZGV4OjZ9LmZjIC5mYy1kYXlncmlkLWV2ZW50LmZjLWV2ZW50LW1pcnJvcnt6LWluZGV4Ojd9LmZjIC5mYy1kYXlncmlkLWRheS1ib3R0b217Zm9udC1zaXplOi44NWVtO21hcmdpbjowIDJweH0uZmMgLmZjLWRheWdyaWQtZGF5LWJvdHRvbTphZnRlciwuZmMgLmZjLWRheWdyaWQtZGF5LWJvdHRvbTpiZWZvcmV7Y2xlYXI6Ym90aDtjb250ZW50OlxcXCJcXFwiO2Rpc3BsYXk6dGFibGV9LmZjIC5mYy1kYXlncmlkLW1vcmUtbGlua3tib3JkZXItcmFkaXVzOjNweDtjdXJzb3I6cG9pbnRlcjtsaW5lLWhlaWdodDoxO21hcmdpbi10b3A6MXB4O21heC13aWR0aDoxMDAlO292ZXJmbG93OmhpZGRlbjtwYWRkaW5nOjJweDtwb3NpdGlvbjpyZWxhdGl2ZTt3aGl0ZS1zcGFjZTpub3dyYXA7ei1pbmRleDo0fS5mYyAuZmMtZGF5Z3JpZC1tb3JlLWxpbms6aG92ZXJ7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDAsMCwwLC4xKX0uZmMgLmZjLWRheWdyaWQtd2Vlay1udW1iZXJ7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1mYy1uZXV0cmFsLWJnLWNvbG9yKTtjb2xvcjp2YXIoLS1mYy1uZXV0cmFsLXRleHQtY29sb3IpO21pbi13aWR0aDoxLjVlbTtwYWRkaW5nOjJweDtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjt0b3A6MDt6LWluZGV4OjV9LmZjIC5mYy1tb3JlLXBvcG92ZXIgLmZjLXBvcG92ZXItYm9keXttaW4td2lkdGg6MjIwcHg7cGFkZGluZzoxMHB4fS5mYy1kaXJlY3Rpb24tbHRyIC5mYy1kYXlncmlkLWV2ZW50LmZjLWV2ZW50LXN0YXJ0LC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1kYXlncmlkLWV2ZW50LmZjLWV2ZW50LWVuZHttYXJnaW4tbGVmdDoycHh9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWRheWdyaWQtZXZlbnQuZmMtZXZlbnQtZW5kLC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1kYXlncmlkLWV2ZW50LmZjLWV2ZW50LXN0YXJ0e21hcmdpbi1yaWdodDoycHh9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWRheWdyaWQtbW9yZS1saW5re2Zsb2F0OmxlZnR9LmZjLWRpcmVjdGlvbi1sdHIgLmZjLWRheWdyaWQtd2Vlay1udW1iZXJ7Ym9yZGVyLXJhZGl1czowIDAgM3B4IDA7bGVmdDowfS5mYy1kaXJlY3Rpb24tcnRsIC5mYy1kYXlncmlkLW1vcmUtbGlua3tmbG9hdDpyaWdodH0uZmMtZGlyZWN0aW9uLXJ0bCAuZmMtZGF5Z3JpZC13ZWVrLW51bWJlcntib3JkZXItcmFkaXVzOjAgMCAwIDNweDtyaWdodDowfS5mYy1saXF1aWQtaGFjayAuZmMtZGF5Z3JpZC1kYXktZnJhbWV7cG9zaXRpb246c3RhdGljfS5mYy1kYXlncmlkLWV2ZW50e2JvcmRlci1yYWRpdXM6M3B4O2ZvbnQtc2l6ZTp2YXIoLS1mYy1zbWFsbC1mb250LXNpemUpO3Bvc2l0aW9uOnJlbGF0aXZlO3doaXRlLXNwYWNlOm5vd3JhcH0uZmMtZGF5Z3JpZC1ibG9jay1ldmVudCAuZmMtZXZlbnQtdGltZXtmb250LXdlaWdodDo3MDB9LmZjLWRheWdyaWQtYmxvY2stZXZlbnQgLmZjLWV2ZW50LXRpbWUsLmZjLWRheWdyaWQtYmxvY2stZXZlbnQgLmZjLWV2ZW50LXRpdGxle3BhZGRpbmc6MXB4fS5mYy1kYXlncmlkLWRvdC1ldmVudHthbGlnbi1pdGVtczpjZW50ZXI7ZGlzcGxheTpmbGV4O3BhZGRpbmc6MnB4IDB9LmZjLWRheWdyaWQtZG90LWV2ZW50IC5mYy1ldmVudC10aXRsZXtmbGV4LWdyb3c6MTtmbGV4LXNocmluazoxO2ZvbnQtd2VpZ2h0OjcwMDttaW4td2lkdGg6MDtvdmVyZmxvdzpoaWRkZW59LmZjLWRheWdyaWQtZG90LWV2ZW50LmZjLWV2ZW50LW1pcnJvciwuZmMtZGF5Z3JpZC1kb3QtZXZlbnQ6aG92ZXJ7YmFja2dyb3VuZDpyZ2JhKDAsMCwwLC4xKX0uZmMtZGF5Z3JpZC1kb3QtZXZlbnQuZmMtZXZlbnQtc2VsZWN0ZWQ6YmVmb3Jle2JvdHRvbTotMTBweDt0b3A6LTEwcHh9LmZjLWRheWdyaWQtZXZlbnQtZG90e2JvcmRlcjpjYWxjKHZhcigtLWZjLWRheWdyaWQtZXZlbnQtZG90LXdpZHRoKS8yKSBzb2xpZCB2YXIoLS1mYy1ldmVudC1ib3JkZXItY29sb3IpO2JvcmRlci1yYWRpdXM6Y2FsYyh2YXIoLS1mYy1kYXlncmlkLWV2ZW50LWRvdC13aWR0aCkvMik7Ym94LXNpemluZzpjb250ZW50LWJveDtoZWlnaHQ6MDttYXJnaW46MCA0cHg7d2lkdGg6MH0uZmMtZGlyZWN0aW9uLWx0ciAuZmMtZGF5Z3JpZC1ldmVudCAuZmMtZXZlbnQtdGltZXttYXJnaW4tcmlnaHQ6M3B4fS5mYy1kaXJlY3Rpb24tcnRsIC5mYy1kYXlncmlkLWV2ZW50IC5mYy1ldmVudC10aW1le21hcmdpbi1sZWZ0OjNweH1cIjtcbmluamVjdFN0eWxlcyhjc3NfMjQ4eik7XG5cbmV4cG9ydCB7IERheVRhYmxlVmlldyBhcyBEYXlHcmlkVmlldywgRGF5VGFibGUsIERheVRhYmxlU2xpY2VyLCBUYWJsZSwgVGFibGVEYXRlUHJvZmlsZUdlbmVyYXRvciwgVGFibGVSb3dzLCBUYWJsZVZpZXcsIGJ1aWxkRGF5VGFibGVNb2RlbCwgYnVpbGREYXlUYWJsZVJlbmRlclJhbmdlIH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///119\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 120:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ index)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(112);\n/* harmony import */ var _internal_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(121);\n\n\n\n\n\n\nconst OPTION_REFINERS = {\n allDaySlot: Boolean,\n};\n\nvar index = (0,_fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__.createPlugin)({\n name: '@fullcalendar/timegrid',\n initialView: 'timeGridWeek',\n optionRefiners: OPTION_REFINERS,\n views: {\n timeGrid: {\n component: _internal_js__WEBPACK_IMPORTED_MODULE_1__.DayTimeColsView,\n usesMinMaxTime: true,\n allDaySlot: true,\n slotDuration: '00:30:00',\n slotEventOverlap: true, // a bad name. confused with overlap/constraint system\n },\n timeGridDay: {\n type: 'timeGrid',\n duration: { days: 1 },\n },\n timeGridWeek: {\n type: 'timeGrid',\n duration: { weeks: 1 },\n },\n },\n});\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTIwLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUEyRDtBQUNYO0FBQ1I7QUFDRjtBQUNLOztBQUUzQztBQUNBO0FBQ0E7O0FBRUEsWUFBWSx5RUFBWTtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHlEQUFlO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx3QkFBd0IsU0FBUztBQUNqQyxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHdCQUF3QixVQUFVO0FBQ2xDLFNBQVM7QUFDVCxLQUFLO0FBQ0wsQ0FBQzs7QUFFMkIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcmNoaXRlY3R1aS1odG1sLWZyZWUvLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci90aW1lZ3JpZC9pbmRleC5qcz8zMTBhIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZVBsdWdpbiB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZS9pbmRleC5qcyc7XG5pbXBvcnQgeyBEYXlUaW1lQ29sc1ZpZXcgfSBmcm9tICcuL2ludGVybmFsLmpzJztcbmltcG9ydCAnQGZ1bGxjYWxlbmRhci9jb3JlL2ludGVybmFsLmpzJztcbmltcG9ydCAnQGZ1bGxjYWxlbmRhci9jb3JlL3ByZWFjdC5qcyc7XG5pbXBvcnQgJ0BmdWxsY2FsZW5kYXIvZGF5Z3JpZC9pbnRlcm5hbC5qcyc7XG5cbmNvbnN0IE9QVElPTl9SRUZJTkVSUyA9IHtcbiAgICBhbGxEYXlTbG90OiBCb29sZWFuLFxufTtcblxudmFyIGluZGV4ID0gY3JlYXRlUGx1Z2luKHtcbiAgICBuYW1lOiAnQGZ1bGxjYWxlbmRhci90aW1lZ3JpZCcsXG4gICAgaW5pdGlhbFZpZXc6ICd0aW1lR3JpZFdlZWsnLFxuICAgIG9wdGlvblJlZmluZXJzOiBPUFRJT05fUkVGSU5FUlMsXG4gICAgdmlld3M6IHtcbiAgICAgICAgdGltZUdyaWQ6IHtcbiAgICAgICAgICAgIGNvbXBvbmVudDogRGF5VGltZUNvbHNWaWV3LFxuICAgICAgICAgICAgdXNlc01pbk1heFRpbWU6IHRydWUsXG4gICAgICAgICAgICBhbGxEYXlTbG90OiB0cnVlLFxuICAgICAgICAgICAgc2xvdER1cmF0aW9uOiAnMDA6MzA6MDAnLFxuICAgICAgICAgICAgc2xvdEV2ZW50T3ZlcmxhcDogdHJ1ZSwgLy8gYSBiYWQgbmFtZS4gY29uZnVzZWQgd2l0aCBvdmVybGFwL2NvbnN0cmFpbnQgc3lzdGVtXG4gICAgICAgIH0sXG4gICAgICAgIHRpbWVHcmlkRGF5OiB7XG4gICAgICAgICAgICB0eXBlOiAndGltZUdyaWQnLFxuICAgICAgICAgICAgZHVyYXRpb246IHsgZGF5czogMSB9LFxuICAgICAgICB9LFxuICAgICAgICB0aW1lR3JpZFdlZWs6IHtcbiAgICAgICAgICAgIHR5cGU6ICd0aW1lR3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyB3ZWVrczogMSB9LFxuICAgICAgICB9LFxuICAgIH0sXG59KTtcblxuZXhwb3J0IHsgaW5kZXggYXMgZGVmYXVsdCB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///120\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 121:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DayTimeCols: () => (/* binding */ DayTimeCols),\n/* harmony export */ DayTimeColsSlicer: () => (/* binding */ DayTimeColsSlicer),\n/* harmony export */ DayTimeColsView: () => (/* binding */ DayTimeColsView),\n/* harmony export */ TimeCols: () => (/* binding */ TimeCols),\n/* harmony export */ TimeColsSlatsCoords: () => (/* binding */ TimeColsSlatsCoords),\n/* harmony export */ TimeColsView: () => (/* binding */ TimeColsView),\n/* harmony export */ buildDayRanges: () => (/* binding */ buildDayRanges),\n/* harmony export */ buildSlatMetas: () => (/* binding */ buildSlatMetas),\n/* harmony export */ buildTimeColsModel: () => (/* binding */ buildTimeColsModel)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113);\n/* harmony import */ var _fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(114);\n/* harmony import */ var _fullcalendar_daygrid_internal_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(119);\n\n\n\n\nclass AllDaySplitter extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.aW {\n getKeyInfo() {\n return {\n allDay: {},\n timed: {},\n };\n }\n getKeysForDateSpan(dateSpan) {\n if (dateSpan.allDay) {\n return ['allDay'];\n }\n return ['timed'];\n }\n getKeysForEventDef(eventDef) {\n if (!eventDef.allDay) {\n return ['timed'];\n }\n if ((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bN)(eventDef)) {\n return ['timed', 'allDay'];\n }\n return ['allDay'];\n }\n}\n\nconst DEFAULT_SLAT_LABEL_FORMAT = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)({\n hour: 'numeric',\n minute: '2-digit',\n omitZeroMinute: true,\n meridiem: 'short',\n});\nfunction TimeColsAxisCell(props) {\n let classNames = [\n 'fc-timegrid-slot',\n 'fc-timegrid-slot-label',\n props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',\n ];\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.V.Consumer, null, (context) => {\n if (!props.isLabeled) {\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"td\", { className: classNames.join(' '), \"data-time\": props.isoTimeStr }));\n }\n let { dateEnv, options, viewApi } = context;\n let labelFormat = // TODO: fully pre-parse\n options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :\n Array.isArray(options.slotLabelFormat) ? (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)(options.slotLabelFormat[0]) :\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)(options.slotLabelFormat);\n let renderProps = {\n level: 0,\n time: props.time,\n date: dateEnv.toDate(props.date),\n view: viewApi,\n text: dateEnv.format(props.date, labelFormat),\n };\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"td\", elClasses: classNames, elAttrs: {\n 'data-time': props.isoTimeStr,\n }, renderProps: renderProps, generatorName: \"slotLabelContent\", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"div\", elClasses: [\n 'fc-timegrid-slot-label-cushion',\n 'fc-scrollgrid-shrink-cushion',\n ] })))));\n }));\n}\nfunction renderInnerContent(props) {\n return props.text;\n}\n\nclass TimeBodyAxis extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n return this.props.slatMetas.map((slatMeta) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { key: slatMeta.key },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColsAxisCell, Object.assign({}, slatMeta)))));\n }\n}\n\nconst DEFAULT_WEEK_NUM_FORMAT = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)({ week: 'short' });\nconst AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;\nclass TimeColsView extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.allDaySplitter = new AllDaySplitter(); // for use by subclasses\n this.headerElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.rootElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.scrollerElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.state = {\n slatCoords: null,\n };\n this.handleScrollTopRequest = (scrollTop) => {\n let scrollerEl = this.scrollerElRef.current;\n if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer\n scrollerEl.scrollTop = scrollTop;\n }\n };\n /* Header Render Methods\n ------------------------------------------------------------------------------------------------------------------*/\n this.renderHeadAxis = (rowKey, frameHeight = '') => {\n let { options } = this.context;\n let { dateProfile } = this.props;\n let range = dateProfile.renderRange;\n let dayCnt = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bj)(range.start, range.end);\n // only do in day views (to avoid doing in week views that dont need it)\n let navLinkAttrs = (dayCnt === 1)\n ? (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a_)(this.context, range.start, 'week')\n : {};\n if (options.weekNumbers && rowKey === 'day') {\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cn, { elTag: \"th\", elClasses: [\n 'fc-timegrid-axis',\n 'fc-scrollgrid-shrink',\n ], elAttrs: {\n 'aria-hidden': true,\n }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: [\n 'fc-timegrid-axis-frame',\n 'fc-scrollgrid-shrink-frame',\n 'fc-timegrid-axis-frame-liquid',\n ].join(' '), style: { height: frameHeight } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"a\", elClasses: [\n 'fc-timegrid-axis-cushion',\n 'fc-scrollgrid-shrink-cushion',\n 'fc-scrollgrid-sync-inner',\n ], elAttrs: navLinkAttrs })))));\n }\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"th\", { \"aria-hidden\": true, className: \"fc-timegrid-axis\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-axis-frame\", style: { height: frameHeight } })));\n };\n /* Table Component Render Methods\n ------------------------------------------------------------------------------------------------------------------*/\n // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,\n // but DayGrid still needs to have classNames on inner elements in order to measure.\n this.renderTableRowAxis = (rowHeight) => {\n let { options, viewApi } = this.context;\n let renderProps = {\n text: options.allDayText,\n view: viewApi,\n };\n return (\n // TODO: make reusable hook. used in list view too\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"td\", elClasses: [\n 'fc-timegrid-axis',\n 'fc-scrollgrid-shrink',\n ], elAttrs: {\n 'aria-hidden': true,\n }, renderProps: renderProps, generatorName: \"allDayContent\", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: [\n 'fc-timegrid-axis-frame',\n 'fc-scrollgrid-shrink-frame',\n rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',\n ].join(' '), style: { height: rowHeight } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"span\", elClasses: [\n 'fc-timegrid-axis-cushion',\n 'fc-scrollgrid-shrink-cushion',\n 'fc-scrollgrid-sync-inner',\n ] })))));\n };\n this.handleSlatCoords = (slatCoords) => {\n this.setState({ slatCoords });\n };\n }\n // rendering\n // ----------------------------------------------------------------------------------------------------\n renderSimpleLayout(headerRowContent, allDayContent, timeContent) {\n let { context, props } = this;\n let sections = [];\n let stickyHeaderDates = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ca)(context.options);\n if (headerRowContent) {\n sections.push({\n type: 'header',\n key: 'header',\n isSticky: stickyHeaderDates,\n chunk: {\n elRef: this.headerElRef,\n tableClassName: 'fc-col-header',\n rowContent: headerRowContent,\n },\n });\n }\n if (allDayContent) {\n sections.push({\n type: 'body',\n key: 'all-day',\n chunk: { content: allDayContent },\n });\n sections.push({\n type: 'body',\n key: 'all-day-divider',\n outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { role: \"presentation\", className: \"fc-scrollgrid-section\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"td\", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),\n });\n }\n sections.push({\n type: 'body',\n key: 'body',\n liquid: true,\n expandRows: Boolean(context.options.expandRows),\n chunk: {\n scrollerElRef: this.scrollerElRef,\n content: timeContent,\n },\n });\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cq, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bZ, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));\n }\n renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {\n let ScrollGrid = this.context.pluginHooks.scrollGridImpl;\n if (!ScrollGrid) {\n throw new Error('No ScrollGrid implementation');\n }\n let { context, props } = this;\n let stickyHeaderDates = !props.forPrint && (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ca)(context.options);\n let stickyFooterScrollbar = !props.forPrint && (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.c9)(context.options);\n let sections = [];\n if (headerRowContent) {\n sections.push({\n type: 'header',\n key: 'header',\n isSticky: stickyHeaderDates,\n syncRowHeights: true,\n chunks: [\n {\n key: 'axis',\n rowContent: (arg) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { role: \"presentation\" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),\n },\n {\n key: 'cols',\n elRef: this.headerElRef,\n tableClassName: 'fc-col-header',\n rowContent: headerRowContent,\n },\n ],\n });\n }\n if (allDayContent) {\n sections.push({\n type: 'body',\n key: 'all-day',\n syncRowHeights: true,\n chunks: [\n {\n key: 'axis',\n rowContent: (contentArg) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { role: \"presentation\" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),\n },\n {\n key: 'cols',\n content: allDayContent,\n },\n ],\n });\n sections.push({\n key: 'all-day-divider',\n type: 'body',\n outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { role: \"presentation\", className: \"fc-scrollgrid-section\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"td\", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),\n });\n }\n let isNowIndicator = context.options.nowIndicator;\n sections.push({\n type: 'body',\n key: 'body',\n liquid: true,\n expandRows: Boolean(context.options.expandRows),\n chunks: [\n {\n key: 'axis',\n content: (arg) => (\n // TODO: make this now-indicator arrow more DRY with TimeColsContent\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-axis-chunk\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"table\", { \"aria-hidden\": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },\n arg.tableColGroupNode,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tbody\", null,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeBodyAxis, { slatMetas: slatMetas }))),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-now-indicator-container\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a6, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {\n let nowIndicatorTop = isNowIndicator &&\n slatCoords &&\n slatCoords.safeComputeTop(nowDate); // might return void\n if (typeof nowIndicatorTop === 'number') {\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ch, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));\n }\n return null;\n })))),\n },\n {\n key: 'cols',\n scrollerElRef: this.scrollerElRef,\n content: timeContent,\n },\n ],\n });\n if (stickyFooterScrollbar) {\n sections.push({\n key: 'footer',\n type: 'footer',\n isSticky: true,\n chunks: [\n {\n key: 'axis',\n content: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.c8,\n },\n {\n key: 'cols',\n content: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.c8,\n },\n ],\n });\n }\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cq, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: false, colGroups: [\n { width: 'shrink', cols: [{ width: 'shrink' }] },\n { cols: [{ span: colCnt, minWidth: dayMinWidth }] },\n ], sections: sections })));\n }\n /* Dimensions\n ------------------------------------------------------------------------------------------------------------------*/\n getAllDayMaxEventProps() {\n let { dayMaxEvents, dayMaxEventRows } = this.context.options;\n if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?\n dayMaxEvents = undefined;\n dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure \"auto\" goes to a real number\n }\n return { dayMaxEvents, dayMaxEventRows };\n }\n}\nfunction renderAllDayInner(renderProps) {\n return renderProps.text;\n}\n\nclass TimeColsSlatsCoords {\n constructor(positions, dateProfile, slotDuration) {\n this.positions = positions;\n this.dateProfile = dateProfile;\n this.slotDuration = slotDuration;\n }\n safeComputeTop(date) {\n let { dateProfile } = this;\n if ((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.G)(dateProfile.currentRange, date)) {\n let startOfDayDate = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.q)(date);\n let timeMs = date.valueOf() - startOfDayDate.valueOf();\n if (timeMs >= (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bq)(dateProfile.slotMinTime) &&\n timeMs < (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bq)(dateProfile.slotMaxTime)) {\n return this.computeTimeTop((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.d)(timeMs));\n }\n }\n return null;\n }\n // Computes the top coordinate, relative to the bounds of the grid, of the given date.\n // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.\n computeDateTop(when, startOfDayDate) {\n if (!startOfDayDate) {\n startOfDayDate = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.q)(when);\n }\n return this.computeTimeTop((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.d)(when.valueOf() - startOfDayDate.valueOf()));\n }\n // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).\n // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.\n // Eventually allow computation with arbirary slat dates.\n computeTimeTop(duration) {\n let { positions, dateProfile } = this;\n let len = positions.els.length;\n // floating-point value of # of slots covered\n let slatCoverage = (duration.milliseconds - (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bq)(dateProfile.slotMinTime)) / (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bq)(this.slotDuration);\n let slatIndex;\n let slatRemainder;\n // compute a floating-point number for how many slats should be progressed through.\n // from 0 to number of slats (inclusive)\n // constrained because slotMinTime/slotMaxTime might be customized.\n slatCoverage = Math.max(0, slatCoverage);\n slatCoverage = Math.min(len, slatCoverage);\n // an integer index of the furthest whole slat\n // from 0 to number slats (*exclusive*, so len-1)\n slatIndex = Math.floor(slatCoverage);\n slatIndex = Math.min(slatIndex, len - 1);\n // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.\n // could be 1.0 if slatCoverage is covering *all* the slots\n slatRemainder = slatCoverage - slatIndex;\n return positions.tops[slatIndex] +\n positions.getHeight(slatIndex) * slatRemainder;\n }\n}\n\nclass TimeColsSlatsBody extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let { props, context } = this;\n let { options } = context;\n let { slatElRefs } = props;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tbody\", null, props.slatMetas.map((slatMeta, i) => {\n let renderProps = {\n time: slatMeta.time,\n date: context.dateEnv.toDate(slatMeta.date),\n view: context.viewApi,\n };\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },\n props.axis && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColsAxisCell, Object.assign({}, slatMeta))),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"td\", elClasses: [\n 'fc-timegrid-slot',\n 'fc-timegrid-slot-lane',\n !slatMeta.isLabeled && 'fc-timegrid-slot-minor',\n ], elAttrs: {\n 'data-time': slatMeta.isoTimeStr,\n }, renderProps: renderProps, generatorName: \"slotLaneContent\", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));\n })));\n }\n}\n\n/*\nfor the horizontal \"slats\" that run width-wise. Has a time axis on a side. Depends on RTL.\n*/\nclass TimeColsSlats extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n constructor() {\n super(...arguments);\n this.rootElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.slatElRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd();\n }\n render() {\n let { props, context } = this;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { ref: this.rootElRef, className: \"fc-timegrid-slots\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"table\", { \"aria-hidden\": true, className: context.theme.getClass('table'), style: {\n minWidth: props.tableMinWidth,\n width: props.clientWidth,\n height: props.minHeight,\n } },\n props.tableColGroupNode /* relies on there only being a single <col> for the axis */,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));\n }\n componentDidMount() {\n this.updateSizing();\n }\n componentDidUpdate() {\n this.updateSizing();\n }\n componentWillUnmount() {\n if (this.props.onCoords) {\n this.props.onCoords(null);\n }\n }\n updateSizing() {\n let { context, props } = this;\n if (props.onCoords &&\n props.clientWidth !== null // means sizing has stabilized\n ) {\n let rootEl = this.rootElRef.current;\n if (rootEl.offsetHeight) { // not hidden by css\n props.onCoords(new TimeColsSlatsCoords(new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.b8(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));\n }\n }\n }\n}\nfunction collectSlatEls(elMap, slatMetas) {\n return slatMetas.map((slatMeta) => elMap[slatMeta.key]);\n}\n\nfunction splitSegsByCol(segs, colCnt) {\n let segsByCol = [];\n let i;\n for (i = 0; i < colCnt; i += 1) {\n segsByCol.push([]);\n }\n if (segs) {\n for (i = 0; i < segs.length; i += 1) {\n segsByCol[segs[i].col].push(segs[i]);\n }\n }\n return segsByCol;\n}\nfunction splitInteractionByCol(ui, colCnt) {\n let byRow = [];\n if (!ui) {\n for (let i = 0; i < colCnt; i += 1) {\n byRow[i] = null;\n }\n }\n else {\n for (let i = 0; i < colCnt; i += 1) {\n byRow[i] = {\n affectedInstances: ui.affectedInstances,\n isEvent: ui.isEvent,\n segs: [],\n };\n }\n for (let seg of ui.segs) {\n byRow[seg.col].segs.push(seg);\n }\n }\n return byRow;\n}\n\nclass TimeColMoreLink extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let { props } = this;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.co, { elClasses: ['fc-timegrid-more-link'], elStyle: {\n top: props.top,\n bottom: props.bottom,\n }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner, forceTimed: true }, (InnerContent) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"div\", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));\n }\n}\nfunction renderMoreLinkInner(props) {\n return props.shortText;\n}\n\n// segInputs assumed sorted\nfunction buildPositioning(segInputs, strictOrder, maxStackCnt) {\n let hierarchy = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.by();\n if (strictOrder != null) {\n hierarchy.strictOrder = strictOrder;\n }\n if (maxStackCnt != null) {\n hierarchy.maxStackCnt = maxStackCnt;\n }\n let hiddenEntries = hierarchy.addSegs(segInputs);\n let hiddenGroups = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bC)(hiddenEntries);\n let web = buildWeb(hierarchy);\n web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0\n let segRects = webToRects(web);\n return { segRects, hiddenGroups };\n}\nfunction buildWeb(hierarchy) {\n const { entriesByLevel } = hierarchy;\n const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {\n let siblingRange = findNextLevelSegs(hierarchy, level, lateral);\n let nextLevelRes = buildNodes(siblingRange, buildNode);\n let entry = entriesByLevel[level][lateral];\n return [\n Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),\n entry.thickness + nextLevelRes[1], // the pressure builds\n ];\n });\n return buildNodes(entriesByLevel.length\n ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }\n : null, buildNode)[0];\n}\nfunction buildNodes(siblingRange, buildNode) {\n if (!siblingRange) {\n return [[], 0];\n }\n let { level, lateralStart, lateralEnd } = siblingRange;\n let lateral = lateralStart;\n let pairs = [];\n while (lateral < lateralEnd) {\n pairs.push(buildNode(level, lateral));\n lateral += 1;\n }\n pairs.sort(cmpDescPressures);\n return [\n pairs.map(extractNode),\n pairs[0][1], // first item's pressure\n ];\n}\nfunction cmpDescPressures(a, b) {\n return b[1] - a[1];\n}\nfunction extractNode(a) {\n return a[0];\n}\nfunction findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {\n let { levelCoords, entriesByLevel } = hierarchy;\n let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];\n let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;\n let levelCnt = levelCoords.length;\n let level = subjectLevel;\n // skip past levels that are too high up\n for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)\n ; // do nothing\n for (; level < levelCnt; level += 1) {\n let entries = entriesByLevel[level];\n let entry;\n let searchIndex = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bB)(entries, subjectEntry.span.start, _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bA);\n let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one\n let lateralEnd = lateralStart;\n while ( // loop through entries that horizontally intersect\n (entry = entries[lateralEnd]) && // but not past the whole seg list\n entry.span.start < subjectEntry.span.end) {\n lateralEnd += 1;\n }\n if (lateralStart < lateralEnd) {\n return { level, lateralStart, lateralEnd };\n }\n }\n return null;\n}\nfunction stretchWeb(topLevelNodes, totalThickness) {\n const stretchNode = cacheable((node, startCoord, prevThickness) => (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bz)(node), (node, startCoord, prevThickness) => {\n let { nextLevelNodes, thickness } = node;\n let allThickness = thickness + prevThickness;\n let thicknessFraction = thickness / allThickness;\n let endCoord;\n let newChildren = [];\n if (!nextLevelNodes.length) {\n endCoord = totalThickness;\n }\n else {\n for (let childNode of nextLevelNodes) {\n if (endCoord === undefined) {\n let res = stretchNode(childNode, startCoord, allThickness);\n endCoord = res[0];\n newChildren.push(res[1]);\n }\n else {\n let res = stretchNode(childNode, endCoord, 0);\n newChildren.push(res[1]);\n }\n }\n }\n let newThickness = (endCoord - startCoord) * thicknessFraction;\n return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];\n });\n return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);\n}\n// not sorted in any particular order\nfunction webToRects(topLevelNodes) {\n let rects = [];\n const processNode = cacheable((node, levelCoord, stackDepth) => (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bz)(node), (node, levelCoord, stackDepth) => {\n let rect = Object.assign(Object.assign({}, node), { levelCoord,\n stackDepth, stackForward: 0 });\n rects.push(rect);\n return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);\n });\n function processNodes(nodes, levelCoord, stackDepth) {\n let stackForward = 0;\n for (let node of nodes) {\n stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);\n }\n return stackForward;\n }\n processNodes(topLevelNodes, 0, 0);\n return rects; // TODO: sort rects by levelCoord to be consistent with toRects?\n}\n// TODO: move to general util\nfunction cacheable(keyFunc, workFunc) {\n const cache = {};\n return (...args) => {\n let key = keyFunc(...args);\n return (key in cache)\n ? cache[key]\n : (cache[key] = workFunc(...args));\n };\n}\n\nfunction computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {\n let vcoords = [];\n if (slatCoords) {\n for (let i = 0; i < segs.length; i += 1) {\n let seg = segs[i];\n let spanStart = slatCoords.computeDateTop(seg.start, colDate);\n let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(\n slatCoords.computeDateTop(seg.end, colDate));\n vcoords.push({\n start: Math.round(spanStart),\n end: Math.round(spanEnd), //\n });\n }\n }\n return vcoords;\n}\nfunction computeFgSegPlacements(segs, segVCoords, // might not have for every seg\neventOrderStrict, eventMaxStack) {\n let segInputs = [];\n let dumbSegs = []; // segs without coords\n for (let i = 0; i < segs.length; i += 1) {\n let vcoords = segVCoords[i];\n if (vcoords) {\n segInputs.push({\n index: i,\n thickness: 1,\n span: vcoords,\n });\n }\n else {\n dumbSegs.push(segs[i]);\n }\n }\n let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);\n let segPlacements = [];\n for (let segRect of segRects) {\n segPlacements.push({\n seg: segs[segRect.index],\n rect: segRect,\n });\n }\n for (let dumbSeg of dumbSegs) {\n segPlacements.push({ seg: dumbSeg, rect: null });\n }\n return { segPlacements, hiddenGroups };\n}\n\nconst DEFAULT_TIME_FORMAT = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)({\n hour: 'numeric',\n minute: '2-digit',\n meridiem: false,\n});\nclass TimeColEvent extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cg, Object.assign({}, this.props, { elClasses: [\n 'fc-timegrid-event',\n 'fc-v-event',\n this.props.isShort && 'fc-timegrid-event-short',\n ], defaultTimeFormat: DEFAULT_TIME_FORMAT })));\n }\n}\n\nclass TimeCol extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n constructor() {\n super(...arguments);\n this.sortEventSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bP);\n }\n // TODO: memoize event-placement?\n render() {\n let { props, context } = this;\n let { options } = context;\n let isSelectMirror = options.selectMirror;\n let mirrorSegs = // yuck\n (props.eventDrag && props.eventDrag.segs) ||\n (props.eventResize && props.eventResize.segs) ||\n (isSelectMirror && props.dateSelectionSegs) ||\n [];\n let interactionAffectedInstances = // TODO: messy way to compute this\n (props.eventDrag && props.eventDrag.affectedInstances) ||\n (props.eventResize && props.eventResize.affectedInstances) ||\n {};\n let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ci, { elTag: \"td\", elRef: props.elRef, elClasses: [\n 'fc-timegrid-col',\n ...(props.extraClassNames || []),\n ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-col-frame\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-col-bg\" },\n this.renderFillSegs(props.businessHourSegs, 'non-business'),\n this.renderFillSegs(props.bgEventSegs, 'bg-event'),\n this.renderFillSegs(props.dateSelectionSegs, 'highlight')),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-col-events\" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-col-events\" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror), 'mirror')),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-now-indicator-container\" }, this.renderNowIndicator(props.nowIndicatorSegs)),\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cj)(options) && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"div\", elClasses: ['fc-timegrid-col-misc'] }))))));\n }\n renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {\n let { props } = this;\n if (props.forPrint) {\n return renderPlainFgSegs(sortedFgSegs, props);\n }\n return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey);\n }\n renderPositionedFgSegs(segs, // if not mirror, needs to be sorted\n segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {\n let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;\n let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;\n let isMirror = isDragging || isResizing || isDateSelecting;\n let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);\n let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n this.renderHiddenGroups(hiddenGroups, segs),\n segPlacements.map((segPlacement) => {\n let { seg, rect } = segPlacement;\n let instanceId = seg.eventRange.instance.instanceId;\n let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);\n let vStyle = computeSegVStyle(rect && rect.span);\n let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };\n let isInset = Boolean(rect) && rect.stackForward > 0;\n let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: 'fc-timegrid-event-harness' +\n (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: forcedKey || instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, todayRange, nowDate)))));\n })));\n }\n // will already have eventMinHeight applied because segInputs already had it\n renderHiddenGroups(hiddenGroups, segs) {\n let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, hiddenGroups.map((hiddenGroup) => {\n let positionCss = computeSegVStyle(hiddenGroup.span);\n let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColMoreLink, { key: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bu)((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cp)(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));\n })));\n }\n renderFillSegs(segs, fillType) {\n let { props, context } = this;\n let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated\n let children = segVCoords.map((vcoords, i) => {\n let seg = segs[i];\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { key: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bR)(seg.eventRange), className: \"fc-timegrid-bg-harness\", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cm, Object.assign({ seg: seg }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, props.todayRange, props.nowDate))) :\n (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cl)(fillType)));\n });\n return (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, children);\n }\n renderNowIndicator(segs) {\n let { slatCoords, date } = this.props;\n if (!slatCoords) {\n return null;\n }\n return segs.map((seg, i) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ch\n // key doesn't matter. will only ever be one\n , { \n // key doesn't matter. will only ever be one\n key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {\n top: slatCoords.computeDateTop(seg.start, date),\n }, isAxis: false, date: date })));\n }\n computeSegHStyle(segHCoords) {\n let { isRtl, options } = this.context;\n let shouldOverlap = options.slotEventOverlap;\n let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point\n let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point\n let left; // amount of space from left edge, a fraction of the total width\n let right; // amount of space from right edge, a fraction of the total width\n if (shouldOverlap) {\n // double the width, but don't go beyond the maximum forward coordinate (1.0)\n farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);\n }\n if (isRtl) {\n left = 1 - farCoord;\n right = nearCoord;\n }\n else {\n left = nearCoord;\n right = 1 - farCoord;\n }\n let props = {\n zIndex: segHCoords.stackDepth + 1,\n left: left * 100 + '%',\n right: right * 100 + '%',\n };\n if (shouldOverlap && !segHCoords.stackForward) {\n // add padding to the edge so that forward stacked events don't cover the resizer's icon\n props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width\n }\n return props;\n }\n}\nfunction renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {\n let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||\n (eventResize ? eventResize.affectedInstances : null) ||\n {};\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, sortedFgSegs.map((seg) => {\n let instanceId = seg.eventRange.instance.instanceId;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, todayRange, nowDate)))));\n })));\n}\nfunction computeSegVStyle(segVCoords) {\n if (!segVCoords) {\n return { top: '', bottom: '' };\n }\n return {\n top: segVCoords.start,\n bottom: -segVCoords.end,\n };\n}\nfunction compileSegsFromEntries(segEntries, allSegs) {\n return segEntries.map((segEntry) => allSegs[segEntry.index]);\n}\n\nclass TimeColsContent extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n constructor() {\n super(...arguments);\n this.splitFgEventSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByCol);\n this.splitBgEventSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByCol);\n this.splitBusinessHourSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByCol);\n this.splitNowIndicatorSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByCol);\n this.splitDateSelectionSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitSegsByCol);\n this.splitEventDrag = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitInteractionByCol);\n this.splitEventResize = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(splitInteractionByCol);\n this.rootElRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n this.cellElRefs = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cd();\n }\n render() {\n let { props, context } = this;\n let nowIndicatorTop = context.options.nowIndicator &&\n props.slatCoords &&\n props.slatCoords.safeComputeTop(props.nowDate); // might return void\n let colCnt = props.cells.length;\n let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);\n let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);\n let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);\n let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);\n let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);\n let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);\n let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-cols\", ref: this.rootElRef },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"table\", { role: \"presentation\", style: {\n minWidth: props.tableMinWidth,\n width: props.clientWidth,\n } },\n props.tableColGroupNode,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tbody\", { role: \"presentation\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", { role: \"row\" },\n props.axis && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"td\", { \"aria-hidden\": true, className: \"fc-timegrid-col fc-timegrid-axis\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-col-frame\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-now-indicator-container\" }, typeof nowIndicatorTop === 'number' && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ch, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),\n props.cells.map((cell, i) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));\n }\n componentDidMount() {\n this.updateCoords();\n }\n componentDidUpdate() {\n this.updateCoords();\n }\n updateCoords() {\n let { props } = this;\n if (props.onColCoords &&\n props.clientWidth !== null // means sizing has stabilized\n ) {\n props.onColCoords(new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.b8(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal\n false));\n }\n }\n}\nfunction collectCellEls(elMap, cells) {\n return cells.map((cell) => elMap[cell.key]);\n}\n\n/* A component that renders one or more columns of vertical time slots\n----------------------------------------------------------------------------------------------------------------------*/\nclass TimeCols extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.processSlotOptions = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(processSlotOptions);\n this.state = {\n slatCoords: null,\n };\n this.handleRootEl = (el) => {\n if (el) {\n this.context.registerInteractiveComponent(this, {\n el,\n isHitComboAllowed: this.props.isHitComboAllowed,\n });\n }\n else {\n this.context.unregisterInteractiveComponent(this);\n }\n };\n this.handleScrollRequest = (request) => {\n let { onScrollTopRequest } = this.props;\n let { slatCoords } = this.state;\n if (onScrollTopRequest && slatCoords) {\n if (request.time) {\n let top = slatCoords.computeTimeTop(request.time);\n top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further\n if (top) {\n top += 1; // to overcome top border that slots beyond the first have. looks better\n }\n onScrollTopRequest(top);\n }\n return true;\n }\n return false;\n };\n this.handleColCoords = (colCoords) => {\n this.colCoords = colCoords;\n };\n this.handleSlatCoords = (slatCoords) => {\n this.setState({ slatCoords });\n if (this.props.onSlatCoords) {\n this.props.onSlatCoords(slatCoords);\n }\n };\n }\n render() {\n let { props, state } = this;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"div\", { className: \"fc-timegrid-body\", ref: this.handleRootEl, style: {\n // these props are important to give this wrapper correct dimensions for interactions\n // TODO: if we set it here, can we avoid giving to inner tables?\n width: props.clientWidth,\n minWidth: props.tableMinWidth,\n } },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));\n }\n componentDidMount() {\n this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);\n }\n componentDidUpdate(prevProps) {\n this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);\n }\n componentWillUnmount() {\n this.scrollResponder.detach();\n }\n queryHit(positionLeft, positionTop) {\n let { dateEnv, options } = this.context;\n let { colCoords } = this;\n let { dateProfile } = this.props;\n let { slatCoords } = this.state;\n let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);\n let colIndex = colCoords.leftToIndex(positionLeft);\n let slatIndex = slatCoords.positions.topToIndex(positionTop);\n if (colIndex != null && slatIndex != null) {\n let cell = this.props.cells[colIndex];\n let slatTop = slatCoords.positions.tops[slatIndex];\n let slatHeight = slatCoords.positions.getHeight(slatIndex);\n let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1\n let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat\n let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;\n let dayDate = this.props.cells[colIndex].date;\n let time = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bn)(dateProfile.slotMinTime, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bm)(snapDuration, snapIndex));\n let start = dateEnv.add(dayDate, time);\n let end = dateEnv.add(start, snapDuration);\n return {\n dateProfile,\n dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),\n dayEl: colCoords.els[colIndex],\n rect: {\n left: colCoords.lefts[colIndex],\n right: colCoords.rights[colIndex],\n top: slatTop,\n bottom: slatTop + slatHeight,\n },\n layer: 0,\n };\n }\n return null;\n }\n}\nfunction processSlotOptions(slotDuration, snapDurationOverride) {\n let snapDuration = snapDurationOverride || slotDuration;\n let snapsPerSlot = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.br)(slotDuration, snapDuration);\n if (snapsPerSlot === null) {\n snapDuration = slotDuration;\n snapsPerSlot = 1;\n // TODO: say warning?\n }\n return { snapDuration, snapsPerSlot };\n}\n\nclass DayTimeColsSlicer extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bU {\n sliceRange(range, dayRanges) {\n let segs = [];\n for (let col = 0; col < dayRanges.length; col += 1) {\n let segRange = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.o)(range, dayRanges[col]);\n if (segRange) {\n segs.push({\n start: segRange.start,\n end: segRange.end,\n isStart: segRange.start.valueOf() === range.start.valueOf(),\n isEnd: segRange.end.valueOf() === range.end.valueOf(),\n col,\n });\n }\n }\n return segs;\n }\n}\n\nclass DayTimeCols extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.buildDayRanges = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildDayRanges);\n this.slicer = new DayTimeColsSlicer();\n this.timeColsRef = (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createRef)();\n }\n render() {\n let { props, context } = this;\n let { dateProfile, dayTableModel } = props;\n let { nowIndicator, nextDayThreshold } = context.options;\n let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);\n // give it the first row of cells\n // TODO: would move this further down hierarchy, but sliceNowDate needs it\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a6, { unit: nowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));\n }\n}\nfunction buildDayRanges(dayTableModel, dateProfile, dateEnv) {\n let ranges = [];\n for (let date of dayTableModel.headerDates) {\n ranges.push({\n start: dateEnv.add(date, dateProfile.slotMinTime),\n end: dateEnv.add(date, dateProfile.slotMaxTime),\n });\n }\n return ranges;\n}\n\n// potential nice values for the slot-duration and interval-duration\n// from largest to smallest\nconst STOCK_SUB_DURATIONS = [\n { hours: 1 },\n { minutes: 30 },\n { minutes: 15 },\n { seconds: 30 },\n { seconds: 15 },\n];\nfunction buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {\n let dayStart = new Date(0);\n let slatTime = slotMinTime;\n let slatIterator = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.d)(0);\n let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);\n let metas = [];\n while ((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bq)(slatTime) < (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bq)(slotMaxTime)) {\n let date = dateEnv.add(dayStart, slatTime);\n let isLabeled = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.br)(slatIterator, labelInterval) !== null;\n metas.push({\n date,\n time: slatTime,\n key: date.toISOString(),\n isoTimeStr: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bs)(date),\n isLabeled,\n });\n slatTime = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bn)(slatTime, slotDuration);\n slatIterator = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bn)(slatIterator, slotDuration);\n }\n return metas;\n}\n// Computes an automatic value for slotLabelInterval\nfunction computeLabelInterval(slotDuration) {\n let i;\n let labelInterval;\n let slotsPerLabel;\n // find the smallest stock label interval that results in more than one slots-per-label\n for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {\n labelInterval = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.d)(STOCK_SUB_DURATIONS[i]);\n slotsPerLabel = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.br)(labelInterval, slotDuration);\n if (slotsPerLabel !== null && slotsPerLabel > 1) {\n return labelInterval;\n }\n }\n return slotDuration; // fall back\n}\n\nclass DayTimeColsView extends TimeColsView {\n constructor() {\n super(...arguments);\n this.buildTimeColsModel = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildTimeColsModel);\n this.buildSlatMetas = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(buildSlatMetas);\n }\n render() {\n let { options, dateEnv, dateProfileGenerator } = this.context;\n let { props } = this;\n let { dateProfile } = props;\n let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);\n let splitProps = this.allDaySplitter.splitProps(props);\n let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);\n let { dayMinWidth } = options;\n let hasAttachedAxis = !dayMinWidth;\n let hasDetachedAxis = dayMinWidth;\n let headerContent = options.dayHeaders && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bI, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));\n let allDayContent = (options.allDaySlot !== false) && ((contentArg) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_daygrid_internal_js__WEBPACK_IMPORTED_MODULE_2__.DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));\n let timeGridContent = (contentArg) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));\n return hasDetachedAxis\n ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)\n : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);\n }\n}\nfunction buildTimeColsModel(dateProfile, dateProfileGenerator) {\n let daySeries = new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bM(dateProfile.renderRange, dateProfileGenerator);\n return new _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bT(daySeries, false);\n}\n\nvar css_248z = \".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\\\"\\\\00a0\\\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\\\"\\\\00a0-\\\\00a0\\\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}\";\n(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ct)(css_248z);\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QkFBb0IsMkJBQTJCLGtCQUFrQiw4Q0FBOEMsU0FBUyxPQUFPLGtCQUFrQixRQUFRLE1BQU0sOEdBQThHLDZDQUE2QywwQ0FBMEMsa0JBQWtCLG9DQUFvQyxtQkFBbUIsa0JBQWtCLGtDQUFrQyxrQkFBa0Isa0NBQWtDLG9DQUFvQyxrQkFBa0IsbUJBQW1CLDhDQUE4QyxtQkFBbUIsZ0JBQWdCLDhDQUE4QywwQkFBMEIseUNBQXlDLG9DQUFvQyx1QkFBdUIsd0NBQXdDLHFDQUFxQyxlQUFlLGtCQUFrQixrQkFBa0IsYUFBYSw2QkFBNkIsZ0JBQWdCLE1BQU0seUNBQXlDLFFBQVEseUNBQXlDLE9BQU8seUVBQXlFLG9CQUFvQixvQ0FBb0MsMkNBQTJDLG1CQUFtQixxQkFBcUIsT0FBTyxrQkFBa0IsUUFBUSxVQUFVLHFDQUFxQywyQ0FBMkMsbUJBQW1CLGdCQUFnQixrQkFBa0IsVUFBVSxtREFBbUQsZ0NBQWdDLDZCQUE2QiwyQkFBMkIsT0FBTyxtREFBbUQsZ0NBQWdDLDZCQUE2QiwyQkFBMkIsUUFBUTtBQUMvMkssa0VBQVk7O0FBRWdKIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vYXJjaGl0ZWN0dWktaHRtbC1mcmVlLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvdGltZWdyaWQvaW50ZXJuYWwuanM/MDBlMSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTcGxpdHRlciwgaGFzQmdSZW5kZXJpbmcsIGNyZWF0ZUZvcm1hdHRlciwgVmlld0NvbnRleHRUeXBlLCBDb250ZW50Q29udGFpbmVyLCBCYXNlQ29tcG9uZW50LCBEYXRlQ29tcG9uZW50LCBkaWZmRGF5cywgYnVpbGROYXZMaW5rQXR0cnMsIFdlZWtOdW1iZXJDb250YWluZXIsIGdldFN0aWNreUhlYWRlckRhdGVzLCBWaWV3Q29udGFpbmVyLCBTaW1wbGVTY3JvbGxHcmlkLCBnZXRTdGlja3lGb290ZXJTY3JvbGxiYXIsIE5vd1RpbWVyLCBOb3dJbmRpY2F0b3JDb250YWluZXIsIHJlbmRlclNjcm9sbFNoaW0sIHJhbmdlQ29udGFpbnNNYXJrZXIsIHN0YXJ0T2ZEYXksIGFzUm91Z2hNcywgY3JlYXRlRHVyYXRpb24sIFJlZk1hcCwgUG9zaXRpb25DYWNoZSwgTW9yZUxpbmtDb250YWluZXIsIFNlZ0hpZXJhcmNoeSwgZ3JvdXBJbnRlcnNlY3RpbmdFbnRyaWVzLCBiaW5hcnlTZWFyY2gsIGdldEVudHJ5U3BhbkVuZCwgYnVpbGRFbnRyeUtleSwgU3RhbmRhcmRFdmVudCwgbWVtb2l6ZSwgc29ydEV2ZW50U2VncywgRGF5Q2VsbENvbnRhaW5lciwgaGFzQ3VzdG9tRGF5Q2VsbENvbnRlbnQsIGdldFNlZ01ldGEsIGJ1aWxkSXNvU3RyaW5nLCBjb21wdXRlRWFybGllc3RTZWdTdGFydCwgYnVpbGRFdmVudFJhbmdlS2V5LCBCZ0V2ZW50LCByZW5kZXJGaWxsLCBhZGREdXJhdGlvbnMsIG11bHRpcGx5RHVyYXRpb24sIHdob2xlRGl2aWRlRHVyYXRpb25zLCBTbGljZXIsIGludGVyc2VjdFJhbmdlcywgZm9ybWF0SXNvVGltZVN0cmluZywgRGF5SGVhZGVyLCBEYXlTZXJpZXNNb2RlbCwgRGF5VGFibGVNb2RlbCwgaW5qZWN0U3R5bGVzIH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9jb3JlL2ludGVybmFsLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVsZW1lbnQsIGNyZWF0ZVJlZiwgRnJhZ21lbnQgfSBmcm9tICdAZnVsbGNhbGVuZGFyL2NvcmUvcHJlYWN0LmpzJztcbmltcG9ydCB7IERheVRhYmxlIH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9kYXlncmlkL2ludGVybmFsLmpzJztcblxuY2xhc3MgQWxsRGF5U3BsaXR0ZXIgZXh0ZW5kcyBTcGxpdHRlciB7XG4gICAgZ2V0S2V5SW5mbygpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGFsbERheToge30sXG4gICAgICAgICAgICB0aW1lZDoge30sXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldEtleXNGb3JEYXRlU3BhbihkYXRlU3Bhbikge1xuICAgICAgICBpZiAoZGF0ZVNwYW4uYWxsRGF5KSB7XG4gICAgICAgICAgICByZXR1cm4gWydhbGxEYXknXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gWyd0aW1lZCddO1xuICAgIH1cbiAgICBnZXRLZXlzRm9yRXZlbnREZWYoZXZlbnREZWYpIHtcbiAgICAgICAgaWYgKCFldmVudERlZi5hbGxEYXkpIHtcbiAgICAgICAgICAgIHJldHVybiBbJ3RpbWVkJ107XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhhc0JnUmVuZGVyaW5nKGV2ZW50RGVmKSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndGltZWQnLCAnYWxsRGF5J107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsnYWxsRGF5J107XG4gICAgfVxufVxuXG5jb25zdCBERUZBVUxUX1NMQVRfTEFCRUxfRk9STUFUID0gY3JlYXRlRm9ybWF0dGVyKHtcbiAgICBob3VyOiAnbnVtZXJpYycsXG4gICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgb21pdFplcm9NaW51dGU6IHRydWUsXG4gICAgbWVyaWRpZW06ICdzaG9ydCcsXG59KTtcbmZ1bmN0aW9uIFRpbWVDb2xzQXhpc0NlbGwocHJvcHMpIHtcbiAgICBsZXQgY2xhc3NOYW1lcyA9IFtcbiAgICAgICAgJ2ZjLXRpbWVncmlkLXNsb3QnLFxuICAgICAgICAnZmMtdGltZWdyaWQtc2xvdC1sYWJlbCcsXG4gICAgICAgIHByb3BzLmlzTGFiZWxlZCA/ICdmYy1zY3JvbGxncmlkLXNocmluaycgOiAnZmMtdGltZWdyaWQtc2xvdC1taW5vcicsXG4gICAgXTtcbiAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoVmlld0NvbnRleHRUeXBlLkNvbnN1bWVyLCBudWxsLCAoY29udGV4dCkgPT4ge1xuICAgICAgICBpZiAoIXByb3BzLmlzTGFiZWxlZCkge1xuICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwidGRcIiwgeyBjbGFzc05hbWU6IGNsYXNzTmFtZXMuam9pbignICcpLCBcImRhdGEtdGltZVwiOiBwcm9wcy5pc29UaW1lU3RyIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgeyBkYXRlRW52LCBvcHRpb25zLCB2aWV3QXBpIH0gPSBjb250ZXh0O1xuICAgICAgICBsZXQgbGFiZWxGb3JtYXQgPSAvLyBUT0RPOiBmdWxseSBwcmUtcGFyc2VcbiAgICAgICAgIG9wdGlvbnMuc2xvdExhYmVsRm9ybWF0ID09IG51bGwgPyBERUZBVUxUX1NMQVRfTEFCRUxfRk9STUFUIDpcbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkob3B0aW9ucy5zbG90TGFiZWxGb3JtYXQpID8gY3JlYXRlRm9ybWF0dGVyKG9wdGlvbnMuc2xvdExhYmVsRm9ybWF0WzBdKSA6XG4gICAgICAgICAgICAgICAgY3JlYXRlRm9ybWF0dGVyKG9wdGlvbnMuc2xvdExhYmVsRm9ybWF0KTtcbiAgICAgICAgbGV0IHJlbmRlclByb3BzID0ge1xuICAgICAgICAgICAgbGV2ZWw6IDAsXG4gICAgICAgICAgICB0aW1lOiBwcm9wcy50aW1lLFxuICAgICAgICAgICAgZGF0ZTogZGF0ZUVudi50b0RhdGUocHJvcHMuZGF0ZSksXG4gICAgICAgICAgICB2aWV3OiB2aWV3QXBpLFxuICAgICAgICAgICAgdGV4dDogZGF0ZUVudi5mb3JtYXQocHJvcHMuZGF0ZSwgbGFiZWxGb3JtYXQpLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoQ29udGVudENvbnRhaW5lciwgeyBlbFRhZzogXCJ0ZFwiLCBlbENsYXNzZXM6IGNsYXNzTmFtZXMsIGVsQXR0cnM6IHtcbiAgICAgICAgICAgICAgICAnZGF0YS10aW1lJzogcHJvcHMuaXNvVGltZVN0cixcbiAgICAgICAgICAgIH0sIHJlbmRlclByb3BzOiByZW5kZXJQcm9wcywgZ2VuZXJhdG9yTmFtZTogXCJzbG90TGFiZWxDb250ZW50XCIsIGN1c3RvbUdlbmVyYXRvcjogb3B0aW9ucy5zbG90TGFiZWxDb250ZW50LCBkZWZhdWx0R2VuZXJhdG9yOiByZW5kZXJJbm5lckNvbnRlbnQsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5zbG90TGFiZWxDbGFzc05hbWVzLCBkaWRNb3VudDogb3B0aW9ucy5zbG90TGFiZWxEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMuc2xvdExhYmVsV2lsbFVubW91bnQgfSwgKElubmVyQ29udGVudCkgPT4gKGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtdGltZWdyaWQtc2xvdC1sYWJlbC1mcmFtZSBmYy1zY3JvbGxncmlkLXNocmluay1mcmFtZVwiIH0sXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KElubmVyQ29udGVudCwgeyBlbFRhZzogXCJkaXZcIiwgZWxDbGFzc2VzOiBbXG4gICAgICAgICAgICAgICAgICAgICdmYy10aW1lZ3JpZC1zbG90LWxhYmVsLWN1c2hpb24nLFxuICAgICAgICAgICAgICAgICAgICAnZmMtc2Nyb2xsZ3JpZC1zaHJpbmstY3VzaGlvbicsXG4gICAgICAgICAgICAgICAgXSB9KSkpKSk7XG4gICAgfSkpO1xufVxuZnVuY3Rpb24gcmVuZGVySW5uZXJDb250ZW50KHByb3BzKSB7XG4gICAgcmV0dXJuIHByb3BzLnRleHQ7XG59XG5cbmNsYXNzIFRpbWVCb2R5QXhpcyBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcHMuc2xhdE1ldGFzLm1hcCgoc2xhdE1ldGEpID0+IChjcmVhdGVFbGVtZW50KFwidHJcIiwgeyBrZXk6IHNsYXRNZXRhLmtleSB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChUaW1lQ29sc0F4aXNDZWxsLCBPYmplY3QuYXNzaWduKHt9LCBzbGF0TWV0YSkpKSkpO1xuICAgIH1cbn1cblxuY29uc3QgREVGQVVMVF9XRUVLX05VTV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrOiAnc2hvcnQnIH0pO1xuY29uc3QgQVVUT19BTExfREFZX01BWF9FVkVOVF9ST1dTID0gNTtcbmNsYXNzIFRpbWVDb2xzVmlldyBleHRlbmRzIERhdGVDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmFsbERheVNwbGl0dGVyID0gbmV3IEFsbERheVNwbGl0dGVyKCk7IC8vIGZvciB1c2UgYnkgc3ViY2xhc3Nlc1xuICAgICAgICB0aGlzLmhlYWRlckVsUmVmID0gY3JlYXRlUmVmKCk7XG4gICAgICAgIHRoaXMucm9vdEVsUmVmID0gY3JlYXRlUmVmKCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsZXJFbFJlZiA9IGNyZWF0ZVJlZigpO1xuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgc2xhdENvb3JkczogbnVsbCxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGxUb3BSZXF1ZXN0ID0gKHNjcm9sbFRvcCkgPT4ge1xuICAgICAgICAgICAgbGV0IHNjcm9sbGVyRWwgPSB0aGlzLnNjcm9sbGVyRWxSZWYuY3VycmVudDtcbiAgICAgICAgICAgIGlmIChzY3JvbGxlckVsKSB7IC8vIFRPRE86IG5vdCBzdXJlIGhvdyB0aGlzIGNvdWxkIGV2ZXIgYmUgbnVsbC4gd2VpcmRuZXNzIHdpdGggdGhlIHJlZHVjZXJcbiAgICAgICAgICAgICAgICBzY3JvbGxlckVsLnNjcm9sbFRvcCA9IHNjcm9sbFRvcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyogSGVhZGVyIFJlbmRlciBNZXRob2RzXG4gICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgICAgIHRoaXMucmVuZGVySGVhZEF4aXMgPSAocm93S2V5LCBmcmFtZUhlaWdodCA9ICcnKSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBvcHRpb25zIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgICAgICBsZXQgeyBkYXRlUHJvZmlsZSB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgICAgIGxldCByYW5nZSA9IGRhdGVQcm9maWxlLnJlbmRlclJhbmdlO1xuICAgICAgICAgICAgbGV0IGRheUNudCA9IGRpZmZEYXlzKHJhbmdlLnN0YXJ0LCByYW5nZS5lbmQpO1xuICAgICAgICAgICAgLy8gb25seSBkbyBpbiBkYXkgdmlld3MgKHRvIGF2b2lkIGRvaW5nIGluIHdlZWsgdmlld3MgdGhhdCBkb250IG5lZWQgaXQpXG4gICAgICAgICAgICBsZXQgbmF2TGlua0F0dHJzID0gKGRheUNudCA9PT0gMSlcbiAgICAgICAgICAgICAgICA/IGJ1aWxkTmF2TGlua0F0dHJzKHRoaXMuY29udGV4dCwgcmFuZ2Uuc3RhcnQsICd3ZWVrJylcbiAgICAgICAgICAgICAgICA6IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMud2Vla051bWJlcnMgJiYgcm93S2V5ID09PSAnZGF5Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChXZWVrTnVtYmVyQ29udGFpbmVyLCB7IGVsVGFnOiBcInRoXCIsIGVsQ2xhc3NlczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLXRpbWVncmlkLWF4aXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLXNjcm9sbGdyaWQtc2hyaW5rJyxcbiAgICAgICAgICAgICAgICAgICAgXSwgZWxBdHRyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2FyaWEtaGlkZGVuJzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgfSwgZGF0ZTogcmFuZ2Uuc3RhcnQsIGRlZmF1bHRGb3JtYXQ6IERFRkFVTFRfV0VFS19OVU1fRk9STUFUIH0sIChJbm5lckNvbnRlbnQpID0+IChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAnZmMtdGltZWdyaWQtYXhpcy1mcmFtZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZmMtc2Nyb2xsZ3JpZC1zaHJpbmstZnJhbWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLXRpbWVncmlkLWF4aXMtZnJhbWUtbGlxdWlkJyxcbiAgICAgICAgICAgICAgICAgICAgXS5qb2luKCcgJyksIHN0eWxlOiB7IGhlaWdodDogZnJhbWVIZWlnaHQgfSB9LFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KElubmVyQ29udGVudCwgeyBlbFRhZzogXCJhXCIsIGVsQ2xhc3NlczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdmYy10aW1lZ3JpZC1heGlzLWN1c2hpb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdmYy1zY3JvbGxncmlkLXNocmluay1jdXNoaW9uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZmMtc2Nyb2xsZ3JpZC1zeW5jLWlubmVyJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sIGVsQXR0cnM6IG5hdkxpbmtBdHRycyB9KSkpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7IFwiYXJpYS1oaWRkZW5cIjogdHJ1ZSwgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLWF4aXNcIiB9LFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtdGltZWdyaWQtYXhpcy1mcmFtZVwiLCBzdHlsZTogeyBoZWlnaHQ6IGZyYW1lSGVpZ2h0IH0gfSkpKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyogVGFibGUgQ29tcG9uZW50IFJlbmRlciBNZXRob2RzXG4gICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgICAgIC8vIG9ubHkgYSBvbmUtd2F5IGhlaWdodCBzeW5jLiB3ZSBkb24ndCBzZW5kIHRoZSBheGlzIGlubmVyLWNvbnRlbnQgaGVpZ2h0IHRvIHRoZSBEYXlHcmlkLFxuICAgICAgICAvLyBidXQgRGF5R3JpZCBzdGlsbCBuZWVkcyB0byBoYXZlIGNsYXNzTmFtZXMgb24gaW5uZXIgZWxlbWVudHMgaW4gb3JkZXIgdG8gbWVhc3VyZS5cbiAgICAgICAgdGhpcy5yZW5kZXJUYWJsZVJvd0F4aXMgPSAocm93SGVpZ2h0KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBvcHRpb25zLCB2aWV3QXBpIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgICAgICBsZXQgcmVuZGVyUHJvcHMgPSB7XG4gICAgICAgICAgICAgICAgdGV4dDogb3B0aW9ucy5hbGxEYXlUZXh0LFxuICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdBcGksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIC8vIFRPRE86IG1ha2UgcmV1c2FibGUgaG9vay4gdXNlZCBpbiBsaXN0IHZpZXcgdG9vXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KENvbnRlbnRDb250YWluZXIsIHsgZWxUYWc6IFwidGRcIiwgZWxDbGFzc2VzOiBbXG4gICAgICAgICAgICAgICAgICAgICdmYy10aW1lZ3JpZC1heGlzJyxcbiAgICAgICAgICAgICAgICAgICAgJ2ZjLXNjcm9sbGdyaWQtc2hyaW5rJyxcbiAgICAgICAgICAgICAgICBdLCBlbEF0dHJzOiB7XG4gICAgICAgICAgICAgICAgICAgICdhcmlhLWhpZGRlbic6IHRydWUsXG4gICAgICAgICAgICAgICAgfSwgcmVuZGVyUHJvcHM6IHJlbmRlclByb3BzLCBnZW5lcmF0b3JOYW1lOiBcImFsbERheUNvbnRlbnRcIiwgY3VzdG9tR2VuZXJhdG9yOiBvcHRpb25zLmFsbERheUNvbnRlbnQsIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlckFsbERheUlubmVyLCBjbGFzc05hbWVHZW5lcmF0b3I6IG9wdGlvbnMuYWxsRGF5Q2xhc3NOYW1lcywgZGlkTW91bnQ6IG9wdGlvbnMuYWxsRGF5RGlkTW91bnQsIHdpbGxVbm1vdW50OiBvcHRpb25zLmFsbERheVdpbGxVbm1vdW50IH0sIChJbm5lckNvbnRlbnQpID0+IChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBbXG4gICAgICAgICAgICAgICAgICAgICdmYy10aW1lZ3JpZC1heGlzLWZyYW1lJyxcbiAgICAgICAgICAgICAgICAgICAgJ2ZjLXNjcm9sbGdyaWQtc2hyaW5rLWZyYW1lJyxcbiAgICAgICAgICAgICAgICAgICAgcm93SGVpZ2h0ID09IG51bGwgPyAnIGZjLXRpbWVncmlkLWF4aXMtZnJhbWUtbGlxdWlkJyA6ICcnLFxuICAgICAgICAgICAgICAgIF0uam9pbignICcpLCBzdHlsZTogeyBoZWlnaHQ6IHJvd0hlaWdodCB9IH0sXG4gICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChJbm5lckNvbnRlbnQsIHsgZWxUYWc6IFwic3BhblwiLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICdmYy10aW1lZ3JpZC1heGlzLWN1c2hpb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLXNjcm9sbGdyaWQtc2hyaW5rLWN1c2hpb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLXNjcm9sbGdyaWQtc3luYy1pbm5lcicsXG4gICAgICAgICAgICAgICAgICAgIF0gfSkpKSkpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVNsYXRDb29yZHMgPSAoc2xhdENvb3JkcykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHNsYXRDb29yZHMgfSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIC8vIHJlbmRlcmluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICByZW5kZXJTaW1wbGVMYXlvdXQoaGVhZGVyUm93Q29udGVudCwgYWxsRGF5Q29udGVudCwgdGltZUNvbnRlbnQpIHtcbiAgICAgICAgbGV0IHsgY29udGV4dCwgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGxldCBzZWN0aW9ucyA9IFtdO1xuICAgICAgICBsZXQgc3RpY2t5SGVhZGVyRGF0ZXMgPSBnZXRTdGlja3lIZWFkZXJEYXRlcyhjb250ZXh0Lm9wdGlvbnMpO1xuICAgICAgICBpZiAoaGVhZGVyUm93Q29udGVudCkge1xuICAgICAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2hlYWRlcicsXG4gICAgICAgICAgICAgICAga2V5OiAnaGVhZGVyJyxcbiAgICAgICAgICAgICAgICBpc1N0aWNreTogc3RpY2t5SGVhZGVyRGF0ZXMsXG4gICAgICAgICAgICAgICAgY2h1bms6IHtcbiAgICAgICAgICAgICAgICAgICAgZWxSZWY6IHRoaXMuaGVhZGVyRWxSZWYsXG4gICAgICAgICAgICAgICAgICAgIHRhYmxlQ2xhc3NOYW1lOiAnZmMtY29sLWhlYWRlcicsXG4gICAgICAgICAgICAgICAgICAgIHJvd0NvbnRlbnQ6IGhlYWRlclJvd0NvbnRlbnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhbGxEYXlDb250ZW50KSB7XG4gICAgICAgICAgICBzZWN0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnYm9keScsXG4gICAgICAgICAgICAgICAga2V5OiAnYWxsLWRheScsXG4gICAgICAgICAgICAgICAgY2h1bms6IHsgY29udGVudDogYWxsRGF5Q29udGVudCB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWN0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnYm9keScsXG4gICAgICAgICAgICAgICAga2V5OiAnYWxsLWRheS1kaXZpZGVyJyxcbiAgICAgICAgICAgICAgICBvdXRlckNvbnRlbnQ6ICggLy8gVE9ETzogcmVuYW1lIHRvIGNlbGxDb250ZW50IHNvIGRvbid0IG5lZWQgdG8gZGVmaW5lIDx0cj4/XG4gICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRyXCIsIHsgcm9sZTogXCJwcmVzZW50YXRpb25cIiwgY2xhc3NOYW1lOiBcImZjLXNjcm9sbGdyaWQtc2VjdGlvblwiIH0sXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7IGNsYXNzTmFtZTogJ2ZjLXRpbWVncmlkLWRpdmlkZXIgJyArIGNvbnRleHQudGhlbWUuZ2V0Q2xhc3MoJ3RhYmxlQ2VsbFNoYWRlZCcpIH0pKSksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBzZWN0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdib2R5JyxcbiAgICAgICAgICAgIGtleTogJ2JvZHknLFxuICAgICAgICAgICAgbGlxdWlkOiB0cnVlLFxuICAgICAgICAgICAgZXhwYW5kUm93czogQm9vbGVhbihjb250ZXh0Lm9wdGlvbnMuZXhwYW5kUm93cyksXG4gICAgICAgICAgICBjaHVuazoge1xuICAgICAgICAgICAgICAgIHNjcm9sbGVyRWxSZWY6IHRoaXMuc2Nyb2xsZXJFbFJlZixcbiAgICAgICAgICAgICAgICBjb250ZW50OiB0aW1lQ29udGVudCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoVmlld0NvbnRhaW5lciwgeyBlbFJlZjogdGhpcy5yb290RWxSZWYsIGVsQ2xhc3NlczogWydmYy10aW1lZ3JpZCddLCB2aWV3U3BlYzogY29udGV4dC52aWV3U3BlYyB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChTaW1wbGVTY3JvbGxHcmlkLCB7IGxpcXVpZDogIXByb3BzLmlzSGVpZ2h0QXV0byAmJiAhcHJvcHMuZm9yUHJpbnQsIGNvbGxhcHNpYmxlV2lkdGg6IHByb3BzLmZvclByaW50LCBjb2xzOiBbeyB3aWR0aDogJ3NocmluaycgfV0sIHNlY3Rpb25zOiBzZWN0aW9ucyB9KSkpO1xuICAgIH1cbiAgICByZW5kZXJIU2Nyb2xsTGF5b3V0KGhlYWRlclJvd0NvbnRlbnQsIGFsbERheUNvbnRlbnQsIHRpbWVDb250ZW50LCBjb2xDbnQsIGRheU1pbldpZHRoLCBzbGF0TWV0YXMsIHNsYXRDb29yZHMpIHtcbiAgICAgICAgbGV0IFNjcm9sbEdyaWQgPSB0aGlzLmNvbnRleHQucGx1Z2luSG9va3Muc2Nyb2xsR3JpZEltcGw7XG4gICAgICAgIGlmICghU2Nyb2xsR3JpZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBTY3JvbGxHcmlkIGltcGxlbWVudGF0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHsgY29udGV4dCwgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGxldCBzdGlja3lIZWFkZXJEYXRlcyA9ICFwcm9wcy5mb3JQcmludCAmJiBnZXRTdGlja3lIZWFkZXJEYXRlcyhjb250ZXh0Lm9wdGlvbnMpO1xuICAgICAgICBsZXQgc3RpY2t5Rm9vdGVyU2Nyb2xsYmFyID0gIXByb3BzLmZvclByaW50ICYmIGdldFN0aWNreUZvb3RlclNjcm9sbGJhcihjb250ZXh0Lm9wdGlvbnMpO1xuICAgICAgICBsZXQgc2VjdGlvbnMgPSBbXTtcbiAgICAgICAgaWYgKGhlYWRlclJvd0NvbnRlbnQpIHtcbiAgICAgICAgICAgIHNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdoZWFkZXInLFxuICAgICAgICAgICAgICAgIGtleTogJ2hlYWRlcicsXG4gICAgICAgICAgICAgICAgaXNTdGlja3k6IHN0aWNreUhlYWRlckRhdGVzLFxuICAgICAgICAgICAgICAgIHN5bmNSb3dIZWlnaHRzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNodW5rczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk6ICdheGlzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvd0NvbnRlbnQ6IChhcmcpID0+IChjcmVhdGVFbGVtZW50KFwidHJcIiwgeyByb2xlOiBcInByZXNlbnRhdGlvblwiIH0sIHRoaXMucmVuZGVySGVhZEF4aXMoJ2RheScsIGFyZy5yb3dTeW5jSGVpZ2h0c1swXSkpKSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5OiAnY29scycsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbFJlZjogdGhpcy5oZWFkZXJFbFJlZixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhYmxlQ2xhc3NOYW1lOiAnZmMtY29sLWhlYWRlcicsXG4gICAgICAgICAgICAgICAgICAgICAgICByb3dDb250ZW50OiBoZWFkZXJSb3dDb250ZW50LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWxsRGF5Q29udGVudCkge1xuICAgICAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2JvZHknLFxuICAgICAgICAgICAgICAgIGtleTogJ2FsbC1kYXknLFxuICAgICAgICAgICAgICAgIHN5bmNSb3dIZWlnaHRzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNodW5rczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk6ICdheGlzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvd0NvbnRlbnQ6IChjb250ZW50QXJnKSA9PiAoY3JlYXRlRWxlbWVudChcInRyXCIsIHsgcm9sZTogXCJwcmVzZW50YXRpb25cIiB9LCB0aGlzLnJlbmRlclRhYmxlUm93QXhpcyhjb250ZW50QXJnLnJvd1N5bmNIZWlnaHRzWzBdKSkpLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk6ICdjb2xzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGFsbERheUNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAga2V5OiAnYWxsLWRheS1kaXZpZGVyJyxcbiAgICAgICAgICAgICAgICB0eXBlOiAnYm9keScsXG4gICAgICAgICAgICAgICAgb3V0ZXJDb250ZW50OiAoIC8vIFRPRE86IHJlbmFtZSB0byBjZWxsQ29udGVudCBzbyBkb24ndCBuZWVkIHRvIGRlZmluZSA8dHI+P1xuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7IHJvbGU6IFwicHJlc2VudGF0aW9uXCIsIGNsYXNzTmFtZTogXCJmYy1zY3JvbGxncmlkLXNlY3Rpb25cIiB9LFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwidGRcIiwgeyBjb2xTcGFuOiAyLCBjbGFzc05hbWU6ICdmYy10aW1lZ3JpZC1kaXZpZGVyICcgKyBjb250ZXh0LnRoZW1lLmdldENsYXNzKCd0YWJsZUNlbGxTaGFkZWQnKSB9KSkpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGlzTm93SW5kaWNhdG9yID0gY29udGV4dC5vcHRpb25zLm5vd0luZGljYXRvcjtcbiAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnYm9keScsXG4gICAgICAgICAgICBrZXk6ICdib2R5JyxcbiAgICAgICAgICAgIGxpcXVpZDogdHJ1ZSxcbiAgICAgICAgICAgIGV4cGFuZFJvd3M6IEJvb2xlYW4oY29udGV4dC5vcHRpb25zLmV4cGFuZFJvd3MpLFxuICAgICAgICAgICAgY2h1bmtzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBrZXk6ICdheGlzJyxcbiAgICAgICAgICAgICAgICAgICAgY29udGVudDogKGFyZykgPT4gKFxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBtYWtlIHRoaXMgbm93LWluZGljYXRvciBhcnJvdyBtb3JlIERSWSB3aXRoIFRpbWVDb2xzQ29udGVudFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLWF4aXMtY2h1bmtcIiB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRhYmxlXCIsIHsgXCJhcmlhLWhpZGRlblwiOiB0cnVlLCBzdHlsZTogeyBoZWlnaHQ6IGFyZy5leHBhbmRSb3dzID8gYXJnLmNsaWVudEhlaWdodCA6ICcnIH0gfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmcudGFibGVDb2xHcm91cE5vZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRib2R5XCIsIG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoVGltZUJvZHlBeGlzLCB7IHNsYXRNZXRhczogc2xhdE1ldGFzIH0pKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItY29udGFpbmVyXCIgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KE5vd1RpbWVyLCB7IHVuaXQ6IGlzTm93SW5kaWNhdG9yID8gJ21pbnV0ZScgOiAnZGF5JyAvKiBoYWNreSAqLyB9LCAobm93RGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbm93SW5kaWNhdG9yVG9wID0gaXNOb3dJbmRpY2F0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsYXRDb29yZHMgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsYXRDb29yZHMuc2FmZUNvbXB1dGVUb3Aobm93RGF0ZSk7IC8vIG1pZ2h0IHJldHVybiB2b2lkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygbm93SW5kaWNhdG9yVG9wID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KE5vd0luZGljYXRvckNvbnRhaW5lciwgeyBlbENsYXNzZXM6IFsnZmMtdGltZWdyaWQtbm93LWluZGljYXRvci1hcnJvdyddLCBlbFN0eWxlOiB7IHRvcDogbm93SW5kaWNhdG9yVG9wIH0sIGlzQXhpczogdHJ1ZSwgZGF0ZTogbm93RGF0ZSB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpKSksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGtleTogJ2NvbHMnLFxuICAgICAgICAgICAgICAgICAgICBzY3JvbGxlckVsUmVmOiB0aGlzLnNjcm9sbGVyRWxSZWYsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHRpbWVDb250ZW50LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHN0aWNreUZvb3RlclNjcm9sbGJhcikge1xuICAgICAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAga2V5OiAnZm9vdGVyJyxcbiAgICAgICAgICAgICAgICB0eXBlOiAnZm9vdGVyJyxcbiAgICAgICAgICAgICAgICBpc1N0aWNreTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaHVua3M6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5OiAnYXhpcycsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiByZW5kZXJTY3JvbGxTaGltLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk6ICdjb2xzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHJlbmRlclNjcm9sbFNoaW0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChWaWV3Q29udGFpbmVyLCB7IGVsUmVmOiB0aGlzLnJvb3RFbFJlZiwgZWxDbGFzc2VzOiBbJ2ZjLXRpbWVncmlkJ10sIHZpZXdTcGVjOiBjb250ZXh0LnZpZXdTcGVjIH0sXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFNjcm9sbEdyaWQsIHsgbGlxdWlkOiAhcHJvcHMuaXNIZWlnaHRBdXRvICYmICFwcm9wcy5mb3JQcmludCwgZm9yUHJpbnQ6IHByb3BzLmZvclByaW50LCBjb2xsYXBzaWJsZVdpZHRoOiBmYWxzZSwgY29sR3JvdXBzOiBbXG4gICAgICAgICAgICAgICAgICAgIHsgd2lkdGg6ICdzaHJpbmsnLCBjb2xzOiBbeyB3aWR0aDogJ3NocmluaycgfV0gfSxcbiAgICAgICAgICAgICAgICAgICAgeyBjb2xzOiBbeyBzcGFuOiBjb2xDbnQsIG1pbldpZHRoOiBkYXlNaW5XaWR0aCB9XSB9LFxuICAgICAgICAgICAgICAgIF0sIHNlY3Rpb25zOiBzZWN0aW9ucyB9KSkpO1xuICAgIH1cbiAgICAvKiBEaW1lbnNpb25zXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBnZXRBbGxEYXlNYXhFdmVudFByb3BzKCkge1xuICAgICAgICBsZXQgeyBkYXlNYXhFdmVudHMsIGRheU1heEV2ZW50Um93cyB9ID0gdGhpcy5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIGlmIChkYXlNYXhFdmVudHMgPT09IHRydWUgfHwgZGF5TWF4RXZlbnRSb3dzID09PSB0cnVlKSB7IC8vIGlzIGF1dG8/XG4gICAgICAgICAgICBkYXlNYXhFdmVudHMgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBkYXlNYXhFdmVudFJvd3MgPSBBVVRPX0FMTF9EQVlfTUFYX0VWRU5UX1JPV1M7IC8vIG1ha2Ugc3VyZSBcImF1dG9cIiBnb2VzIHRvIGEgcmVhbCBudW1iZXJcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBkYXlNYXhFdmVudHMsIGRheU1heEV2ZW50Um93cyB9O1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlbmRlckFsbERheUlubmVyKHJlbmRlclByb3BzKSB7XG4gICAgcmV0dXJuIHJlbmRlclByb3BzLnRleHQ7XG59XG5cbmNsYXNzIFRpbWVDb2xzU2xhdHNDb29yZHMge1xuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9ucywgZGF0ZVByb2ZpbGUsIHNsb3REdXJhdGlvbikge1xuICAgICAgICB0aGlzLnBvc2l0aW9ucyA9IHBvc2l0aW9ucztcbiAgICAgICAgdGhpcy5kYXRlUHJvZmlsZSA9IGRhdGVQcm9maWxlO1xuICAgICAgICB0aGlzLnNsb3REdXJhdGlvbiA9IHNsb3REdXJhdGlvbjtcbiAgICB9XG4gICAgc2FmZUNvbXB1dGVUb3AoZGF0ZSkge1xuICAgICAgICBsZXQgeyBkYXRlUHJvZmlsZSB9ID0gdGhpcztcbiAgICAgICAgaWYgKHJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLCBkYXRlKSkge1xuICAgICAgICAgICAgbGV0IHN0YXJ0T2ZEYXlEYXRlID0gc3RhcnRPZkRheShkYXRlKTtcbiAgICAgICAgICAgIGxldCB0aW1lTXMgPSBkYXRlLnZhbHVlT2YoKSAtIHN0YXJ0T2ZEYXlEYXRlLnZhbHVlT2YoKTtcbiAgICAgICAgICAgIGlmICh0aW1lTXMgPj0gYXNSb3VnaE1zKGRhdGVQcm9maWxlLnNsb3RNaW5UaW1lKSAmJlxuICAgICAgICAgICAgICAgIHRpbWVNcyA8IGFzUm91Z2hNcyhkYXRlUHJvZmlsZS5zbG90TWF4VGltZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wdXRlVGltZVRvcChjcmVhdGVEdXJhdGlvbih0aW1lTXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gQ29tcHV0ZXMgdGhlIHRvcCBjb29yZGluYXRlLCByZWxhdGl2ZSB0byB0aGUgYm91bmRzIG9mIHRoZSBncmlkLCBvZiB0aGUgZ2l2ZW4gZGF0ZS5cbiAgICAvLyBBIGBzdGFydE9mRGF5RGF0ZWAgbXVzdCBiZSBnaXZlbiBmb3IgYXZvaWRpbmcgYW1iaWd1aXR5IG92ZXIgaG93IHRvIHRyZWF0IG1pZG5pZ2h0LlxuICAgIGNvbXB1dGVEYXRlVG9wKHdoZW4sIHN0YXJ0T2ZEYXlEYXRlKSB7XG4gICAgICAgIGlmICghc3RhcnRPZkRheURhdGUpIHtcbiAgICAgICAgICAgIHN0YXJ0T2ZEYXlEYXRlID0gc3RhcnRPZkRheSh3aGVuKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5jb21wdXRlVGltZVRvcChjcmVhdGVEdXJhdGlvbih3aGVuLnZhbHVlT2YoKSAtIHN0YXJ0T2ZEYXlEYXRlLnZhbHVlT2YoKSkpO1xuICAgIH1cbiAgICAvLyBDb21wdXRlcyB0aGUgdG9wIGNvb3JkaW5hdGUsIHJlbGF0aXZlIHRvIHRoZSBib3VuZHMgb2YgdGhlIGdyaWQsIG9mIHRoZSBnaXZlbiB0aW1lIChhIER1cmF0aW9uKS5cbiAgICAvLyBUaGlzIGlzIGEgbWFrZXNoaWZ5IHdheSB0byBjb21wdXRlIHRoZSB0aW1lLXRvcC4gQXNzdW1lcyBhbGwgc2xhdE1ldGFzIGRhdGVzIGFyZSB1bmlmb3JtLlxuICAgIC8vIEV2ZW50dWFsbHkgYWxsb3cgY29tcHV0YXRpb24gd2l0aCBhcmJpcmFyeSBzbGF0IGRhdGVzLlxuICAgIGNvbXB1dGVUaW1lVG9wKGR1cmF0aW9uKSB7XG4gICAgICAgIGxldCB7IHBvc2l0aW9ucywgZGF0ZVByb2ZpbGUgfSA9IHRoaXM7XG4gICAgICAgIGxldCBsZW4gPSBwb3NpdGlvbnMuZWxzLmxlbmd0aDtcbiAgICAgICAgLy8gZmxvYXRpbmctcG9pbnQgdmFsdWUgb2YgIyBvZiBzbG90cyBjb3ZlcmVkXG4gICAgICAgIGxldCBzbGF0Q292ZXJhZ2UgPSAoZHVyYXRpb24ubWlsbGlzZWNvbmRzIC0gYXNSb3VnaE1zKGRhdGVQcm9maWxlLnNsb3RNaW5UaW1lKSkgLyBhc1JvdWdoTXModGhpcy5zbG90RHVyYXRpb24pO1xuICAgICAgICBsZXQgc2xhdEluZGV4O1xuICAgICAgICBsZXQgc2xhdFJlbWFpbmRlcjtcbiAgICAgICAgLy8gY29tcHV0ZSBhIGZsb2F0aW5nLXBvaW50IG51bWJlciBmb3IgaG93IG1hbnkgc2xhdHMgc2hvdWxkIGJlIHByb2dyZXNzZWQgdGhyb3VnaC5cbiAgICAgICAgLy8gZnJvbSAwIHRvIG51bWJlciBvZiBzbGF0cyAoaW5jbHVzaXZlKVxuICAgICAgICAvLyBjb25zdHJhaW5lZCBiZWNhdXNlIHNsb3RNaW5UaW1lL3Nsb3RNYXhUaW1lIG1pZ2h0IGJlIGN1c3RvbWl6ZWQuXG4gICAgICAgIHNsYXRDb3ZlcmFnZSA9IE1hdGgubWF4KDAsIHNsYXRDb3ZlcmFnZSk7XG4gICAgICAgIHNsYXRDb3ZlcmFnZSA9IE1hdGgubWluKGxlbiwgc2xhdENvdmVyYWdlKTtcbiAgICAgICAgLy8gYW4gaW50ZWdlciBpbmRleCBvZiB0aGUgZnVydGhlc3Qgd2hvbGUgc2xhdFxuICAgICAgICAvLyBmcm9tIDAgdG8gbnVtYmVyIHNsYXRzICgqZXhjbHVzaXZlKiwgc28gbGVuLTEpXG4gICAgICAgIHNsYXRJbmRleCA9IE1hdGguZmxvb3Ioc2xhdENvdmVyYWdlKTtcbiAgICAgICAgc2xhdEluZGV4ID0gTWF0aC5taW4oc2xhdEluZGV4LCBsZW4gLSAxKTtcbiAgICAgICAgLy8gaG93IG11Y2ggZnVydGhlciB0aHJvdWdoIHRoZSBzbGF0SW5kZXggc2xhdCAoZnJvbSAwLjAtMS4wKSBtdXN0IGJlIGNvdmVyZWQgaW4gYWRkaXRpb24uXG4gICAgICAgIC8vIGNvdWxkIGJlIDEuMCBpZiBzbGF0Q292ZXJhZ2UgaXMgY292ZXJpbmcgKmFsbCogdGhlIHNsb3RzXG4gICAgICAgIHNsYXRSZW1haW5kZXIgPSBzbGF0Q292ZXJhZ2UgLSBzbGF0SW5kZXg7XG4gICAgICAgIHJldHVybiBwb3NpdGlvbnMudG9wc1tzbGF0SW5kZXhdICtcbiAgICAgICAgICAgIHBvc2l0aW9ucy5nZXRIZWlnaHQoc2xhdEluZGV4KSAqIHNsYXRSZW1haW5kZXI7XG4gICAgfVxufVxuXG5jbGFzcyBUaW1lQ29sc1NsYXRzQm9keSBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgICAgIGxldCB7IHNsYXRFbFJlZnMgfSA9IHByb3BzO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJ0Ym9keVwiLCBudWxsLCBwcm9wcy5zbGF0TWV0YXMubWFwKChzbGF0TWV0YSwgaSkgPT4ge1xuICAgICAgICAgICAgbGV0IHJlbmRlclByb3BzID0ge1xuICAgICAgICAgICAgICAgIHRpbWU6IHNsYXRNZXRhLnRpbWUsXG4gICAgICAgICAgICAgICAgZGF0ZTogY29udGV4dC5kYXRlRW52LnRvRGF0ZShzbGF0TWV0YS5kYXRlKSxcbiAgICAgICAgICAgICAgICB2aWV3OiBjb250ZXh0LnZpZXdBcGksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwidHJcIiwgeyBrZXk6IHNsYXRNZXRhLmtleSwgcmVmOiBzbGF0RWxSZWZzLmNyZWF0ZVJlZihzbGF0TWV0YS5rZXkpIH0sXG4gICAgICAgICAgICAgICAgcHJvcHMuYXhpcyAmJiAoY3JlYXRlRWxlbWVudChUaW1lQ29sc0F4aXNDZWxsLCBPYmplY3QuYXNzaWduKHt9LCBzbGF0TWV0YSkpKSxcbiAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KENvbnRlbnRDb250YWluZXIsIHsgZWxUYWc6IFwidGRcIiwgZWxDbGFzc2VzOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAnZmMtdGltZWdyaWQtc2xvdCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZmMtdGltZWdyaWQtc2xvdC1sYW5lJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICFzbGF0TWV0YS5pc0xhYmVsZWQgJiYgJ2ZjLXRpbWVncmlkLXNsb3QtbWlub3InLFxuICAgICAgICAgICAgICAgICAgICBdLCBlbEF0dHJzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAnZGF0YS10aW1lJzogc2xhdE1ldGEuaXNvVGltZVN0cixcbiAgICAgICAgICAgICAgICAgICAgfSwgcmVuZGVyUHJvcHM6IHJlbmRlclByb3BzLCBnZW5lcmF0b3JOYW1lOiBcInNsb3RMYW5lQ29udGVudFwiLCBjdXN0b21HZW5lcmF0b3I6IG9wdGlvbnMuc2xvdExhbmVDb250ZW50LCBjbGFzc05hbWVHZW5lcmF0b3I6IG9wdGlvbnMuc2xvdExhbmVDbGFzc05hbWVzLCBkaWRNb3VudDogb3B0aW9ucy5zbG90TGFuZURpZE1vdW50LCB3aWxsVW5tb3VudDogb3B0aW9ucy5zbG90TGFuZVdpbGxVbm1vdW50IH0pKSk7XG4gICAgICAgIH0pKSk7XG4gICAgfVxufVxuXG4vKlxuZm9yIHRoZSBob3Jpem9udGFsIFwic2xhdHNcIiB0aGF0IHJ1biB3aWR0aC13aXNlLiBIYXMgYSB0aW1lIGF4aXMgb24gYSBzaWRlLiBEZXBlbmRzIG9uIFJUTC5cbiovXG5jbGFzcyBUaW1lQ29sc1NsYXRzIGV4dGVuZHMgQmFzZUNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMucm9vdEVsUmVmID0gY3JlYXRlUmVmKCk7XG4gICAgICAgIHRoaXMuc2xhdEVsUmVmcyA9IG5ldyBSZWZNYXAoKTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcywgY29udGV4dCB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgcmVmOiB0aGlzLnJvb3RFbFJlZiwgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLXNsb3RzXCIgfSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJ0YWJsZVwiLCB7IFwiYXJpYS1oaWRkZW5cIjogdHJ1ZSwgY2xhc3NOYW1lOiBjb250ZXh0LnRoZW1lLmdldENsYXNzKCd0YWJsZScpLCBzdHlsZToge1xuICAgICAgICAgICAgICAgICAgICBtaW5XaWR0aDogcHJvcHMudGFibGVNaW5XaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHByb3BzLmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHByb3BzLm1pbkhlaWdodCxcbiAgICAgICAgICAgICAgICB9IH0sXG4gICAgICAgICAgICAgICAgcHJvcHMudGFibGVDb2xHcm91cE5vZGUgLyogcmVsaWVzIG9uIHRoZXJlIG9ubHkgYmVpbmcgYSBzaW5nbGUgPGNvbD4gZm9yIHRoZSBheGlzICovLFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoVGltZUNvbHNTbGF0c0JvZHksIHsgc2xhdEVsUmVmczogdGhpcy5zbGF0RWxSZWZzLCBheGlzOiBwcm9wcy5heGlzLCBzbGF0TWV0YXM6IHByb3BzLnNsYXRNZXRhcyB9KSkpKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlU2l6aW5nKCk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZFVwZGF0ZSgpIHtcbiAgICAgICAgdGhpcy51cGRhdGVTaXppbmcoKTtcbiAgICB9XG4gICAgY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLm9uQ29vcmRzKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLm9uQ29vcmRzKG51bGwpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHVwZGF0ZVNpemluZygpIHtcbiAgICAgICAgbGV0IHsgY29udGV4dCwgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIGlmIChwcm9wcy5vbkNvb3JkcyAmJlxuICAgICAgICAgICAgcHJvcHMuY2xpZW50V2lkdGggIT09IG51bGwgLy8gbWVhbnMgc2l6aW5nIGhhcyBzdGFiaWxpemVkXG4gICAgICAgICkge1xuICAgICAgICAgICAgbGV0IHJvb3RFbCA9IHRoaXMucm9vdEVsUmVmLmN1cnJlbnQ7XG4gICAgICAgICAgICBpZiAocm9vdEVsLm9mZnNldEhlaWdodCkgeyAvLyBub3QgaGlkZGVuIGJ5IGNzc1xuICAgICAgICAgICAgICAgIHByb3BzLm9uQ29vcmRzKG5ldyBUaW1lQ29sc1NsYXRzQ29vcmRzKG5ldyBQb3NpdGlvbkNhY2hlKHRoaXMucm9vdEVsUmVmLmN1cnJlbnQsIGNvbGxlY3RTbGF0RWxzKHRoaXMuc2xhdEVsUmVmcy5jdXJyZW50TWFwLCBwcm9wcy5zbGF0TWV0YXMpLCBmYWxzZSwgdHJ1ZSksIHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUsIGNvbnRleHQub3B0aW9ucy5zbG90RHVyYXRpb24pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbmZ1bmN0aW9uIGNvbGxlY3RTbGF0RWxzKGVsTWFwLCBzbGF0TWV0YXMpIHtcbiAgICByZXR1cm4gc2xhdE1ldGFzLm1hcCgoc2xhdE1ldGEpID0+IGVsTWFwW3NsYXRNZXRhLmtleV0pO1xufVxuXG5mdW5jdGlvbiBzcGxpdFNlZ3NCeUNvbChzZWdzLCBjb2xDbnQpIHtcbiAgICBsZXQgc2Vnc0J5Q29sID0gW107XG4gICAgbGV0IGk7XG4gICAgZm9yIChpID0gMDsgaSA8IGNvbENudDsgaSArPSAxKSB7XG4gICAgICAgIHNlZ3NCeUNvbC5wdXNoKFtdKTtcbiAgICB9XG4gICAgaWYgKHNlZ3MpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHNlZ3NCeUNvbFtzZWdzW2ldLmNvbF0ucHVzaChzZWdzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc2Vnc0J5Q29sO1xufVxuZnVuY3Rpb24gc3BsaXRJbnRlcmFjdGlvbkJ5Q29sKHVpLCBjb2xDbnQpIHtcbiAgICBsZXQgYnlSb3cgPSBbXTtcbiAgICBpZiAoIXVpKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29sQ250OyBpICs9IDEpIHtcbiAgICAgICAgICAgIGJ5Um93W2ldID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2xDbnQ7IGkgKz0gMSkge1xuICAgICAgICAgICAgYnlSb3dbaV0gPSB7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRJbnN0YW5jZXM6IHVpLmFmZmVjdGVkSW5zdGFuY2VzLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IHVpLmlzRXZlbnQsXG4gICAgICAgICAgICAgICAgc2VnczogW10sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IHNlZyBvZiB1aS5zZWdzKSB7XG4gICAgICAgICAgICBieVJvd1tzZWcuY29sXS5zZWdzLnB1c2goc2VnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYnlSb3c7XG59XG5cbmNsYXNzIFRpbWVDb2xNb3JlTGluayBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMgfSA9IHRoaXM7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChNb3JlTGlua0NvbnRhaW5lciwgeyBlbENsYXNzZXM6IFsnZmMtdGltZWdyaWQtbW9yZS1saW5rJ10sIGVsU3R5bGU6IHtcbiAgICAgICAgICAgICAgICB0b3A6IHByb3BzLnRvcCxcbiAgICAgICAgICAgICAgICBib3R0b206IHByb3BzLmJvdHRvbSxcbiAgICAgICAgICAgIH0sIGFsbERheURhdGU6IG51bGwsIG1vcmVDbnQ6IHByb3BzLmhpZGRlblNlZ3MubGVuZ3RoLCBhbGxTZWdzOiBwcm9wcy5oaWRkZW5TZWdzLCBoaWRkZW5TZWdzOiBwcm9wcy5oaWRkZW5TZWdzLCBleHRyYURhdGVTcGFuOiBwcm9wcy5leHRyYURhdGVTcGFuLCBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2U6IHByb3BzLnRvZGF5UmFuZ2UsIHBvcG92ZXJDb250ZW50OiAoKSA9PiByZW5kZXJQbGFpbkZnU2Vncyhwcm9wcy5oaWRkZW5TZWdzLCBwcm9wcyksIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlck1vcmVMaW5rSW5uZXIsIGZvcmNlVGltZWQ6IHRydWUgfSwgKElubmVyQ29udGVudCkgPT4gKGNyZWF0ZUVsZW1lbnQoSW5uZXJDb250ZW50LCB7IGVsVGFnOiBcImRpdlwiLCBlbENsYXNzZXM6IFsnZmMtdGltZWdyaWQtbW9yZS1saW5rLWlubmVyJywgJ2ZjLXN0aWNreSddIH0pKSkpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlbmRlck1vcmVMaW5rSW5uZXIocHJvcHMpIHtcbiAgICByZXR1cm4gcHJvcHMuc2hvcnRUZXh0O1xufVxuXG4vLyBzZWdJbnB1dHMgYXNzdW1lZCBzb3J0ZWRcbmZ1bmN0aW9uIGJ1aWxkUG9zaXRpb25pbmcoc2VnSW5wdXRzLCBzdHJpY3RPcmRlciwgbWF4U3RhY2tDbnQpIHtcbiAgICBsZXQgaGllcmFyY2h5ID0gbmV3IFNlZ0hpZXJhcmNoeSgpO1xuICAgIGlmIChzdHJpY3RPcmRlciAhPSBudWxsKSB7XG4gICAgICAgIGhpZXJhcmNoeS5zdHJpY3RPcmRlciA9IHN0cmljdE9yZGVyO1xuICAgIH1cbiAgICBpZiAobWF4U3RhY2tDbnQgIT0gbnVsbCkge1xuICAgICAgICBoaWVyYXJjaHkubWF4U3RhY2tDbnQgPSBtYXhTdGFja0NudDtcbiAgICB9XG4gICAgbGV0IGhpZGRlbkVudHJpZXMgPSBoaWVyYXJjaHkuYWRkU2VncyhzZWdJbnB1dHMpO1xuICAgIGxldCBoaWRkZW5Hcm91cHMgPSBncm91cEludGVyc2VjdGluZ0VudHJpZXMoaGlkZGVuRW50cmllcyk7XG4gICAgbGV0IHdlYiA9IGJ1aWxkV2ViKGhpZXJhcmNoeSk7XG4gICAgd2ViID0gc3RyZXRjaFdlYih3ZWIsIDEpOyAvLyBhbGwgbGV2ZWxDb29yZHMvdGhpY2tuZXNzIHdpbGwgaGF2ZSAwLjAtMS4wXG4gICAgbGV0IHNlZ1JlY3RzID0gd2ViVG9SZWN0cyh3ZWIpO1xuICAgIHJldHVybiB7IHNlZ1JlY3RzLCBoaWRkZW5Hcm91cHMgfTtcbn1cbmZ1bmN0aW9uIGJ1aWxkV2ViKGhpZXJhcmNoeSkge1xuICAgIGNvbnN0IHsgZW50cmllc0J5TGV2ZWwgfSA9IGhpZXJhcmNoeTtcbiAgICBjb25zdCBidWlsZE5vZGUgPSBjYWNoZWFibGUoKGxldmVsLCBsYXRlcmFsKSA9PiBsZXZlbCArICc6JyArIGxhdGVyYWwsIChsZXZlbCwgbGF0ZXJhbCkgPT4ge1xuICAgICAgICBsZXQgc2libGluZ1JhbmdlID0gZmluZE5leHRMZXZlbFNlZ3MoaGllcmFyY2h5LCBsZXZlbCwgbGF0ZXJhbCk7XG4gICAgICAgIGxldCBuZXh0TGV2ZWxSZXMgPSBidWlsZE5vZGVzKHNpYmxpbmdSYW5nZSwgYnVpbGROb2RlKTtcbiAgICAgICAgbGV0IGVudHJ5ID0gZW50cmllc0J5TGV2ZWxbbGV2ZWxdW2xhdGVyYWxdO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBlbnRyeSksIHsgbmV4dExldmVsTm9kZXM6IG5leHRMZXZlbFJlc1swXSB9KSxcbiAgICAgICAgICAgIGVudHJ5LnRoaWNrbmVzcyArIG5leHRMZXZlbFJlc1sxXSwgLy8gdGhlIHByZXNzdXJlIGJ1aWxkc1xuICAgICAgICBdO1xuICAgIH0pO1xuICAgIHJldHVybiBidWlsZE5vZGVzKGVudHJpZXNCeUxldmVsLmxlbmd0aFxuICAgICAgICA/IHsgbGV2ZWw6IDAsIGxhdGVyYWxTdGFydDogMCwgbGF0ZXJhbEVuZDogZW50cmllc0J5TGV2ZWxbMF0ubGVuZ3RoIH1cbiAgICAgICAgOiBudWxsLCBidWlsZE5vZGUpWzBdO1xufVxuZnVuY3Rpb24gYnVpbGROb2RlcyhzaWJsaW5nUmFuZ2UsIGJ1aWxkTm9kZSkge1xuICAgIGlmICghc2libGluZ1JhbmdlKSB7XG4gICAgICAgIHJldHVybiBbW10sIDBdO1xuICAgIH1cbiAgICBsZXQgeyBsZXZlbCwgbGF0ZXJhbFN0YXJ0LCBsYXRlcmFsRW5kIH0gPSBzaWJsaW5nUmFuZ2U7XG4gICAgbGV0IGxhdGVyYWwgPSBsYXRlcmFsU3RhcnQ7XG4gICAgbGV0IHBhaXJzID0gW107XG4gICAgd2hpbGUgKGxhdGVyYWwgPCBsYXRlcmFsRW5kKSB7XG4gICAgICAgIHBhaXJzLnB1c2goYnVpbGROb2RlKGxldmVsLCBsYXRlcmFsKSk7XG4gICAgICAgIGxhdGVyYWwgKz0gMTtcbiAgICB9XG4gICAgcGFpcnMuc29ydChjbXBEZXNjUHJlc3N1cmVzKTtcbiAgICByZXR1cm4gW1xuICAgICAgICBwYWlycy5tYXAoZXh0cmFjdE5vZGUpLFxuICAgICAgICBwYWlyc1swXVsxXSwgLy8gZmlyc3QgaXRlbSdzIHByZXNzdXJlXG4gICAgXTtcbn1cbmZ1bmN0aW9uIGNtcERlc2NQcmVzc3VyZXMoYSwgYikge1xuICAgIHJldHVybiBiWzFdIC0gYVsxXTtcbn1cbmZ1bmN0aW9uIGV4dHJhY3ROb2RlKGEpIHtcbiAgICByZXR1cm4gYVswXTtcbn1cbmZ1bmN0aW9uIGZpbmROZXh0TGV2ZWxTZWdzKGhpZXJhcmNoeSwgc3ViamVjdExldmVsLCBzdWJqZWN0TGF0ZXJhbCkge1xuICAgIGxldCB7IGxldmVsQ29vcmRzLCBlbnRyaWVzQnlMZXZlbCB9ID0gaGllcmFyY2h5O1xuICAgIGxldCBzdWJqZWN0RW50cnkgPSBlbnRyaWVzQnlMZXZlbFtzdWJqZWN0TGV2ZWxdW3N1YmplY3RMYXRlcmFsXTtcbiAgICBsZXQgYWZ0ZXJTdWJqZWN0ID0gbGV2ZWxDb29yZHNbc3ViamVjdExldmVsXSArIHN1YmplY3RFbnRyeS50aGlja25lc3M7XG4gICAgbGV0IGxldmVsQ250ID0gbGV2ZWxDb29yZHMubGVuZ3RoO1xuICAgIGxldCBsZXZlbCA9IHN1YmplY3RMZXZlbDtcbiAgICAvLyBza2lwIHBhc3QgbGV2ZWxzIHRoYXQgYXJlIHRvbyBoaWdoIHVwXG4gICAgZm9yICg7IGxldmVsIDwgbGV2ZWxDbnQgJiYgbGV2ZWxDb29yZHNbbGV2ZWxdIDwgYWZ0ZXJTdWJqZWN0OyBsZXZlbCArPSAxKVxuICAgICAgICA7IC8vIGRvIG5vdGhpbmdcbiAgICBmb3IgKDsgbGV2ZWwgPCBsZXZlbENudDsgbGV2ZWwgKz0gMSkge1xuICAgICAgICBsZXQgZW50cmllcyA9IGVudHJpZXNCeUxldmVsW2xldmVsXTtcbiAgICAgICAgbGV0IGVudHJ5O1xuICAgICAgICBsZXQgc2VhcmNoSW5kZXggPSBiaW5hcnlTZWFyY2goZW50cmllcywgc3ViamVjdEVudHJ5LnNwYW4uc3RhcnQsIGdldEVudHJ5U3BhbkVuZCk7XG4gICAgICAgIGxldCBsYXRlcmFsU3RhcnQgPSBzZWFyY2hJbmRleFswXSArIHNlYXJjaEluZGV4WzFdOyAvLyBpZiBleGFjdCBtYXRjaCAod2hpY2ggZG9lc24ndCBjb2xsaWRlKSwgZ28gdG8gbmV4dCBvbmVcbiAgICAgICAgbGV0IGxhdGVyYWxFbmQgPSBsYXRlcmFsU3RhcnQ7XG4gICAgICAgIHdoaWxlICggLy8gbG9vcCB0aHJvdWdoIGVudHJpZXMgdGhhdCBob3Jpem9udGFsbHkgaW50ZXJzZWN0XG4gICAgICAgIChlbnRyeSA9IGVudHJpZXNbbGF0ZXJhbEVuZF0pICYmIC8vIGJ1dCBub3QgcGFzdCB0aGUgd2hvbGUgc2VnIGxpc3RcbiAgICAgICAgICAgIGVudHJ5LnNwYW4uc3RhcnQgPCBzdWJqZWN0RW50cnkuc3Bhbi5lbmQpIHtcbiAgICAgICAgICAgIGxhdGVyYWxFbmQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGF0ZXJhbFN0YXJ0IDwgbGF0ZXJhbEVuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgbGV2ZWwsIGxhdGVyYWxTdGFydCwgbGF0ZXJhbEVuZCB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gc3RyZXRjaFdlYih0b3BMZXZlbE5vZGVzLCB0b3RhbFRoaWNrbmVzcykge1xuICAgIGNvbnN0IHN0cmV0Y2hOb2RlID0gY2FjaGVhYmxlKChub2RlLCBzdGFydENvb3JkLCBwcmV2VGhpY2tuZXNzKSA9PiBidWlsZEVudHJ5S2V5KG5vZGUpLCAobm9kZSwgc3RhcnRDb29yZCwgcHJldlRoaWNrbmVzcykgPT4ge1xuICAgICAgICBsZXQgeyBuZXh0TGV2ZWxOb2RlcywgdGhpY2tuZXNzIH0gPSBub2RlO1xuICAgICAgICBsZXQgYWxsVGhpY2tuZXNzID0gdGhpY2tuZXNzICsgcHJldlRoaWNrbmVzcztcbiAgICAgICAgbGV0IHRoaWNrbmVzc0ZyYWN0aW9uID0gdGhpY2tuZXNzIC8gYWxsVGhpY2tuZXNzO1xuICAgICAgICBsZXQgZW5kQ29vcmQ7XG4gICAgICAgIGxldCBuZXdDaGlsZHJlbiA9IFtdO1xuICAgICAgICBpZiAoIW5leHRMZXZlbE5vZGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgZW5kQ29vcmQgPSB0b3RhbFRoaWNrbmVzcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvciAobGV0IGNoaWxkTm9kZSBvZiBuZXh0TGV2ZWxOb2Rlcykge1xuICAgICAgICAgICAgICAgIGlmIChlbmRDb29yZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCByZXMgPSBzdHJldGNoTm9kZShjaGlsZE5vZGUsIHN0YXJ0Q29vcmQsIGFsbFRoaWNrbmVzcyk7XG4gICAgICAgICAgICAgICAgICAgIGVuZENvb3JkID0gcmVzWzBdO1xuICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKHJlc1sxXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsZXQgcmVzID0gc3RyZXRjaE5vZGUoY2hpbGROb2RlLCBlbmRDb29yZCwgMCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gocmVzWzFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IG5ld1RoaWNrbmVzcyA9IChlbmRDb29yZCAtIHN0YXJ0Q29vcmQpICogdGhpY2tuZXNzRnJhY3Rpb247XG4gICAgICAgIHJldHVybiBbZW5kQ29vcmQgLSBuZXdUaGlja25lc3MsIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgbm9kZSksIHsgdGhpY2tuZXNzOiBuZXdUaGlja25lc3MsIG5leHRMZXZlbE5vZGVzOiBuZXdDaGlsZHJlbiB9KV07XG4gICAgfSk7XG4gICAgcmV0dXJuIHRvcExldmVsTm9kZXMubWFwKChub2RlKSA9PiBzdHJldGNoTm9kZShub2RlLCAwLCAwKVsxXSk7XG59XG4vLyBub3Qgc29ydGVkIGluIGFueSBwYXJ0aWN1bGFyIG9yZGVyXG5mdW5jdGlvbiB3ZWJUb1JlY3RzKHRvcExldmVsTm9kZXMpIHtcbiAgICBsZXQgcmVjdHMgPSBbXTtcbiAgICBjb25zdCBwcm9jZXNzTm9kZSA9IGNhY2hlYWJsZSgobm9kZSwgbGV2ZWxDb29yZCwgc3RhY2tEZXB0aCkgPT4gYnVpbGRFbnRyeUtleShub2RlKSwgKG5vZGUsIGxldmVsQ29vcmQsIHN0YWNrRGVwdGgpID0+IHtcbiAgICAgICAgbGV0IHJlY3QgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIG5vZGUpLCB7IGxldmVsQ29vcmQsXG4gICAgICAgICAgICBzdGFja0RlcHRoLCBzdGFja0ZvcndhcmQ6IDAgfSk7XG4gICAgICAgIHJlY3RzLnB1c2gocmVjdCk7XG4gICAgICAgIHJldHVybiAocmVjdC5zdGFja0ZvcndhcmQgPSBwcm9jZXNzTm9kZXMobm9kZS5uZXh0TGV2ZWxOb2RlcywgbGV2ZWxDb29yZCArIG5vZGUudGhpY2tuZXNzLCBzdGFja0RlcHRoICsgMSkgKyAxKTtcbiAgICB9KTtcbiAgICBmdW5jdGlvbiBwcm9jZXNzTm9kZXMobm9kZXMsIGxldmVsQ29vcmQsIHN0YWNrRGVwdGgpIHtcbiAgICAgICAgbGV0IHN0YWNrRm9yd2FyZCA9IDA7XG4gICAgICAgIGZvciAobGV0IG5vZGUgb2Ygbm9kZXMpIHtcbiAgICAgICAgICAgIHN0YWNrRm9yd2FyZCA9IE1hdGgubWF4KHByb2Nlc3NOb2RlKG5vZGUsIGxldmVsQ29vcmQsIHN0YWNrRGVwdGgpLCBzdGFja0ZvcndhcmQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdGFja0ZvcndhcmQ7XG4gICAgfVxuICAgIHByb2Nlc3NOb2Rlcyh0b3BMZXZlbE5vZGVzLCAwLCAwKTtcbiAgICByZXR1cm4gcmVjdHM7IC8vIFRPRE86IHNvcnQgcmVjdHMgYnkgbGV2ZWxDb29yZCB0byBiZSBjb25zaXN0ZW50IHdpdGggdG9SZWN0cz9cbn1cbi8vIFRPRE86IG1vdmUgdG8gZ2VuZXJhbCB1dGlsXG5mdW5jdGlvbiBjYWNoZWFibGUoa2V5RnVuYywgd29ya0Z1bmMpIHtcbiAgICBjb25zdCBjYWNoZSA9IHt9O1xuICAgIHJldHVybiAoLi4uYXJncykgPT4ge1xuICAgICAgICBsZXQga2V5ID0ga2V5RnVuYyguLi5hcmdzKTtcbiAgICAgICAgcmV0dXJuIChrZXkgaW4gY2FjaGUpXG4gICAgICAgICAgICA/IGNhY2hlW2tleV1cbiAgICAgICAgICAgIDogKGNhY2hlW2tleV0gPSB3b3JrRnVuYyguLi5hcmdzKSk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZVNlZ1ZDb29yZHMoc2VncywgY29sRGF0ZSwgc2xhdENvb3JkcyA9IG51bGwsIGV2ZW50TWluSGVpZ2h0ID0gMCkge1xuICAgIGxldCB2Y29vcmRzID0gW107XG4gICAgaWYgKHNsYXRDb29yZHMpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBsZXQgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgIGxldCBzcGFuU3RhcnQgPSBzbGF0Q29vcmRzLmNvbXB1dGVEYXRlVG9wKHNlZy5zdGFydCwgY29sRGF0ZSk7XG4gICAgICAgICAgICBsZXQgc3BhbkVuZCA9IE1hdGgubWF4KHNwYW5TdGFydCArIChldmVudE1pbkhlaWdodCB8fCAwKSwgLy8gOihcbiAgICAgICAgICAgIHNsYXRDb29yZHMuY29tcHV0ZURhdGVUb3Aoc2VnLmVuZCwgY29sRGF0ZSkpO1xuICAgICAgICAgICAgdmNvb3Jkcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBzdGFydDogTWF0aC5yb3VuZChzcGFuU3RhcnQpLFxuICAgICAgICAgICAgICAgIGVuZDogTWF0aC5yb3VuZChzcGFuRW5kKSwgLy9cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2Y29vcmRzO1xufVxuZnVuY3Rpb24gY29tcHV0ZUZnU2VnUGxhY2VtZW50cyhzZWdzLCBzZWdWQ29vcmRzLCAvLyBtaWdodCBub3QgaGF2ZSBmb3IgZXZlcnkgc2VnXG5ldmVudE9yZGVyU3RyaWN0LCBldmVudE1heFN0YWNrKSB7XG4gICAgbGV0IHNlZ0lucHV0cyA9IFtdO1xuICAgIGxldCBkdW1iU2VncyA9IFtdOyAvLyBzZWdzIHdpdGhvdXQgY29vcmRzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGxldCB2Y29vcmRzID0gc2VnVkNvb3Jkc1tpXTtcbiAgICAgICAgaWYgKHZjb29yZHMpIHtcbiAgICAgICAgICAgIHNlZ0lucHV0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgICAgICB0aGlja25lc3M6IDEsXG4gICAgICAgICAgICAgICAgc3BhbjogdmNvb3JkcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZHVtYlNlZ3MucHVzaChzZWdzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQgeyBzZWdSZWN0cywgaGlkZGVuR3JvdXBzIH0gPSBidWlsZFBvc2l0aW9uaW5nKHNlZ0lucHV0cywgZXZlbnRPcmRlclN0cmljdCwgZXZlbnRNYXhTdGFjayk7XG4gICAgbGV0IHNlZ1BsYWNlbWVudHMgPSBbXTtcbiAgICBmb3IgKGxldCBzZWdSZWN0IG9mIHNlZ1JlY3RzKSB7XG4gICAgICAgIHNlZ1BsYWNlbWVudHMucHVzaCh7XG4gICAgICAgICAgICBzZWc6IHNlZ3Nbc2VnUmVjdC5pbmRleF0sXG4gICAgICAgICAgICByZWN0OiBzZWdSZWN0LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZm9yIChsZXQgZHVtYlNlZyBvZiBkdW1iU2Vncykge1xuICAgICAgICBzZWdQbGFjZW1lbnRzLnB1c2goeyBzZWc6IGR1bWJTZWcsIHJlY3Q6IG51bGwgfSk7XG4gICAgfVxuICAgIHJldHVybiB7IHNlZ1BsYWNlbWVudHMsIGhpZGRlbkdyb3VwcyB9O1xufVxuXG5jb25zdCBERUZBVUxUX1RJTUVfRk9STUFUID0gY3JlYXRlRm9ybWF0dGVyKHtcbiAgICBob3VyOiAnbnVtZXJpYycsXG4gICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgbWVyaWRpZW06IGZhbHNlLFxufSk7XG5jbGFzcyBUaW1lQ29sRXZlbnQgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICByZW5kZXIoKSB7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChTdGFuZGFyZEV2ZW50LCBPYmplY3QuYXNzaWduKHt9LCB0aGlzLnByb3BzLCB7IGVsQ2xhc3NlczogW1xuICAgICAgICAgICAgICAgICdmYy10aW1lZ3JpZC1ldmVudCcsXG4gICAgICAgICAgICAgICAgJ2ZjLXYtZXZlbnQnLFxuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuaXNTaG9ydCAmJiAnZmMtdGltZWdyaWQtZXZlbnQtc2hvcnQnLFxuICAgICAgICAgICAgXSwgZGVmYXVsdFRpbWVGb3JtYXQ6IERFRkFVTFRfVElNRV9GT1JNQVQgfSkpKTtcbiAgICB9XG59XG5cbmNsYXNzIFRpbWVDb2wgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5zb3J0RXZlbnRTZWdzID0gbWVtb2l6ZShzb3J0RXZlbnRTZWdzKTtcbiAgICB9XG4gICAgLy8gVE9ETzogbWVtb2l6ZSBldmVudC1wbGFjZW1lbnQ/XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgeyBwcm9wcywgY29udGV4dCB9ID0gdGhpcztcbiAgICAgICAgbGV0IHsgb3B0aW9ucyB9ID0gY29udGV4dDtcbiAgICAgICAgbGV0IGlzU2VsZWN0TWlycm9yID0gb3B0aW9ucy5zZWxlY3RNaXJyb3I7XG4gICAgICAgIGxldCBtaXJyb3JTZWdzID0gLy8geXVja1xuICAgICAgICAgKHByb3BzLmV2ZW50RHJhZyAmJiBwcm9wcy5ldmVudERyYWcuc2VncykgfHxcbiAgICAgICAgICAgIChwcm9wcy5ldmVudFJlc2l6ZSAmJiBwcm9wcy5ldmVudFJlc2l6ZS5zZWdzKSB8fFxuICAgICAgICAgICAgKGlzU2VsZWN0TWlycm9yICYmIHByb3BzLmRhdGVTZWxlY3Rpb25TZWdzKSB8fFxuICAgICAgICAgICAgW107XG4gICAgICAgIGxldCBpbnRlcmFjdGlvbkFmZmVjdGVkSW5zdGFuY2VzID0gLy8gVE9ETzogbWVzc3kgd2F5IHRvIGNvbXB1dGUgdGhpc1xuICAgICAgICAgKHByb3BzLmV2ZW50RHJhZyAmJiBwcm9wcy5ldmVudERyYWcuYWZmZWN0ZWRJbnN0YW5jZXMpIHx8XG4gICAgICAgICAgICAocHJvcHMuZXZlbnRSZXNpemUgJiYgcHJvcHMuZXZlbnRSZXNpemUuYWZmZWN0ZWRJbnN0YW5jZXMpIHx8XG4gICAgICAgICAgICB7fTtcbiAgICAgICAgbGV0IHNvcnRlZEZnU2VncyA9IHRoaXMuc29ydEV2ZW50U2Vncyhwcm9wcy5mZ0V2ZW50U2Vncywgb3B0aW9ucy5ldmVudE9yZGVyKTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KERheUNlbGxDb250YWluZXIsIHsgZWxUYWc6IFwidGRcIiwgZWxSZWY6IHByb3BzLmVsUmVmLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAnZmMtdGltZWdyaWQtY29sJyxcbiAgICAgICAgICAgICAgICAuLi4ocHJvcHMuZXh0cmFDbGFzc05hbWVzIHx8IFtdKSxcbiAgICAgICAgICAgIF0sIGVsQXR0cnM6IE9iamVjdC5hc3NpZ24oeyByb2xlOiAnZ3JpZGNlbGwnIH0sIHByb3BzLmV4dHJhRGF0YUF0dHJzKSwgZGF0ZTogcHJvcHMuZGF0ZSwgZGF0ZVByb2ZpbGU6IHByb3BzLmRhdGVQcm9maWxlLCB0b2RheVJhbmdlOiBwcm9wcy50b2RheVJhbmdlLCBleHRyYVJlbmRlclByb3BzOiBwcm9wcy5leHRyYVJlbmRlclByb3BzIH0sIChJbm5lckNvbnRlbnQpID0+IChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLWNvbC1mcmFtZVwiIH0sXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLWNvbC1iZ1wiIH0sXG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJGaWxsU2Vncyhwcm9wcy5idXNpbmVzc0hvdXJTZWdzLCAnbm9uLWJ1c2luZXNzJyksXG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJGaWxsU2Vncyhwcm9wcy5iZ0V2ZW50U2VncywgJ2JnLWV2ZW50JyksXG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJGaWxsU2Vncyhwcm9wcy5kYXRlU2VsZWN0aW9uU2VncywgJ2hpZ2hsaWdodCcpKSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtdGltZWdyaWQtY29sLWV2ZW50c1wiIH0sIHRoaXMucmVuZGVyRmdTZWdzKHNvcnRlZEZnU2VncywgaW50ZXJhY3Rpb25BZmZlY3RlZEluc3RhbmNlcywgZmFsc2UsIGZhbHNlLCBmYWxzZSkpLFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy10aW1lZ3JpZC1jb2wtZXZlbnRzXCIgfSwgdGhpcy5yZW5kZXJGZ1NlZ3MobWlycm9yU2Vncywge30sIEJvb2xlYW4ocHJvcHMuZXZlbnREcmFnKSwgQm9vbGVhbihwcm9wcy5ldmVudFJlc2l6ZSksIEJvb2xlYW4oaXNTZWxlY3RNaXJyb3IpLCAnbWlycm9yJykpLFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy10aW1lZ3JpZC1ub3ctaW5kaWNhdG9yLWNvbnRhaW5lclwiIH0sIHRoaXMucmVuZGVyTm93SW5kaWNhdG9yKHByb3BzLm5vd0luZGljYXRvclNlZ3MpKSxcbiAgICAgICAgICAgIGhhc0N1c3RvbURheUNlbGxDb250ZW50KG9wdGlvbnMpICYmIChjcmVhdGVFbGVtZW50KElubmVyQ29udGVudCwgeyBlbFRhZzogXCJkaXZcIiwgZWxDbGFzc2VzOiBbJ2ZjLXRpbWVncmlkLWNvbC1taXNjJ10gfSkpKSkpKTtcbiAgICB9XG4gICAgcmVuZGVyRmdTZWdzKHNvcnRlZEZnU2Vncywgc2VnSXNJbnZpc2libGUsIGlzRHJhZ2dpbmcsIGlzUmVzaXppbmcsIGlzRGF0ZVNlbGVjdGluZywgZm9yY2VkS2V5KSB7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBpZiAocHJvcHMuZm9yUHJpbnQpIHtcbiAgICAgICAgICAgIHJldHVybiByZW5kZXJQbGFpbkZnU2Vncyhzb3J0ZWRGZ1NlZ3MsIHByb3BzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJQb3NpdGlvbmVkRmdTZWdzKHNvcnRlZEZnU2Vncywgc2VnSXNJbnZpc2libGUsIGlzRHJhZ2dpbmcsIGlzUmVzaXppbmcsIGlzRGF0ZVNlbGVjdGluZywgZm9yY2VkS2V5KTtcbiAgICB9XG4gICAgcmVuZGVyUG9zaXRpb25lZEZnU2VncyhzZWdzLCAvLyBpZiBub3QgbWlycm9yLCBuZWVkcyB0byBiZSBzb3J0ZWRcbiAgICBzZWdJc0ludmlzaWJsZSwgaXNEcmFnZ2luZywgaXNSZXNpemluZywgaXNEYXRlU2VsZWN0aW5nLCBmb3JjZWRLZXkpIHtcbiAgICAgICAgbGV0IHsgZXZlbnRNYXhTdGFjaywgZXZlbnRTaG9ydEhlaWdodCwgZXZlbnRPcmRlclN0cmljdCwgZXZlbnRNaW5IZWlnaHQgfSA9IHRoaXMuY29udGV4dC5vcHRpb25zO1xuICAgICAgICBsZXQgeyBkYXRlLCBzbGF0Q29vcmRzLCBldmVudFNlbGVjdGlvbiwgdG9kYXlSYW5nZSwgbm93RGF0ZSB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IGlzTWlycm9yID0gaXNEcmFnZ2luZyB8fCBpc1Jlc2l6aW5nIHx8IGlzRGF0ZVNlbGVjdGluZztcbiAgICAgICAgbGV0IHNlZ1ZDb29yZHMgPSBjb21wdXRlU2VnVkNvb3JkcyhzZWdzLCBkYXRlLCBzbGF0Q29vcmRzLCBldmVudE1pbkhlaWdodCk7XG4gICAgICAgIGxldCB7IHNlZ1BsYWNlbWVudHMsIGhpZGRlbkdyb3VwcyB9ID0gY29tcHV0ZUZnU2VnUGxhY2VtZW50cyhzZWdzLCBzZWdWQ29vcmRzLCBldmVudE9yZGVyU3RyaWN0LCBldmVudE1heFN0YWNrKTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJIaWRkZW5Hcm91cHMoaGlkZGVuR3JvdXBzLCBzZWdzKSxcbiAgICAgICAgICAgIHNlZ1BsYWNlbWVudHMubWFwKChzZWdQbGFjZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgeyBzZWcsIHJlY3QgfSA9IHNlZ1BsYWNlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgaW5zdGFuY2VJZCA9IHNlZy5ldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWQ7XG4gICAgICAgICAgICAgICAgbGV0IGlzVmlzaWJsZSA9IGlzTWlycm9yIHx8IEJvb2xlYW4oIXNlZ0lzSW52aXNpYmxlW2luc3RhbmNlSWRdICYmIHJlY3QpO1xuICAgICAgICAgICAgICAgIGxldCB2U3R5bGUgPSBjb21wdXRlU2VnVlN0eWxlKHJlY3QgJiYgcmVjdC5zcGFuKTtcbiAgICAgICAgICAgICAgICBsZXQgaFN0eWxlID0gKCFpc01pcnJvciAmJiByZWN0KSA/IHRoaXMuY29tcHV0ZVNlZ0hTdHlsZShyZWN0KSA6IHsgbGVmdDogMCwgcmlnaHQ6IDAgfTtcbiAgICAgICAgICAgICAgICBsZXQgaXNJbnNldCA9IEJvb2xlYW4ocmVjdCkgJiYgcmVjdC5zdGFja0ZvcndhcmQgPiAwO1xuICAgICAgICAgICAgICAgIGxldCBpc1Nob3J0ID0gQm9vbGVhbihyZWN0KSAmJiAocmVjdC5zcGFuLmVuZCAtIHJlY3Quc3Bhbi5zdGFydCkgPCBldmVudFNob3J0SGVpZ2h0OyAvLyBsb29rIGF0IG90aGVyIHBsYWNlcyBmb3IgdGhpcyBwcm9ibGVtXG4gICAgICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiAnZmMtdGltZWdyaWQtZXZlbnQtaGFybmVzcycgK1xuICAgICAgICAgICAgICAgICAgICAgICAgKGlzSW5zZXQgPyAnIGZjLXRpbWVncmlkLWV2ZW50LWhhcm5lc3MtaW5zZXQnIDogJycpLCBrZXk6IGZvcmNlZEtleSB8fCBpbnN0YW5jZUlkLCBzdHlsZTogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHsgdmlzaWJpbGl0eTogaXNWaXNpYmxlID8gJycgOiAnaGlkZGVuJyB9LCB2U3R5bGUpLCBoU3R5bGUpIH0sXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoVGltZUNvbEV2ZW50LCBPYmplY3QuYXNzaWduKHsgc2VnOiBzZWcsIGlzRHJhZ2dpbmc6IGlzRHJhZ2dpbmcsIGlzUmVzaXppbmc6IGlzUmVzaXppbmcsIGlzRGF0ZVNlbGVjdGluZzogaXNEYXRlU2VsZWN0aW5nLCBpc1NlbGVjdGVkOiBpbnN0YW5jZUlkID09PSBldmVudFNlbGVjdGlvbiwgaXNTaG9ydDogaXNTaG9ydCB9LCBnZXRTZWdNZXRhKHNlZywgdG9kYXlSYW5nZSwgbm93RGF0ZSkpKSkpO1xuICAgICAgICAgICAgfSkpKTtcbiAgICB9XG4gICAgLy8gd2lsbCBhbHJlYWR5IGhhdmUgZXZlbnRNaW5IZWlnaHQgYXBwbGllZCBiZWNhdXNlIHNlZ0lucHV0cyBhbHJlYWR5IGhhZCBpdFxuICAgIHJlbmRlckhpZGRlbkdyb3VwcyhoaWRkZW5Hcm91cHMsIHNlZ3MpIHtcbiAgICAgICAgbGV0IHsgZXh0cmFEYXRlU3BhbiwgZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2UsIG5vd0RhdGUsIGV2ZW50U2VsZWN0aW9uLCBldmVudERyYWcsIGV2ZW50UmVzaXplIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoRnJhZ21lbnQsIG51bGwsIGhpZGRlbkdyb3Vwcy5tYXAoKGhpZGRlbkdyb3VwKSA9PiB7XG4gICAgICAgICAgICBsZXQgcG9zaXRpb25Dc3MgPSBjb21wdXRlU2VnVlN0eWxlKGhpZGRlbkdyb3VwLnNwYW4pO1xuICAgICAgICAgICAgbGV0IGhpZGRlblNlZ3MgPSBjb21waWxlU2Vnc0Zyb21FbnRyaWVzKGhpZGRlbkdyb3VwLmVudHJpZXMsIHNlZ3MpO1xuICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFRpbWVDb2xNb3JlTGluaywgeyBrZXk6IGJ1aWxkSXNvU3RyaW5nKGNvbXB1dGVFYXJsaWVzdFNlZ1N0YXJ0KGhpZGRlblNlZ3MpKSwgaGlkZGVuU2VnczogaGlkZGVuU2VncywgdG9wOiBwb3NpdGlvbkNzcy50b3AsIGJvdHRvbTogcG9zaXRpb25Dc3MuYm90dG9tLCBleHRyYURhdGVTcGFuOiBleHRyYURhdGVTcGFuLCBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIHRvZGF5UmFuZ2U6IHRvZGF5UmFuZ2UsIG5vd0RhdGU6IG5vd0RhdGUsIGV2ZW50U2VsZWN0aW9uOiBldmVudFNlbGVjdGlvbiwgZXZlbnREcmFnOiBldmVudERyYWcsIGV2ZW50UmVzaXplOiBldmVudFJlc2l6ZSB9KSk7XG4gICAgICAgIH0pKSk7XG4gICAgfVxuICAgIHJlbmRlckZpbGxTZWdzKHNlZ3MsIGZpbGxUeXBlKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBsZXQgc2VnVkNvb3JkcyA9IGNvbXB1dGVTZWdWQ29vcmRzKHNlZ3MsIHByb3BzLmRhdGUsIHByb3BzLnNsYXRDb29yZHMsIGNvbnRleHQub3B0aW9ucy5ldmVudE1pbkhlaWdodCk7IC8vIGRvbid0IGFzc3VtZSBhbGwgcG9wdWxhdGVkXG4gICAgICAgIGxldCBjaGlsZHJlbiA9IHNlZ1ZDb29yZHMubWFwKCh2Y29vcmRzLCBpKSA9PiB7XG4gICAgICAgICAgICBsZXQgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGtleTogYnVpbGRFdmVudFJhbmdlS2V5KHNlZy5ldmVudFJhbmdlKSwgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLWJnLWhhcm5lc3NcIiwgc3R5bGU6IGNvbXB1dGVTZWdWU3R5bGUodmNvb3JkcykgfSwgZmlsbFR5cGUgPT09ICdiZy1ldmVudCcgP1xuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoQmdFdmVudCwgT2JqZWN0LmFzc2lnbih7IHNlZzogc2VnIH0sIGdldFNlZ01ldGEoc2VnLCBwcm9wcy50b2RheVJhbmdlLCBwcm9wcy5ub3dEYXRlKSkpIDpcbiAgICAgICAgICAgICAgICByZW5kZXJGaWxsKGZpbGxUeXBlKSkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUVsZW1lbnQoRnJhZ21lbnQsIG51bGwsIGNoaWxkcmVuKTtcbiAgICB9XG4gICAgcmVuZGVyTm93SW5kaWNhdG9yKHNlZ3MpIHtcbiAgICAgICAgbGV0IHsgc2xhdENvb3JkcywgZGF0ZSB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgaWYgKCFzbGF0Q29vcmRzKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2Vncy5tYXAoKHNlZywgaSkgPT4gKGNyZWF0ZUVsZW1lbnQoTm93SW5kaWNhdG9yQ29udGFpbmVyXG4gICAgICAgIC8vIGtleSBkb2Vzbid0IG1hdHRlci4gd2lsbCBvbmx5IGV2ZXIgYmUgb25lXG4gICAgICAgICwgeyBcbiAgICAgICAgICAgIC8vIGtleSBkb2Vzbid0IG1hdHRlci4gd2lsbCBvbmx5IGV2ZXIgYmUgb25lXG4gICAgICAgICAgICBrZXk6IGksIGVsQ2xhc3NlczogWydmYy10aW1lZ3JpZC1ub3ctaW5kaWNhdG9yLWxpbmUnXSwgZWxTdHlsZToge1xuICAgICAgICAgICAgICAgIHRvcDogc2xhdENvb3Jkcy5jb21wdXRlRGF0ZVRvcChzZWcuc3RhcnQsIGRhdGUpLFxuICAgICAgICAgICAgfSwgaXNBeGlzOiBmYWxzZSwgZGF0ZTogZGF0ZSB9KSkpO1xuICAgIH1cbiAgICBjb21wdXRlU2VnSFN0eWxlKHNlZ0hDb29yZHMpIHtcbiAgICAgICAgbGV0IHsgaXNSdGwsIG9wdGlvbnMgfSA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgbGV0IHNob3VsZE92ZXJsYXAgPSBvcHRpb25zLnNsb3RFdmVudE92ZXJsYXA7XG4gICAgICAgIGxldCBuZWFyQ29vcmQgPSBzZWdIQ29vcmRzLmxldmVsQ29vcmQ7IC8vIHRoZSBsZWZ0IHNpZGUgaWYgTFRSLiB0aGUgcmlnaHQgc2lkZSBpZiBSVEwuIGZsb2F0aW5nLXBvaW50XG4gICAgICAgIGxldCBmYXJDb29yZCA9IHNlZ0hDb29yZHMubGV2ZWxDb29yZCArIHNlZ0hDb29yZHMudGhpY2tuZXNzOyAvLyB0aGUgcmlnaHQgc2lkZSBpZiBMVFIuIHRoZSBsZWZ0IHNpZGUgaWYgUlRMLiBmbG9hdGluZy1wb2ludFxuICAgICAgICBsZXQgbGVmdDsgLy8gYW1vdW50IG9mIHNwYWNlIGZyb20gbGVmdCBlZGdlLCBhIGZyYWN0aW9uIG9mIHRoZSB0b3RhbCB3aWR0aFxuICAgICAgICBsZXQgcmlnaHQ7IC8vIGFtb3VudCBvZiBzcGFjZSBmcm9tIHJpZ2h0IGVkZ2UsIGEgZnJhY3Rpb24gb2YgdGhlIHRvdGFsIHdpZHRoXG4gICAgICAgIGlmIChzaG91bGRPdmVybGFwKSB7XG4gICAgICAgICAgICAvLyBkb3VibGUgdGhlIHdpZHRoLCBidXQgZG9uJ3QgZ28gYmV5b25kIHRoZSBtYXhpbXVtIGZvcndhcmQgY29vcmRpbmF0ZSAoMS4wKVxuICAgICAgICAgICAgZmFyQ29vcmQgPSBNYXRoLm1pbigxLCBuZWFyQ29vcmQgKyAoZmFyQ29vcmQgLSBuZWFyQ29vcmQpICogMik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzUnRsKSB7XG4gICAgICAgICAgICBsZWZ0ID0gMSAtIGZhckNvb3JkO1xuICAgICAgICAgICAgcmlnaHQgPSBuZWFyQ29vcmQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZWZ0ID0gbmVhckNvb3JkO1xuICAgICAgICAgICAgcmlnaHQgPSAxIC0gZmFyQ29vcmQ7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHByb3BzID0ge1xuICAgICAgICAgICAgekluZGV4OiBzZWdIQ29vcmRzLnN0YWNrRGVwdGggKyAxLFxuICAgICAgICAgICAgbGVmdDogbGVmdCAqIDEwMCArICclJyxcbiAgICAgICAgICAgIHJpZ2h0OiByaWdodCAqIDEwMCArICclJyxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHNob3VsZE92ZXJsYXAgJiYgIXNlZ0hDb29yZHMuc3RhY2tGb3J3YXJkKSB7XG4gICAgICAgICAgICAvLyBhZGQgcGFkZGluZyB0byB0aGUgZWRnZSBzbyB0aGF0IGZvcndhcmQgc3RhY2tlZCBldmVudHMgZG9uJ3QgY292ZXIgdGhlIHJlc2l6ZXIncyBpY29uXG4gICAgICAgICAgICBwcm9wc1tpc1J0bCA/ICdtYXJnaW5MZWZ0JyA6ICdtYXJnaW5SaWdodCddID0gMTAgKiAyOyAvLyAxMCBpcyBhIGd1ZXNzdGltYXRlIG9mIHRoZSBpY29uJ3Mgd2lkdGhcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVuZGVyUGxhaW5GZ1NlZ3Moc29ydGVkRmdTZWdzLCB7IHRvZGF5UmFuZ2UsIG5vd0RhdGUsIGV2ZW50U2VsZWN0aW9uLCBldmVudERyYWcsIGV2ZW50UmVzaXplIH0pIHtcbiAgICBsZXQgaGlkZGVuSW5zdGFuY2VzID0gKGV2ZW50RHJhZyA/IGV2ZW50RHJhZy5hZmZlY3RlZEluc3RhbmNlcyA6IG51bGwpIHx8XG4gICAgICAgIChldmVudFJlc2l6ZSA/IGV2ZW50UmVzaXplLmFmZmVjdGVkSW5zdGFuY2VzIDogbnVsbCkgfHxcbiAgICAgICAge307XG4gICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLCBzb3J0ZWRGZ1NlZ3MubWFwKChzZWcpID0+IHtcbiAgICAgICAgbGV0IGluc3RhbmNlSWQgPSBzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBrZXk6IGluc3RhbmNlSWQsIHN0eWxlOiB7IHZpc2liaWxpdHk6IGhpZGRlbkluc3RhbmNlc1tpbnN0YW5jZUlkXSA/ICdoaWRkZW4nIDogJycgfSB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChUaW1lQ29sRXZlbnQsIE9iamVjdC5hc3NpZ24oeyBzZWc6IHNlZywgaXNEcmFnZ2luZzogZmFsc2UsIGlzUmVzaXppbmc6IGZhbHNlLCBpc0RhdGVTZWxlY3Rpbmc6IGZhbHNlLCBpc1NlbGVjdGVkOiBpbnN0YW5jZUlkID09PSBldmVudFNlbGVjdGlvbiwgaXNTaG9ydDogZmFsc2UgfSwgZ2V0U2VnTWV0YShzZWcsIHRvZGF5UmFuZ2UsIG5vd0RhdGUpKSkpKTtcbiAgICB9KSkpO1xufVxuZnVuY3Rpb24gY29tcHV0ZVNlZ1ZTdHlsZShzZWdWQ29vcmRzKSB7XG4gICAgaWYgKCFzZWdWQ29vcmRzKSB7XG4gICAgICAgIHJldHVybiB7IHRvcDogJycsIGJvdHRvbTogJycgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiBzZWdWQ29vcmRzLnN0YXJ0LFxuICAgICAgICBib3R0b206IC1zZWdWQ29vcmRzLmVuZCxcbiAgICB9O1xufVxuZnVuY3Rpb24gY29tcGlsZVNlZ3NGcm9tRW50cmllcyhzZWdFbnRyaWVzLCBhbGxTZWdzKSB7XG4gICAgcmV0dXJuIHNlZ0VudHJpZXMubWFwKChzZWdFbnRyeSkgPT4gYWxsU2Vnc1tzZWdFbnRyeS5pbmRleF0pO1xufVxuXG5jbGFzcyBUaW1lQ29sc0NvbnRlbnQgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5zcGxpdEZnRXZlbnRTZWdzID0gbWVtb2l6ZShzcGxpdFNlZ3NCeUNvbCk7XG4gICAgICAgIHRoaXMuc3BsaXRCZ0V2ZW50U2VncyA9IG1lbW9pemUoc3BsaXRTZWdzQnlDb2wpO1xuICAgICAgICB0aGlzLnNwbGl0QnVzaW5lc3NIb3VyU2VncyA9IG1lbW9pemUoc3BsaXRTZWdzQnlDb2wpO1xuICAgICAgICB0aGlzLnNwbGl0Tm93SW5kaWNhdG9yU2VncyA9IG1lbW9pemUoc3BsaXRTZWdzQnlDb2wpO1xuICAgICAgICB0aGlzLnNwbGl0RGF0ZVNlbGVjdGlvblNlZ3MgPSBtZW1vaXplKHNwbGl0U2Vnc0J5Q29sKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50RHJhZyA9IG1lbW9pemUoc3BsaXRJbnRlcmFjdGlvbkJ5Q29sKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50UmVzaXplID0gbWVtb2l6ZShzcGxpdEludGVyYWN0aW9uQnlDb2wpO1xuICAgICAgICB0aGlzLnJvb3RFbFJlZiA9IGNyZWF0ZVJlZigpO1xuICAgICAgICB0aGlzLmNlbGxFbFJlZnMgPSBuZXcgUmVmTWFwKCk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCBub3dJbmRpY2F0b3JUb3AgPSBjb250ZXh0Lm9wdGlvbnMubm93SW5kaWNhdG9yICYmXG4gICAgICAgICAgICBwcm9wcy5zbGF0Q29vcmRzICYmXG4gICAgICAgICAgICBwcm9wcy5zbGF0Q29vcmRzLnNhZmVDb21wdXRlVG9wKHByb3BzLm5vd0RhdGUpOyAvLyBtaWdodCByZXR1cm4gdm9pZFxuICAgICAgICBsZXQgY29sQ250ID0gcHJvcHMuY2VsbHMubGVuZ3RoO1xuICAgICAgICBsZXQgZmdFdmVudFNlZ3NCeVJvdyA9IHRoaXMuc3BsaXRGZ0V2ZW50U2Vncyhwcm9wcy5mZ0V2ZW50U2VncywgY29sQ250KTtcbiAgICAgICAgbGV0IGJnRXZlbnRTZWdzQnlSb3cgPSB0aGlzLnNwbGl0QmdFdmVudFNlZ3MocHJvcHMuYmdFdmVudFNlZ3MsIGNvbENudCk7XG4gICAgICAgIGxldCBidXNpbmVzc0hvdXJTZWdzQnlSb3cgPSB0aGlzLnNwbGl0QnVzaW5lc3NIb3VyU2Vncyhwcm9wcy5idXNpbmVzc0hvdXJTZWdzLCBjb2xDbnQpO1xuICAgICAgICBsZXQgbm93SW5kaWNhdG9yU2Vnc0J5Um93ID0gdGhpcy5zcGxpdE5vd0luZGljYXRvclNlZ3MocHJvcHMubm93SW5kaWNhdG9yU2VncywgY29sQ250KTtcbiAgICAgICAgbGV0IGRhdGVTZWxlY3Rpb25TZWdzQnlSb3cgPSB0aGlzLnNwbGl0RGF0ZVNlbGVjdGlvblNlZ3MocHJvcHMuZGF0ZVNlbGVjdGlvblNlZ3MsIGNvbENudCk7XG4gICAgICAgIGxldCBldmVudERyYWdCeVJvdyA9IHRoaXMuc3BsaXRFdmVudERyYWcocHJvcHMuZXZlbnREcmFnLCBjb2xDbnQpO1xuICAgICAgICBsZXQgZXZlbnRSZXNpemVCeVJvdyA9IHRoaXMuc3BsaXRFdmVudFJlc2l6ZShwcm9wcy5ldmVudFJlc2l6ZSwgY29sQ250KTtcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLWNvbHNcIiwgcmVmOiB0aGlzLnJvb3RFbFJlZiB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRhYmxlXCIsIHsgcm9sZTogXCJwcmVzZW50YXRpb25cIiwgc3R5bGU6IHtcbiAgICAgICAgICAgICAgICAgICAgbWluV2lkdGg6IHByb3BzLnRhYmxlTWluV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBwcm9wcy5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgICAgICB9IH0sXG4gICAgICAgICAgICAgICAgcHJvcHMudGFibGVDb2xHcm91cE5vZGUsXG4gICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRib2R5XCIsIHsgcm9sZTogXCJwcmVzZW50YXRpb25cIiB9LFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwidHJcIiwgeyByb2xlOiBcInJvd1wiIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5heGlzICYmIChjcmVhdGVFbGVtZW50KFwidGRcIiwgeyBcImFyaWEtaGlkZGVuXCI6IHRydWUsIGNsYXNzTmFtZTogXCJmYy10aW1lZ3JpZC1jb2wgZmMtdGltZWdyaWQtYXhpc1wiIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJmYy10aW1lZ3JpZC1jb2wtZnJhbWVcIiB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcImZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItY29udGFpbmVyXCIgfSwgdHlwZW9mIG5vd0luZGljYXRvclRvcCA9PT0gJ251bWJlcicgJiYgKGNyZWF0ZUVsZW1lbnQoTm93SW5kaWNhdG9yQ29udGFpbmVyLCB7IGVsQ2xhc3NlczogWydmYy10aW1lZ3JpZC1ub3ctaW5kaWNhdG9yLWFycm93J10sIGVsU3R5bGU6IHsgdG9wOiBub3dJbmRpY2F0b3JUb3AgfSwgaXNBeGlzOiB0cnVlLCBkYXRlOiBwcm9wcy5ub3dEYXRlIH0pKSkpKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5jZWxscy5tYXAoKGNlbGwsIGkpID0+IChjcmVhdGVFbGVtZW50KFRpbWVDb2wsIHsga2V5OiBjZWxsLmtleSwgZWxSZWY6IHRoaXMuY2VsbEVsUmVmcy5jcmVhdGVSZWYoY2VsbC5rZXkpLCBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsIGRhdGU6IGNlbGwuZGF0ZSwgbm93RGF0ZTogcHJvcHMubm93RGF0ZSwgdG9kYXlSYW5nZTogcHJvcHMudG9kYXlSYW5nZSwgZXh0cmFSZW5kZXJQcm9wczogY2VsbC5leHRyYVJlbmRlclByb3BzLCBleHRyYURhdGFBdHRyczogY2VsbC5leHRyYURhdGFBdHRycywgZXh0cmFDbGFzc05hbWVzOiBjZWxsLmV4dHJhQ2xhc3NOYW1lcywgZXh0cmFEYXRlU3BhbjogY2VsbC5leHRyYURhdGVTcGFuLCBmZ0V2ZW50U2VnczogZmdFdmVudFNlZ3NCeVJvd1tpXSwgYmdFdmVudFNlZ3M6IGJnRXZlbnRTZWdzQnlSb3dbaV0sIGJ1c2luZXNzSG91clNlZ3M6IGJ1c2luZXNzSG91clNlZ3NCeVJvd1tpXSwgbm93SW5kaWNhdG9yU2Vnczogbm93SW5kaWNhdG9yU2Vnc0J5Um93W2ldLCBkYXRlU2VsZWN0aW9uU2VnczogZGF0ZVNlbGVjdGlvblNlZ3NCeVJvd1tpXSwgZXZlbnREcmFnOiBldmVudERyYWdCeVJvd1tpXSwgZXZlbnRSZXNpemU6IGV2ZW50UmVzaXplQnlSb3dbaV0sIHNsYXRDb29yZHM6IHByb3BzLnNsYXRDb29yZHMsIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvbiwgZm9yUHJpbnQ6IHByb3BzLmZvclByaW50IH0pKSkpKSkpKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlQ29vcmRzKCk7XG4gICAgfVxuICAgIGNvbXBvbmVudERpZFVwZGF0ZSgpIHtcbiAgICAgICAgdGhpcy51cGRhdGVDb29yZHMoKTtcbiAgICB9XG4gICAgdXBkYXRlQ29vcmRzKCkge1xuICAgICAgICBsZXQgeyBwcm9wcyB9ID0gdGhpcztcbiAgICAgICAgaWYgKHByb3BzLm9uQ29sQ29vcmRzICYmXG4gICAgICAgICAgICBwcm9wcy5jbGllbnRXaWR0aCAhPT0gbnVsbCAvLyBtZWFucyBzaXppbmcgaGFzIHN0YWJpbGl6ZWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBwcm9wcy5vbkNvbENvb3JkcyhuZXcgUG9zaXRpb25DYWNoZSh0aGlzLnJvb3RFbFJlZi5jdXJyZW50LCBjb2xsZWN0Q2VsbEVscyh0aGlzLmNlbGxFbFJlZnMuY3VycmVudE1hcCwgcHJvcHMuY2VsbHMpLCB0cnVlLCAvLyBob3Jpem9udGFsXG4gICAgICAgICAgICBmYWxzZSkpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gY29sbGVjdENlbGxFbHMoZWxNYXAsIGNlbGxzKSB7XG4gICAgcmV0dXJuIGNlbGxzLm1hcCgoY2VsbCkgPT4gZWxNYXBbY2VsbC5rZXldKTtcbn1cblxuLyogQSBjb21wb25lbnQgdGhhdCByZW5kZXJzIG9uZSBvciBtb3JlIGNvbHVtbnMgb2YgdmVydGljYWwgdGltZSBzbG90c1xuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5jbGFzcyBUaW1lQ29scyBleHRlbmRzIERhdGVDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLnByb2Nlc3NTbG90T3B0aW9ucyA9IG1lbW9pemUocHJvY2Vzc1Nsb3RPcHRpb25zKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHNsYXRDb29yZHM6IG51bGwsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUm9vdEVsID0gKGVsKSA9PiB7XG4gICAgICAgICAgICBpZiAoZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRleHQucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGVsLFxuICAgICAgICAgICAgICAgICAgICBpc0hpdENvbWJvQWxsb3dlZDogdGhpcy5wcm9wcy5pc0hpdENvbWJvQWxsb3dlZCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udGV4dC51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsUmVxdWVzdCA9IChyZXF1ZXN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBvblNjcm9sbFRvcFJlcXVlc3QgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgICAgICBsZXQgeyBzbGF0Q29vcmRzIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICAgICAgaWYgKG9uU2Nyb2xsVG9wUmVxdWVzdCAmJiBzbGF0Q29vcmRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlcXVlc3QudGltZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgdG9wID0gc2xhdENvb3Jkcy5jb21wdXRlVGltZVRvcChyZXF1ZXN0LnRpbWUpO1xuICAgICAgICAgICAgICAgICAgICB0b3AgPSBNYXRoLmNlaWwodG9wKTsgLy8gem9vbSBjYW4gZ2l2ZSB3ZWlyZCBmbG9hdGluZy1wb2ludCB2YWx1ZXMuIHJhdGhlciBzY3JvbGwgYSBsaXR0bGUgYml0IGZ1cnRoZXJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9wICs9IDE7IC8vIHRvIG92ZXJjb21lIHRvcCBib3JkZXIgdGhhdCBzbG90cyBiZXlvbmQgdGhlIGZpcnN0IGhhdmUuIGxvb2tzIGJldHRlclxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG9uU2Nyb2xsVG9wUmVxdWVzdCh0b3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVDb2xDb29yZHMgPSAoY29sQ29vcmRzKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbENvb3JkcyA9IGNvbENvb3JkcztcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVTbGF0Q29vcmRzID0gKHNsYXRDb29yZHMpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBzbGF0Q29vcmRzIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMucHJvcHMub25TbGF0Q29vcmRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5vblNsYXRDb29yZHMoc2xhdENvb3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIHN0YXRlIH0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwiZmMtdGltZWdyaWQtYm9keVwiLCByZWY6IHRoaXMuaGFuZGxlUm9vdEVsLCBzdHlsZToge1xuICAgICAgICAgICAgICAgIC8vIHRoZXNlIHByb3BzIGFyZSBpbXBvcnRhbnQgdG8gZ2l2ZSB0aGlzIHdyYXBwZXIgY29ycmVjdCBkaW1lbnNpb25zIGZvciBpbnRlcmFjdGlvbnNcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBpZiB3ZSBzZXQgaXQgaGVyZSwgY2FuIHdlIGF2b2lkIGdpdmluZyB0byBpbm5lciB0YWJsZXM/XG4gICAgICAgICAgICAgICAgd2lkdGg6IHByb3BzLmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgICAgIG1pbldpZHRoOiBwcm9wcy50YWJsZU1pbldpZHRoLFxuICAgICAgICAgICAgfSB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChUaW1lQ29sc1NsYXRzLCB7IGF4aXM6IHByb3BzLmF4aXMsIGRhdGVQcm9maWxlOiBwcm9wcy5kYXRlUHJvZmlsZSwgc2xhdE1ldGFzOiBwcm9wcy5zbGF0TWV0YXMsIGNsaWVudFdpZHRoOiBwcm9wcy5jbGllbnRXaWR0aCwgbWluSGVpZ2h0OiBwcm9wcy5leHBhbmRSb3dzID8gcHJvcHMuY2xpZW50SGVpZ2h0IDogJycsIHRhYmxlTWluV2lkdGg6IHByb3BzLnRhYmxlTWluV2lkdGgsIHRhYmxlQ29sR3JvdXBOb2RlOiBwcm9wcy5heGlzID8gcHJvcHMudGFibGVDb2xHcm91cE5vZGUgOiBudWxsIC8qIGF4aXMgZGVwZW5kcyBvbiB0aGUgY29sZ3JvdXAncyBzaHJpbmtpbmcgKi8sIG9uQ29vcmRzOiB0aGlzLmhhbmRsZVNsYXRDb29yZHMgfSksXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFRpbWVDb2xzQ29udGVudCwgeyBjZWxsczogcHJvcHMuY2VsbHMsIGF4aXM6IHByb3BzLmF4aXMsIGRhdGVQcm9maWxlOiBwcm9wcy5kYXRlUHJvZmlsZSwgYnVzaW5lc3NIb3VyU2VnczogcHJvcHMuYnVzaW5lc3NIb3VyU2VncywgYmdFdmVudFNlZ3M6IHByb3BzLmJnRXZlbnRTZWdzLCBmZ0V2ZW50U2VnczogcHJvcHMuZmdFdmVudFNlZ3MsIGRhdGVTZWxlY3Rpb25TZWdzOiBwcm9wcy5kYXRlU2VsZWN0aW9uU2VncywgZXZlbnRTZWxlY3Rpb246IHByb3BzLmV2ZW50U2VsZWN0aW9uLCBldmVudERyYWc6IHByb3BzLmV2ZW50RHJhZywgZXZlbnRSZXNpemU6IHByb3BzLmV2ZW50UmVzaXplLCB0b2RheVJhbmdlOiBwcm9wcy50b2RheVJhbmdlLCBub3dEYXRlOiBwcm9wcy5ub3dEYXRlLCBub3dJbmRpY2F0b3JTZWdzOiBwcm9wcy5ub3dJbmRpY2F0b3JTZWdzLCBjbGllbnRXaWR0aDogcHJvcHMuY2xpZW50V2lkdGgsIHRhYmxlTWluV2lkdGg6IHByb3BzLnRhYmxlTWluV2lkdGgsIHRhYmxlQ29sR3JvdXBOb2RlOiBwcm9wcy50YWJsZUNvbEdyb3VwTm9kZSwgc2xhdENvb3Jkczogc3RhdGUuc2xhdENvb3Jkcywgb25Db2xDb29yZHM6IHRoaXMuaGFuZGxlQ29sQ29vcmRzLCBmb3JQcmludDogcHJvcHMuZm9yUHJpbnQgfSkpKTtcbiAgICB9XG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsUmVzcG9uZGVyID0gdGhpcy5jb250ZXh0LmNyZWF0ZVNjcm9sbFJlc3BvbmRlcih0aGlzLmhhbmRsZVNjcm9sbFJlcXVlc3QpO1xuICAgIH1cbiAgICBjb21wb25lbnREaWRVcGRhdGUocHJldlByb3BzKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsUmVzcG9uZGVyLnVwZGF0ZShwcmV2UHJvcHMuZGF0ZVByb2ZpbGUgIT09IHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUpO1xuICAgIH1cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgdGhpcy5zY3JvbGxSZXNwb25kZXIuZGV0YWNoKCk7XG4gICAgfVxuICAgIHF1ZXJ5SGl0KHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3ApIHtcbiAgICAgICAgbGV0IHsgZGF0ZUVudiwgb3B0aW9ucyB9ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBsZXQgeyBjb2xDb29yZHMgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IGRhdGVQcm9maWxlIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBsZXQgeyBzbGF0Q29vcmRzIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICBsZXQgeyBzbmFwRHVyYXRpb24sIHNuYXBzUGVyU2xvdCB9ID0gdGhpcy5wcm9jZXNzU2xvdE9wdGlvbnModGhpcy5wcm9wcy5zbG90RHVyYXRpb24sIG9wdGlvbnMuc25hcER1cmF0aW9uKTtcbiAgICAgICAgbGV0IGNvbEluZGV4ID0gY29sQ29vcmRzLmxlZnRUb0luZGV4KHBvc2l0aW9uTGVmdCk7XG4gICAgICAgIGxldCBzbGF0SW5kZXggPSBzbGF0Q29vcmRzLnBvc2l0aW9ucy50b3BUb0luZGV4KHBvc2l0aW9uVG9wKTtcbiAgICAgICAgaWYgKGNvbEluZGV4ICE9IG51bGwgJiYgc2xhdEluZGV4ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGxldCBjZWxsID0gdGhpcy5wcm9wcy5jZWxsc1tjb2xJbmRleF07XG4gICAgICAgICAgICBsZXQgc2xhdFRvcCA9IHNsYXRDb29yZHMucG9zaXRpb25zLnRvcHNbc2xhdEluZGV4XTtcbiAgICAgICAgICAgIGxldCBzbGF0SGVpZ2h0ID0gc2xhdENvb3Jkcy5wb3NpdGlvbnMuZ2V0SGVpZ2h0KHNsYXRJbmRleCk7XG4gICAgICAgICAgICBsZXQgcGFydGlhbCA9IChwb3NpdGlvblRvcCAtIHNsYXRUb3ApIC8gc2xhdEhlaWdodDsgLy8gZmxvYXRpbmcgcG9pbnQgbnVtYmVyIGJldHdlZW4gMCBhbmQgMVxuICAgICAgICAgICAgbGV0IGxvY2FsU25hcEluZGV4ID0gTWF0aC5mbG9vcihwYXJ0aWFsICogc25hcHNQZXJTbG90KTsgLy8gdGhlIHNuYXAgIyByZWxhdGl2ZSB0byBzdGFydCBvZiBzbGF0XG4gICAgICAgICAgICBsZXQgc25hcEluZGV4ID0gc2xhdEluZGV4ICogc25hcHNQZXJTbG90ICsgbG9jYWxTbmFwSW5kZXg7XG4gICAgICAgICAgICBsZXQgZGF5RGF0ZSA9IHRoaXMucHJvcHMuY2VsbHNbY29sSW5kZXhdLmRhdGU7XG4gICAgICAgICAgICBsZXQgdGltZSA9IGFkZER1cmF0aW9ucyhkYXRlUHJvZmlsZS5zbG90TWluVGltZSwgbXVsdGlwbHlEdXJhdGlvbihzbmFwRHVyYXRpb24sIHNuYXBJbmRleCkpO1xuICAgICAgICAgICAgbGV0IHN0YXJ0ID0gZGF0ZUVudi5hZGQoZGF5RGF0ZSwgdGltZSk7XG4gICAgICAgICAgICBsZXQgZW5kID0gZGF0ZUVudi5hZGQoc3RhcnQsIHNuYXBEdXJhdGlvbik7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGRhdGVQcm9maWxlLFxuICAgICAgICAgICAgICAgIGRhdGVTcGFuOiBPYmplY3QuYXNzaWduKHsgcmFuZ2U6IHsgc3RhcnQsIGVuZCB9LCBhbGxEYXk6IGZhbHNlIH0sIGNlbGwuZXh0cmFEYXRlU3BhbiksXG4gICAgICAgICAgICAgICAgZGF5RWw6IGNvbENvb3Jkcy5lbHNbY29sSW5kZXhdLFxuICAgICAgICAgICAgICAgIHJlY3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogY29sQ29vcmRzLmxlZnRzW2NvbEluZGV4XSxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGNvbENvb3Jkcy5yaWdodHNbY29sSW5kZXhdLFxuICAgICAgICAgICAgICAgICAgICB0b3A6IHNsYXRUb3AsXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbTogc2xhdFRvcCArIHNsYXRIZWlnaHQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsYXllcjogMCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufVxuZnVuY3Rpb24gcHJvY2Vzc1Nsb3RPcHRpb25zKHNsb3REdXJhdGlvbiwgc25hcER1cmF0aW9uT3ZlcnJpZGUpIHtcbiAgICBsZXQgc25hcER1cmF0aW9uID0gc25hcER1cmF0aW9uT3ZlcnJpZGUgfHwgc2xvdER1cmF0aW9uO1xuICAgIGxldCBzbmFwc1BlclNsb3QgPSB3aG9sZURpdmlkZUR1cmF0aW9ucyhzbG90RHVyYXRpb24sIHNuYXBEdXJhdGlvbik7XG4gICAgaWYgKHNuYXBzUGVyU2xvdCA9PT0gbnVsbCkge1xuICAgICAgICBzbmFwRHVyYXRpb24gPSBzbG90RHVyYXRpb247XG4gICAgICAgIHNuYXBzUGVyU2xvdCA9IDE7XG4gICAgICAgIC8vIFRPRE86IHNheSB3YXJuaW5nP1xuICAgIH1cbiAgICByZXR1cm4geyBzbmFwRHVyYXRpb24sIHNuYXBzUGVyU2xvdCB9O1xufVxuXG5jbGFzcyBEYXlUaW1lQ29sc1NsaWNlciBleHRlbmRzIFNsaWNlciB7XG4gICAgc2xpY2VSYW5nZShyYW5nZSwgZGF5UmFuZ2VzKSB7XG4gICAgICAgIGxldCBzZWdzID0gW107XG4gICAgICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IGRheVJhbmdlcy5sZW5ndGg7IGNvbCArPSAxKSB7XG4gICAgICAgICAgICBsZXQgc2VnUmFuZ2UgPSBpbnRlcnNlY3RSYW5nZXMocmFuZ2UsIGRheVJhbmdlc1tjb2xdKTtcbiAgICAgICAgICAgIGlmIChzZWdSYW5nZSkge1xuICAgICAgICAgICAgICAgIHNlZ3MucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBzZWdSYW5nZS5zdGFydCxcbiAgICAgICAgICAgICAgICAgICAgZW5kOiBzZWdSYW5nZS5lbmQsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IHNlZ1JhbmdlLnN0YXJ0LnZhbHVlT2YoKSA9PT0gcmFuZ2Uuc3RhcnQudmFsdWVPZigpLFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogc2VnUmFuZ2UuZW5kLnZhbHVlT2YoKSA9PT0gcmFuZ2UuZW5kLnZhbHVlT2YoKSxcbiAgICAgICAgICAgICAgICAgICAgY29sLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH1cbn1cblxuY2xhc3MgRGF5VGltZUNvbHMgZXh0ZW5kcyBEYXRlQ29tcG9uZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5idWlsZERheVJhbmdlcyA9IG1lbW9pemUoYnVpbGREYXlSYW5nZXMpO1xuICAgICAgICB0aGlzLnNsaWNlciA9IG5ldyBEYXlUaW1lQ29sc1NsaWNlcigpO1xuICAgICAgICB0aGlzLnRpbWVDb2xzUmVmID0gY3JlYXRlUmVmKCk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IGRhdGVQcm9maWxlLCBkYXlUYWJsZU1vZGVsIH0gPSBwcm9wcztcbiAgICAgICAgbGV0IHsgbm93SW5kaWNhdG9yLCBuZXh0RGF5VGhyZXNob2xkIH0gPSBjb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIGxldCBkYXlSYW5nZXMgPSB0aGlzLmJ1aWxkRGF5UmFuZ2VzKGRheVRhYmxlTW9kZWwsIGRhdGVQcm9maWxlLCBjb250ZXh0LmRhdGVFbnYpO1xuICAgICAgICAvLyBnaXZlIGl0IHRoZSBmaXJzdCByb3cgb2YgY2VsbHNcbiAgICAgICAgLy8gVE9ETzogd291bGQgbW92ZSB0aGlzIGZ1cnRoZXIgZG93biBoaWVyYXJjaHksIGJ1dCBzbGljZU5vd0RhdGUgbmVlZHMgaXRcbiAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KE5vd1RpbWVyLCB7IHVuaXQ6IG5vd0luZGljYXRvciA/ICdtaW51dGUnIDogJ2RheScgfSwgKG5vd0RhdGUsIHRvZGF5UmFuZ2UpID0+IChjcmVhdGVFbGVtZW50KFRpbWVDb2xzLCBPYmplY3QuYXNzaWduKHsgcmVmOiB0aGlzLnRpbWVDb2xzUmVmIH0sIHRoaXMuc2xpY2VyLnNsaWNlUHJvcHMocHJvcHMsIGRhdGVQcm9maWxlLCBudWxsLCBjb250ZXh0LCBkYXlSYW5nZXMpLCB7IGZvclByaW50OiBwcm9wcy5mb3JQcmludCwgYXhpczogcHJvcHMuYXhpcywgZGF0ZVByb2ZpbGU6IGRhdGVQcm9maWxlLCBzbGF0TWV0YXM6IHByb3BzLnNsYXRNZXRhcywgc2xvdER1cmF0aW9uOiBwcm9wcy5zbG90RHVyYXRpb24sIGNlbGxzOiBkYXlUYWJsZU1vZGVsLmNlbGxzWzBdLCB0YWJsZUNvbEdyb3VwTm9kZTogcHJvcHMudGFibGVDb2xHcm91cE5vZGUsIHRhYmxlTWluV2lkdGg6IHByb3BzLnRhYmxlTWluV2lkdGgsIGNsaWVudFdpZHRoOiBwcm9wcy5jbGllbnRXaWR0aCwgY2xpZW50SGVpZ2h0OiBwcm9wcy5jbGllbnRIZWlnaHQsIGV4cGFuZFJvd3M6IHByb3BzLmV4cGFuZFJvd3MsIG5vd0RhdGU6IG5vd0RhdGUsIG5vd0luZGljYXRvclNlZ3M6IG5vd0luZGljYXRvciAmJiB0aGlzLnNsaWNlci5zbGljZU5vd0RhdGUobm93RGF0ZSwgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbnRleHQsIGRheVJhbmdlcyksIHRvZGF5UmFuZ2U6IHRvZGF5UmFuZ2UsIG9uU2Nyb2xsVG9wUmVxdWVzdDogcHJvcHMub25TY3JvbGxUb3BSZXF1ZXN0LCBvblNsYXRDb29yZHM6IHByb3BzLm9uU2xhdENvb3JkcyB9KSkpKSk7XG4gICAgfVxufVxuZnVuY3Rpb24gYnVpbGREYXlSYW5nZXMoZGF5VGFibGVNb2RlbCwgZGF0ZVByb2ZpbGUsIGRhdGVFbnYpIHtcbiAgICBsZXQgcmFuZ2VzID0gW107XG4gICAgZm9yIChsZXQgZGF0ZSBvZiBkYXlUYWJsZU1vZGVsLmhlYWRlckRhdGVzKSB7XG4gICAgICAgIHJhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgIHN0YXJ0OiBkYXRlRW52LmFkZChkYXRlLCBkYXRlUHJvZmlsZS5zbG90TWluVGltZSksXG4gICAgICAgICAgICBlbmQ6IGRhdGVFbnYuYWRkKGRhdGUsIGRhdGVQcm9maWxlLnNsb3RNYXhUaW1lKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByYW5nZXM7XG59XG5cbi8vIHBvdGVudGlhbCBuaWNlIHZhbHVlcyBmb3IgdGhlIHNsb3QtZHVyYXRpb24gYW5kIGludGVydmFsLWR1cmF0aW9uXG4vLyBmcm9tIGxhcmdlc3QgdG8gc21hbGxlc3RcbmNvbnN0IFNUT0NLX1NVQl9EVVJBVElPTlMgPSBbXG4gICAgeyBob3VyczogMSB9LFxuICAgIHsgbWludXRlczogMzAgfSxcbiAgICB7IG1pbnV0ZXM6IDE1IH0sXG4gICAgeyBzZWNvbmRzOiAzMCB9LFxuICAgIHsgc2Vjb25kczogMTUgfSxcbl07XG5mdW5jdGlvbiBidWlsZFNsYXRNZXRhcyhzbG90TWluVGltZSwgc2xvdE1heFRpbWUsIGV4cGxpY2l0TGFiZWxJbnRlcnZhbCwgc2xvdER1cmF0aW9uLCBkYXRlRW52KSB7XG4gICAgbGV0IGRheVN0YXJ0ID0gbmV3IERhdGUoMCk7XG4gICAgbGV0IHNsYXRUaW1lID0gc2xvdE1pblRpbWU7XG4gICAgbGV0IHNsYXRJdGVyYXRvciA9IGNyZWF0ZUR1cmF0aW9uKDApO1xuICAgIGxldCBsYWJlbEludGVydmFsID0gZXhwbGljaXRMYWJlbEludGVydmFsIHx8IGNvbXB1dGVMYWJlbEludGVydmFsKHNsb3REdXJhdGlvbik7XG4gICAgbGV0IG1ldGFzID0gW107XG4gICAgd2hpbGUgKGFzUm91Z2hNcyhzbGF0VGltZSkgPCBhc1JvdWdoTXMoc2xvdE1heFRpbWUpKSB7XG4gICAgICAgIGxldCBkYXRlID0gZGF0ZUVudi5hZGQoZGF5U3RhcnQsIHNsYXRUaW1lKTtcbiAgICAgICAgbGV0IGlzTGFiZWxlZCA9IHdob2xlRGl2aWRlRHVyYXRpb25zKHNsYXRJdGVyYXRvciwgbGFiZWxJbnRlcnZhbCkgIT09IG51bGw7XG4gICAgICAgIG1ldGFzLnB1c2goe1xuICAgICAgICAgICAgZGF0ZSxcbiAgICAgICAgICAgIHRpbWU6IHNsYXRUaW1lLFxuICAgICAgICAgICAga2V5OiBkYXRlLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICBpc29UaW1lU3RyOiBmb3JtYXRJc29UaW1lU3RyaW5nKGRhdGUpLFxuICAgICAgICAgICAgaXNMYWJlbGVkLFxuICAgICAgICB9KTtcbiAgICAgICAgc2xhdFRpbWUgPSBhZGREdXJhdGlvbnMoc2xhdFRpbWUsIHNsb3REdXJhdGlvbik7XG4gICAgICAgIHNsYXRJdGVyYXRvciA9IGFkZER1cmF0aW9ucyhzbGF0SXRlcmF0b3IsIHNsb3REdXJhdGlvbik7XG4gICAgfVxuICAgIHJldHVybiBtZXRhcztcbn1cbi8vIENvbXB1dGVzIGFuIGF1dG9tYXRpYyB2YWx1ZSBmb3Igc2xvdExhYmVsSW50ZXJ2YWxcbmZ1bmN0aW9uIGNvbXB1dGVMYWJlbEludGVydmFsKHNsb3REdXJhdGlvbikge1xuICAgIGxldCBpO1xuICAgIGxldCBsYWJlbEludGVydmFsO1xuICAgIGxldCBzbG90c1BlckxhYmVsO1xuICAgIC8vIGZpbmQgdGhlIHNtYWxsZXN0IHN0b2NrIGxhYmVsIGludGVydmFsIHRoYXQgcmVzdWx0cyBpbiBtb3JlIHRoYW4gb25lIHNsb3RzLXBlci1sYWJlbFxuICAgIGZvciAoaSA9IFNUT0NLX1NVQl9EVVJBVElPTlMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICAgICAgbGFiZWxJbnRlcnZhbCA9IGNyZWF0ZUR1cmF0aW9uKFNUT0NLX1NVQl9EVVJBVElPTlNbaV0pO1xuICAgICAgICBzbG90c1BlckxhYmVsID0gd2hvbGVEaXZpZGVEdXJhdGlvbnMobGFiZWxJbnRlcnZhbCwgc2xvdER1cmF0aW9uKTtcbiAgICAgICAgaWYgKHNsb3RzUGVyTGFiZWwgIT09IG51bGwgJiYgc2xvdHNQZXJMYWJlbCA+IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBsYWJlbEludGVydmFsO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzbG90RHVyYXRpb247IC8vIGZhbGwgYmFja1xufVxuXG5jbGFzcyBEYXlUaW1lQ29sc1ZpZXcgZXh0ZW5kcyBUaW1lQ29sc1ZpZXcge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmJ1aWxkVGltZUNvbHNNb2RlbCA9IG1lbW9pemUoYnVpbGRUaW1lQ29sc01vZGVsKTtcbiAgICAgICAgdGhpcy5idWlsZFNsYXRNZXRhcyA9IG1lbW9pemUoYnVpbGRTbGF0TWV0YXMpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IG9wdGlvbnMsIGRhdGVFbnYsIGRhdGVQcm9maWxlR2VuZXJhdG9yIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgIGxldCB7IHByb3BzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBkYXRlUHJvZmlsZSB9ID0gcHJvcHM7XG4gICAgICAgIGxldCBkYXlUYWJsZU1vZGVsID0gdGhpcy5idWlsZFRpbWVDb2xzTW9kZWwoZGF0ZVByb2ZpbGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKTtcbiAgICAgICAgbGV0IHNwbGl0UHJvcHMgPSB0aGlzLmFsbERheVNwbGl0dGVyLnNwbGl0UHJvcHMocHJvcHMpO1xuICAgICAgICBsZXQgc2xhdE1ldGFzID0gdGhpcy5idWlsZFNsYXRNZXRhcyhkYXRlUHJvZmlsZS5zbG90TWluVGltZSwgZGF0ZVByb2ZpbGUuc2xvdE1heFRpbWUsIG9wdGlvbnMuc2xvdExhYmVsSW50ZXJ2YWwsIG9wdGlvbnMuc2xvdER1cmF0aW9uLCBkYXRlRW52KTtcbiAgICAgICAgbGV0IHsgZGF5TWluV2lkdGggfSA9IG9wdGlvbnM7XG4gICAgICAgIGxldCBoYXNBdHRhY2hlZEF4aXMgPSAhZGF5TWluV2lkdGg7XG4gICAgICAgIGxldCBoYXNEZXRhY2hlZEF4aXMgPSBkYXlNaW5XaWR0aDtcbiAgICAgICAgbGV0IGhlYWRlckNvbnRlbnQgPSBvcHRpb25zLmRheUhlYWRlcnMgJiYgKGNyZWF0ZUVsZW1lbnQoRGF5SGVhZGVyLCB7IGRhdGVzOiBkYXlUYWJsZU1vZGVsLmhlYWRlckRhdGVzLCBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIGRhdGVzUmVwRGlzdGluY3REYXlzOiB0cnVlLCByZW5kZXJJbnRybzogaGFzQXR0YWNoZWRBeGlzID8gdGhpcy5yZW5kZXJIZWFkQXhpcyA6IG51bGwgfSkpO1xuICAgICAgICBsZXQgYWxsRGF5Q29udGVudCA9IChvcHRpb25zLmFsbERheVNsb3QgIT09IGZhbHNlKSAmJiAoKGNvbnRlbnRBcmcpID0+IChjcmVhdGVFbGVtZW50KERheVRhYmxlLCBPYmplY3QuYXNzaWduKHt9LCBzcGxpdFByb3BzLmFsbERheSwgeyBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIGRheVRhYmxlTW9kZWw6IGRheVRhYmxlTW9kZWwsIG5leHREYXlUaHJlc2hvbGQ6IG9wdGlvbnMubmV4dERheVRocmVzaG9sZCwgdGFibGVNaW5XaWR0aDogY29udGVudEFyZy50YWJsZU1pbldpZHRoLCBjb2xHcm91cE5vZGU6IGNvbnRlbnRBcmcudGFibGVDb2xHcm91cE5vZGUsIHJlbmRlclJvd0ludHJvOiBoYXNBdHRhY2hlZEF4aXMgPyB0aGlzLnJlbmRlclRhYmxlUm93QXhpcyA6IG51bGwsIHNob3dXZWVrTnVtYmVyczogZmFsc2UsIGV4cGFuZFJvd3M6IGZhbHNlLCBoZWFkZXJBbGlnbkVsUmVmOiB0aGlzLmhlYWRlckVsUmVmLCBjbGllbnRXaWR0aDogY29udGVudEFyZy5jbGllbnRXaWR0aCwgY2xpZW50SGVpZ2h0OiBjb250ZW50QXJnLmNsaWVudEhlaWdodCwgZm9yUHJpbnQ6IHByb3BzLmZvclByaW50IH0sIHRoaXMuZ2V0QWxsRGF5TWF4RXZlbnRQcm9wcygpKSkpKTtcbiAgICAgICAgbGV0IHRpbWVHcmlkQ29udGVudCA9IChjb250ZW50QXJnKSA9PiAoY3JlYXRlRWxlbWVudChEYXlUaW1lQ29scywgT2JqZWN0LmFzc2lnbih7fSwgc3BsaXRQcm9wcy50aW1lZCwgeyBkYXlUYWJsZU1vZGVsOiBkYXlUYWJsZU1vZGVsLCBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIGF4aXM6IGhhc0F0dGFjaGVkQXhpcywgc2xvdER1cmF0aW9uOiBvcHRpb25zLnNsb3REdXJhdGlvbiwgc2xhdE1ldGFzOiBzbGF0TWV0YXMsIGZvclByaW50OiBwcm9wcy5mb3JQcmludCwgdGFibGVDb2xHcm91cE5vZGU6IGNvbnRlbnRBcmcudGFibGVDb2xHcm91cE5vZGUsIHRhYmxlTWluV2lkdGg6IGNvbnRlbnRBcmcudGFibGVNaW5XaWR0aCwgY2xpZW50V2lkdGg6IGNvbnRlbnRBcmcuY2xpZW50V2lkdGgsIGNsaWVudEhlaWdodDogY29udGVudEFyZy5jbGllbnRIZWlnaHQsIG9uU2xhdENvb3JkczogdGhpcy5oYW5kbGVTbGF0Q29vcmRzLCBleHBhbmRSb3dzOiBjb250ZW50QXJnLmV4cGFuZFJvd3MsIG9uU2Nyb2xsVG9wUmVxdWVzdDogdGhpcy5oYW5kbGVTY3JvbGxUb3BSZXF1ZXN0IH0pKSk7XG4gICAgICAgIHJldHVybiBoYXNEZXRhY2hlZEF4aXNcbiAgICAgICAgICAgID8gdGhpcy5yZW5kZXJIU2Nyb2xsTGF5b3V0KGhlYWRlckNvbnRlbnQsIGFsbERheUNvbnRlbnQsIHRpbWVHcmlkQ29udGVudCwgZGF5VGFibGVNb2RlbC5jb2xDbnQsIGRheU1pbldpZHRoLCBzbGF0TWV0YXMsIHRoaXMuc3RhdGUuc2xhdENvb3JkcylcbiAgICAgICAgICAgIDogdGhpcy5yZW5kZXJTaW1wbGVMYXlvdXQoaGVhZGVyQ29udGVudCwgYWxsRGF5Q29udGVudCwgdGltZUdyaWRDb250ZW50KTtcbiAgICB9XG59XG5mdW5jdGlvbiBidWlsZFRpbWVDb2xzTW9kZWwoZGF0ZVByb2ZpbGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKSB7XG4gICAgbGV0IGRheVNlcmllcyA9IG5ldyBEYXlTZXJpZXNNb2RlbChkYXRlUHJvZmlsZS5yZW5kZXJSYW5nZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpO1xuICAgIHJldHVybiBuZXcgRGF5VGFibGVNb2RlbChkYXlTZXJpZXMsIGZhbHNlKTtcbn1cblxudmFyIGNzc18yNDh6ID0gXCIuZmMtdi1ldmVudHtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLWZjLWV2ZW50LWJnLWNvbG9yKTtib3JkZXI6MXB4IHNvbGlkIHZhcigtLWZjLWV2ZW50LWJvcmRlci1jb2xvcik7ZGlzcGxheTpibG9ja30uZmMtdi1ldmVudCAuZmMtZXZlbnQtbWFpbntjb2xvcjp2YXIoLS1mYy1ldmVudC10ZXh0LWNvbG9yKTtoZWlnaHQ6MTAwJX0uZmMtdi1ldmVudCAuZmMtZXZlbnQtbWFpbi1mcmFtZXtkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246Y29sdW1uO2hlaWdodDoxMDAlfS5mYy12LWV2ZW50IC5mYy1ldmVudC10aW1le2ZsZXgtZ3JvdzowO2ZsZXgtc2hyaW5rOjA7bWF4LWhlaWdodDoxMDAlO292ZXJmbG93OmhpZGRlbn0uZmMtdi1ldmVudCAuZmMtZXZlbnQtdGl0bGUtY29udGFpbmVye2ZsZXgtZ3JvdzoxO2ZsZXgtc2hyaW5rOjE7bWluLWhlaWdodDowfS5mYy12LWV2ZW50IC5mYy1ldmVudC10aXRsZXtib3R0b206MDttYXgtaGVpZ2h0OjEwMCU7b3ZlcmZsb3c6aGlkZGVuO3RvcDowfS5mYy12LWV2ZW50Om5vdCguZmMtZXZlbnQtc3RhcnQpe2JvcmRlci10b3AtbGVmdC1yYWRpdXM6MDtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czowO2JvcmRlci10b3Atd2lkdGg6MH0uZmMtdi1ldmVudDpub3QoLmZjLWV2ZW50LWVuZCl7Ym9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czowO2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjA7Ym9yZGVyLWJvdHRvbS13aWR0aDowfS5mYy12LWV2ZW50LmZjLWV2ZW50LXNlbGVjdGVkOmJlZm9yZXtsZWZ0Oi0xMHB4O3JpZ2h0Oi0xMHB4fS5mYy12LWV2ZW50IC5mYy1ldmVudC1yZXNpemVyLXN0YXJ0e2N1cnNvcjpuLXJlc2l6ZX0uZmMtdi1ldmVudCAuZmMtZXZlbnQtcmVzaXplci1lbmR7Y3Vyc29yOnMtcmVzaXplfS5mYy12LWV2ZW50Om5vdCguZmMtZXZlbnQtc2VsZWN0ZWQpIC5mYy1ldmVudC1yZXNpemVye2hlaWdodDp2YXIoLS1mYy1ldmVudC1yZXNpemVyLXRoaWNrbmVzcyk7bGVmdDowO3JpZ2h0OjB9LmZjLXYtZXZlbnQ6bm90KC5mYy1ldmVudC1zZWxlY3RlZCkgLmZjLWV2ZW50LXJlc2l6ZXItc3RhcnR7dG9wOmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci10aGlja25lc3MpLy0yKX0uZmMtdi1ldmVudDpub3QoLmZjLWV2ZW50LXNlbGVjdGVkKSAuZmMtZXZlbnQtcmVzaXplci1lbmR7Ym90dG9tOmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci10aGlja25lc3MpLy0yKX0uZmMtdi1ldmVudC5mYy1ldmVudC1zZWxlY3RlZCAuZmMtZXZlbnQtcmVzaXplcntsZWZ0OjUwJTttYXJnaW4tbGVmdDpjYWxjKHZhcigtLWZjLWV2ZW50LXJlc2l6ZXItZG90LXRvdGFsLXdpZHRoKS8tMil9LmZjLXYtZXZlbnQuZmMtZXZlbnQtc2VsZWN0ZWQgLmZjLWV2ZW50LXJlc2l6ZXItc3RhcnR7dG9wOmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci1kb3QtdG90YWwtd2lkdGgpLy0yKX0uZmMtdi1ldmVudC5mYy1ldmVudC1zZWxlY3RlZCAuZmMtZXZlbnQtcmVzaXplci1lbmR7Ym90dG9tOmNhbGModmFyKC0tZmMtZXZlbnQtcmVzaXplci1kb3QtdG90YWwtd2lkdGgpLy0yKX0uZmMgLmZjLXRpbWVncmlkIC5mYy1kYXlncmlkLWJvZHl7ei1pbmRleDoyfS5mYyAuZmMtdGltZWdyaWQtZGl2aWRlcntwYWRkaW5nOjAgMCAycHh9LmZjIC5mYy10aW1lZ3JpZC1ib2R5e21pbi1oZWlnaHQ6MTAwJTtwb3NpdGlvbjpyZWxhdGl2ZTt6LWluZGV4OjF9LmZjIC5mYy10aW1lZ3JpZC1heGlzLWNodW5re3Bvc2l0aW9uOnJlbGF0aXZlfS5mYyAuZmMtdGltZWdyaWQtYXhpcy1jaHVuaz50YWJsZSwuZmMgLmZjLXRpbWVncmlkLXNsb3Rze3Bvc2l0aW9uOnJlbGF0aXZlO3otaW5kZXg6MX0uZmMgLmZjLXRpbWVncmlkLXNsb3R7Ym9yZGVyLWJvdHRvbTowO2hlaWdodDoxLjVlbX0uZmMgLmZjLXRpbWVncmlkLXNsb3Q6ZW1wdHk6YmVmb3Jle2NvbnRlbnQ6XFxcIlxcXFwwMGEwXFxcIn0uZmMgLmZjLXRpbWVncmlkLXNsb3QtbWlub3J7Ym9yZGVyLXRvcC1zdHlsZTpkb3R0ZWR9LmZjIC5mYy10aW1lZ3JpZC1zbG90LWxhYmVsLWN1c2hpb257ZGlzcGxheTppbmxpbmUtYmxvY2s7d2hpdGUtc3BhY2U6bm93cmFwfS5mYyAuZmMtdGltZWdyaWQtc2xvdC1sYWJlbHt2ZXJ0aWNhbC1hbGlnbjptaWRkbGV9LmZjIC5mYy10aW1lZ3JpZC1heGlzLWN1c2hpb24sLmZjIC5mYy10aW1lZ3JpZC1zbG90LWxhYmVsLWN1c2hpb257cGFkZGluZzowIDRweH0uZmMgLmZjLXRpbWVncmlkLWF4aXMtZnJhbWUtbGlxdWlke2hlaWdodDoxMDAlfS5mYyAuZmMtdGltZWdyaWQtYXhpcy1mcmFtZXthbGlnbi1pdGVtczpjZW50ZXI7ZGlzcGxheTpmbGV4O2p1c3RpZnktY29udGVudDpmbGV4LWVuZDtvdmVyZmxvdzpoaWRkZW59LmZjIC5mYy10aW1lZ3JpZC1heGlzLWN1c2hpb257ZmxleC1zaHJpbms6MDttYXgtd2lkdGg6NjBweH0uZmMtZGlyZWN0aW9uLWx0ciAuZmMtdGltZWdyaWQtc2xvdC1sYWJlbC1mcmFtZXt0ZXh0LWFsaWduOnJpZ2h0fS5mYy1kaXJlY3Rpb24tcnRsIC5mYy10aW1lZ3JpZC1zbG90LWxhYmVsLWZyYW1le3RleHQtYWxpZ246bGVmdH0uZmMtbGlxdWlkLWhhY2sgLmZjLXRpbWVncmlkLWF4aXMtZnJhbWUtbGlxdWlke2JvdHRvbTowO2hlaWdodDphdXRvO2xlZnQ6MDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3RvcDowfS5mYyAuZmMtdGltZWdyaWQtY29sLmZjLWRheS10b2RheXtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLWZjLXRvZGF5LWJnLWNvbG9yKX0uZmMgLmZjLXRpbWVncmlkLWNvbC1mcmFtZXttaW4taGVpZ2h0OjEwMCU7cG9zaXRpb246cmVsYXRpdmV9LmZjLW1lZGlhLXNjcmVlbi5mYy1saXF1aWQtaGFjayAuZmMtdGltZWdyaWQtY29sLWZyYW1le2JvdHRvbTowO2hlaWdodDphdXRvO2xlZnQ6MDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3RvcDowfS5mYy1tZWRpYS1zY3JlZW4gLmZjLXRpbWVncmlkLWNvbHN7Ym90dG9tOjA7bGVmdDowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjB9LmZjLW1lZGlhLXNjcmVlbiAuZmMtdGltZWdyaWQtY29scz50YWJsZXtoZWlnaHQ6MTAwJX0uZmMtbWVkaWEtc2NyZWVuIC5mYy10aW1lZ3JpZC1jb2wtYmcsLmZjLW1lZGlhLXNjcmVlbiAuZmMtdGltZWdyaWQtY29sLWV2ZW50cywuZmMtbWVkaWEtc2NyZWVuIC5mYy10aW1lZ3JpZC1ub3ctaW5kaWNhdG9yLWNvbnRhaW5lcntsZWZ0OjA7cG9zaXRpb246YWJzb2x1dGU7cmlnaHQ6MDt0b3A6MH0uZmMgLmZjLXRpbWVncmlkLWNvbC1iZ3t6LWluZGV4OjJ9LmZjIC5mYy10aW1lZ3JpZC1jb2wtYmcgLmZjLW5vbi1idXNpbmVzc3t6LWluZGV4OjF9LmZjIC5mYy10aW1lZ3JpZC1jb2wtYmcgLmZjLWJnLWV2ZW50e3otaW5kZXg6Mn0uZmMgLmZjLXRpbWVncmlkLWNvbC1iZyAuZmMtaGlnaGxpZ2h0e3otaW5kZXg6M30uZmMgLmZjLXRpbWVncmlkLWJnLWhhcm5lc3N7bGVmdDowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjB9LmZjIC5mYy10aW1lZ3JpZC1jb2wtZXZlbnRze3otaW5kZXg6M30uZmMgLmZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItY29udGFpbmVye2JvdHRvbTowO292ZXJmbG93OmhpZGRlbn0uZmMtZGlyZWN0aW9uLWx0ciAuZmMtdGltZWdyaWQtY29sLWV2ZW50c3ttYXJnaW46MCAyLjUlIDAgMnB4fS5mYy1kaXJlY3Rpb24tcnRsIC5mYy10aW1lZ3JpZC1jb2wtZXZlbnRze21hcmdpbjowIDJweCAwIDIuNSV9LmZjLXRpbWVncmlkLWV2ZW50LWhhcm5lc3N7cG9zaXRpb246YWJzb2x1dGV9LmZjLXRpbWVncmlkLWV2ZW50LWhhcm5lc3M+LmZjLXRpbWVncmlkLWV2ZW50e2JvdHRvbTowO2xlZnQ6MDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3RvcDowfS5mYy10aW1lZ3JpZC1ldmVudC1oYXJuZXNzLWluc2V0IC5mYy10aW1lZ3JpZC1ldmVudCwuZmMtdGltZWdyaWQtZXZlbnQuZmMtZXZlbnQtbWlycm9yLC5mYy10aW1lZ3JpZC1tb3JlLWxpbmt7Ym94LXNoYWRvdzowIDAgMCAxcHggdmFyKC0tZmMtcGFnZS1iZy1jb2xvcil9LmZjLXRpbWVncmlkLWV2ZW50LC5mYy10aW1lZ3JpZC1tb3JlLWxpbmt7Ym9yZGVyLXJhZGl1czozcHg7Zm9udC1zaXplOnZhcigtLWZjLXNtYWxsLWZvbnQtc2l6ZSl9LmZjLXRpbWVncmlkLWV2ZW50e21hcmdpbi1ib3R0b206MXB4fS5mYy10aW1lZ3JpZC1ldmVudCAuZmMtZXZlbnQtbWFpbntwYWRkaW5nOjFweCAxcHggMH0uZmMtdGltZWdyaWQtZXZlbnQgLmZjLWV2ZW50LXRpbWV7Zm9udC1zaXplOnZhcigtLWZjLXNtYWxsLWZvbnQtc2l6ZSk7bWFyZ2luLWJvdHRvbToxcHg7d2hpdGUtc3BhY2U6bm93cmFwfS5mYy10aW1lZ3JpZC1ldmVudC1zaG9ydCAuZmMtZXZlbnQtbWFpbi1mcmFtZXtmbGV4LWRpcmVjdGlvbjpyb3c7b3ZlcmZsb3c6aGlkZGVufS5mYy10aW1lZ3JpZC1ldmVudC1zaG9ydCAuZmMtZXZlbnQtdGltZTphZnRlcntjb250ZW50OlxcXCJcXFxcMDBhMC1cXFxcMDBhMFxcXCJ9LmZjLXRpbWVncmlkLWV2ZW50LXNob3J0IC5mYy1ldmVudC10aXRsZXtmb250LXNpemU6dmFyKC0tZmMtc21hbGwtZm9udC1zaXplKX0uZmMtdGltZWdyaWQtbW9yZS1saW5re2JhY2tncm91bmQ6dmFyKC0tZmMtbW9yZS1saW5rLWJnLWNvbG9yKTtjb2xvcjp2YXIoLS1mYy1tb3JlLWxpbmstdGV4dC1jb2xvcik7Y3Vyc29yOnBvaW50ZXI7bWFyZ2luLWJvdHRvbToxcHg7cG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDo5OTk5fS5mYy10aW1lZ3JpZC1tb3JlLWxpbmstaW5uZXJ7cGFkZGluZzozcHggMnB4O3RvcDowfS5mYy1kaXJlY3Rpb24tbHRyIC5mYy10aW1lZ3JpZC1tb3JlLWxpbmt7cmlnaHQ6MH0uZmMtZGlyZWN0aW9uLXJ0bCAuZmMtdGltZWdyaWQtbW9yZS1saW5re2xlZnQ6MH0uZmMgLmZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItYXJyb3csLmZjIC5mYy10aW1lZ3JpZC1ub3ctaW5kaWNhdG9yLWxpbmV7cG9pbnRlci1ldmVudHM6bm9uZX0uZmMgLmZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItbGluZXtib3JkZXItY29sb3I6dmFyKC0tZmMtbm93LWluZGljYXRvci1jb2xvcik7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDoxcHggMCAwO2xlZnQ6MDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3otaW5kZXg6NH0uZmMgLmZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItYXJyb3d7Ym9yZGVyLWNvbG9yOnZhcigtLWZjLW5vdy1pbmRpY2F0b3ItY29sb3IpO2JvcmRlci1zdHlsZTpzb2xpZDttYXJnaW4tdG9wOi01cHg7cG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDo0fS5mYy1kaXJlY3Rpb24tbHRyIC5mYy10aW1lZ3JpZC1ub3ctaW5kaWNhdG9yLWFycm93e2JvcmRlci1ib3R0b20tY29sb3I6dHJhbnNwYXJlbnQ7Ym9yZGVyLXRvcC1jb2xvcjp0cmFuc3BhcmVudDtib3JkZXItd2lkdGg6NXB4IDAgNXB4IDZweDtsZWZ0OjB9LmZjLWRpcmVjdGlvbi1ydGwgLmZjLXRpbWVncmlkLW5vdy1pbmRpY2F0b3ItYXJyb3d7Ym9yZGVyLWJvdHRvbS1jb2xvcjp0cmFuc3BhcmVudDtib3JkZXItdG9wLWNvbG9yOnRyYW5zcGFyZW50O2JvcmRlci13aWR0aDo1cHggNnB4IDVweCAwO3JpZ2h0OjB9XCI7XG5pbmplY3RTdHlsZXMoY3NzXzI0OHopO1xuXG5leHBvcnQgeyBEYXlUaW1lQ29scywgRGF5VGltZUNvbHNTbGljZXIsIERheVRpbWVDb2xzVmlldywgVGltZUNvbHMsIFRpbWVDb2xzU2xhdHNDb29yZHMsIFRpbWVDb2xzVmlldywgYnVpbGREYXlSYW5nZXMsIGJ1aWxkU2xhdE1ldGFzLCBidWlsZFRpbWVDb2xzTW9kZWwgfTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///121\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 122:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ index)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(112);\n/* harmony import */ var _internal_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(123);\n/* harmony import */ var _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(113);\n\n\n\n\n\nconst OPTION_REFINERS = {\n listDayFormat: createFalsableFormatter,\n listDaySideFormat: createFalsableFormatter,\n noEventsClassNames: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_2__.n,\n noEventsContent: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_2__.n,\n noEventsDidMount: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_2__.n,\n noEventsWillUnmount: _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_2__.n,\n // noEventsText is defined in base options\n};\nfunction createFalsableFormatter(input) {\n return input === false ? null : (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_2__.x)(input);\n}\n\nvar index = (0,_fullcalendar_core_index_js__WEBPACK_IMPORTED_MODULE_0__.createPlugin)({\n name: '@fullcalendar/list',\n optionRefiners: OPTION_REFINERS,\n views: {\n list: {\n component: _internal_js__WEBPACK_IMPORTED_MODULE_1__.ListView,\n buttonTextKey: 'list',\n listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like \"January 1, 2016\"\n },\n listDay: {\n type: 'list',\n duration: { days: 1 },\n listDayFormat: { weekday: 'long' }, // day-of-week is all we need. full date is probably in headerToolbar\n },\n listWeek: {\n type: 'list',\n duration: { weeks: 1 },\n listDayFormat: { weekday: 'long' },\n listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' },\n },\n listMonth: {\n type: 'list',\n duration: { month: 1 },\n listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have\n },\n listYear: {\n type: 'list',\n duration: { year: 1 },\n listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have\n },\n },\n});\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTIyLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBMkQ7QUFDbEI7QUFDa0M7QUFDckM7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qiw2REFBUTtBQUNoQyxxQkFBcUIsNkRBQVE7QUFDN0Isc0JBQXNCLDZEQUFRO0FBQzlCLHlCQUF5Qiw2REFBUTtBQUNqQztBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsaUVBQWU7QUFDbkQ7O0FBRUEsWUFBWSx5RUFBWTtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixrREFBUTtBQUMvQjtBQUNBLDZCQUE2QixnREFBZ0Q7QUFDN0UsU0FBUztBQUNUO0FBQ0E7QUFDQSx3QkFBd0IsU0FBUztBQUNqQyw2QkFBNkIsaUJBQWlCO0FBQzlDLFNBQVM7QUFDVDtBQUNBO0FBQ0Esd0JBQXdCLFVBQVU7QUFDbEMsNkJBQTZCLGlCQUFpQjtBQUM5QyxpQ0FBaUMsZ0RBQWdEO0FBQ2pGLFNBQVM7QUFDVDtBQUNBO0FBQ0Esd0JBQXdCLFVBQVU7QUFDbEMsaUNBQWlDLGlCQUFpQjtBQUNsRCxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHdCQUF3QixTQUFTO0FBQ2pDLGlDQUFpQyxpQkFBaUI7QUFDbEQsU0FBUztBQUNULEtBQUs7QUFDTCxDQUFDOztBQUUyQiIsInNvdXJjZXMiOlsid2VicGFjazovL2FyY2hpdGVjdHVpLWh0bWwtZnJlZS8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2xpc3QvaW5kZXguanM/N2IwNyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVQbHVnaW4gfSBmcm9tICdAZnVsbGNhbGVuZGFyL2NvcmUvaW5kZXguanMnO1xuaW1wb3J0IHsgTGlzdFZpZXcgfSBmcm9tICcuL2ludGVybmFsLmpzJztcbmltcG9ydCB7IGlkZW50aXR5LCBjcmVhdGVGb3JtYXR0ZXIgfSBmcm9tICdAZnVsbGNhbGVuZGFyL2NvcmUvaW50ZXJuYWwuanMnO1xuaW1wb3J0ICdAZnVsbGNhbGVuZGFyL2NvcmUvcHJlYWN0LmpzJztcblxuY29uc3QgT1BUSU9OX1JFRklORVJTID0ge1xuICAgIGxpc3REYXlGb3JtYXQ6IGNyZWF0ZUZhbHNhYmxlRm9ybWF0dGVyLFxuICAgIGxpc3REYXlTaWRlRm9ybWF0OiBjcmVhdGVGYWxzYWJsZUZvcm1hdHRlcixcbiAgICBub0V2ZW50c0NsYXNzTmFtZXM6IGlkZW50aXR5LFxuICAgIG5vRXZlbnRzQ29udGVudDogaWRlbnRpdHksXG4gICAgbm9FdmVudHNEaWRNb3VudDogaWRlbnRpdHksXG4gICAgbm9FdmVudHNXaWxsVW5tb3VudDogaWRlbnRpdHksXG4gICAgLy8gbm9FdmVudHNUZXh0IGlzIGRlZmluZWQgaW4gYmFzZSBvcHRpb25zXG59O1xuZnVuY3Rpb24gY3JlYXRlRmFsc2FibGVGb3JtYXR0ZXIoaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXQgPT09IGZhbHNlID8gbnVsbCA6IGNyZWF0ZUZvcm1hdHRlcihpbnB1dCk7XG59XG5cbnZhciBpbmRleCA9IGNyZWF0ZVBsdWdpbih7XG4gICAgbmFtZTogJ0BmdWxsY2FsZW5kYXIvbGlzdCcsXG4gICAgb3B0aW9uUmVmaW5lcnM6IE9QVElPTl9SRUZJTkVSUyxcbiAgICB2aWV3czoge1xuICAgICAgICBsaXN0OiB7XG4gICAgICAgICAgICBjb21wb25lbnQ6IExpc3RWaWV3LFxuICAgICAgICAgICAgYnV0dG9uVGV4dEtleTogJ2xpc3QnLFxuICAgICAgICAgICAgbGlzdERheUZvcm1hdDogeyBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJywgeWVhcjogJ251bWVyaWMnIH0sIC8vIGxpa2UgXCJKYW51YXJ5IDEsIDIwMTZcIlxuICAgICAgICB9LFxuICAgICAgICBsaXN0RGF5OiB7XG4gICAgICAgICAgICB0eXBlOiAnbGlzdCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyBkYXlzOiAxIH0sXG4gICAgICAgICAgICBsaXN0RGF5Rm9ybWF0OiB7IHdlZWtkYXk6ICdsb25nJyB9LCAvLyBkYXktb2Ytd2VlayBpcyBhbGwgd2UgbmVlZC4gZnVsbCBkYXRlIGlzIHByb2JhYmx5IGluIGhlYWRlclRvb2xiYXJcbiAgICAgICAgfSxcbiAgICAgICAgbGlzdFdlZWs6IHtcbiAgICAgICAgICAgIHR5cGU6ICdsaXN0JyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB7IHdlZWtzOiAxIH0sXG4gICAgICAgICAgICBsaXN0RGF5Rm9ybWF0OiB7IHdlZWtkYXk6ICdsb25nJyB9LFxuICAgICAgICAgICAgbGlzdERheVNpZGVGb3JtYXQ6IHsgbW9udGg6ICdsb25nJywgZGF5OiAnbnVtZXJpYycsIHllYXI6ICdudW1lcmljJyB9LFxuICAgICAgICB9LFxuICAgICAgICBsaXN0TW9udGg6IHtcbiAgICAgICAgICAgIHR5cGU6ICdsaXN0JyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB7IG1vbnRoOiAxIH0sXG4gICAgICAgICAgICBsaXN0RGF5U2lkZUZvcm1hdDogeyB3ZWVrZGF5OiAnbG9uZycgfSwgLy8gZGF5LW9mLXdlZWsgaXMgbmljZS10by1oYXZlXG4gICAgICAgIH0sXG4gICAgICAgIGxpc3RZZWFyOiB7XG4gICAgICAgICAgICB0eXBlOiAnbGlzdCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyB5ZWFyOiAxIH0sXG4gICAgICAgICAgICBsaXN0RGF5U2lkZUZvcm1hdDogeyB3ZWVrZGF5OiAnbG9uZycgfSwgLy8gZGF5LW9mLXdlZWsgaXMgbmljZS10by1oYXZlXG4gICAgICAgIH0sXG4gICAgfSxcbn0pO1xuXG5leHBvcnQgeyBpbmRleCBhcyBkZWZhdWx0IH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///122\n\n}");
|
|
|
|
/***/ }),
|
|
|
|
/***/ 123:
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ListView: () => (/* binding */ ListView)\n/* harmony export */ });\n/* harmony import */ var _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113);\n/* harmony import */ var _fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(114);\n\n\n\nclass ListViewHeaderRow extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n constructor() {\n super(...arguments);\n this.state = {\n textId: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a3)(),\n };\n }\n render() {\n let { theme, dateEnv, options, viewApi } = this.context;\n let { cellId, dayDate, todayRange } = this.props;\n let { textId } = this.state;\n let dayMeta = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.aY)(dayDate, todayRange);\n // will ever be falsy?\n let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';\n // will ever be falsy? also, BAD NAME \"alt\"\n let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';\n let renderProps = Object.assign({ date: dateEnv.toDate(dayDate), view: viewApi, textId,\n text,\n sideText, navLinkAttrs: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a_)(this.context, dayDate), sideNavLinkAttrs: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a_)(this.context, dayDate, 'day', false) }, dayMeta);\n // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"tr\", elClasses: [\n 'fc-list-day',\n ...(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.aX)(dayMeta, theme),\n ], elAttrs: {\n 'data-date': (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bt)(dayDate),\n }, renderProps: renderProps, generatorName: \"dayHeaderContent\", customGenerator: options.dayHeaderContent, defaultGenerator: renderInnerContent, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ( // TODO: force-hide top border based on :first-child\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"th\", { scope: \"colgroup\", colSpan: 3, id: cellId, \"aria-labelledby\": textId },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"div\", elClasses: [\n 'fc-list-day-cushion',\n theme.getClass('tableCellShaded'),\n ] })))));\n }\n}\nfunction renderInnerContent(props) {\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n props.text && ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"a\", Object.assign({ id: props.textId, className: \"fc-list-day-text\" }, props.navLinkAttrs), props.text)),\n props.sideText && ( /* not keyboard tabbable */(0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"a\", Object.assign({ \"aria-hidden\": true, className: \"fc-list-day-side-text\" }, props.sideNavLinkAttrs), props.sideText))));\n}\n\nconst DEFAULT_TIME_FORMAT = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.x)({\n hour: 'numeric',\n minute: '2-digit',\n meridiem: 'short',\n});\nclass ListViewEventRow extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.B {\n render() {\n let { props, context } = this;\n let { options } = context;\n let { seg, timeHeaderId, eventHeaderId, dateHeaderId } = props;\n let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ck, Object.assign({}, props, { elTag: \"tr\", elClasses: [\n 'fc-list-event',\n seg.eventRange.def.url && 'fc-event-forced-url',\n ], defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */, seg: seg, timeText: \"\", disableDragging: true, disableResizing: true }), (InnerContent, eventContentArg) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.Fragment, null,\n buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"td\", { \"aria-hidden\": true, className: \"fc-list-event-graphic\" },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"span\", { className: \"fc-list-event-dot\", style: {\n borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,\n } })),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"td\", elClasses: ['fc-list-event-title'], elAttrs: { headers: `${eventHeaderId} ${dateHeaderId}` } })))));\n }\n}\nfunction renderEventInnerContent(seg, context) {\n let interactiveAttrs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bS)(seg, context);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"a\", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));\n}\nfunction buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {\n let { options } = context;\n if (options.displayEventTime !== false) {\n let eventDef = seg.eventRange.def;\n let eventInstance = seg.eventRange.instance;\n let doAllDay = false;\n let timeText;\n if (eventDef.allDay) {\n doAllDay = true;\n }\n else if ((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ax)(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?\n if (seg.isStart) {\n timeText = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bO)(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);\n }\n else if (seg.isEnd) {\n timeText = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bO)(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);\n }\n else {\n doAllDay = true;\n }\n }\n else {\n timeText = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bO)(seg, timeFormat, context);\n }\n if (doAllDay) {\n let renderProps = {\n text: context.options.allDayText,\n view: context.viewApi,\n };\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"td\", elClasses: ['fc-list-event-time'], elAttrs: {\n headers: `${timeHeaderId} ${dateHeaderId}`,\n }, renderProps: renderProps, generatorName: \"allDayContent\", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }));\n }\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"td\", { className: \"fc-list-event-time\" }, timeText));\n }\n return null;\n}\nfunction renderAllDayInner(renderProps) {\n return renderProps.text;\n}\n\n/*\nResponsible for the scroller, and forwarding event-related actions into the \"grid\".\n*/\nclass ListView extends _fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bc {\n constructor() {\n super(...arguments);\n this.computeDateVars = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(computeDateVars);\n this.eventStoreToSegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.z)(this._eventStoreToSegs);\n this.state = {\n timeHeaderId: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a3)(),\n eventHeaderId: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a3)(),\n dateHeaderIdRoot: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a3)(),\n };\n this.setRootEl = (rootEl) => {\n if (rootEl) {\n this.context.registerInteractiveComponent(this, {\n el: rootEl,\n });\n }\n else {\n this.context.unregisterInteractiveComponent(this);\n }\n };\n }\n render() {\n let { props, context } = this;\n let { dayDates, dayRanges } = this.computeDateVars(props.dateProfile);\n let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cq, { elRef: this.setRootEl, elClasses: [\n 'fc-list',\n context.theme.getClass('table'),\n context.options.stickyHeaderDates !== false ?\n 'fc-list-sticky' :\n '',\n ], viewSpec: context.viewSpec },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.cb, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ?\n this.renderSegList(eventSegs, dayDates) :\n this.renderEmptyMessage())));\n }\n renderEmptyMessage() {\n let { options, viewApi } = this.context;\n let renderProps = {\n text: options.noEventsText,\n view: viewApi,\n };\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.C, { elTag: \"div\", elClasses: ['fc-list-empty'], renderProps: renderProps, generatorName: \"noEventsContent\", customGenerator: options.noEventsContent, defaultGenerator: renderNoEventsInner, classNameGenerator: options.noEventsClassNames, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, (InnerContent) => ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(InnerContent, { elTag: \"div\", elClasses: ['fc-list-empty-cushion'] }))));\n }\n renderSegList(allSegs, dayDates) {\n let { theme, options } = this.context;\n let { timeHeaderId, eventHeaderId, dateHeaderIdRoot } = this.state;\n let segsByDay = groupSegsByDay(allSegs); // sparse array\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.a6, { unit: \"day\" }, (nowDate, todayRange) => {\n let innerNodes = [];\n for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {\n let daySegs = segsByDay[dayIndex];\n if (daySegs) { // sparse array, so might be undefined\n let dayStr = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bt)(dayDates[dayIndex]);\n let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;\n // append a day header\n innerNodes.push((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(ListViewHeaderRow, { key: dayStr, cellId: dateHeaderId, dayDate: dayDates[dayIndex], todayRange: todayRange }));\n daySegs = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bP)(daySegs, options.eventOrder);\n for (let seg of daySegs) {\n innerNodes.push((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(ListViewEventRow, Object.assign({ key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, timeHeaderId: timeHeaderId, eventHeaderId: eventHeaderId, dateHeaderId: dateHeaderId }, (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.bQ)(seg, todayRange, nowDate))));\n }\n }\n }\n return ((0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"table\", { className: 'fc-list-table ' + theme.getClass('table') },\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"thead\", null,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tr\", null,\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"th\", { scope: \"col\", id: timeHeaderId }, options.timeHint),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"th\", { scope: \"col\", \"aria-hidden\": true }),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"th\", { scope: \"col\", id: eventHeaderId }, options.eventHint))),\n (0,_fullcalendar_core_preact_js__WEBPACK_IMPORTED_MODULE_1__.createElement)(\"tbody\", null, innerNodes)));\n }));\n }\n _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {\n return this.eventRangesToSegs((0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ad)(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);\n }\n eventRangesToSegs(eventRanges, dayRanges) {\n let segs = [];\n for (let eventRange of eventRanges) {\n segs.push(...this.eventRangeToSegs(eventRange, dayRanges));\n }\n return segs;\n }\n eventRangeToSegs(eventRange, dayRanges) {\n let { dateEnv } = this.context;\n let { nextDayThreshold } = this.context.options;\n let range = eventRange.range;\n let allDay = eventRange.def.allDay;\n let dayIndex;\n let segRange;\n let seg;\n let segs = [];\n for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {\n segRange = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.o)(range, dayRanges[dayIndex]);\n if (segRange) {\n seg = {\n component: this,\n eventRange,\n start: segRange.start,\n end: segRange.end,\n isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),\n isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),\n dayIndex,\n };\n segs.push(seg);\n // detect when range won't go fully into the next day,\n // and mutate the latest seg to the be the end.\n if (!seg.isEnd && !allDay &&\n dayIndex + 1 < dayRanges.length &&\n range.end <\n dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {\n seg.end = range.end;\n seg.isEnd = true;\n break;\n }\n }\n }\n return segs;\n }\n}\nfunction renderNoEventsInner(renderProps) {\n return renderProps.text;\n}\nfunction computeDateVars(dateProfile) {\n let dayStart = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.q)(dateProfile.renderRange.start);\n let viewEnd = dateProfile.renderRange.end;\n let dayDates = [];\n let dayRanges = [];\n while (dayStart < viewEnd) {\n dayDates.push(dayStart);\n dayRanges.push({\n start: dayStart,\n end: (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.t)(dayStart, 1),\n });\n dayStart = (0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.t)(dayStart, 1);\n }\n return { dayDates, dayRanges };\n}\n// Returns a sparse array of arrays, segs grouped by their dayIndex\nfunction groupSegsByDay(segs) {\n let segsByDay = []; // sparse array\n let i;\n let seg;\n for (i = 0; i < segs.length; i += 1) {\n seg = segs[i];\n (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))\n .push(seg);\n }\n return segsByDay;\n}\n\nvar css_248z = \":root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:\\\"\\\";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}\";\n(0,_fullcalendar_core_internal_js__WEBPACK_IMPORTED_MODULE_0__.ct)(css_248z);\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLGlFQUFPO0FBQ3hCLFNBQVM7QUFDVCxtQkFBbUIsaUVBQU87QUFDMUI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQSxnQkFBZ0IsaUJBQWlCO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IsK0JBQStCLHVDQUF1Qyw0QkFBNEIsd0NBQXdDLG1CQUFtQixtQkFBbUIsNENBQTRDLGFBQWEsWUFBWSx1QkFBdUIsMkJBQTJCLGFBQWEsbUJBQW1CLG9CQUFvQixXQUFXLHdCQUF3QixjQUFjLGVBQWUsbUNBQW1DLG1DQUFtQyxnQkFBZ0IsTUFBTSx5QkFBeUIsY0FBYyxrQkFBa0IsMkNBQTJDLGFBQWEsc0JBQXNCLFVBQVUsK0NBQStDLGlCQUFpQiwrQkFBK0IsV0FBVyxhQUFhLGNBQWMsd0NBQXdDLDRDQUE0Qyw2RUFBNkUsV0FBVyw2RUFBNkUsWUFBWSx3REFBd0QsZ0JBQWdCLHdEQUF3RCxlQUFlLHVDQUF1QyxlQUFlLDRCQUE0QixxREFBcUQsbURBQW1ELG1CQUFtQixVQUFVLHVCQUF1QixpRkFBaUYscURBQXFELHVCQUF1QixxQkFBcUIsU0FBUyxRQUFRLDJCQUEyQixjQUFjLHFCQUFxQiwrQ0FBK0MsMEJBQTBCO0FBQy91RCxrRUFBWTs7QUFFUSIsInNvdXJjZXMiOlsid2VicGFjazovL2FyY2hpdGVjdHVpLWh0bWwtZnJlZS8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2xpc3QvaW50ZXJuYWwuanM/MDViNSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCYXNlQ29tcG9uZW50LCBnZXRVbmlxdWVEb21JZCwgZ2V0RGF0ZU1ldGEsIGJ1aWxkTmF2TGlua0F0dHJzLCBDb250ZW50Q29udGFpbmVyLCBnZXREYXlDbGFzc05hbWVzLCBmb3JtYXREYXlTdHJpbmcsIGNyZWF0ZUZvcm1hdHRlciwgRXZlbnRDb250YWluZXIsIGdldFNlZ0FuY2hvckF0dHJzLCBpc011bHRpRGF5UmFuZ2UsIGJ1aWxkU2VnVGltZVRleHQsIERhdGVDb21wb25lbnQsIG1lbW9pemUsIFZpZXdDb250YWluZXIsIFNjcm9sbGVyLCBOb3dUaW1lciwgc29ydEV2ZW50U2VncywgZ2V0U2VnTWV0YSwgc2xpY2VFdmVudFN0b3JlLCBpbnRlcnNlY3RSYW5nZXMsIHN0YXJ0T2ZEYXksIGFkZERheXMsIGluamVjdFN0eWxlcyB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZS9pbnRlcm5hbC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbGVtZW50LCBGcmFnbWVudCB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZS9wcmVhY3QuanMnO1xuXG5jbGFzcyBMaXN0Vmlld0hlYWRlclJvdyBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgdGV4dElkOiBnZXRVbmlxdWVEb21JZCgpLFxuICAgICAgICB9O1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHRoZW1lLCBkYXRlRW52LCBvcHRpb25zLCB2aWV3QXBpIH0gPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgIGxldCB7IGNlbGxJZCwgZGF5RGF0ZSwgdG9kYXlSYW5nZSB9ID0gdGhpcy5wcm9wcztcbiAgICAgICAgbGV0IHsgdGV4dElkIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICBsZXQgZGF5TWV0YSA9IGdldERhdGVNZXRhKGRheURhdGUsIHRvZGF5UmFuZ2UpO1xuICAgICAgICAvLyB3aWxsIGV2ZXIgYmUgZmFsc3k/XG4gICAgICAgIGxldCB0ZXh0ID0gb3B0aW9ucy5saXN0RGF5Rm9ybWF0ID8gZGF0ZUVudi5mb3JtYXQoZGF5RGF0ZSwgb3B0aW9ucy5saXN0RGF5Rm9ybWF0KSA6ICcnO1xuICAgICAgICAvLyB3aWxsIGV2ZXIgYmUgZmFsc3k/IGFsc28sIEJBRCBOQU1FIFwiYWx0XCJcbiAgICAgICAgbGV0IHNpZGVUZXh0ID0gb3B0aW9ucy5saXN0RGF5U2lkZUZvcm1hdCA/IGRhdGVFbnYuZm9ybWF0KGRheURhdGUsIG9wdGlvbnMubGlzdERheVNpZGVGb3JtYXQpIDogJyc7XG4gICAgICAgIGxldCByZW5kZXJQcm9wcyA9IE9iamVjdC5hc3NpZ24oeyBkYXRlOiBkYXRlRW52LnRvRGF0ZShkYXlEYXRlKSwgdmlldzogdmlld0FwaSwgdGV4dElkLFxuICAgICAgICAgICAgdGV4dCxcbiAgICAgICAgICAgIHNpZGVUZXh0LCBuYXZMaW5rQXR0cnM6IGJ1aWxkTmF2TGlua0F0dHJzKHRoaXMuY29udGV4dCwgZGF5RGF0ZSksIHNpZGVOYXZMaW5rQXR0cnM6IGJ1aWxkTmF2TGlua0F0dHJzKHRoaXMuY29udGV4dCwgZGF5RGF0ZSwgJ2RheScsIGZhbHNlKSB9LCBkYXlNZXRhKTtcbiAgICAgICAgLy8gVE9ETzogbWFrZSBhIHJldXNhYmxlIEhPQyBmb3IgZGF5SGVhZGVyICh1c2VkIGluIGRheWdyaWQvdGltZWdyaWQgdG9vKVxuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoQ29udGVudENvbnRhaW5lciwgeyBlbFRhZzogXCJ0clwiLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAnZmMtbGlzdC1kYXknLFxuICAgICAgICAgICAgICAgIC4uLmdldERheUNsYXNzTmFtZXMoZGF5TWV0YSwgdGhlbWUpLFxuICAgICAgICAgICAgXSwgZWxBdHRyczoge1xuICAgICAgICAgICAgICAgICdkYXRhLWRhdGUnOiBmb3JtYXREYXlTdHJpbmcoZGF5RGF0ZSksXG4gICAgICAgICAgICB9LCByZW5kZXJQcm9wczogcmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IFwiZGF5SGVhZGVyQ29udGVudFwiLCBjdXN0b21HZW5lcmF0b3I6IG9wdGlvbnMuZGF5SGVhZGVyQ29udGVudCwgZGVmYXVsdEdlbmVyYXRvcjogcmVuZGVySW5uZXJDb250ZW50LCBjbGFzc05hbWVHZW5lcmF0b3I6IG9wdGlvbnMuZGF5SGVhZGVyQ2xhc3NOYW1lcywgZGlkTW91bnQ6IG9wdGlvbnMuZGF5SGVhZGVyRGlkTW91bnQsIHdpbGxVbm1vdW50OiBvcHRpb25zLmRheUhlYWRlcldpbGxVbm1vdW50IH0sIChJbm5lckNvbnRlbnQpID0+ICggLy8gVE9ETzogZm9yY2UtaGlkZSB0b3AgYm9yZGVyIGJhc2VkIG9uIDpmaXJzdC1jaGlsZFxuICAgICAgICBjcmVhdGVFbGVtZW50KFwidGhcIiwgeyBzY29wZTogXCJjb2xncm91cFwiLCBjb2xTcGFuOiAzLCBpZDogY2VsbElkLCBcImFyaWEtbGFiZWxsZWRieVwiOiB0ZXh0SWQgfSxcbiAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoSW5uZXJDb250ZW50LCB7IGVsVGFnOiBcImRpdlwiLCBlbENsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgJ2ZjLWxpc3QtZGF5LWN1c2hpb24nLFxuICAgICAgICAgICAgICAgICAgICB0aGVtZS5nZXRDbGFzcygndGFibGVDZWxsU2hhZGVkJyksXG4gICAgICAgICAgICAgICAgXSB9KSkpKSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVuZGVySW5uZXJDb250ZW50KHByb3BzKSB7XG4gICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KEZyYWdtZW50LCBudWxsLFxuICAgICAgICBwcm9wcy50ZXh0ICYmIChjcmVhdGVFbGVtZW50KFwiYVwiLCBPYmplY3QuYXNzaWduKHsgaWQ6IHByb3BzLnRleHRJZCwgY2xhc3NOYW1lOiBcImZjLWxpc3QtZGF5LXRleHRcIiB9LCBwcm9wcy5uYXZMaW5rQXR0cnMpLCBwcm9wcy50ZXh0KSksXG4gICAgICAgIHByb3BzLnNpZGVUZXh0ICYmICggLyogbm90IGtleWJvYXJkIHRhYmJhYmxlICovY3JlYXRlRWxlbWVudChcImFcIiwgT2JqZWN0LmFzc2lnbih7IFwiYXJpYS1oaWRkZW5cIjogdHJ1ZSwgY2xhc3NOYW1lOiBcImZjLWxpc3QtZGF5LXNpZGUtdGV4dFwiIH0sIHByb3BzLnNpZGVOYXZMaW5rQXR0cnMpLCBwcm9wcy5zaWRlVGV4dCkpKSk7XG59XG5cbmNvbnN0IERFRkFVTFRfVElNRV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoe1xuICAgIGhvdXI6ICdudW1lcmljJyxcbiAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICBtZXJpZGllbTogJ3Nob3J0Jyxcbn0pO1xuY2xhc3MgTGlzdFZpZXdFdmVudFJvdyBleHRlbmRzIEJhc2VDb21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgbGV0IHsgcHJvcHMsIGNvbnRleHQgfSA9IHRoaXM7XG4gICAgICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgICAgIGxldCB7IHNlZywgdGltZUhlYWRlcklkLCBldmVudEhlYWRlcklkLCBkYXRlSGVhZGVySWQgfSA9IHByb3BzO1xuICAgICAgICBsZXQgdGltZUZvcm1hdCA9IG9wdGlvbnMuZXZlbnRUaW1lRm9ybWF0IHx8IERFRkFVTFRfVElNRV9GT1JNQVQ7XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChFdmVudENvbnRhaW5lciwgT2JqZWN0LmFzc2lnbih7fSwgcHJvcHMsIHsgZWxUYWc6IFwidHJcIiwgZWxDbGFzc2VzOiBbXG4gICAgICAgICAgICAgICAgJ2ZjLWxpc3QtZXZlbnQnLFxuICAgICAgICAgICAgICAgIHNlZy5ldmVudFJhbmdlLmRlZi51cmwgJiYgJ2ZjLWV2ZW50LWZvcmNlZC11cmwnLFxuICAgICAgICAgICAgXSwgZGVmYXVsdEdlbmVyYXRvcjogKCkgPT4gcmVuZGVyRXZlbnRJbm5lckNvbnRlbnQoc2VnLCBjb250ZXh0KSAvKiB3ZWlyZCAqLywgc2VnOiBzZWcsIHRpbWVUZXh0OiBcIlwiLCBkaXNhYmxlRHJhZ2dpbmc6IHRydWUsIGRpc2FibGVSZXNpemluZzogdHJ1ZSB9KSwgKElubmVyQ29udGVudCwgZXZlbnRDb250ZW50QXJnKSA9PiAoY3JlYXRlRWxlbWVudChGcmFnbWVudCwgbnVsbCxcbiAgICAgICAgICAgIGJ1aWxkVGltZUNvbnRlbnQoc2VnLCB0aW1lRm9ybWF0LCBjb250ZXh0LCB0aW1lSGVhZGVySWQsIGRhdGVIZWFkZXJJZCksXG4gICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwidGRcIiwgeyBcImFyaWEtaGlkZGVuXCI6IHRydWUsIGNsYXNzTmFtZTogXCJmYy1saXN0LWV2ZW50LWdyYXBoaWNcIiB9LFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHsgY2xhc3NOYW1lOiBcImZjLWxpc3QtZXZlbnQtZG90XCIsIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogZXZlbnRDb250ZW50QXJnLmJvcmRlckNvbG9yIHx8IGV2ZW50Q29udGVudEFyZy5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICAgICAgICAgIH0gfSkpLFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChJbm5lckNvbnRlbnQsIHsgZWxUYWc6IFwidGRcIiwgZWxDbGFzc2VzOiBbJ2ZjLWxpc3QtZXZlbnQtdGl0bGUnXSwgZWxBdHRyczogeyBoZWFkZXJzOiBgJHtldmVudEhlYWRlcklkfSAke2RhdGVIZWFkZXJJZH1gIH0gfSkpKSkpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlbmRlckV2ZW50SW5uZXJDb250ZW50KHNlZywgY29udGV4dCkge1xuICAgIGxldCBpbnRlcmFjdGl2ZUF0dHJzID0gZ2V0U2VnQW5jaG9yQXR0cnMoc2VnLCBjb250ZXh0KTtcbiAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJhXCIsIE9iamVjdC5hc3NpZ24oe30sIGludGVyYWN0aXZlQXR0cnMpLCBzZWcuZXZlbnRSYW5nZS5kZWYudGl0bGUpKTtcbn1cbmZ1bmN0aW9uIGJ1aWxkVGltZUNvbnRlbnQoc2VnLCB0aW1lRm9ybWF0LCBjb250ZXh0LCB0aW1lSGVhZGVySWQsIGRhdGVIZWFkZXJJZCkge1xuICAgIGxldCB7IG9wdGlvbnMgfSA9IGNvbnRleHQ7XG4gICAgaWYgKG9wdGlvbnMuZGlzcGxheUV2ZW50VGltZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgbGV0IGV2ZW50RGVmID0gc2VnLmV2ZW50UmFuZ2UuZGVmO1xuICAgICAgICBsZXQgZXZlbnRJbnN0YW5jZSA9IHNlZy5ldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICBsZXQgZG9BbGxEYXkgPSBmYWxzZTtcbiAgICAgICAgbGV0IHRpbWVUZXh0O1xuICAgICAgICBpZiAoZXZlbnREZWYuYWxsRGF5KSB7XG4gICAgICAgICAgICBkb0FsbERheSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNNdWx0aURheVJhbmdlKHNlZy5ldmVudFJhbmdlLnJhbmdlKSkgeyAvLyBUT0RPOiB1c2UgKCFpc1N0YXJ0IHx8ICFpc0VuZCkgaW5zdGVhZD9cbiAgICAgICAgICAgIGlmIChzZWcuaXNTdGFydCkge1xuICAgICAgICAgICAgICAgIHRpbWVUZXh0ID0gYnVpbGRTZWdUaW1lVGV4dChzZWcsIHRpbWVGb3JtYXQsIGNvbnRleHQsIG51bGwsIG51bGwsIGV2ZW50SW5zdGFuY2UucmFuZ2Uuc3RhcnQsIHNlZy5lbmQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoc2VnLmlzRW5kKSB7XG4gICAgICAgICAgICAgICAgdGltZVRleHQgPSBidWlsZFNlZ1RpbWVUZXh0KHNlZywgdGltZUZvcm1hdCwgY29udGV4dCwgbnVsbCwgbnVsbCwgc2VnLnN0YXJ0LCBldmVudEluc3RhbmNlLnJhbmdlLmVuZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkb0FsbERheSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aW1lVGV4dCA9IGJ1aWxkU2VnVGltZVRleHQoc2VnLCB0aW1lRm9ybWF0LCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZG9BbGxEYXkpIHtcbiAgICAgICAgICAgIGxldCByZW5kZXJQcm9wcyA9IHtcbiAgICAgICAgICAgICAgICB0ZXh0OiBjb250ZXh0Lm9wdGlvbnMuYWxsRGF5VGV4dCxcbiAgICAgICAgICAgICAgICB2aWV3OiBjb250ZXh0LnZpZXdBcGksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIChjcmVhdGVFbGVtZW50KENvbnRlbnRDb250YWluZXIsIHsgZWxUYWc6IFwidGRcIiwgZWxDbGFzc2VzOiBbJ2ZjLWxpc3QtZXZlbnQtdGltZSddLCBlbEF0dHJzOiB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlcnM6IGAke3RpbWVIZWFkZXJJZH0gJHtkYXRlSGVhZGVySWR9YCxcbiAgICAgICAgICAgICAgICB9LCByZW5kZXJQcm9wczogcmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IFwiYWxsRGF5Q29udGVudFwiLCBjdXN0b21HZW5lcmF0b3I6IG9wdGlvbnMuYWxsRGF5Q29udGVudCwgZGVmYXVsdEdlbmVyYXRvcjogcmVuZGVyQWxsRGF5SW5uZXIsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5hbGxEYXlDbGFzc05hbWVzLCBkaWRNb3VudDogb3B0aW9ucy5hbGxEYXlEaWRNb3VudCwgd2lsbFVubW91bnQ6IG9wdGlvbnMuYWxsRGF5V2lsbFVubW91bnQgfSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChcInRkXCIsIHsgY2xhc3NOYW1lOiBcImZjLWxpc3QtZXZlbnQtdGltZVwiIH0sIHRpbWVUZXh0KSk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gcmVuZGVyQWxsRGF5SW5uZXIocmVuZGVyUHJvcHMpIHtcbiAgICByZXR1cm4gcmVuZGVyUHJvcHMudGV4dDtcbn1cblxuLypcblJlc3BvbnNpYmxlIGZvciB0aGUgc2Nyb2xsZXIsIGFuZCBmb3J3YXJkaW5nIGV2ZW50LXJlbGF0ZWQgYWN0aW9ucyBpbnRvIHRoZSBcImdyaWRcIi5cbiovXG5jbGFzcyBMaXN0VmlldyBleHRlbmRzIERhdGVDb21wb25lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmNvbXB1dGVEYXRlVmFycyA9IG1lbW9pemUoY29tcHV0ZURhdGVWYXJzKTtcbiAgICAgICAgdGhpcy5ldmVudFN0b3JlVG9TZWdzID0gbWVtb2l6ZSh0aGlzLl9ldmVudFN0b3JlVG9TZWdzKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHRpbWVIZWFkZXJJZDogZ2V0VW5pcXVlRG9tSWQoKSxcbiAgICAgICAgICAgIGV2ZW50SGVhZGVySWQ6IGdldFVuaXF1ZURvbUlkKCksXG4gICAgICAgICAgICBkYXRlSGVhZGVySWRSb290OiBnZXRVbmlxdWVEb21JZCgpLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNldFJvb3RFbCA9IChyb290RWwpID0+IHtcbiAgICAgICAgICAgIGlmIChyb290RWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRleHQucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGVsOiByb290RWwsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRleHQudW5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGxldCB7IHByb3BzLCBjb250ZXh0IH0gPSB0aGlzO1xuICAgICAgICBsZXQgeyBkYXlEYXRlcywgZGF5UmFuZ2VzIH0gPSB0aGlzLmNvbXB1dGVEYXRlVmFycyhwcm9wcy5kYXRlUHJvZmlsZSk7XG4gICAgICAgIGxldCBldmVudFNlZ3MgPSB0aGlzLmV2ZW50U3RvcmVUb1NlZ3MocHJvcHMuZXZlbnRTdG9yZSwgcHJvcHMuZXZlbnRVaUJhc2VzLCBkYXlSYW5nZXMpO1xuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoVmlld0NvbnRhaW5lciwgeyBlbFJlZjogdGhpcy5zZXRSb290RWwsIGVsQ2xhc3NlczogW1xuICAgICAgICAgICAgICAgICdmYy1saXN0JyxcbiAgICAgICAgICAgICAgICBjb250ZXh0LnRoZW1lLmdldENsYXNzKCd0YWJsZScpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQub3B0aW9ucy5zdGlja3lIZWFkZXJEYXRlcyAhPT0gZmFsc2UgP1xuICAgICAgICAgICAgICAgICAgICAnZmMtbGlzdC1zdGlja3knIDpcbiAgICAgICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICBdLCB2aWV3U3BlYzogY29udGV4dC52aWV3U3BlYyB9LFxuICAgICAgICAgICAgY3JlYXRlRWxlbWVudChTY3JvbGxlciwgeyBsaXF1aWQ6ICFwcm9wcy5pc0hlaWdodEF1dG8sIG92ZXJmbG93WDogcHJvcHMuaXNIZWlnaHRBdXRvID8gJ3Zpc2libGUnIDogJ2hpZGRlbicsIG92ZXJmbG93WTogcHJvcHMuaXNIZWlnaHRBdXRvID8gJ3Zpc2libGUnIDogJ2F1dG8nIH0sIGV2ZW50U2Vncy5sZW5ndGggPiAwID9cbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclNlZ0xpc3QoZXZlbnRTZWdzLCBkYXlEYXRlcykgOlxuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyRW1wdHlNZXNzYWdlKCkpKSk7XG4gICAgfVxuICAgIHJlbmRlckVtcHR5TWVzc2FnZSgpIHtcbiAgICAgICAgbGV0IHsgb3B0aW9ucywgdmlld0FwaSB9ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBsZXQgcmVuZGVyUHJvcHMgPSB7XG4gICAgICAgICAgICB0ZXh0OiBvcHRpb25zLm5vRXZlbnRzVGV4dCxcbiAgICAgICAgICAgIHZpZXc6IHZpZXdBcGksXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiAoY3JlYXRlRWxlbWVudChDb250ZW50Q29udGFpbmVyLCB7IGVsVGFnOiBcImRpdlwiLCBlbENsYXNzZXM6IFsnZmMtbGlzdC1lbXB0eSddLCByZW5kZXJQcm9wczogcmVuZGVyUHJvcHMsIGdlbmVyYXRvck5hbWU6IFwibm9FdmVudHNDb250ZW50XCIsIGN1c3RvbUdlbmVyYXRvcjogb3B0aW9ucy5ub0V2ZW50c0NvbnRlbnQsIGRlZmF1bHRHZW5lcmF0b3I6IHJlbmRlck5vRXZlbnRzSW5uZXIsIGNsYXNzTmFtZUdlbmVyYXRvcjogb3B0aW9ucy5ub0V2ZW50c0NsYXNzTmFtZXMsIGRpZE1vdW50OiBvcHRpb25zLm5vRXZlbnRzRGlkTW91bnQsIHdpbGxVbm1vdW50OiBvcHRpb25zLm5vRXZlbnRzV2lsbFVubW91bnQgfSwgKElubmVyQ29udGVudCkgPT4gKGNyZWF0ZUVsZW1lbnQoSW5uZXJDb250ZW50LCB7IGVsVGFnOiBcImRpdlwiLCBlbENsYXNzZXM6IFsnZmMtbGlzdC1lbXB0eS1jdXNoaW9uJ10gfSkpKSk7XG4gICAgfVxuICAgIHJlbmRlclNlZ0xpc3QoYWxsU2VncywgZGF5RGF0ZXMpIHtcbiAgICAgICAgbGV0IHsgdGhlbWUsIG9wdGlvbnMgfSA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgbGV0IHsgdGltZUhlYWRlcklkLCBldmVudEhlYWRlcklkLCBkYXRlSGVhZGVySWRSb290IH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICBsZXQgc2Vnc0J5RGF5ID0gZ3JvdXBTZWdzQnlEYXkoYWxsU2Vncyk7IC8vIHNwYXJzZSBhcnJheVxuICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoTm93VGltZXIsIHsgdW5pdDogXCJkYXlcIiB9LCAobm93RGF0ZSwgdG9kYXlSYW5nZSkgPT4ge1xuICAgICAgICAgICAgbGV0IGlubmVyTm9kZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGRheUluZGV4ID0gMDsgZGF5SW5kZXggPCBzZWdzQnlEYXkubGVuZ3RoOyBkYXlJbmRleCArPSAxKSB7XG4gICAgICAgICAgICAgICAgbGV0IGRheVNlZ3MgPSBzZWdzQnlEYXlbZGF5SW5kZXhdO1xuICAgICAgICAgICAgICAgIGlmIChkYXlTZWdzKSB7IC8vIHNwYXJzZSBhcnJheSwgc28gbWlnaHQgYmUgdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgIGxldCBkYXlTdHIgPSBmb3JtYXREYXlTdHJpbmcoZGF5RGF0ZXNbZGF5SW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGVIZWFkZXJJZCA9IGRhdGVIZWFkZXJJZFJvb3QgKyAnLScgKyBkYXlTdHI7XG4gICAgICAgICAgICAgICAgICAgIC8vIGFwcGVuZCBhIGRheSBoZWFkZXJcbiAgICAgICAgICAgICAgICAgICAgaW5uZXJOb2Rlcy5wdXNoKGNyZWF0ZUVsZW1lbnQoTGlzdFZpZXdIZWFkZXJSb3csIHsga2V5OiBkYXlTdHIsIGNlbGxJZDogZGF0ZUhlYWRlcklkLCBkYXlEYXRlOiBkYXlEYXRlc1tkYXlJbmRleF0sIHRvZGF5UmFuZ2U6IHRvZGF5UmFuZ2UgfSkpO1xuICAgICAgICAgICAgICAgICAgICBkYXlTZWdzID0gc29ydEV2ZW50U2VncyhkYXlTZWdzLCBvcHRpb25zLmV2ZW50T3JkZXIpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBzZWcgb2YgZGF5U2Vncykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJOb2Rlcy5wdXNoKGNyZWF0ZUVsZW1lbnQoTGlzdFZpZXdFdmVudFJvdywgT2JqZWN0LmFzc2lnbih7IGtleTogZGF5U3RyICsgJzonICsgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZCAvKiBhcmUgbXVsdGlwbGUgc2VncyBmb3IgYW4gaW5zdGFuY2VJZCAqLywgc2VnOiBzZWcsIGlzRHJhZ2dpbmc6IGZhbHNlLCBpc1Jlc2l6aW5nOiBmYWxzZSwgaXNEYXRlU2VsZWN0aW5nOiBmYWxzZSwgaXNTZWxlY3RlZDogZmFsc2UsIHRpbWVIZWFkZXJJZDogdGltZUhlYWRlcklkLCBldmVudEhlYWRlcklkOiBldmVudEhlYWRlcklkLCBkYXRlSGVhZGVySWQ6IGRhdGVIZWFkZXJJZCB9LCBnZXRTZWdNZXRhKHNlZywgdG9kYXlSYW5nZSwgbm93RGF0ZSkpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKGNyZWF0ZUVsZW1lbnQoXCJ0YWJsZVwiLCB7IGNsYXNzTmFtZTogJ2ZjLWxpc3QtdGFibGUgJyArIHRoZW1lLmdldENsYXNzKCd0YWJsZScpIH0sXG4gICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRoZWFkXCIsIG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJ0clwiLCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRoXCIsIHsgc2NvcGU6IFwiY29sXCIsIGlkOiB0aW1lSGVhZGVySWQgfSwgb3B0aW9ucy50aW1lSGludCksXG4gICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KFwidGhcIiwgeyBzY29wZTogXCJjb2xcIiwgXCJhcmlhLWhpZGRlblwiOiB0cnVlIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlRWxlbWVudChcInRoXCIsIHsgc2NvcGU6IFwiY29sXCIsIGlkOiBldmVudEhlYWRlcklkIH0sIG9wdGlvbnMuZXZlbnRIaW50KSkpLFxuICAgICAgICAgICAgICAgIGNyZWF0ZUVsZW1lbnQoXCJ0Ym9keVwiLCBudWxsLCBpbm5lck5vZGVzKSkpO1xuICAgICAgICB9KSk7XG4gICAgfVxuICAgIF9ldmVudFN0b3JlVG9TZWdzKGV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgZGF5UmFuZ2VzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmV2ZW50UmFuZ2VzVG9TZWdzKHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIHRoaXMuY29udGV4dC5vcHRpb25zLm5leHREYXlUaHJlc2hvbGQpLmZnLCBkYXlSYW5nZXMpO1xuICAgIH1cbiAgICBldmVudFJhbmdlc1RvU2VncyhldmVudFJhbmdlcywgZGF5UmFuZ2VzKSB7XG4gICAgICAgIGxldCBzZWdzID0gW107XG4gICAgICAgIGZvciAobGV0IGV2ZW50UmFuZ2Ugb2YgZXZlbnRSYW5nZXMpIHtcbiAgICAgICAgICAgIHNlZ3MucHVzaCguLi50aGlzLmV2ZW50UmFuZ2VUb1NlZ3MoZXZlbnRSYW5nZSwgZGF5UmFuZ2VzKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfVxuICAgIGV2ZW50UmFuZ2VUb1NlZ3MoZXZlbnRSYW5nZSwgZGF5UmFuZ2VzKSB7XG4gICAgICAgIGxldCB7IGRhdGVFbnYgfSA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgbGV0IHsgbmV4dERheVRocmVzaG9sZCB9ID0gdGhpcy5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIGxldCByYW5nZSA9IGV2ZW50UmFuZ2UucmFuZ2U7XG4gICAgICAgIGxldCBhbGxEYXkgPSBldmVudFJhbmdlLmRlZi5hbGxEYXk7XG4gICAgICAgIGxldCBkYXlJbmRleDtcbiAgICAgICAgbGV0IHNlZ1JhbmdlO1xuICAgICAgICBsZXQgc2VnO1xuICAgICAgICBsZXQgc2VncyA9IFtdO1xuICAgICAgICBmb3IgKGRheUluZGV4ID0gMDsgZGF5SW5kZXggPCBkYXlSYW5nZXMubGVuZ3RoOyBkYXlJbmRleCArPSAxKSB7XG4gICAgICAgICAgICBzZWdSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhyYW5nZSwgZGF5UmFuZ2VzW2RheUluZGV4XSk7XG4gICAgICAgICAgICBpZiAoc2VnUmFuZ2UpIHtcbiAgICAgICAgICAgICAgICBzZWcgPSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudDogdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRSYW5nZSxcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHNlZ1JhbmdlLnN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IHNlZ1JhbmdlLmVuZCxcbiAgICAgICAgICAgICAgICAgICAgaXNTdGFydDogZXZlbnRSYW5nZS5pc1N0YXJ0ICYmIHNlZ1JhbmdlLnN0YXJ0LnZhbHVlT2YoKSA9PT0gcmFuZ2Uuc3RhcnQudmFsdWVPZigpLFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogZXZlbnRSYW5nZS5pc0VuZCAmJiBzZWdSYW5nZS5lbmQudmFsdWVPZigpID09PSByYW5nZS5lbmQudmFsdWVPZigpLFxuICAgICAgICAgICAgICAgICAgICBkYXlJbmRleCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHNlZ3MucHVzaChzZWcpO1xuICAgICAgICAgICAgICAgIC8vIGRldGVjdCB3aGVuIHJhbmdlIHdvbid0IGdvIGZ1bGx5IGludG8gdGhlIG5leHQgZGF5LFxuICAgICAgICAgICAgICAgIC8vIGFuZCBtdXRhdGUgdGhlIGxhdGVzdCBzZWcgdG8gdGhlIGJlIHRoZSBlbmQuXG4gICAgICAgICAgICAgICAgaWYgKCFzZWcuaXNFbmQgJiYgIWFsbERheSAmJlxuICAgICAgICAgICAgICAgICAgICBkYXlJbmRleCArIDEgPCBkYXlSYW5nZXMubGVuZ3RoICYmXG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLmVuZCA8XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlRW52LmFkZChkYXlSYW5nZXNbZGF5SW5kZXggKyAxXS5zdGFydCwgbmV4dERheVRocmVzaG9sZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmVuZCA9IHJhbmdlLmVuZDtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmlzRW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlbmRlck5vRXZlbnRzSW5uZXIocmVuZGVyUHJvcHMpIHtcbiAgICByZXR1cm4gcmVuZGVyUHJvcHMudGV4dDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVEYXRlVmFycyhkYXRlUHJvZmlsZSkge1xuICAgIGxldCBkYXlTdGFydCA9IHN0YXJ0T2ZEYXkoZGF0ZVByb2ZpbGUucmVuZGVyUmFuZ2Uuc3RhcnQpO1xuICAgIGxldCB2aWV3RW5kID0gZGF0ZVByb2ZpbGUucmVuZGVyUmFuZ2UuZW5kO1xuICAgIGxldCBkYXlEYXRlcyA9IFtdO1xuICAgIGxldCBkYXlSYW5nZXMgPSBbXTtcbiAgICB3aGlsZSAoZGF5U3RhcnQgPCB2aWV3RW5kKSB7XG4gICAgICAgIGRheURhdGVzLnB1c2goZGF5U3RhcnQpO1xuICAgICAgICBkYXlSYW5nZXMucHVzaCh7XG4gICAgICAgICAgICBzdGFydDogZGF5U3RhcnQsXG4gICAgICAgICAgICBlbmQ6IGFkZERheXMoZGF5U3RhcnQsIDEpLFxuICAgICAgICB9KTtcbiAgICAgICAgZGF5U3RhcnQgPSBhZGREYXlzKGRheVN0YXJ0LCAxKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgZGF5RGF0ZXMsIGRheVJhbmdlcyB9O1xufVxuLy8gUmV0dXJucyBhIHNwYXJzZSBhcnJheSBvZiBhcnJheXMsIHNlZ3MgZ3JvdXBlZCBieSB0aGVpciBkYXlJbmRleFxuZnVuY3Rpb24gZ3JvdXBTZWdzQnlEYXkoc2Vncykge1xuICAgIGxldCBzZWdzQnlEYXkgPSBbXTsgLy8gc3BhcnNlIGFycmF5XG4gICAgbGV0IGk7XG4gICAgbGV0IHNlZztcbiAgICBmb3IgKGkgPSAwOyBpIDwgc2Vncy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBzZWcgPSBzZWdzW2ldO1xuICAgICAgICAoc2Vnc0J5RGF5W3NlZy5kYXlJbmRleF0gfHwgKHNlZ3NCeURheVtzZWcuZGF5SW5kZXhdID0gW10pKVxuICAgICAgICAgICAgLnB1c2goc2VnKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlZ3NCeURheTtcbn1cblxudmFyIGNzc18yNDh6ID0gXCI6cm9vdHstLWZjLWxpc3QtZXZlbnQtZG90LXdpZHRoOjEwcHg7LS1mYy1saXN0LWV2ZW50LWhvdmVyLWJnLWNvbG9yOiNmNWY1ZjV9LmZjLXRoZW1lLXN0YW5kYXJkIC5mYy1saXN0e2JvcmRlcjoxcHggc29saWQgdmFyKC0tZmMtYm9yZGVyLWNvbG9yKX0uZmMgLmZjLWxpc3QtZW1wdHl7YWxpZ24taXRlbXM6Y2VudGVyO2JhY2tncm91bmQtY29sb3I6dmFyKC0tZmMtbmV1dHJhbC1iZy1jb2xvcik7ZGlzcGxheTpmbGV4O2hlaWdodDoxMDAlO2p1c3RpZnktY29udGVudDpjZW50ZXJ9LmZjIC5mYy1saXN0LWVtcHR5LWN1c2hpb257bWFyZ2luOjVlbSAwfS5mYyAuZmMtbGlzdC10YWJsZXtib3JkZXItc3R5bGU6aGlkZGVuO3dpZHRoOjEwMCV9LmZjIC5mYy1saXN0LXRhYmxlIHRyPip7Ym9yZGVyLWxlZnQ6MDtib3JkZXItcmlnaHQ6MH0uZmMgLmZjLWxpc3Qtc3RpY2t5IC5mYy1saXN0LWRheT4qe2JhY2tncm91bmQ6dmFyKC0tZmMtcGFnZS1iZy1jb2xvcik7cG9zaXRpb246c3RpY2t5O3RvcDowfS5mYyAuZmMtbGlzdC10YWJsZSB0aGVhZHtsZWZ0Oi0xMDAwMHB4O3Bvc2l0aW9uOmFic29sdXRlfS5mYyAuZmMtbGlzdC10YWJsZSB0Ym9keT50cjpmaXJzdC1jaGlsZCB0aHtib3JkZXItdG9wOjB9LmZjIC5mYy1saXN0LXRhYmxlIHRoe3BhZGRpbmc6MH0uZmMgLmZjLWxpc3QtZGF5LWN1c2hpb24sLmZjIC5mYy1saXN0LXRhYmxlIHRke3BhZGRpbmc6OHB4IDE0cHh9LmZjIC5mYy1saXN0LWRheS1jdXNoaW9uOmFmdGVye2NsZWFyOmJvdGg7Y29udGVudDpcXFwiXFxcIjtkaXNwbGF5OnRhYmxlfS5mYy10aGVtZS1zdGFuZGFyZCAuZmMtbGlzdC1kYXktY3VzaGlvbntiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLWZjLW5ldXRyYWwtYmctY29sb3IpfS5mYy1kaXJlY3Rpb24tbHRyIC5mYy1saXN0LWRheS10ZXh0LC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1saXN0LWRheS1zaWRlLXRleHR7ZmxvYXQ6bGVmdH0uZmMtZGlyZWN0aW9uLWx0ciAuZmMtbGlzdC1kYXktc2lkZS10ZXh0LC5mYy1kaXJlY3Rpb24tcnRsIC5mYy1saXN0LWRheS10ZXh0e2Zsb2F0OnJpZ2h0fS5mYy1kaXJlY3Rpb24tbHRyIC5mYy1saXN0LXRhYmxlIC5mYy1saXN0LWV2ZW50LWdyYXBoaWN7cGFkZGluZy1yaWdodDowfS5mYy1kaXJlY3Rpb24tcnRsIC5mYy1saXN0LXRhYmxlIC5mYy1saXN0LWV2ZW50LWdyYXBoaWN7cGFkZGluZy1sZWZ0OjB9LmZjIC5mYy1saXN0LWV2ZW50LmZjLWV2ZW50LWZvcmNlZC11cmx7Y3Vyc29yOnBvaW50ZXJ9LmZjIC5mYy1saXN0LWV2ZW50OmhvdmVyIHRke2JhY2tncm91bmQtY29sb3I6dmFyKC0tZmMtbGlzdC1ldmVudC1ob3Zlci1iZy1jb2xvcil9LmZjIC5mYy1saXN0LWV2ZW50LWdyYXBoaWMsLmZjIC5mYy1saXN0LWV2ZW50LXRpbWV7d2hpdGUtc3BhY2U6bm93cmFwO3dpZHRoOjFweH0uZmMgLmZjLWxpc3QtZXZlbnQtZG90e2JvcmRlcjpjYWxjKHZhcigtLWZjLWxpc3QtZXZlbnQtZG90LXdpZHRoKS8yKSBzb2xpZCB2YXIoLS1mYy1ldmVudC1ib3JkZXItY29sb3IpO2JvcmRlci1yYWRpdXM6Y2FsYyh2YXIoLS1mYy1saXN0LWV2ZW50LWRvdC13aWR0aCkvMik7Ym94LXNpemluZzpjb250ZW50LWJveDtkaXNwbGF5OmlubGluZS1ibG9jaztoZWlnaHQ6MDt3aWR0aDowfS5mYyAuZmMtbGlzdC1ldmVudC10aXRsZSBhe2NvbG9yOmluaGVyaXQ7dGV4dC1kZWNvcmF0aW9uOm5vbmV9LmZjIC5mYy1saXN0LWV2ZW50LmZjLWV2ZW50LWZvcmNlZC11cmw6aG92ZXIgYXt0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lfVwiO1xuaW5qZWN0U3R5bGVzKGNzc18yNDh6KTtcblxuZXhwb3J0IHsgTGlzdFZpZXcgfTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///123\n\n}");
|
|
|
|
/***/ })
|
|
|
|
/******/ });
|
|
/************************************************************************/
|
|
/******/ // 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) {
|
|
/******/ if (cachedModule.error !== undefined) throw cachedModule.error;
|
|
/******/ 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
|
|
/******/ try {
|
|
/******/ var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };
|
|
/******/ __webpack_require__.i.forEach(function(handler) { handler(execOptions); });
|
|
/******/ module = execOptions.module;
|
|
/******/ execOptions.factory.call(module.exports, module, module.exports, execOptions.require);
|
|
/******/ } catch(e) {
|
|
/******/ module.error = e;
|
|
/******/ throw e;
|
|
/******/ }
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = __webpack_modules__;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = __webpack_module_cache__;
|
|
/******/
|
|
/******/ // expose the module execution interceptor
|
|
/******/ __webpack_require__.i = [];
|
|
/******/
|
|
/************************************************************************/
|
|
/******/ /* webpack/runtime/define property getters */
|
|
/******/ (() => {
|
|
/******/ // define getter functions for harmony exports
|
|
/******/ __webpack_require__.d = (exports, definition) => {
|
|
/******/ for(var key in definition) {
|
|
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
/******/ }
|
|
/******/ }
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/get javascript update chunk filename */
|
|
/******/ (() => {
|
|
/******/ // This function allow to reference all chunks
|
|
/******/ __webpack_require__.hu = (chunkId) => {
|
|
/******/ // return url for filenames based on template
|
|
/******/ return "" + chunkId + "." + __webpack_require__.h() + ".hot-update.js";
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/get update manifest filename */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.hmrF = () => ("fullcalendar." + __webpack_require__.h() + ".hot-update.json");
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/getFullHash */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.h = () => ("80c182c72d717043613b")
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/global */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.g = (function() {
|
|
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
/******/ try {
|
|
/******/ return this || new Function('return this')();
|
|
/******/ } catch (e) {
|
|
/******/ if (typeof window === 'object') return window;
|
|
/******/ }
|
|
/******/ })();
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/load script */
|
|
/******/ (() => {
|
|
/******/ var inProgress = {};
|
|
/******/ var dataWebpackPrefix = "architectui-html-free:";
|
|
/******/ // loadScript function to load a script via script tag
|
|
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
|
|
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
|
|
/******/ var script, needAttach;
|
|
/******/ if(key !== undefined) {
|
|
/******/ var scripts = document.getElementsByTagName("script");
|
|
/******/ for(var i = 0; i < scripts.length; i++) {
|
|
/******/ var s = scripts[i];
|
|
/******/ if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ if(!script) {
|
|
/******/ needAttach = true;
|
|
/******/ script = document.createElement('script');
|
|
/******/
|
|
/******/ script.charset = 'utf-8';
|
|
/******/ if (__webpack_require__.nc) {
|
|
/******/ script.setAttribute("nonce", __webpack_require__.nc);
|
|
/******/ }
|
|
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
|
|
/******/
|
|
/******/ script.src = url;
|
|
/******/ }
|
|
/******/ inProgress[url] = [done];
|
|
/******/ var onScriptComplete = (prev, event) => {
|
|
/******/ // avoid mem leaks in IE.
|
|
/******/ script.onerror = script.onload = null;
|
|
/******/ clearTimeout(timeout);
|
|
/******/ var doneFns = inProgress[url];
|
|
/******/ delete inProgress[url];
|
|
/******/ script.parentNode && script.parentNode.removeChild(script);
|
|
/******/ doneFns && doneFns.forEach((fn) => (fn(event)));
|
|
/******/ if(prev) return prev(event);
|
|
/******/ }
|
|
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
|
|
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
|
|
/******/ script.onload = onScriptComplete.bind(null, script.onload);
|
|
/******/ needAttach && document.head.appendChild(script);
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/make namespace object */
|
|
/******/ (() => {
|
|
/******/ // define __esModule on exports
|
|
/******/ __webpack_require__.r = (exports) => {
|
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
/******/ }
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/hot module replacement */
|
|
/******/ (() => {
|
|
/******/ var currentModuleData = {};
|
|
/******/ var installedModules = __webpack_require__.c;
|
|
/******/
|
|
/******/ // module and require creation
|
|
/******/ var currentChildModule;
|
|
/******/ var currentParents = [];
|
|
/******/
|
|
/******/ // status
|
|
/******/ var registeredStatusHandlers = [];
|
|
/******/ var currentStatus = "idle";
|
|
/******/
|
|
/******/ // while downloading
|
|
/******/ var blockingPromises = 0;
|
|
/******/ var blockingPromisesWaiting = [];
|
|
/******/
|
|
/******/ // The update info
|
|
/******/ var currentUpdateApplyHandlers;
|
|
/******/ var queuedInvalidatedModules;
|
|
/******/
|
|
/******/ __webpack_require__.hmrD = currentModuleData;
|
|
/******/
|
|
/******/ __webpack_require__.i.push(function (options) {
|
|
/******/ var module = options.module;
|
|
/******/ var require = createRequire(options.require, options.id);
|
|
/******/ module.hot = createModuleHotObject(options.id, module);
|
|
/******/ module.parents = currentParents;
|
|
/******/ module.children = [];
|
|
/******/ currentParents = [];
|
|
/******/ options.require = require;
|
|
/******/ });
|
|
/******/
|
|
/******/ __webpack_require__.hmrC = {};
|
|
/******/ __webpack_require__.hmrI = {};
|
|
/******/
|
|
/******/ function createRequire(require, moduleId) {
|
|
/******/ var me = installedModules[moduleId];
|
|
/******/ if (!me) return require;
|
|
/******/ var fn = function (request) {
|
|
/******/ if (me.hot.active) {
|
|
/******/ if (installedModules[request]) {
|
|
/******/ var parents = installedModules[request].parents;
|
|
/******/ if (parents.indexOf(moduleId) === -1) {
|
|
/******/ parents.push(moduleId);
|
|
/******/ }
|
|
/******/ } else {
|
|
/******/ currentParents = [moduleId];
|
|
/******/ currentChildModule = request;
|
|
/******/ }
|
|
/******/ if (me.children.indexOf(request) === -1) {
|
|
/******/ me.children.push(request);
|
|
/******/ }
|
|
/******/ } else {
|
|
/******/ console.warn(
|
|
/******/ "[HMR] unexpected require(" +
|
|
/******/ request +
|
|
/******/ ") from disposed module " +
|
|
/******/ moduleId
|
|
/******/ );
|
|
/******/ currentParents = [];
|
|
/******/ }
|
|
/******/ return require(request);
|
|
/******/ };
|
|
/******/ var createPropertyDescriptor = function (name) {
|
|
/******/ return {
|
|
/******/ configurable: true,
|
|
/******/ enumerable: true,
|
|
/******/ get: function () {
|
|
/******/ return require[name];
|
|
/******/ },
|
|
/******/ set: function (value) {
|
|
/******/ require[name] = value;
|
|
/******/ }
|
|
/******/ };
|
|
/******/ };
|
|
/******/ for (var name in require) {
|
|
/******/ if (Object.prototype.hasOwnProperty.call(require, name) && name !== "e") {
|
|
/******/ Object.defineProperty(fn, name, createPropertyDescriptor(name));
|
|
/******/ }
|
|
/******/ }
|
|
/******/ fn.e = function (chunkId, fetchPriority) {
|
|
/******/ return trackBlockingPromise(require.e(chunkId, fetchPriority));
|
|
/******/ };
|
|
/******/ return fn;
|
|
/******/ }
|
|
/******/
|
|
/******/ function createModuleHotObject(moduleId, me) {
|
|
/******/ var _main = currentChildModule !== moduleId;
|
|
/******/ var hot = {
|
|
/******/ // private stuff
|
|
/******/ _acceptedDependencies: {},
|
|
/******/ _acceptedErrorHandlers: {},
|
|
/******/ _declinedDependencies: {},
|
|
/******/ _selfAccepted: false,
|
|
/******/ _selfDeclined: false,
|
|
/******/ _selfInvalidated: false,
|
|
/******/ _disposeHandlers: [],
|
|
/******/ _main: _main,
|
|
/******/ _requireSelf: function () {
|
|
/******/ currentParents = me.parents.slice();
|
|
/******/ currentChildModule = _main ? undefined : moduleId;
|
|
/******/ __webpack_require__(moduleId);
|
|
/******/ },
|
|
/******/
|
|
/******/ // Module API
|
|
/******/ active: true,
|
|
/******/ accept: function (dep, callback, errorHandler) {
|
|
/******/ if (dep === undefined) hot._selfAccepted = true;
|
|
/******/ else if (typeof dep === "function") hot._selfAccepted = dep;
|
|
/******/ else if (typeof dep === "object" && dep !== null) {
|
|
/******/ for (var i = 0; i < dep.length; i++) {
|
|
/******/ hot._acceptedDependencies[dep[i]] = callback || function () {};
|
|
/******/ hot._acceptedErrorHandlers[dep[i]] = errorHandler;
|
|
/******/ }
|
|
/******/ } else {
|
|
/******/ hot._acceptedDependencies[dep] = callback || function () {};
|
|
/******/ hot._acceptedErrorHandlers[dep] = errorHandler;
|
|
/******/ }
|
|
/******/ },
|
|
/******/ decline: function (dep) {
|
|
/******/ if (dep === undefined) hot._selfDeclined = true;
|
|
/******/ else if (typeof dep === "object" && dep !== null)
|
|
/******/ for (var i = 0; i < dep.length; i++)
|
|
/******/ hot._declinedDependencies[dep[i]] = true;
|
|
/******/ else hot._declinedDependencies[dep] = true;
|
|
/******/ },
|
|
/******/ dispose: function (callback) {
|
|
/******/ hot._disposeHandlers.push(callback);
|
|
/******/ },
|
|
/******/ addDisposeHandler: function (callback) {
|
|
/******/ hot._disposeHandlers.push(callback);
|
|
/******/ },
|
|
/******/ removeDisposeHandler: function (callback) {
|
|
/******/ var idx = hot._disposeHandlers.indexOf(callback);
|
|
/******/ if (idx >= 0) hot._disposeHandlers.splice(idx, 1);
|
|
/******/ },
|
|
/******/ invalidate: function () {
|
|
/******/ this._selfInvalidated = true;
|
|
/******/ switch (currentStatus) {
|
|
/******/ case "idle":
|
|
/******/ currentUpdateApplyHandlers = [];
|
|
/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) {
|
|
/******/ __webpack_require__.hmrI[key](
|
|
/******/ moduleId,
|
|
/******/ currentUpdateApplyHandlers
|
|
/******/ );
|
|
/******/ });
|
|
/******/ setStatus("ready");
|
|
/******/ break;
|
|
/******/ case "ready":
|
|
/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) {
|
|
/******/ __webpack_require__.hmrI[key](
|
|
/******/ moduleId,
|
|
/******/ currentUpdateApplyHandlers
|
|
/******/ );
|
|
/******/ });
|
|
/******/ break;
|
|
/******/ case "prepare":
|
|
/******/ case "check":
|
|
/******/ case "dispose":
|
|
/******/ case "apply":
|
|
/******/ (queuedInvalidatedModules = queuedInvalidatedModules || []).push(
|
|
/******/ moduleId
|
|
/******/ );
|
|
/******/ break;
|
|
/******/ default:
|
|
/******/ // ignore requests in error states
|
|
/******/ break;
|
|
/******/ }
|
|
/******/ },
|
|
/******/
|
|
/******/ // Management API
|
|
/******/ check: hotCheck,
|
|
/******/ apply: hotApply,
|
|
/******/ status: function (l) {
|
|
/******/ if (!l) return currentStatus;
|
|
/******/ registeredStatusHandlers.push(l);
|
|
/******/ },
|
|
/******/ addStatusHandler: function (l) {
|
|
/******/ registeredStatusHandlers.push(l);
|
|
/******/ },
|
|
/******/ removeStatusHandler: function (l) {
|
|
/******/ var idx = registeredStatusHandlers.indexOf(l);
|
|
/******/ if (idx >= 0) registeredStatusHandlers.splice(idx, 1);
|
|
/******/ },
|
|
/******/
|
|
/******/ // inherit from previous dispose call
|
|
/******/ data: currentModuleData[moduleId]
|
|
/******/ };
|
|
/******/ currentChildModule = undefined;
|
|
/******/ return hot;
|
|
/******/ }
|
|
/******/
|
|
/******/ function setStatus(newStatus) {
|
|
/******/ currentStatus = newStatus;
|
|
/******/ var results = [];
|
|
/******/
|
|
/******/ for (var i = 0; i < registeredStatusHandlers.length; i++)
|
|
/******/ results[i] = registeredStatusHandlers[i].call(null, newStatus);
|
|
/******/
|
|
/******/ return Promise.all(results).then(function () {});
|
|
/******/ }
|
|
/******/
|
|
/******/ function unblock() {
|
|
/******/ if (--blockingPromises === 0) {
|
|
/******/ setStatus("ready").then(function () {
|
|
/******/ if (blockingPromises === 0) {
|
|
/******/ var list = blockingPromisesWaiting;
|
|
/******/ blockingPromisesWaiting = [];
|
|
/******/ for (var i = 0; i < list.length; i++) {
|
|
/******/ list[i]();
|
|
/******/ }
|
|
/******/ }
|
|
/******/ });
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ function trackBlockingPromise(promise) {
|
|
/******/ switch (currentStatus) {
|
|
/******/ case "ready":
|
|
/******/ setStatus("prepare");
|
|
/******/ /* fallthrough */
|
|
/******/ case "prepare":
|
|
/******/ blockingPromises++;
|
|
/******/ promise.then(unblock, unblock);
|
|
/******/ return promise;
|
|
/******/ default:
|
|
/******/ return promise;
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ function waitForBlockingPromises(fn) {
|
|
/******/ if (blockingPromises === 0) return fn();
|
|
/******/ return new Promise(function (resolve) {
|
|
/******/ blockingPromisesWaiting.push(function () {
|
|
/******/ resolve(fn());
|
|
/******/ });
|
|
/******/ });
|
|
/******/ }
|
|
/******/
|
|
/******/ function hotCheck(applyOnUpdate) {
|
|
/******/ if (currentStatus !== "idle") {
|
|
/******/ throw new Error("check() is only allowed in idle status");
|
|
/******/ }
|
|
/******/ return setStatus("check")
|
|
/******/ .then(__webpack_require__.hmrM)
|
|
/******/ .then(function (update) {
|
|
/******/ if (!update) {
|
|
/******/ return setStatus(applyInvalidatedModules() ? "ready" : "idle").then(
|
|
/******/ function () {
|
|
/******/ return null;
|
|
/******/ }
|
|
/******/ );
|
|
/******/ }
|
|
/******/
|
|
/******/ return setStatus("prepare").then(function () {
|
|
/******/ var updatedModules = [];
|
|
/******/ currentUpdateApplyHandlers = [];
|
|
/******/
|
|
/******/ return Promise.all(
|
|
/******/ Object.keys(__webpack_require__.hmrC).reduce(function (
|
|
/******/ promises,
|
|
/******/ key
|
|
/******/ ) {
|
|
/******/ __webpack_require__.hmrC[key](
|
|
/******/ update.c,
|
|
/******/ update.r,
|
|
/******/ update.m,
|
|
/******/ promises,
|
|
/******/ currentUpdateApplyHandlers,
|
|
/******/ updatedModules
|
|
/******/ );
|
|
/******/ return promises;
|
|
/******/ }, [])
|
|
/******/ ).then(function () {
|
|
/******/ return waitForBlockingPromises(function () {
|
|
/******/ if (applyOnUpdate) {
|
|
/******/ return internalApply(applyOnUpdate);
|
|
/******/ }
|
|
/******/ return setStatus("ready").then(function () {
|
|
/******/ return updatedModules;
|
|
/******/ });
|
|
/******/ });
|
|
/******/ });
|
|
/******/ });
|
|
/******/ });
|
|
/******/ }
|
|
/******/
|
|
/******/ function hotApply(options) {
|
|
/******/ if (currentStatus !== "ready") {
|
|
/******/ return Promise.resolve().then(function () {
|
|
/******/ throw new Error(
|
|
/******/ "apply() is only allowed in ready status (state: " +
|
|
/******/ currentStatus +
|
|
/******/ ")"
|
|
/******/ );
|
|
/******/ });
|
|
/******/ }
|
|
/******/ return internalApply(options);
|
|
/******/ }
|
|
/******/
|
|
/******/ function internalApply(options) {
|
|
/******/ options = options || {};
|
|
/******/
|
|
/******/ applyInvalidatedModules();
|
|
/******/
|
|
/******/ var results = currentUpdateApplyHandlers.map(function (handler) {
|
|
/******/ return handler(options);
|
|
/******/ });
|
|
/******/ currentUpdateApplyHandlers = undefined;
|
|
/******/
|
|
/******/ var errors = results
|
|
/******/ .map(function (r) {
|
|
/******/ return r.error;
|
|
/******/ })
|
|
/******/ .filter(Boolean);
|
|
/******/
|
|
/******/ if (errors.length > 0) {
|
|
/******/ return setStatus("abort").then(function () {
|
|
/******/ throw errors[0];
|
|
/******/ });
|
|
/******/ }
|
|
/******/
|
|
/******/ // Now in "dispose" phase
|
|
/******/ var disposePromise = setStatus("dispose");
|
|
/******/
|
|
/******/ results.forEach(function (result) {
|
|
/******/ if (result.dispose) result.dispose();
|
|
/******/ });
|
|
/******/
|
|
/******/ // Now in "apply" phase
|
|
/******/ var applyPromise = setStatus("apply");
|
|
/******/
|
|
/******/ var error;
|
|
/******/ var reportError = function (err) {
|
|
/******/ if (!error) error = err;
|
|
/******/ };
|
|
/******/
|
|
/******/ var outdatedModules = [];
|
|
/******/
|
|
/******/ var onAccepted = function () {
|
|
/******/ return Promise.all([disposePromise, applyPromise]).then(function () {
|
|
/******/ // handle errors in accept handlers and self accepted module load
|
|
/******/ if (error) {
|
|
/******/ return setStatus("fail").then(function () {
|
|
/******/ throw error;
|
|
/******/ });
|
|
/******/ }
|
|
/******/
|
|
/******/ if (queuedInvalidatedModules) {
|
|
/******/ return internalApply(options).then(function (list) {
|
|
/******/ outdatedModules.forEach(function (moduleId) {
|
|
/******/ if (list.indexOf(moduleId) < 0) list.push(moduleId);
|
|
/******/ });
|
|
/******/ return list;
|
|
/******/ });
|
|
/******/ }
|
|
/******/
|
|
/******/ return setStatus("idle").then(function () {
|
|
/******/ return outdatedModules;
|
|
/******/ });
|
|
/******/ });
|
|
/******/ };
|
|
/******/
|
|
/******/ return Promise.all(
|
|
/******/ results
|
|
/******/ .filter(function (result) {
|
|
/******/ return result.apply;
|
|
/******/ })
|
|
/******/ .map(function (result) {
|
|
/******/ return result.apply(reportError);
|
|
/******/ })
|
|
/******/ )
|
|
/******/ .then(function (applyResults) {
|
|
/******/ applyResults.forEach(function (modules) {
|
|
/******/ if (modules) {
|
|
/******/ for (var i = 0; i < modules.length; i++) {
|
|
/******/ outdatedModules.push(modules[i]);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ });
|
|
/******/ })
|
|
/******/ .then(onAccepted);
|
|
/******/ }
|
|
/******/
|
|
/******/ function applyInvalidatedModules() {
|
|
/******/ if (queuedInvalidatedModules) {
|
|
/******/ if (!currentUpdateApplyHandlers) currentUpdateApplyHandlers = [];
|
|
/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) {
|
|
/******/ queuedInvalidatedModules.forEach(function (moduleId) {
|
|
/******/ __webpack_require__.hmrI[key](
|
|
/******/ moduleId,
|
|
/******/ currentUpdateApplyHandlers
|
|
/******/ );
|
|
/******/ });
|
|
/******/ });
|
|
/******/ queuedInvalidatedModules = undefined;
|
|
/******/ return true;
|
|
/******/ }
|
|
/******/ }
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/publicPath */
|
|
/******/ (() => {
|
|
/******/ var scriptUrl;
|
|
/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
|
|
/******/ var document = __webpack_require__.g.document;
|
|
/******/ if (!scriptUrl && document) {
|
|
/******/ if (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')
|
|
/******/ scriptUrl = document.currentScript.src;
|
|
/******/ if (!scriptUrl) {
|
|
/******/ var scripts = document.getElementsByTagName("script");
|
|
/******/ if(scripts.length) {
|
|
/******/ var i = scripts.length - 1;
|
|
/******/ while (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
|
|
/******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
|
|
/******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
|
|
/******/ scriptUrl = scriptUrl.replace(/^blob:/, "").replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
|
|
/******/ __webpack_require__.p = scriptUrl + "../../";
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/jsonp chunk loading */
|
|
/******/ (() => {
|
|
/******/ // no baseURI
|
|
/******/
|
|
/******/ // object to store loaded and loading chunks
|
|
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
|
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
|
|
/******/ var installedChunks = __webpack_require__.hmrS_jsonp = __webpack_require__.hmrS_jsonp || {
|
|
/******/ 2: 0
|
|
/******/ };
|
|
/******/
|
|
/******/ // no chunk on demand loading
|
|
/******/
|
|
/******/ // no prefetching
|
|
/******/
|
|
/******/ // no preloaded
|
|
/******/
|
|
/******/ var currentUpdatedModulesList;
|
|
/******/ var waitingUpdateResolves = {};
|
|
/******/ function loadUpdateChunk(chunkId, updatedModulesList) {
|
|
/******/ currentUpdatedModulesList = updatedModulesList;
|
|
/******/ return new Promise((resolve, reject) => {
|
|
/******/ waitingUpdateResolves[chunkId] = resolve;
|
|
/******/ // start update chunk loading
|
|
/******/ var url = __webpack_require__.p + __webpack_require__.hu(chunkId);
|
|
/******/ // create error before stack unwound to get useful stacktrace later
|
|
/******/ var error = new Error();
|
|
/******/ var loadingEnded = (event) => {
|
|
/******/ if(waitingUpdateResolves[chunkId]) {
|
|
/******/ waitingUpdateResolves[chunkId] = undefined
|
|
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
|
|
/******/ var realSrc = event && event.target && event.target.src;
|
|
/******/ error.message = 'Loading hot update chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
|
|
/******/ error.name = 'ChunkLoadError';
|
|
/******/ error.type = errorType;
|
|
/******/ error.request = realSrc;
|
|
/******/ reject(error);
|
|
/******/ }
|
|
/******/ };
|
|
/******/ __webpack_require__.l(url, loadingEnded);
|
|
/******/ });
|
|
/******/ }
|
|
/******/
|
|
/******/ self["webpackHotUpdatearchitectui_html_free"] = (chunkId, moreModules, runtime) => {
|
|
/******/ for(var moduleId in moreModules) {
|
|
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
|
/******/ currentUpdate[moduleId] = moreModules[moduleId];
|
|
/******/ if(currentUpdatedModulesList) currentUpdatedModulesList.push(moduleId);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ if(runtime) currentUpdateRuntime.push(runtime);
|
|
/******/ if(waitingUpdateResolves[chunkId]) {
|
|
/******/ waitingUpdateResolves[chunkId]();
|
|
/******/ waitingUpdateResolves[chunkId] = undefined;
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ var currentUpdateChunks;
|
|
/******/ var currentUpdate;
|
|
/******/ var currentUpdateRemovedChunks;
|
|
/******/ var currentUpdateRuntime;
|
|
/******/ function applyHandler(options) {
|
|
/******/ if (__webpack_require__.f) delete __webpack_require__.f.jsonpHmr;
|
|
/******/ currentUpdateChunks = undefined;
|
|
/******/ function getAffectedModuleEffects(updateModuleId) {
|
|
/******/ var outdatedModules = [updateModuleId];
|
|
/******/ var outdatedDependencies = {};
|
|
/******/
|
|
/******/ var queue = outdatedModules.map(function (id) {
|
|
/******/ return {
|
|
/******/ chain: [id],
|
|
/******/ id: id
|
|
/******/ };
|
|
/******/ });
|
|
/******/ while (queue.length > 0) {
|
|
/******/ var queueItem = queue.pop();
|
|
/******/ var moduleId = queueItem.id;
|
|
/******/ var chain = queueItem.chain;
|
|
/******/ var module = __webpack_require__.c[moduleId];
|
|
/******/ if (
|
|
/******/ !module ||
|
|
/******/ (module.hot._selfAccepted && !module.hot._selfInvalidated)
|
|
/******/ )
|
|
/******/ continue;
|
|
/******/ if (module.hot._selfDeclined) {
|
|
/******/ return {
|
|
/******/ type: "self-declined",
|
|
/******/ chain: chain,
|
|
/******/ moduleId: moduleId
|
|
/******/ };
|
|
/******/ }
|
|
/******/ if (module.hot._main) {
|
|
/******/ return {
|
|
/******/ type: "unaccepted",
|
|
/******/ chain: chain,
|
|
/******/ moduleId: moduleId
|
|
/******/ };
|
|
/******/ }
|
|
/******/ for (var i = 0; i < module.parents.length; i++) {
|
|
/******/ var parentId = module.parents[i];
|
|
/******/ var parent = __webpack_require__.c[parentId];
|
|
/******/ if (!parent) continue;
|
|
/******/ if (parent.hot._declinedDependencies[moduleId]) {
|
|
/******/ return {
|
|
/******/ type: "declined",
|
|
/******/ chain: chain.concat([parentId]),
|
|
/******/ moduleId: moduleId,
|
|
/******/ parentId: parentId
|
|
/******/ };
|
|
/******/ }
|
|
/******/ if (outdatedModules.indexOf(parentId) !== -1) continue;
|
|
/******/ if (parent.hot._acceptedDependencies[moduleId]) {
|
|
/******/ if (!outdatedDependencies[parentId])
|
|
/******/ outdatedDependencies[parentId] = [];
|
|
/******/ addAllToSet(outdatedDependencies[parentId], [moduleId]);
|
|
/******/ continue;
|
|
/******/ }
|
|
/******/ delete outdatedDependencies[parentId];
|
|
/******/ outdatedModules.push(parentId);
|
|
/******/ queue.push({
|
|
/******/ chain: chain.concat([parentId]),
|
|
/******/ id: parentId
|
|
/******/ });
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ return {
|
|
/******/ type: "accepted",
|
|
/******/ moduleId: updateModuleId,
|
|
/******/ outdatedModules: outdatedModules,
|
|
/******/ outdatedDependencies: outdatedDependencies
|
|
/******/ };
|
|
/******/ }
|
|
/******/
|
|
/******/ function addAllToSet(a, b) {
|
|
/******/ for (var i = 0; i < b.length; i++) {
|
|
/******/ var item = b[i];
|
|
/******/ if (a.indexOf(item) === -1) a.push(item);
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ // at begin all updates modules are outdated
|
|
/******/ // the "outdated" status can propagate to parents if they don't accept the children
|
|
/******/ var outdatedDependencies = {};
|
|
/******/ var outdatedModules = [];
|
|
/******/ var appliedUpdate = {};
|
|
/******/
|
|
/******/ var warnUnexpectedRequire = function warnUnexpectedRequire(module) {
|
|
/******/ console.warn(
|
|
/******/ "[HMR] unexpected require(" + module.id + ") to disposed module"
|
|
/******/ );
|
|
/******/ };
|
|
/******/
|
|
/******/ for (var moduleId in currentUpdate) {
|
|
/******/ if (__webpack_require__.o(currentUpdate, moduleId)) {
|
|
/******/ var newModuleFactory = currentUpdate[moduleId];
|
|
/******/ var result = newModuleFactory
|
|
/******/ ? getAffectedModuleEffects(moduleId)
|
|
/******/ : {
|
|
/******/ type: "disposed",
|
|
/******/ moduleId: moduleId
|
|
/******/ };
|
|
/******/ /** @type {Error|false} */
|
|
/******/ var abortError = false;
|
|
/******/ var doApply = false;
|
|
/******/ var doDispose = false;
|
|
/******/ var chainInfo = "";
|
|
/******/ if (result.chain) {
|
|
/******/ chainInfo = "\nUpdate propagation: " + result.chain.join(" -> ");
|
|
/******/ }
|
|
/******/ switch (result.type) {
|
|
/******/ case "self-declined":
|
|
/******/ if (options.onDeclined) options.onDeclined(result);
|
|
/******/ if (!options.ignoreDeclined)
|
|
/******/ abortError = new Error(
|
|
/******/ "Aborted because of self decline: " +
|
|
/******/ result.moduleId +
|
|
/******/ chainInfo
|
|
/******/ );
|
|
/******/ break;
|
|
/******/ case "declined":
|
|
/******/ if (options.onDeclined) options.onDeclined(result);
|
|
/******/ if (!options.ignoreDeclined)
|
|
/******/ abortError = new Error(
|
|
/******/ "Aborted because of declined dependency: " +
|
|
/******/ result.moduleId +
|
|
/******/ " in " +
|
|
/******/ result.parentId +
|
|
/******/ chainInfo
|
|
/******/ );
|
|
/******/ break;
|
|
/******/ case "unaccepted":
|
|
/******/ if (options.onUnaccepted) options.onUnaccepted(result);
|
|
/******/ if (!options.ignoreUnaccepted)
|
|
/******/ abortError = new Error(
|
|
/******/ "Aborted because " + moduleId + " is not accepted" + chainInfo
|
|
/******/ );
|
|
/******/ break;
|
|
/******/ case "accepted":
|
|
/******/ if (options.onAccepted) options.onAccepted(result);
|
|
/******/ doApply = true;
|
|
/******/ break;
|
|
/******/ case "disposed":
|
|
/******/ if (options.onDisposed) options.onDisposed(result);
|
|
/******/ doDispose = true;
|
|
/******/ break;
|
|
/******/ default:
|
|
/******/ throw new Error("Unexception type " + result.type);
|
|
/******/ }
|
|
/******/ if (abortError) {
|
|
/******/ return {
|
|
/******/ error: abortError
|
|
/******/ };
|
|
/******/ }
|
|
/******/ if (doApply) {
|
|
/******/ appliedUpdate[moduleId] = newModuleFactory;
|
|
/******/ addAllToSet(outdatedModules, result.outdatedModules);
|
|
/******/ for (moduleId in result.outdatedDependencies) {
|
|
/******/ if (__webpack_require__.o(result.outdatedDependencies, moduleId)) {
|
|
/******/ if (!outdatedDependencies[moduleId])
|
|
/******/ outdatedDependencies[moduleId] = [];
|
|
/******/ addAllToSet(
|
|
/******/ outdatedDependencies[moduleId],
|
|
/******/ result.outdatedDependencies[moduleId]
|
|
/******/ );
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ if (doDispose) {
|
|
/******/ addAllToSet(outdatedModules, [result.moduleId]);
|
|
/******/ appliedUpdate[moduleId] = warnUnexpectedRequire;
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ currentUpdate = undefined;
|
|
/******/
|
|
/******/ // Store self accepted outdated modules to require them later by the module system
|
|
/******/ var outdatedSelfAcceptedModules = [];
|
|
/******/ for (var j = 0; j < outdatedModules.length; j++) {
|
|
/******/ var outdatedModuleId = outdatedModules[j];
|
|
/******/ var module = __webpack_require__.c[outdatedModuleId];
|
|
/******/ if (
|
|
/******/ module &&
|
|
/******/ (module.hot._selfAccepted || module.hot._main) &&
|
|
/******/ // removed self-accepted modules should not be required
|
|
/******/ appliedUpdate[outdatedModuleId] !== warnUnexpectedRequire &&
|
|
/******/ // when called invalidate self-accepting is not possible
|
|
/******/ !module.hot._selfInvalidated
|
|
/******/ ) {
|
|
/******/ outdatedSelfAcceptedModules.push({
|
|
/******/ module: outdatedModuleId,
|
|
/******/ require: module.hot._requireSelf,
|
|
/******/ errorHandler: module.hot._selfAccepted
|
|
/******/ });
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ var moduleOutdatedDependencies;
|
|
/******/
|
|
/******/ return {
|
|
/******/ dispose: function () {
|
|
/******/ currentUpdateRemovedChunks.forEach(function (chunkId) {
|
|
/******/ delete installedChunks[chunkId];
|
|
/******/ });
|
|
/******/ currentUpdateRemovedChunks = undefined;
|
|
/******/
|
|
/******/ var idx;
|
|
/******/ var queue = outdatedModules.slice();
|
|
/******/ while (queue.length > 0) {
|
|
/******/ var moduleId = queue.pop();
|
|
/******/ var module = __webpack_require__.c[moduleId];
|
|
/******/ if (!module) continue;
|
|
/******/
|
|
/******/ var data = {};
|
|
/******/
|
|
/******/ // Call dispose handlers
|
|
/******/ var disposeHandlers = module.hot._disposeHandlers;
|
|
/******/ for (j = 0; j < disposeHandlers.length; j++) {
|
|
/******/ disposeHandlers[j].call(null, data);
|
|
/******/ }
|
|
/******/ __webpack_require__.hmrD[moduleId] = data;
|
|
/******/
|
|
/******/ // disable module (this disables requires from this module)
|
|
/******/ module.hot.active = false;
|
|
/******/
|
|
/******/ // remove module from cache
|
|
/******/ delete __webpack_require__.c[moduleId];
|
|
/******/
|
|
/******/ // when disposing there is no need to call dispose handler
|
|
/******/ delete outdatedDependencies[moduleId];
|
|
/******/
|
|
/******/ // remove "parents" references from all children
|
|
/******/ for (j = 0; j < module.children.length; j++) {
|
|
/******/ var child = __webpack_require__.c[module.children[j]];
|
|
/******/ if (!child) continue;
|
|
/******/ idx = child.parents.indexOf(moduleId);
|
|
/******/ if (idx >= 0) {
|
|
/******/ child.parents.splice(idx, 1);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ // remove outdated dependency from module children
|
|
/******/ var dependency;
|
|
/******/ for (var outdatedModuleId in outdatedDependencies) {
|
|
/******/ if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) {
|
|
/******/ module = __webpack_require__.c[outdatedModuleId];
|
|
/******/ if (module) {
|
|
/******/ moduleOutdatedDependencies =
|
|
/******/ outdatedDependencies[outdatedModuleId];
|
|
/******/ for (j = 0; j < moduleOutdatedDependencies.length; j++) {
|
|
/******/ dependency = moduleOutdatedDependencies[j];
|
|
/******/ idx = module.children.indexOf(dependency);
|
|
/******/ if (idx >= 0) module.children.splice(idx, 1);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ },
|
|
/******/ apply: function (reportError) {
|
|
/******/ var acceptPromises = [];
|
|
/******/ // insert new code
|
|
/******/ for (var updateModuleId in appliedUpdate) {
|
|
/******/ if (__webpack_require__.o(appliedUpdate, updateModuleId)) {
|
|
/******/ __webpack_require__.m[updateModuleId] = appliedUpdate[updateModuleId];
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ // run new runtime modules
|
|
/******/ for (var i = 0; i < currentUpdateRuntime.length; i++) {
|
|
/******/ currentUpdateRuntime[i](__webpack_require__);
|
|
/******/ }
|
|
/******/
|
|
/******/ // call accept handlers
|
|
/******/ for (var outdatedModuleId in outdatedDependencies) {
|
|
/******/ if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) {
|
|
/******/ var module = __webpack_require__.c[outdatedModuleId];
|
|
/******/ if (module) {
|
|
/******/ moduleOutdatedDependencies =
|
|
/******/ outdatedDependencies[outdatedModuleId];
|
|
/******/ var callbacks = [];
|
|
/******/ var errorHandlers = [];
|
|
/******/ var dependenciesForCallbacks = [];
|
|
/******/ for (var j = 0; j < moduleOutdatedDependencies.length; j++) {
|
|
/******/ var dependency = moduleOutdatedDependencies[j];
|
|
/******/ var acceptCallback =
|
|
/******/ module.hot._acceptedDependencies[dependency];
|
|
/******/ var errorHandler =
|
|
/******/ module.hot._acceptedErrorHandlers[dependency];
|
|
/******/ if (acceptCallback) {
|
|
/******/ if (callbacks.indexOf(acceptCallback) !== -1) continue;
|
|
/******/ callbacks.push(acceptCallback);
|
|
/******/ errorHandlers.push(errorHandler);
|
|
/******/ dependenciesForCallbacks.push(dependency);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ for (var k = 0; k < callbacks.length; k++) {
|
|
/******/ var result;
|
|
/******/ try {
|
|
/******/ result = callbacks[k].call(null, moduleOutdatedDependencies);
|
|
/******/ } catch (err) {
|
|
/******/ if (typeof errorHandlers[k] === "function") {
|
|
/******/ try {
|
|
/******/ errorHandlers[k](err, {
|
|
/******/ moduleId: outdatedModuleId,
|
|
/******/ dependencyId: dependenciesForCallbacks[k]
|
|
/******/ });
|
|
/******/ } catch (err2) {
|
|
/******/ if (options.onErrored) {
|
|
/******/ options.onErrored({
|
|
/******/ type: "accept-error-handler-errored",
|
|
/******/ moduleId: outdatedModuleId,
|
|
/******/ dependencyId: dependenciesForCallbacks[k],
|
|
/******/ error: err2,
|
|
/******/ originalError: err
|
|
/******/ });
|
|
/******/ }
|
|
/******/ if (!options.ignoreErrored) {
|
|
/******/ reportError(err2);
|
|
/******/ reportError(err);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ } else {
|
|
/******/ if (options.onErrored) {
|
|
/******/ options.onErrored({
|
|
/******/ type: "accept-errored",
|
|
/******/ moduleId: outdatedModuleId,
|
|
/******/ dependencyId: dependenciesForCallbacks[k],
|
|
/******/ error: err
|
|
/******/ });
|
|
/******/ }
|
|
/******/ if (!options.ignoreErrored) {
|
|
/******/ reportError(err);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ if (result && typeof result.then === "function") {
|
|
/******/ acceptPromises.push(result);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/
|
|
/******/ var onAccepted = function () {
|
|
/******/ // Load self accepted modules
|
|
/******/ for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) {
|
|
/******/ var item = outdatedSelfAcceptedModules[o];
|
|
/******/ var moduleId = item.module;
|
|
/******/ try {
|
|
/******/ item.require(moduleId);
|
|
/******/ } catch (err) {
|
|
/******/ if (typeof item.errorHandler === "function") {
|
|
/******/ try {
|
|
/******/ item.errorHandler(err, {
|
|
/******/ moduleId: moduleId,
|
|
/******/ module: __webpack_require__.c[moduleId]
|
|
/******/ });
|
|
/******/ } catch (err1) {
|
|
/******/ if (options.onErrored) {
|
|
/******/ options.onErrored({
|
|
/******/ type: "self-accept-error-handler-errored",
|
|
/******/ moduleId: moduleId,
|
|
/******/ error: err1,
|
|
/******/ originalError: err
|
|
/******/ });
|
|
/******/ }
|
|
/******/ if (!options.ignoreErrored) {
|
|
/******/ reportError(err1);
|
|
/******/ reportError(err);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ } else {
|
|
/******/ if (options.onErrored) {
|
|
/******/ options.onErrored({
|
|
/******/ type: "self-accept-errored",
|
|
/******/ moduleId: moduleId,
|
|
/******/ error: err
|
|
/******/ });
|
|
/******/ }
|
|
/******/ if (!options.ignoreErrored) {
|
|
/******/ reportError(err);
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ return Promise.all(acceptPromises)
|
|
/******/ .then(onAccepted)
|
|
/******/ .then(function () {
|
|
/******/ return outdatedModules;
|
|
/******/ });
|
|
/******/ }
|
|
/******/ };
|
|
/******/ }
|
|
/******/ __webpack_require__.hmrI.jsonp = function (moduleId, applyHandlers) {
|
|
/******/ if (!currentUpdate) {
|
|
/******/ currentUpdate = {};
|
|
/******/ currentUpdateRuntime = [];
|
|
/******/ currentUpdateRemovedChunks = [];
|
|
/******/ applyHandlers.push(applyHandler);
|
|
/******/ }
|
|
/******/ if (!__webpack_require__.o(currentUpdate, moduleId)) {
|
|
/******/ currentUpdate[moduleId] = __webpack_require__.m[moduleId];
|
|
/******/ }
|
|
/******/ };
|
|
/******/ __webpack_require__.hmrC.jsonp = function (
|
|
/******/ chunkIds,
|
|
/******/ removedChunks,
|
|
/******/ removedModules,
|
|
/******/ promises,
|
|
/******/ applyHandlers,
|
|
/******/ updatedModulesList
|
|
/******/ ) {
|
|
/******/ applyHandlers.push(applyHandler);
|
|
/******/ currentUpdateChunks = {};
|
|
/******/ currentUpdateRemovedChunks = removedChunks;
|
|
/******/ currentUpdate = removedModules.reduce(function (obj, key) {
|
|
/******/ obj[key] = false;
|
|
/******/ return obj;
|
|
/******/ }, {});
|
|
/******/ currentUpdateRuntime = [];
|
|
/******/ chunkIds.forEach(function (chunkId) {
|
|
/******/ if (
|
|
/******/ __webpack_require__.o(installedChunks, chunkId) &&
|
|
/******/ installedChunks[chunkId] !== undefined
|
|
/******/ ) {
|
|
/******/ promises.push(loadUpdateChunk(chunkId, updatedModulesList));
|
|
/******/ currentUpdateChunks[chunkId] = true;
|
|
/******/ } else {
|
|
/******/ currentUpdateChunks[chunkId] = false;
|
|
/******/ }
|
|
/******/ });
|
|
/******/ if (__webpack_require__.f) {
|
|
/******/ __webpack_require__.f.jsonpHmr = function (chunkId, promises) {
|
|
/******/ if (
|
|
/******/ currentUpdateChunks &&
|
|
/******/ __webpack_require__.o(currentUpdateChunks, chunkId) &&
|
|
/******/ !currentUpdateChunks[chunkId]
|
|
/******/ ) {
|
|
/******/ promises.push(loadUpdateChunk(chunkId));
|
|
/******/ currentUpdateChunks[chunkId] = true;
|
|
/******/ }
|
|
/******/ };
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ __webpack_require__.hmrM = () => {
|
|
/******/ if (typeof fetch === "undefined") throw new Error("No browser support: need fetch API");
|
|
/******/ return fetch(__webpack_require__.p + __webpack_require__.hmrF()).then((response) => {
|
|
/******/ if(response.status === 404) return; // no update available
|
|
/******/ if(!response.ok) throw new Error("Failed to fetch update manifest " + response.statusText);
|
|
/******/ return response.json();
|
|
/******/ });
|
|
/******/ };
|
|
/******/
|
|
/******/ // no on chunks loaded
|
|
/******/
|
|
/******/ // no jsonp function
|
|
/******/ })();
|
|
/******/
|
|
/************************************************************************/
|
|
/******/
|
|
/******/ // module cache are used so entry inlining is disabled
|
|
/******/ // startup
|
|
/******/ // Load entry module and return exports
|
|
/******/ var __webpack_exports__ = __webpack_require__(111);
|
|
/******/
|
|
/******/ })()
|
|
; |