ninefolio/public/build/vendors~fullcalendar.js

14175 lines
1.4 MiB

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["vendors~fullcalendar"],{
/***/ "./node_modules/@fullcalendar/core/locales/fr.js":
/*!*******************************************************!*\
!*** ./node_modules/@fullcalendar/core/locales/fr.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
(function (global, factory) {
true ? module.exports = factory() :
undefined;
}(this, function () { 'use strict';
var fr = {
code: "fr",
week: {
dow: 1,
doy: 4 // The week that contains Jan 4th is the first week of the year.
},
buttonText: {
prev: "Précédent",
next: "Suivant",
today: "Aujourd'hui",
year: "Année",
month: "Mois",
week: "Semaine",
day: "Jour",
list: "Planning"
},
weekLabel: "Sem.",
allDayHtml: "Toute la<br/>journée",
eventLimitText: "en plus",
noEventsMessage: "Aucun événement à afficher"
};
return fr;
}));
/***/ }),
/***/ "./node_modules/@fullcalendar/core/main.css":
/*!**************************************************!*\
!*** ./node_modules/@fullcalendar/core/main.css ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "./node_modules/@fullcalendar/core/main.esm.js":
/*!*****************************************************!*\
!*** ./node_modules/@fullcalendar/core/main.esm.js ***!
\*****************************************************/
/*! exports provided: Calendar, Component, ComponentContext, DateComponent, DateEnv, DateProfileGenerator, DayHeader, DaySeries, DayTable, ElementDragging, ElementScrollController, EmitterMixin, EventApi, FgEventRenderer, FillRenderer, Interaction, Mixin, NamedTimeZoneImpl, PositionCache, ScrollComponent, ScrollController, Slicer, Splitter, Theme, View, WindowScrollController, addDays, addDurations, addMs, addWeeks, allowContextMenu, allowSelection, appendToElement, applyAll, applyMutationToEventStore, applyStyle, applyStyleProp, asRoughMinutes, asRoughMs, asRoughSeconds, buildGotoAnchorHtml, buildSegCompareObj, capitaliseFirstLetter, combineEventUis, compareByFieldSpec, compareByFieldSpecs, compareNumbers, compensateScroll, computeClippingRect, computeEdges, computeEventDraggable, computeEventEndResizable, computeEventStartResizable, computeFallbackHeaderFormat, computeHeightAndMargins, computeInnerRect, computeRect, computeVisibleDayRange, config, constrainPoint, createDuration, createElement, createEmptyEventStore, createEventInstance, createFormatter, createPlugin, cssToStr, debounce, diffDates, diffDayAndTime, diffDays, diffPoints, diffWeeks, diffWholeDays, diffWholeWeeks, disableCursor, distributeHeight, elementClosest, elementMatches, enableCursor, eventTupleToStore, filterEventStoreDefs, filterHash, findChildren, findElements, flexibleCompare, forceClassName, formatDate, formatIsoTimeString, formatRange, getAllDayHtml, getClippingParents, getDayClasses, getElSeg, getRectCenter, getRelevantEvents, globalDefaults, greatestDurationDenominator, hasBgRendering, htmlEscape, htmlToElement, insertAfterElement, interactionSettingsStore, interactionSettingsToStore, intersectRanges, intersectRects, isArraysEqual, isDateSpansEqual, isInt, isInteractionValid, isMultiDayRange, isPropsEqual, isPropsValid, isSingleDay, isValidDate, listenBySelector, mapHash, matchCellWidths, memoize, memoizeOutput, memoizeRendering, mergeEventStores, multiplyDuration, padStart, parseBusinessHours, parseDragMeta, parseEventDef, parseFieldSpecs, parseMarker, pointInsideRect, prependToElement, preventContextMenu, preventDefault, preventSelection, processScopedUiProps, rangeContainsMarker, rangeContainsRange, rangesEqual, rangesIntersect, refineProps, removeElement, removeExact, renderDateCell, requestJson, sliceEventStore, startOfDay, subtractInnerElHeight, translateRect, uncompensateScroll, undistributeHeight, unpromisify, version, whenTransitionDone, wholeDivideDurations */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Calendar", function() { return Calendar; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Component", function() { return Component; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ComponentContext", function() { return ComponentContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DateComponent", function() { return DateComponent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DateEnv", function() { return DateEnv; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DateProfileGenerator", function() { return DateProfileGenerator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DayHeader", function() { return DayHeader; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DaySeries", function() { return DaySeries; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DayTable", function() { return DayTable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ElementDragging", function() { return ElementDragging; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ElementScrollController", function() { return ElementScrollController; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmitterMixin", function() { return EmitterMixin; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EventApi", function() { return EventApi; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FgEventRenderer", function() { return FgEventRenderer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FillRenderer", function() { return FillRenderer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Interaction", function() { return Interaction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Mixin", function() { return Mixin; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NamedTimeZoneImpl", function() { return NamedTimeZoneImpl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PositionCache", function() { return PositionCache; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollComponent", function() { return ScrollComponent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollController", function() { return ScrollController; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Slicer", function() { return Slicer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Splitter", function() { return Splitter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Theme", function() { return Theme; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "View", function() { return View; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WindowScrollController", function() { return WindowScrollController; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addDays", function() { return addDays; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addDurations", function() { return addDurations; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addMs", function() { return addMs; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addWeeks", function() { return addWeeks; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "allowContextMenu", function() { return allowContextMenu; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "allowSelection", function() { return allowSelection; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "appendToElement", function() { return appendToElement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyAll", function() { return applyAll; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyMutationToEventStore", function() { return applyMutationToEventStore; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyStyle", function() { return applyStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyStyleProp", function() { return applyStyleProp; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asRoughMinutes", function() { return asRoughMinutes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asRoughMs", function() { return asRoughMs; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asRoughSeconds", function() { return asRoughSeconds; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildGotoAnchorHtml", function() { return buildGotoAnchorHtml; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildSegCompareObj", function() { return buildSegCompareObj; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "capitaliseFirstLetter", function() { return capitaliseFirstLetter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineEventUis", function() { return combineEventUis; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compareByFieldSpec", function() { return compareByFieldSpec; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compareByFieldSpecs", function() { return compareByFieldSpecs; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compareNumbers", function() { return compareNumbers; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compensateScroll", function() { return compensateScroll; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeClippingRect", function() { return computeClippingRect; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeEdges", function() { return computeEdges; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeEventDraggable", function() { return computeEventDraggable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeEventEndResizable", function() { return computeEventEndResizable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeEventStartResizable", function() { return computeEventStartResizable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeFallbackHeaderFormat", function() { return computeFallbackHeaderFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeHeightAndMargins", function() { return computeHeightAndMargins; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeInnerRect", function() { return computeInnerRect; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeRect", function() { return computeRect; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeVisibleDayRange", function() { return computeVisibleDayRange; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "config", function() { return config; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "constrainPoint", function() { return constrainPoint; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createDuration", function() { return createDuration; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createElement", function() { return createElement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createEmptyEventStore", function() { return createEmptyEventStore; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createEventInstance", function() { return createEventInstance; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createFormatter", function() { return createFormatter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createPlugin", function() { return createPlugin; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "cssToStr", function() { return cssToStr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffDates", function() { return diffDates; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffDayAndTime", function() { return diffDayAndTime; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffDays", function() { return diffDays; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffPoints", function() { return diffPoints; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffWeeks", function() { return diffWeeks; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffWholeDays", function() { return diffWholeDays; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "diffWholeWeeks", function() { return diffWholeWeeks; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "disableCursor", function() { return disableCursor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distributeHeight", function() { return distributeHeight; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementClosest", function() { return elementClosest; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementMatches", function() { return elementMatches; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "enableCursor", function() { return enableCursor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "eventTupleToStore", function() { return eventTupleToStore; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filterEventStoreDefs", function() { return filterEventStoreDefs; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filterHash", function() { return filterHash; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findChildren", function() { return findChildren; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findElements", function() { return findElements; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "flexibleCompare", function() { return flexibleCompare; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "forceClassName", function() { return forceClassName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatDate", function() { return formatDate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatIsoTimeString", function() { return formatIsoTimeString; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatRange", function() { return formatRange; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllDayHtml", function() { return getAllDayHtml; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getClippingParents", function() { return getClippingParents; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getDayClasses", function() { return getDayClasses; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getElSeg", function() { return getElSeg; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRectCenter", function() { return getRectCenter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRelevantEvents", function() { return getRelevantEvents; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "globalDefaults", function() { return globalDefaults; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "greatestDurationDenominator", function() { return greatestDurationDenominator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasBgRendering", function() { return hasBgRendering; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "htmlEscape", function() { return htmlEscape; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "htmlToElement", function() { return htmlToElement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "insertAfterElement", function() { return insertAfterElement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interactionSettingsStore", function() { return interactionSettingsStore; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interactionSettingsToStore", function() { return interactionSettingsToStore; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "intersectRanges", function() { return intersectRanges; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "intersectRects", function() { return intersectRects; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isArraysEqual", function() { return isArraysEqual; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isDateSpansEqual", function() { return isDateSpansEqual; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInt", function() { return isInt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteractionValid", function() { return isInteractionValid; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isMultiDayRange", function() { return isMultiDayRange; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPropsEqual", function() { return isPropsEqual; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPropsValid", function() { return isPropsValid; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isSingleDay", function() { return isSingleDay; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isValidDate", function() { return isValidDate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "listenBySelector", function() { return listenBySelector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mapHash", function() { return mapHash; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "matchCellWidths", function() { return matchCellWidths; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "memoize", function() { return memoize; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "memoizeOutput", function() { return memoizeOutput; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "memoizeRendering", function() { return memoizeRendering; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeEventStores", function() { return mergeEventStores; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "multiplyDuration", function() { return multiplyDuration; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "padStart", function() { return padStart; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseBusinessHours", function() { return parseBusinessHours; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseDragMeta", function() { return parseDragMeta; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseEventDef", function() { return parseEventDef; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseFieldSpecs", function() { return parseFieldSpecs; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseMarker", function() { return parse; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pointInsideRect", function() { return pointInsideRect; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prependToElement", function() { return prependToElement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preventContextMenu", function() { return preventContextMenu; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preventDefault", function() { return preventDefault; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preventSelection", function() { return preventSelection; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "processScopedUiProps", function() { return processScopedUiProps; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rangeContainsMarker", function() { return rangeContainsMarker; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rangeContainsRange", function() { return rangeContainsRange; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rangesEqual", function() { return rangesEqual; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rangesIntersect", function() { return rangesIntersect; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "refineProps", function() { return refineProps; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeElement", function() { return removeElement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeExact", function() { return removeExact; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renderDateCell", function() { return renderDateCell; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "requestJson", function() { return requestJson; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sliceEventStore", function() { return sliceEventStore; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "startOfDay", function() { return startOfDay; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subtractInnerElHeight", function() { return subtractInnerElHeight; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "translateRect", function() { return translateRect; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "uncompensateScroll", function() { return uncompensateScroll; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "undistributeHeight", function() { return undistributeHeight; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unpromisify", function() { return unpromisify; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "version", function() { return version; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "whenTransitionDone", function() { return whenTransitionDone; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "wholeDivideDurations", function() { return wholeDivideDurations; });
/*!
FullCalendar Core Package v4.4.2
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
// Creating
// ----------------------------------------------------------------------------------------------------------------
var elementPropHash = {
className: true,
colSpan: true,
rowSpan: true
};
var containerTagHash = {
'<tr': 'tbody',
'<td': 'tr'
};
function createElement(tagName, attrs, content) {
var el = document.createElement(tagName);
if (attrs) {
for (var attrName in attrs) {
if (attrName === 'style') {
applyStyle(el, attrs[attrName]);
}
else if (elementPropHash[attrName]) {
el[attrName] = attrs[attrName];
}
else {
el.setAttribute(attrName, attrs[attrName]);
}
}
}
if (typeof content === 'string') {
el.innerHTML = content; // shortcut. no need to process HTML in any way
}
else if (content != null) {
appendToElement(el, content);
}
return el;
}
function htmlToElement(html) {
html = html.trim();
var container = document.createElement(computeContainerTag(html));
container.innerHTML = html;
return container.firstChild;
}
function htmlToElements(html) {
return Array.prototype.slice.call(htmlToNodeList(html));
}
function htmlToNodeList(html) {
html = html.trim();
var container = document.createElement(computeContainerTag(html));
container.innerHTML = html;
return container.childNodes;
}
// assumes html already trimmed and tag names are lowercase
function computeContainerTag(html) {
return containerTagHash[html.substr(0, 3) // faster than using regex
] || 'div';
}
function appendToElement(el, content) {
var childNodes = normalizeContent(content);
for (var i = 0; i < childNodes.length; i++) {
el.appendChild(childNodes[i]);
}
}
function prependToElement(parent, content) {
var newEls = normalizeContent(content);
var afterEl = parent.firstChild || null; // if no firstChild, will append to end, but that's okay, b/c there were no children
for (var i = 0; i < newEls.length; i++) {
parent.insertBefore(newEls[i], afterEl);
}
}
function insertAfterElement(refEl, content) {
var newEls = normalizeContent(content);
var afterEl = refEl.nextSibling || null;
for (var i = 0; i < newEls.length; i++) {
refEl.parentNode.insertBefore(newEls[i], afterEl);
}
}
function normalizeContent(content) {
var els;
if (typeof content === 'string') {
els = htmlToElements(content);
}
else if (content instanceof Node) {
els = [content];
}
else { // Node[] or NodeList
els = Array.prototype.slice.call(content);
}
return els;
}
function removeElement(el) {
if (el.parentNode) {
el.parentNode.removeChild(el);
}
}
// Querying
// ----------------------------------------------------------------------------------------------------------------
// from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
var matchesMethod = Element.prototype.matches ||
Element.prototype.matchesSelector ||
Element.prototype.msMatchesSelector;
var closestMethod = Element.prototype.closest || function (selector) {
// polyfill
var el = this;
if (!document.documentElement.contains(el)) {
return null;
}
do {
if (elementMatches(el, selector)) {
return el;
}
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
function elementClosest(el, selector) {
return closestMethod.call(el, selector);
}
function elementMatches(el, selector) {
return matchesMethod.call(el, selector);
}
// accepts multiple subject els
// returns a real array. good for methods like forEach
function findElements(container, selector) {
var containers = container instanceof HTMLElement ? [container] : container;
var allMatches = [];
for (var i = 0; i < containers.length; i++) {
var matches = containers[i].querySelectorAll(selector);
for (var j = 0; j < matches.length; j++) {
allMatches.push(matches[j]);
}
}
return allMatches;
}
// accepts multiple subject els
// only queries direct child elements
function findChildren(parent, selector) {
var parents = parent instanceof HTMLElement ? [parent] : parent;
var allMatches = [];
for (var i = 0; i < parents.length; i++) {
var childNodes = parents[i].children; // only ever elements
for (var j = 0; j < childNodes.length; j++) {
var childNode = childNodes[j];
if (!selector || elementMatches(childNode, selector)) {
allMatches.push(childNode);
}
}
}
return allMatches;
}
// Attributes
// ----------------------------------------------------------------------------------------------------------------
function forceClassName(el, className, bool) {
if (bool) {
el.classList.add(className);
}
else {
el.classList.remove(className);
}
}
// Style
// ----------------------------------------------------------------------------------------------------------------
var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
function applyStyle(el, props) {
for (var propName in props) {
applyStyleProp(el, propName, props[propName]);
}
}
function applyStyleProp(el, name, val) {
if (val == null) {
el.style[name] = '';
}
else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
el.style[name] = val + 'px';
}
else {
el.style[name] = val;
}
}
function pointInsideRect(point, rect) {
return point.left >= rect.left &&
point.left < rect.right &&
point.top >= rect.top &&
point.top < rect.bottom;
}
// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
function intersectRects(rect1, rect2) {
var res = {
left: Math.max(rect1.left, rect2.left),
right: Math.min(rect1.right, rect2.right),
top: Math.max(rect1.top, rect2.top),
bottom: Math.min(rect1.bottom, rect2.bottom)
};
if (res.left < res.right && res.top < res.bottom) {
return res;
}
return false;
}
function translateRect(rect, deltaX, deltaY) {
return {
left: rect.left + deltaX,
right: rect.right + deltaX,
top: rect.top + deltaY,
bottom: rect.bottom + deltaY
};
}
// Returns a new point that will have been moved to reside within the given rectangle
function constrainPoint(point, rect) {
return {
left: Math.min(Math.max(point.left, rect.left), rect.right),
top: Math.min(Math.max(point.top, rect.top), rect.bottom)
};
}
// Returns a point that is the center of the given rectangle
function getRectCenter(rect) {
return {
left: (rect.left + rect.right) / 2,
top: (rect.top + rect.bottom) / 2
};
}
// Subtracts point2's coordinates from point1's coordinates, returning a delta
function diffPoints(point1, point2) {
return {
left: point1.left - point2.left,
top: point1.top - point2.top
};
}
// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side
var isRtlScrollbarOnLeft = null;
function getIsRtlScrollbarOnLeft() {
if (isRtlScrollbarOnLeft === null) {
isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
}
return isRtlScrollbarOnLeft;
}
function computeIsRtlScrollbarOnLeft() {
var outerEl = createElement('div', {
style: {
position: 'absolute',
top: -1000,
left: 0,
border: 0,
padding: 0,
overflow: 'scroll',
direction: 'rtl'
}
}, '<div></div>');
document.body.appendChild(outerEl);
var innerEl = outerEl.firstChild;
var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
removeElement(outerEl);
return res;
}
// The scrollbar width computations in computeEdges are sometimes flawed when it comes to
// retina displays, rounding, and IE11. Massage them into a usable value.
function sanitizeScrollbarWidth(width) {
width = Math.max(0, width); // no negatives
width = Math.round(width);
return width;
}
function computeEdges(el, getPadding) {
if (getPadding === void 0) { getPadding = false; }
var computedStyle = window.getComputedStyle(el);
var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
// must use offset(Width|Height) because compatible with client(Width|Height)
var scrollbarLeftRight = sanitizeScrollbarWidth(el.offsetWidth - el.clientWidth - borderLeft - borderRight);
var scrollbarBottom = sanitizeScrollbarWidth(el.offsetHeight - el.clientHeight - borderTop - borderBottom);
var res = {
borderLeft: borderLeft,
borderRight: borderRight,
borderTop: borderTop,
borderBottom: borderBottom,
scrollbarBottom: scrollbarBottom,
scrollbarLeft: 0,
scrollbarRight: 0
};
if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
res.scrollbarLeft = scrollbarLeftRight;
}
else {
res.scrollbarRight = scrollbarLeftRight;
}
if (getPadding) {
res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
}
return res;
}
function computeInnerRect(el, goWithinPadding) {
if (goWithinPadding === void 0) { goWithinPadding = false; }
var outerRect = computeRect(el);
var edges = computeEdges(el, goWithinPadding);
var res = {
left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
right: outerRect.right - edges.borderRight - edges.scrollbarRight,
top: outerRect.top + edges.borderTop,
bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom
};
if (goWithinPadding) {
res.left += edges.paddingLeft;
res.right -= edges.paddingRight;
res.top += edges.paddingTop;
res.bottom -= edges.paddingBottom;
}
return res;
}
function computeRect(el) {
var rect = el.getBoundingClientRect();
return {
left: rect.left + window.pageXOffset,
top: rect.top + window.pageYOffset,
right: rect.right + window.pageXOffset,
bottom: rect.bottom + window.pageYOffset
};
}
function computeViewportRect() {
return {
left: window.pageXOffset,
right: window.pageXOffset + document.documentElement.clientWidth,
top: window.pageYOffset,
bottom: window.pageYOffset + document.documentElement.clientHeight
};
}
function computeHeightAndMargins(el) {
return el.getBoundingClientRect().height + computeVMargins(el);
}
function computeVMargins(el) {
var computed = window.getComputedStyle(el);
return parseInt(computed.marginTop, 10) +
parseInt(computed.marginBottom, 10);
}
// does not return window
function getClippingParents(el) {
var parents = [];
while (el instanceof HTMLElement) { // will stop when gets to document or null
var computedStyle = window.getComputedStyle(el);
if (computedStyle.position === 'fixed') {
break;
}
if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
parents.push(el);
}
el = el.parentNode;
}
return parents;
}
function computeClippingRect(el) {
return getClippingParents(el)
.map(function (el) {
return computeInnerRect(el);
})
.concat(computeViewportRect())
.reduce(function (rect0, rect1) {
return intersectRects(rect0, rect1) || rect1; // should always intersect
});
}
// Stops a mouse/touch event from doing it's native browser action
function preventDefault(ev) {
ev.preventDefault();
}
// Event Delegation
// ----------------------------------------------------------------------------------------------------------------
function listenBySelector(container, eventType, selector, handler) {
function realHandler(ev) {
var matchedChild = elementClosest(ev.target, selector);
if (matchedChild) {
handler.call(matchedChild, ev, matchedChild);
}
}
container.addEventListener(eventType, realHandler);
return function () {
container.removeEventListener(eventType, realHandler);
};
}
function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
var currentMatchedChild;
return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) {
if (matchedChild !== currentMatchedChild) {
currentMatchedChild = matchedChild;
onMouseEnter(ev, matchedChild);
var realOnMouseLeave_1 = function (ev) {
currentMatchedChild = null;
onMouseLeave(ev, matchedChild);
matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1);
};
// listen to the next mouseleave, and then unattach
matchedChild.addEventListener('mouseleave', realOnMouseLeave_1);
}
});
}
// Animation
// ----------------------------------------------------------------------------------------------------------------
var transitionEventNames = [
'webkitTransitionEnd',
'otransitionend',
'oTransitionEnd',
'msTransitionEnd',
'transitionend'
];
// triggered only when the next single subsequent transition finishes
function whenTransitionDone(el, callback) {
var realCallback = function (ev) {
callback(ev);
transitionEventNames.forEach(function (eventName) {
el.removeEventListener(eventName, realCallback);
});
};
transitionEventNames.forEach(function (eventName) {
el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
});
}
var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
// Adding
function addWeeks(m, n) {
var a = dateToUtcArray(m);
a[2] += n * 7;
return arrayToUtcDate(a);
}
function addDays(m, n) {
var a = dateToUtcArray(m);
a[2] += n;
return arrayToUtcDate(a);
}
function addMs(m, n) {
var a = dateToUtcArray(m);
a[6] += n;
return arrayToUtcDate(a);
}
// Diffing (all return floats)
function diffWeeks(m0, m1) {
return diffDays(m0, m1) / 7;
}
function diffDays(m0, m1) {
return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
}
function diffHours(m0, m1) {
return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
}
function diffMinutes(m0, m1) {
return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
}
function diffSeconds(m0, m1) {
return (m1.valueOf() - m0.valueOf()) / 1000;
}
function diffDayAndTime(m0, m1) {
var m0day = startOfDay(m0);
var m1day = startOfDay(m1);
return {
years: 0,
months: 0,
days: Math.round(diffDays(m0day, m1day)),
milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf())
};
}
// Diffing Whole Units
function diffWholeWeeks(m0, m1) {
var d = diffWholeDays(m0, m1);
if (d !== null && d % 7 === 0) {
return d / 7;
}
return null;
}
function diffWholeDays(m0, m1) {
if (timeAsMs(m0) === timeAsMs(m1)) {
return Math.round(diffDays(m0, m1));
}
return null;
}
// Start-Of
function startOfDay(m) {
return arrayToUtcDate([
m.getUTCFullYear(),
m.getUTCMonth(),
m.getUTCDate()
]);
}
function startOfHour(m) {
return arrayToUtcDate([
m.getUTCFullYear(),
m.getUTCMonth(),
m.getUTCDate(),
m.getUTCHours()
]);
}
function startOfMinute(m) {
return arrayToUtcDate([
m.getUTCFullYear(),
m.getUTCMonth(),
m.getUTCDate(),
m.getUTCHours(),
m.getUTCMinutes()
]);
}
function startOfSecond(m) {
return arrayToUtcDate([
m.getUTCFullYear(),
m.getUTCMonth(),
m.getUTCDate(),
m.getUTCHours(),
m.getUTCMinutes(),
m.getUTCSeconds()
]);
}
// Week Computation
function weekOfYear(marker, dow, doy) {
var y = marker.getUTCFullYear();
var w = weekOfGivenYear(marker, y, dow, doy);
if (w < 1) {
return weekOfGivenYear(marker, y - 1, dow, doy);
}
var nextW = weekOfGivenYear(marker, y + 1, dow, doy);
if (nextW >= 1) {
return Math.min(w, nextW);
}
return w;
}
function weekOfGivenYear(marker, year, dow, doy) {
var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
var dayStart = startOfDay(marker);
var days = Math.round(diffDays(firstWeekStart, dayStart));
return Math.floor(days / 7) + 1; // zero-indexed
}
// start-of-first-week - start-of-year
function firstWeekOffset(year, dow, doy) {
// first-week day -- which january is always in the first week (4 for iso, 1 for other)
var fwd = 7 + dow - doy;
// first-week day local weekday -- which local weekday is fwd
var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
return -fwdlw + fwd - 1;
}
// Array Conversion
function dateToLocalArray(date) {
return [
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
];
}
function arrayToLocalDate(a) {
return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
a[3] || 0, a[4] || 0, a[5] || 0);
}
function dateToUtcArray(date) {
return [
date.getUTCFullYear(),
date.getUTCMonth(),
date.getUTCDate(),
date.getUTCHours(),
date.getUTCMinutes(),
date.getUTCSeconds(),
date.getUTCMilliseconds()
];
}
function arrayToUtcDate(a) {
// according to web standards (and Safari), a month index is required.
// massage if only given a year.
if (a.length === 1) {
a = a.concat([0]);
}
return new Date(Date.UTC.apply(Date, a));
}
// Other Utils
function isValidDate(m) {
return !isNaN(m.valueOf());
}
function timeAsMs(m) {
return m.getUTCHours() * 1000 * 60 * 60 +
m.getUTCMinutes() * 1000 * 60 +
m.getUTCSeconds() * 1000 +
m.getUTCMilliseconds();
}
var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
// Parsing and Creation
function createDuration(input, unit) {
var _a;
if (typeof input === 'string') {
return parseString(input);
}
else if (typeof input === 'object' && input) { // non-null object
return normalizeObject(input);
}
else if (typeof input === 'number') {
return normalizeObject((_a = {}, _a[unit || 'milliseconds'] = input, _a));
}
else {
return null;
}
}
function parseString(s) {
var m = PARSE_RE.exec(s);
if (m) {
var sign = m[1] ? -1 : 1;
return {
years: 0,
months: 0,
days: sign * (m[2] ? parseInt(m[2], 10) : 0),
milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
(m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
(m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
(m[6] ? parseInt(m[6], 10) : 0) // ms
)
};
}
return null;
}
function normalizeObject(obj) {
return {
years: obj.years || obj.year || 0,
months: obj.months || obj.month || 0,
days: (obj.days || obj.day || 0) +
getWeeksFromInput(obj) * 7,
milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
(obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
(obj.seconds || obj.second || 0) * 1000 + // seconds
(obj.milliseconds || obj.millisecond || obj.ms || 0) // ms
};
}
function getWeeksFromInput(obj) {
return obj.weeks || obj.week || 0;
}
// Equality
function durationsEqual(d0, d1) {
return d0.years === d1.years &&
d0.months === d1.months &&
d0.days === d1.days &&
d0.milliseconds === d1.milliseconds;
}
function isSingleDay(dur) {
return dur.years === 0 && dur.months === 0 && dur.days === 1 && dur.milliseconds === 0;
}
// Simple Math
function addDurations(d0, d1) {
return {
years: d0.years + d1.years,
months: d0.months + d1.months,
days: d0.days + d1.days,
milliseconds: d0.milliseconds + d1.milliseconds
};
}
function subtractDurations(d1, d0) {
return {
years: d1.years - d0.years,
months: d1.months - d0.months,
days: d1.days - d0.days,
milliseconds: d1.milliseconds - d0.milliseconds
};
}
function multiplyDuration(d, n) {
return {
years: d.years * n,
months: d.months * n,
days: d.days * n,
milliseconds: d.milliseconds * n
};
}
// Conversions
// "Rough" because they are based on average-case Gregorian months/years
function asRoughYears(dur) {
return asRoughDays(dur) / 365;
}
function asRoughMonths(dur) {
return asRoughDays(dur) / 30;
}
function asRoughDays(dur) {
return asRoughMs(dur) / 864e5;
}
function asRoughMinutes(dur) {
return asRoughMs(dur) / (1000 * 60);
}
function asRoughSeconds(dur) {
return asRoughMs(dur) / 1000;
}
function asRoughMs(dur) {
return dur.years * (365 * 864e5) +
dur.months * (30 * 864e5) +
dur.days * 864e5 +
dur.milliseconds;
}
// Advanced Math
function wholeDivideDurations(numerator, denominator) {
var res = null;
for (var i = 0; i < INTERNAL_UNITS.length; i++) {
var unit = INTERNAL_UNITS[i];
if (denominator[unit]) {
var localRes = numerator[unit] / denominator[unit];
if (!isInt(localRes) || (res !== null && res !== localRes)) {
return null;
}
res = localRes;
}
else if (numerator[unit]) {
// needs to divide by something but can't!
return null;
}
}
return res;
}
function greatestDurationDenominator(dur, dontReturnWeeks) {
var ms = dur.milliseconds;
if (ms) {
if (ms % 1000 !== 0) {
return { unit: 'millisecond', value: ms };
}
if (ms % (1000 * 60) !== 0) {
return { unit: 'second', value: ms / 1000 };
}
if (ms % (1000 * 60 * 60) !== 0) {
return { unit: 'minute', value: ms / (1000 * 60) };
}
if (ms) {
return { unit: 'hour', value: ms / (1000 * 60 * 60) };
}
}
if (dur.days) {
if (!dontReturnWeeks && dur.days % 7 === 0) {
return { unit: 'week', value: dur.days / 7 };
}
return { unit: 'day', value: dur.days };
}
if (dur.months) {
return { unit: 'month', value: dur.months };
}
if (dur.years) {
return { unit: 'year', value: dur.years };
}
return { unit: 'millisecond', value: 0 };
}
/* FullCalendar-specific DOM Utilities
----------------------------------------------------------------------------------------------------------------------*/
// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left
// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that.
function compensateScroll(rowEl, scrollbarWidths) {
if (scrollbarWidths.left) {
applyStyle(rowEl, {
borderLeftWidth: 1,
marginLeft: scrollbarWidths.left - 1
});
}
if (scrollbarWidths.right) {
applyStyle(rowEl, {
borderRightWidth: 1,
marginRight: scrollbarWidths.right - 1
});
}
}
// Undoes compensateScroll and restores all borders/margins
function uncompensateScroll(rowEl) {
applyStyle(rowEl, {
marginLeft: '',
marginRight: '',
borderLeftWidth: '',
borderRightWidth: ''
});
}
// Make the mouse cursor express that an event is not allowed in the current area
function disableCursor() {
document.body.classList.add('fc-not-allowed');
}
// Returns the mouse cursor to its original look
function enableCursor() {
document.body.classList.remove('fc-not-allowed');
}
// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate.
// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering
// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and
// reduces the available height.
function distributeHeight(els, availableHeight, shouldRedistribute) {
// *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions,
// and it is better to be shorter than taller, to avoid creating unnecessary scrollbars.
var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element
var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE*
var flexEls = []; // elements that are allowed to expand. array of DOM nodes
var flexOffsets = []; // amount of vertical space it takes up
var flexHeights = []; // actual css height
var usedHeight = 0;
undistributeHeight(els); // give all elements their natural height
// find elements that are below the recommended height (expandable).
// important to query for heights in a single first pass (to avoid reflow oscillation).
els.forEach(function (el, i) {
var minOffset = i === els.length - 1 ? minOffset2 : minOffset1;
var naturalHeight = el.getBoundingClientRect().height;
var naturalOffset = naturalHeight + computeVMargins(el);
if (naturalOffset < minOffset) {
flexEls.push(el);
flexOffsets.push(naturalOffset);
flexHeights.push(naturalHeight);
}
else {
// this element stretches past recommended height (non-expandable). mark the space as occupied.
usedHeight += naturalOffset;
}
});
// readjust the recommended height to only consider the height available to non-maxed-out rows.
if (shouldRedistribute) {
availableHeight -= usedHeight;
minOffset1 = Math.floor(availableHeight / flexEls.length);
minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE*
}
// assign heights to all expandable elements
flexEls.forEach(function (el, i) {
var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1;
var naturalOffset = flexOffsets[i];
var naturalHeight = flexHeights[i];
var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding
if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things
el.style.height = newHeight + 'px';
}
});
}
// Undoes distrubuteHeight, restoring all els to their natural height
function undistributeHeight(els) {
els.forEach(function (el) {
el.style.height = '';
});
}
// Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the
// cells to be that width.
// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline
function matchCellWidths(els) {
var maxInnerWidth = 0;
els.forEach(function (el) {
var innerEl = el.firstChild; // hopefully an element
if (innerEl instanceof HTMLElement) {
var innerWidth_1 = innerEl.getBoundingClientRect().width;
if (innerWidth_1 > maxInnerWidth) {
maxInnerWidth = innerWidth_1;
}
}
});
maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance
els.forEach(function (el) {
el.style.width = maxInnerWidth + 'px';
});
return maxInnerWidth;
}
// Given one element that resides inside another,
// Subtracts the height of the inner element from the outer element.
function subtractInnerElHeight(outerEl, innerEl) {
// effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
var reflowStyleProps = {
position: 'relative',
left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
};
applyStyle(outerEl, reflowStyleProps);
applyStyle(innerEl, reflowStyleProps);
var diff = // grab the dimensions
outerEl.getBoundingClientRect().height -
innerEl.getBoundingClientRect().height;
// undo hack
var resetStyleProps = { position: '', left: '' };
applyStyle(outerEl, resetStyleProps);
applyStyle(innerEl, resetStyleProps);
return diff;
}
/* Selection
----------------------------------------------------------------------------------------------------------------------*/
function preventSelection(el) {
el.classList.add('fc-unselectable');
el.addEventListener('selectstart', preventDefault);
}
function allowSelection(el) {
el.classList.remove('fc-unselectable');
el.removeEventListener('selectstart', preventDefault);
}
/* Context Menu
----------------------------------------------------------------------------------------------------------------------*/
function preventContextMenu(el) {
el.addEventListener('contextmenu', preventDefault);
}
function allowContextMenu(el) {
el.removeEventListener('contextmenu', preventDefault);
}
/* Object Ordering by Field
----------------------------------------------------------------------------------------------------------------------*/
function parseFieldSpecs(input) {
var specs = [];
var tokens = [];
var i;
var token;
if (typeof input === 'string') {
tokens = input.split(/\s*,\s*/);
}
else if (typeof input === 'function') {
tokens = [input];
}
else if (Array.isArray(input)) {
tokens = input;
}
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
if (typeof token === 'string') {
specs.push(token.charAt(0) === '-' ?
{ field: token.substring(1), order: -1 } :
{ field: token, order: 1 });
}
else if (typeof token === 'function') {
specs.push({ func: token });
}
}
return specs;
}
function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
var i;
var cmp;
for (i = 0; i < fieldSpecs.length; i++) {
cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
if (cmp) {
return cmp;
}
}
return 0;
}
function compareByFieldSpec(obj0, obj1, fieldSpec) {
if (fieldSpec.func) {
return fieldSpec.func(obj0, obj1);
}
return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
* (fieldSpec.order || 1);
}
function flexibleCompare(a, b) {
if (!a && !b) {
return 0;
}
if (b == null) {
return -1;
}
if (a == null) {
return 1;
}
if (typeof a === 'string' || typeof b === 'string') {
return String(a).localeCompare(String(b));
}
return a - b;
}
/* String Utilities
----------------------------------------------------------------------------------------------------------------------*/
function capitaliseFirstLetter(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
function padStart(val, len) {
var s = String(val);
return '000'.substr(0, len - s.length) + s;
}
/* Number Utilities
----------------------------------------------------------------------------------------------------------------------*/
function compareNumbers(a, b) {
return a - b;
}
function isInt(n) {
return n % 1 === 0;
}
/* Weird Utilities
----------------------------------------------------------------------------------------------------------------------*/
function applyAll(functions, thisObj, args) {
if (typeof functions === 'function') { // supplied a single function
functions = [functions];
}
if (functions) {
var i = void 0;
var ret = void 0;
for (i = 0; i < functions.length; i++) {
ret = functions[i].apply(thisObj, args) || ret;
}
return ret;
}
}
function firstDefined() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
for (var i = 0; i < args.length; i++) {
if (args[i] !== undefined) {
return args[i];
}
}
}
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714
function debounce(func, wait) {
var timeout;
var args;
var context;
var timestamp;
var result;
var later = function () {
var last = new Date().valueOf() - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
}
else {
timeout = null;
result = func.apply(context, args);
context = args = null;
}
};
return function () {
context = this;
args = arguments;
timestamp = new Date().valueOf();
if (!timeout) {
timeout = setTimeout(later, wait);
}
return result;
};
}
// Number and Boolean are only types that defaults or not computed for
// TODO: write more comments
function refineProps(rawProps, processors, defaults, leftoverProps) {
if (defaults === void 0) { defaults = {}; }
var refined = {};
for (var key in processors) {
var processor = processors[key];
if (rawProps[key] !== undefined) {
// found
if (processor === Function) {
refined[key] = typeof rawProps[key] === 'function' ? rawProps[key] : null;
}
else if (processor) { // a refining function?
refined[key] = processor(rawProps[key]);
}
else {
refined[key] = rawProps[key];
}
}
else if (defaults[key] !== undefined) {
// there's an explicit default
refined[key] = defaults[key];
}
else {
// must compute a default
if (processor === String) {
refined[key] = ''; // empty string is default for String
}
else if (!processor || processor === Number || processor === Boolean || processor === Function) {
refined[key] = null; // assign null for other non-custom processor funcs
}
else {
refined[key] = processor(null); // run the custom processor func
}
}
}
if (leftoverProps) {
for (var key in rawProps) {
if (processors[key] === undefined) {
leftoverProps[key] = rawProps[key];
}
}
}
return refined;
}
/* Date stuff that doesn't belong in datelib core
----------------------------------------------------------------------------------------------------------------------*/
// given a timed range, computes an all-day range that has the same exact duration,
// but whose start time is aligned with the start of the day.
function computeAlignedDayRange(timedRange) {
var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
var start = startOfDay(timedRange.start);
var end = addDays(start, dayCnt);
return { start: start, end: end };
}
// given a timed range, computes an all-day range based on how for the end date bleeds into the next day
// TODO: give nextDayThreshold a default arg
function computeVisibleDayRange(timedRange, nextDayThreshold) {
if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); }
var startDay = null;
var endDay = null;
if (timedRange.end) {
endDay = startOfDay(timedRange.end);
var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
// If the end time is actually inclusively part of the next day and is equal to or
// beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
// Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
endDay = addDays(endDay, 1);
}
}
if (timedRange.start) {
startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
// If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
if (endDay && endDay <= startDay) {
endDay = addDays(startDay, 1);
}
}
return { start: startDay, end: endDay };
}
// spans from one day into another?
function isMultiDayRange(range) {
var visibleRange = computeVisibleDayRange(range);
return diffDays(visibleRange.start, visibleRange.end) > 1;
}
function diffDates(date0, date1, dateEnv, largeUnit) {
if (largeUnit === 'year') {
return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
}
else if (largeUnit === 'month') {
return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
}
else {
return diffDayAndTime(date0, date1); // returns a duration
}
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function parseRecurring(eventInput, allDayDefault, dateEnv, recurringTypes, leftovers) {
for (var i = 0; i < recurringTypes.length; i++) {
var localLeftovers = {};
var parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv);
if (parsed) {
var allDay = localLeftovers.allDay;
delete localLeftovers.allDay; // remove from leftovers
if (allDay == null) {
allDay = allDayDefault;
if (allDay == null) {
allDay = parsed.allDayGuess;
if (allDay == null) {
allDay = false;
}
}
}
__assign(leftovers, localLeftovers);
return {
allDay: allDay,
duration: parsed.duration,
typeData: parsed.typeData,
typeId: i
};
}
}
return null;
}
/*
Event MUST have a recurringDef
*/
function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
var typeDef = recurringTypes[eventDef.recurringDef.typeId];
var markers = typeDef.expand(eventDef.recurringDef.typeData, {
start: dateEnv.subtract(framingRange.start, duration),
end: framingRange.end
}, dateEnv);
// the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
if (eventDef.allDay) {
markers = markers.map(startOfDay);
}
return markers;
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
// Merges an array of objects into a single object.
// The second argument allows for an array of property names who's object values will be merged together.
function mergeProps(propObjs, complexProps) {
var dest = {};
var i;
var name;
var complexObjs;
var j;
var val;
var props;
if (complexProps) {
for (i = 0; i < complexProps.length; i++) {
name = complexProps[i];
complexObjs = [];
// collect the trailing object values, stopping when a non-object is discovered
for (j = propObjs.length - 1; j >= 0; j--) {
val = propObjs[j][name];
if (typeof val === 'object' && val) { // non-null object
complexObjs.unshift(val);
}
else if (val !== undefined) {
dest[name] = val; // if there were no objects, this value will be used
break;
}
}
// if the trailing values were objects, use the merged value
if (complexObjs.length) {
dest[name] = mergeProps(complexObjs);
}
}
}
// copy values into the destination, going from last to first
for (i = propObjs.length - 1; i >= 0; i--) {
props = propObjs[i];
for (name in props) {
if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
dest[name] = props[name];
}
}
}
return dest;
}
function filterHash(hash, func) {
var filtered = {};
for (var key in hash) {
if (func(hash[key], key)) {
filtered[key] = hash[key];
}
}
return filtered;
}
function mapHash(hash, func) {
var newHash = {};
for (var key in hash) {
newHash[key] = func(hash[key], key);
}
return newHash;
}
function arrayToHash(a) {
var hash = {};
for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
var item = a_1[_i];
hash[item] = true;
}
return hash;
}
function hashValuesToArray(obj) {
var a = [];
for (var key in obj) {
a.push(obj[key]);
}
return a;
}
function isPropsEqual(obj0, obj1) {
for (var key in obj0) {
if (hasOwnProperty.call(obj0, key)) {
if (!(key in obj1)) {
return false;
}
}
}
for (var key in obj1) {
if (hasOwnProperty.call(obj1, key)) {
if (obj0[key] !== obj1[key]) {
return false;
}
}
}
return true;
}
function parseEvents(rawEvents, sourceId, calendar, allowOpenRange) {
var eventStore = createEmptyEventStore();
for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) {
var rawEvent = rawEvents_1[_i];
var tuple = parseEvent(rawEvent, sourceId, calendar, allowOpenRange);
if (tuple) {
eventTupleToStore(tuple, eventStore);
}
}
return eventStore;
}
function eventTupleToStore(tuple, eventStore) {
if (eventStore === void 0) { eventStore = createEmptyEventStore(); }
eventStore.defs[tuple.def.defId] = tuple.def;
if (tuple.instance) {
eventStore.instances[tuple.instance.instanceId] = tuple.instance;
}
return eventStore;
}
function expandRecurring(eventStore, framingRange, calendar) {
var dateEnv = calendar.dateEnv;
var defs = eventStore.defs, instances = eventStore.instances;
// remove existing recurring instances
instances = filterHash(instances, function (instance) {
return !defs[instance.defId].recurringDef;
});
for (var defId in defs) {
var def = defs[defId];
if (def.recurringDef) {
var duration = def.recurringDef.duration;
if (!duration) {
duration = def.allDay ?
calendar.defaultAllDayEventDuration :
calendar.defaultTimedEventDuration;
}
var starts = expandRecurringRanges(def, duration, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes);
for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) {
var start = starts_1[_i];
var instance = createEventInstance(defId, {
start: start,
end: dateEnv.add(start, duration)
});
instances[instance.instanceId] = instance;
}
}
}
return { defs: defs, instances: instances };
}
// retrieves events that have the same groupId as the instance specified by `instanceId`
// or they are the same as the instance.
// why might instanceId not be in the store? an event from another calendar?
function getRelevantEvents(eventStore, instanceId) {
var instance = eventStore.instances[instanceId];
if (instance) {
var def_1 = eventStore.defs[instance.defId];
// get events/instances with same group
var newStore = filterEventStoreDefs(eventStore, function (lookDef) {
return isEventDefsGrouped(def_1, lookDef);
});
// add the original
// TODO: wish we could use eventTupleToStore or something like it
newStore.defs[def_1.defId] = def_1;
newStore.instances[instance.instanceId] = instance;
return newStore;
}
return createEmptyEventStore();
}
function isEventDefsGrouped(def0, def1) {
return Boolean(def0.groupId && def0.groupId === def1.groupId);
}
function transformRawEvents(rawEvents, eventSource, calendar) {
var calEachTransform = calendar.opt('eventDataTransform');
var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
if (sourceEachTransform) {
rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
}
if (calEachTransform) {
rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
}
return rawEvents;
}
function transformEachRawEvent(rawEvents, func) {
var refinedEvents;
if (!func) {
refinedEvents = rawEvents;
}
else {
refinedEvents = [];
for (var _i = 0, rawEvents_2 = rawEvents; _i < rawEvents_2.length; _i++) {
var rawEvent = rawEvents_2[_i];
var refinedEvent = func(rawEvent);
if (refinedEvent) {
refinedEvents.push(refinedEvent);
}
else if (refinedEvent == null) {
refinedEvents.push(rawEvent);
} // if a different falsy value, do nothing
}
}
return refinedEvents;
}
function createEmptyEventStore() {
return { defs: {}, instances: {} };
}
function mergeEventStores(store0, store1) {
return {
defs: __assign({}, store0.defs, store1.defs),
instances: __assign({}, store0.instances, store1.instances)
};
}
function filterEventStoreDefs(eventStore, filterFunc) {
var defs = filterHash(eventStore.defs, filterFunc);
var instances = filterHash(eventStore.instances, function (instance) {
return defs[instance.defId]; // still exists?
});
return { defs: defs, instances: instances };
}
function parseRange(input, dateEnv) {
var start = null;
var end = null;
if (input.start) {
start = dateEnv.createMarker(input.start);
}
if (input.end) {
end = dateEnv.createMarker(input.end);
}
if (!start && !end) {
return null;
}
if (start && end && end < start) {
return null;
}
return { start: start, end: end };
}
// SIDE-EFFECT: will mutate ranges.
// Will return a new array result.
function invertRanges(ranges, constraintRange) {
var invertedRanges = [];
var start = constraintRange.start; // the end of the previous range. the start of the new range
var i;
var dateRange;
// ranges need to be in order. required for our date-walking algorithm
ranges.sort(compareRanges);
for (i = 0; i < ranges.length; i++) {
dateRange = ranges[i];
// add the span of time before the event (if there is any)
if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
invertedRanges.push({ start: start, end: dateRange.start });
}
if (dateRange.end > start) {
start = dateRange.end;
}
}
// add the span of time after the last event (if there is any)
if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
invertedRanges.push({ start: start, end: constraintRange.end });
}
return invertedRanges;
}
function compareRanges(range0, range1) {
return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
}
function intersectRanges(range0, range1) {
var start = range0.start;
var end = range0.end;
var newRange = null;
if (range1.start !== null) {
if (start === null) {
start = range1.start;
}
else {
start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
}
}
if (range1.end != null) {
if (end === null) {
end = range1.end;
}
else {
end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
}
}
if (start === null || end === null || start < end) {
newRange = { start: start, end: end };
}
return newRange;
}
function rangesEqual(range0, range1) {
return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
(range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
}
function rangesIntersect(range0, range1) {
return (range0.end === null || range1.start === null || range0.end > range1.start) &&
(range0.start === null || range1.end === null || range0.start < range1.end);
}
function rangeContainsRange(outerRange, innerRange) {
return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
(outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
}
function rangeContainsMarker(range, date) {
return (range.start === null || date >= range.start) &&
(range.end === null || date < range.end);
}
// If the given date is not within the given range, move it inside.
// (If it's past the end, make it one millisecond before the end).
function constrainMarkerToRange(date, range) {
if (range.start != null && date < range.start) {
return range.start;
}
if (range.end != null && date >= range.end) {
return new Date(range.end.valueOf() - 1);
}
return date;
}
function removeExact(array, exactVal) {
var removeCnt = 0;
var i = 0;
while (i < array.length) {
if (array[i] === exactVal) {
array.splice(i, 1);
removeCnt++;
}
else {
i++;
}
}
return removeCnt;
}
function isArraysEqual(a0, a1) {
var len = a0.length;
var i;
if (len !== a1.length) { // not array? or not same length?
return false;
}
for (i = 0; i < len; i++) {
if (a0[i] !== a1[i]) {
return false;
}
}
return true;
}
function memoize(workerFunc) {
var args;
var res;
return function () {
if (!args || !isArraysEqual(args, arguments)) {
args = arguments;
res = workerFunc.apply(this, arguments);
}
return res;
};
}
/*
always executes the workerFunc, but if the result is equal to the previous result,
return the previous result instead.
*/
function memoizeOutput(workerFunc, equalityFunc) {
var cachedRes = null;
return function () {
var newRes = workerFunc.apply(this, arguments);
if (cachedRes === null || !(cachedRes === newRes || equalityFunc(cachedRes, newRes))) {
cachedRes = newRes;
}
return cachedRes;
};
}
var EXTENDED_SETTINGS_AND_SEVERITIES = {
week: 3,
separator: 0,
omitZeroMinute: 0,
meridiem: 0,
omitCommas: 0
};
var STANDARD_DATE_PROP_SEVERITIES = {
timeZoneName: 7,
era: 6,
year: 5,
month: 4,
day: 2,
weekday: 2,
hour: 1,
minute: 1,
second: 1
};
var MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
var COMMA_RE = /,/g; // we need re for globalness
var MULTI_SPACE_RE = /\s+/g;
var LTR_RE = /\u200e/g; // control character
var UTC_RE = /UTC|GMT/;
var NativeFormatter = /** @class */ (function () {
function NativeFormatter(formatSettings) {
var standardDateProps = {};
var extendedSettings = {};
var severity = 0;
for (var name_1 in formatSettings) {
if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) {
extendedSettings[name_1] = formatSettings[name_1];
severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity);
}
else {
standardDateProps[name_1] = formatSettings[name_1];
if (name_1 in STANDARD_DATE_PROP_SEVERITIES) {
severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity);
}
}
}
this.standardDateProps = standardDateProps;
this.extendedSettings = extendedSettings;
this.severity = severity;
this.buildFormattingFunc = memoize(buildFormattingFunc);
}
NativeFormatter.prototype.format = function (date, context) {
return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
};
NativeFormatter.prototype.formatRange = function (start, end, context) {
var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings;
var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
if (!diffSeverity) {
return this.format(start, context);
}
var biggestUnitForPartial = diffSeverity;
if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
(standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
(standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
(standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
}
var full0 = this.format(start, context);
var full1 = this.format(end, context);
if (full0 === full1) {
return full0;
}
var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
var partial0 = partialFormattingFunc(start);
var partial1 = partialFormattingFunc(end);
var insertion = findCommonInsertion(full0, partial0, full1, partial1);
var separator = extendedSettings.separator || '';
if (insertion) {
return insertion.before + partial0 + separator + partial1 + insertion.after;
}
return full0 + separator + full1;
};
NativeFormatter.prototype.getLargestUnit = function () {
switch (this.severity) {
case 7:
case 6:
case 5:
return 'year';
case 4:
return 'month';
case 3:
return 'week';
default:
return 'day';
}
};
return NativeFormatter;
}());
function buildFormattingFunc(standardDateProps, extendedSettings, context) {
var standardDatePropCnt = Object.keys(standardDateProps).length;
if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
return function (date) {
return formatTimeZoneOffset(date.timeZoneOffset);
};
}
if (standardDatePropCnt === 0 && extendedSettings.week) {
return function (date) {
return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekLabel, context.locale, extendedSettings.week);
};
}
return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
}
function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
standardDateProps = __assign({}, standardDateProps); // copy
extendedSettings = __assign({}, extendedSettings); // copy
sanitizeSettings(standardDateProps, extendedSettings);
standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
var zeroFormat; // needed?
if (extendedSettings.omitZeroMinute) {
var zeroProps = __assign({}, standardDateProps);
delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
}
return function (date) {
var marker = date.marker;
var format;
if (zeroFormat && !marker.getUTCMinutes()) {
format = zeroFormat;
}
else {
format = normalFormat;
}
var s = format.format(marker);
return postProcess(s, date, standardDateProps, extendedSettings, context);
};
}
function sanitizeSettings(standardDateProps, extendedSettings) {
// deal with a browser inconsistency where formatting the timezone
// requires that the hour/minute be present.
if (standardDateProps.timeZoneName) {
if (!standardDateProps.hour) {
standardDateProps.hour = '2-digit';
}
if (!standardDateProps.minute) {
standardDateProps.minute = '2-digit';
}
}
// only support short timezone names
if (standardDateProps.timeZoneName === 'long') {
standardDateProps.timeZoneName = 'short';
}
// if requesting to display seconds, MUST display minutes
if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
delete extendedSettings.omitZeroMinute;
}
}
function postProcess(s, date, standardDateProps, extendedSettings, context) {
s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
if (standardDateProps.timeZoneName === 'short') {
s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
'UTC' : // important to normalize for IE, which does "GMT"
formatTimeZoneOffset(date.timeZoneOffset));
}
if (extendedSettings.omitCommas) {
s = s.replace(COMMA_RE, '').trim();
}
if (extendedSettings.omitZeroMinute) {
s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
}
// ^ do anything that might create adjacent spaces before this point,
// because MERIDIEM_RE likes to eat up loading spaces
if (extendedSettings.meridiem === false) {
s = s.replace(MERIDIEM_RE, '').trim();
}
else if (extendedSettings.meridiem === 'narrow') { // a/p
s = s.replace(MERIDIEM_RE, function (m0, m1) {
return m1.toLocaleLowerCase();
});
}
else if (extendedSettings.meridiem === 'short') { // am/pm
s = s.replace(MERIDIEM_RE, function (m0, m1) {
return m1.toLocaleLowerCase() + 'm';
});
}
else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
s = s.replace(MERIDIEM_RE, function (m0) {
return m0.toLocaleLowerCase();
});
}
s = s.replace(MULTI_SPACE_RE, ' ');
s = s.trim();
return s;
}
function injectTzoStr(s, tzoStr) {
var replaced = false;
s = s.replace(UTC_RE, function () {
replaced = true;
return tzoStr;
});
// IE11 doesn't include UTC/GMT in the original string, so append to end
if (!replaced) {
s += ' ' + tzoStr;
}
return s;
}
function formatWeekNumber(num, weekLabel, locale, display) {
var parts = [];
if (display === 'narrow') {
parts.push(weekLabel);
}
else if (display === 'short') {
parts.push(weekLabel, ' ');
}
// otherwise, considered 'numeric'
parts.push(locale.simpleNumberFormat.format(num));
if (locale.options.isRtl) { // TODO: use control characters instead?
parts.reverse();
}
return parts.join('');
}
// Range Formatting Utils
// 0 = exactly the same
// 1 = different by time
// and bigger
function computeMarkerDiffSeverity(d0, d1, ca) {
if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
return 5;
}
if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
return 4;
}
if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
return 2;
}
if (timeAsMs(d0) !== timeAsMs(d1)) {
return 1;
}
return 0;
}
function computePartialFormattingOptions(options, biggestUnit) {
var partialOptions = {};
for (var name_2 in options) {
if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) {
partialOptions[name_2] = options[name_2];
}
}
return partialOptions;
}
function findCommonInsertion(full0, partial0, full1, partial1) {
var i0 = 0;
while (i0 < full0.length) {
var found0 = full0.indexOf(partial0, i0);
if (found0 === -1) {
break;
}
var before0 = full0.substr(0, found0);
i0 = found0 + partial0.length;
var after0 = full0.substr(i0);
var i1 = 0;
while (i1 < full1.length) {
var found1 = full1.indexOf(partial1, i1);
if (found1 === -1) {
break;
}
var before1 = full1.substr(0, found1);
i1 = found1 + partial1.length;
var after1 = full1.substr(i1);
if (before0 === before1 && after0 === after1) {
return {
before: before0,
after: after0
};
}
}
}
return null;
}
/*
TODO: fix the terminology of "formatter" vs "formatting func"
*/
/*
At the time of instantiation, this object does not know which cmd-formatting system it will use.
It receives this at the time of formatting, as a setting.
*/
var CmdFormatter = /** @class */ (function () {
function CmdFormatter(cmdStr, separator) {
this.cmdStr = cmdStr;
this.separator = separator;
}
CmdFormatter.prototype.format = function (date, context) {
return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, this.separator));
};
CmdFormatter.prototype.formatRange = function (start, end, context) {
return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, this.separator));
};
return CmdFormatter;
}());
var FuncFormatter = /** @class */ (function () {
function FuncFormatter(func) {
this.func = func;
}
FuncFormatter.prototype.format = function (date, context) {
return this.func(createVerboseFormattingArg(date, null, context));
};
FuncFormatter.prototype.formatRange = function (start, end, context) {
return this.func(createVerboseFormattingArg(start, end, context));
};
return FuncFormatter;
}());
// Formatter Object Creation
function createFormatter(input, defaultSeparator) {
if (typeof input === 'object' && input) { // non-null object
if (typeof defaultSeparator === 'string') {
input = __assign({ separator: defaultSeparator }, input);
}
return new NativeFormatter(input);
}
else if (typeof input === 'string') {
return new CmdFormatter(input, defaultSeparator);
}
else if (typeof input === 'function') {
return new FuncFormatter(input);
}
}
// String Utils
// timeZoneOffset is in minutes
function buildIsoString(marker, timeZoneOffset, stripZeroTime) {
if (stripZeroTime === void 0) { stripZeroTime = false; }
var s = marker.toISOString();
s = s.replace('.000', '');
if (stripZeroTime) {
s = s.replace('T00:00:00Z', '');
}
if (s.length > 10) { // time part wasn't stripped, can add timezone info
if (timeZoneOffset == null) {
s = s.replace('Z', '');
}
else if (timeZoneOffset !== 0) {
s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
}
// otherwise, its UTC-0 and we want to keep the Z
}
return s;
}
function formatIsoTimeString(marker) {
return padStart(marker.getUTCHours(), 2) + ':' +
padStart(marker.getUTCMinutes(), 2) + ':' +
padStart(marker.getUTCSeconds(), 2);
}
function formatTimeZoneOffset(minutes, doIso) {
if (doIso === void 0) { doIso = false; }
var sign = minutes < 0 ? '-' : '+';
var abs = Math.abs(minutes);
var hours = Math.floor(abs / 60);
var mins = Math.round(abs % 60);
if (doIso) {
return sign + padStart(hours, 2) + ':' + padStart(mins, 2);
}
else {
return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : '');
}
}
// Arg Utils
function createVerboseFormattingArg(start, end, context, separator) {
var startInfo = expandZonedMarker(start, context.calendarSystem);
var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
return {
date: startInfo,
start: startInfo,
end: endInfo,
timeZone: context.timeZone,
localeCodes: context.locale.codes,
separator: separator
};
}
function expandZonedMarker(dateInfo, calendarSystem) {
var a = calendarSystem.markerToArray(dateInfo.marker);
return {
marker: dateInfo.marker,
timeZoneOffset: dateInfo.timeZoneOffset,
array: a,
year: a[0],
month: a[1],
day: a[2],
hour: a[3],
minute: a[4],
second: a[5],
millisecond: a[6]
};
}
var EventSourceApi = /** @class */ (function () {
function EventSourceApi(calendar, internalEventSource) {
this.calendar = calendar;
this.internalEventSource = internalEventSource;
}
EventSourceApi.prototype.remove = function () {
this.calendar.dispatch({
type: 'REMOVE_EVENT_SOURCE',
sourceId: this.internalEventSource.sourceId
});
};
EventSourceApi.prototype.refetch = function () {
this.calendar.dispatch({
type: 'FETCH_EVENT_SOURCES',
sourceIds: [this.internalEventSource.sourceId]
});
};
Object.defineProperty(EventSourceApi.prototype, "id", {
get: function () {
return this.internalEventSource.publicId;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EventSourceApi.prototype, "url", {
// only relevant to json-feed event sources
get: function () {
return this.internalEventSource.meta.url;
},
enumerable: true,
configurable: true
});
return EventSourceApi;
}());
var EventApi = /** @class */ (function () {
function EventApi(calendar, def, instance) {
this._calendar = calendar;
this._def = def;
this._instance = instance || null;
}
/*
TODO: make event struct more responsible for this
*/
EventApi.prototype.setProp = function (name, val) {
var _a, _b;
if (name in DATE_PROPS) ;
else if (name in NON_DATE_PROPS) {
if (typeof NON_DATE_PROPS[name] === 'function') {
val = NON_DATE_PROPS[name](val);
}
this.mutate({
standardProps: (_a = {}, _a[name] = val, _a)
});
}
else if (name in UNSCOPED_EVENT_UI_PROPS) {
var ui = void 0;
if (typeof UNSCOPED_EVENT_UI_PROPS[name] === 'function') {
val = UNSCOPED_EVENT_UI_PROPS[name](val);
}
if (name === 'color') {
ui = { backgroundColor: val, borderColor: val };
}
else if (name === 'editable') {
ui = { startEditable: val, durationEditable: val };
}
else {
ui = (_b = {}, _b[name] = val, _b);
}
this.mutate({
standardProps: { ui: ui }
});
}
};
EventApi.prototype.setExtendedProp = function (name, val) {
var _a;
this.mutate({
extendedProps: (_a = {}, _a[name] = val, _a)
});
};
EventApi.prototype.setStart = function (startInput, options) {
if (options === void 0) { options = {}; }
var dateEnv = this._calendar.dateEnv;
var start = dateEnv.createMarker(startInput);
if (start && this._instance) { // TODO: warning if parsed bad
var instanceRange = this._instance.range;
var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
if (options.maintainDuration) {
this.mutate({ datesDelta: startDelta });
}
else {
this.mutate({ startDelta: startDelta });
}
}
};
EventApi.prototype.setEnd = function (endInput, options) {
if (options === void 0) { options = {}; }
var dateEnv = this._calendar.dateEnv;
var end;
if (endInput != null) {
end = dateEnv.createMarker(endInput);
if (!end) {
return; // TODO: warning if parsed bad
}
}
if (this._instance) {
if (end) {
var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
this.mutate({ endDelta: endDelta });
}
else {
this.mutate({ standardProps: { hasEnd: false } });
}
}
};
EventApi.prototype.setDates = function (startInput, endInput, options) {
if (options === void 0) { options = {}; }
var dateEnv = this._calendar.dateEnv;
var standardProps = { allDay: options.allDay };
var start = dateEnv.createMarker(startInput);
var end;
if (!start) {
return; // TODO: warning if parsed bad
}
if (endInput != null) {
end = dateEnv.createMarker(endInput);
if (!end) { // TODO: warning if parsed bad
return;
}
}
if (this._instance) {
var instanceRange = this._instance.range;
// when computing the diff for an event being converted to all-day,
// compute diff off of the all-day values the way event-mutation does.
if (options.allDay === true) {
instanceRange = computeAlignedDayRange(instanceRange);
}
var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
if (end) {
var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
if (durationsEqual(startDelta, endDelta)) {
this.mutate({ datesDelta: startDelta, standardProps: standardProps });
}
else {
this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps });
}
}
else { // means "clear the end"
standardProps.hasEnd = false;
this.mutate({ datesDelta: startDelta, standardProps: standardProps });
}
}
};
EventApi.prototype.moveStart = function (deltaInput) {
var delta = createDuration(deltaInput);
if (delta) { // TODO: warning if parsed bad
this.mutate({ startDelta: delta });
}
};
EventApi.prototype.moveEnd = function (deltaInput) {
var delta = createDuration(deltaInput);
if (delta) { // TODO: warning if parsed bad
this.mutate({ endDelta: delta });
}
};
EventApi.prototype.moveDates = function (deltaInput) {
var delta = createDuration(deltaInput);
if (delta) { // TODO: warning if parsed bad
this.mutate({ datesDelta: delta });
}
};
EventApi.prototype.setAllDay = function (allDay, options) {
if (options === void 0) { options = {}; }
var standardProps = { allDay: allDay };
var maintainDuration = options.maintainDuration;
if (maintainDuration == null) {
maintainDuration = this._calendar.opt('allDayMaintainDuration');
}
if (this._def.allDay !== allDay) {
standardProps.hasEnd = maintainDuration;
}
this.mutate({ standardProps: standardProps });
};
EventApi.prototype.formatRange = function (formatInput) {
var dateEnv = this._calendar.dateEnv;
var instance = this._instance;
var formatter = createFormatter(formatInput, this._calendar.opt('defaultRangeSeparator'));
if (this._def.hasEnd) {
return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
forcedStartTzo: instance.forcedStartTzo,
forcedEndTzo: instance.forcedEndTzo
});
}
else {
return dateEnv.format(instance.range.start, formatter, {
forcedTzo: instance.forcedStartTzo
});
}
};
EventApi.prototype.mutate = function (mutation) {
var def = this._def;
var instance = this._instance;
if (instance) {
this._calendar.dispatch({
type: 'MUTATE_EVENTS',
instanceId: instance.instanceId,
mutation: mutation,
fromApi: true
});
var eventStore = this._calendar.state.eventStore;
this._def = eventStore.defs[def.defId];
this._instance = eventStore.instances[instance.instanceId];
}
};
EventApi.prototype.remove = function () {
this._calendar.dispatch({
type: 'REMOVE_EVENT_DEF',
defId: this._def.defId
});
};
Object.defineProperty(EventApi.prototype, "source", {
get: function () {
var sourceId = this._def.sourceId;
if (sourceId) {
return new EventSourceApi(this._calendar, this._calendar.state.eventSources[sourceId]);
}
return null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "start", {
get: function () {
return this._instance ?
this._calendar.dateEnv.toDate(this._instance.range.start) :
null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "end", {
get: function () {
return (this._instance && this._def.hasEnd) ?
this._calendar.dateEnv.toDate(this._instance.range.end) :
null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "id", {
// computable props that all access the def
// TODO: find a TypeScript-compatible way to do this at scale
get: function () { return this._def.publicId; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "groupId", {
get: function () { return this._def.groupId; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "allDay", {
get: function () { return this._def.allDay; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "title", {
get: function () { return this._def.title; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "url", {
get: function () { return this._def.url; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "rendering", {
get: function () { return this._def.rendering; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "startEditable", {
get: function () { return this._def.ui.startEditable; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "durationEditable", {
get: function () { return this._def.ui.durationEditable; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "constraint", {
get: function () { return this._def.ui.constraints[0] || null; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "overlap", {
get: function () { return this._def.ui.overlap; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "allow", {
get: function () { return this._def.ui.allows[0] || null; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "backgroundColor", {
get: function () { return this._def.ui.backgroundColor; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "borderColor", {
get: function () { return this._def.ui.borderColor; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "textColor", {
get: function () { return this._def.ui.textColor; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "classNames", {
// NOTE: user can't modify these because Object.freeze was called in event-def parsing
get: function () { return this._def.ui.classNames; },
enumerable: true,
configurable: true
});
Object.defineProperty(EventApi.prototype, "extendedProps", {
get: function () { return this._def.extendedProps; },
enumerable: true,
configurable: true
});
return EventApi;
}());
/*
Specifying nextDayThreshold signals that all-day ranges should be sliced.
*/
function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
var inverseBgByGroupId = {};
var inverseBgByDefId = {};
var defByGroupId = {};
var bgRanges = [];
var fgRanges = [];
var eventUis = compileEventUis(eventStore.defs, eventUiBases);
for (var defId in eventStore.defs) {
var def = eventStore.defs[defId];
if (def.rendering === 'inverse-background') {
if (def.groupId) {
inverseBgByGroupId[def.groupId] = [];
if (!defByGroupId[def.groupId]) {
defByGroupId[def.groupId] = def;
}
}
else {
inverseBgByDefId[defId] = [];
}
}
}
for (var instanceId in eventStore.instances) {
var instance = eventStore.instances[instanceId];
var def = eventStore.defs[instance.defId];
var ui = eventUis[def.defId];
var origRange = instance.range;
var normalRange = (!def.allDay && nextDayThreshold) ?
computeVisibleDayRange(origRange, nextDayThreshold) :
origRange;
var slicedRange = intersectRanges(normalRange, framingRange);
if (slicedRange) {
if (def.rendering === 'inverse-background') {
if (def.groupId) {
inverseBgByGroupId[def.groupId].push(slicedRange);
}
else {
inverseBgByDefId[instance.defId].push(slicedRange);
}
}
else {
(def.rendering === 'background' ? bgRanges : fgRanges).push({
def: def,
ui: ui,
instance: instance,
range: slicedRange,
isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf()
});
}
}
}
for (var groupId in inverseBgByGroupId) { // BY GROUP
var ranges = inverseBgByGroupId[groupId];
var invertedRanges = invertRanges(ranges, framingRange);
for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) {
var invertedRange = invertedRanges_1[_i];
var def = defByGroupId[groupId];
var ui = eventUis[def.defId];
bgRanges.push({
def: def,
ui: ui,
instance: null,
range: invertedRange,
isStart: false,
isEnd: false
});
}
}
for (var defId in inverseBgByDefId) {
var ranges = inverseBgByDefId[defId];
var invertedRanges = invertRanges(ranges, framingRange);
for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) {
var invertedRange = invertedRanges_2[_a];
bgRanges.push({
def: eventStore.defs[defId],
ui: eventUis[defId],
instance: null,
range: invertedRange,
isStart: false,
isEnd: false
});
}
}
return { bg: bgRanges, fg: fgRanges };
}
function hasBgRendering(def) {
return def.rendering === 'background' || def.rendering === 'inverse-background';
}
function filterSegsViaEls(context, segs, isMirror) {
var calendar = context.calendar, view = context.view;
if (calendar.hasPublicHandlers('eventRender')) {
segs = segs.filter(function (seg) {
var custom = calendar.publiclyTrigger('eventRender', [
{
event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
isMirror: isMirror,
isStart: seg.isStart,
isEnd: seg.isEnd,
// TODO: include seg.range once all components consistently generate it
el: seg.el,
view: view
}
]);
if (custom === false) { // means don't render at all
return false;
}
else if (custom && custom !== true) {
seg.el = custom;
}
return true;
});
}
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
setElSeg(seg.el, seg);
}
return segs;
}
function setElSeg(el, seg) {
el.fcSeg = seg;
}
function getElSeg(el) {
return el.fcSeg || null;
}
// event ui computation
function compileEventUis(eventDefs, eventUiBases) {
return mapHash(eventDefs, function (eventDef) {
return compileEventUi(eventDef, eventUiBases);
});
}
function compileEventUi(eventDef, eventUiBases) {
var uis = [];
if (eventUiBases['']) {
uis.push(eventUiBases['']);
}
if (eventUiBases[eventDef.defId]) {
uis.push(eventUiBases[eventDef.defId]);
}
uis.push(eventDef.ui);
return combineEventUis(uis);
}
// triggers
function triggerRenderedSegs(context, segs, isMirrors) {
var calendar = context.calendar, view = context.view;
if (calendar.hasPublicHandlers('eventPositioned')) {
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
calendar.publiclyTriggerAfterSizing('eventPositioned', [
{
event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
isMirror: isMirrors,
isStart: seg.isStart,
isEnd: seg.isEnd,
el: seg.el,
view: view
}
]);
}
}
if (!calendar.state.eventSourceLoadingLevel) { // avoid initial empty state while pending
calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once
}
}
function triggerWillRemoveSegs(context, segs, isMirrors) {
var calendar = context.calendar, view = context.view;
for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
var seg = segs_3[_i];
calendar.trigger('eventElRemove', seg.el);
}
if (calendar.hasPublicHandlers('eventDestroy')) {
for (var _a = 0, segs_4 = segs; _a < segs_4.length; _a++) {
var seg = segs_4[_a];
calendar.publiclyTrigger('eventDestroy', [
{
event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
isMirror: isMirrors,
el: seg.el,
view: view
}
]);
}
}
}
// is-interactable
function computeEventDraggable(context, eventDef, eventUi) {
var calendar = context.calendar, view = context.view;
var transformers = calendar.pluginSystem.hooks.isDraggableTransformers;
var val = eventUi.startEditable;
for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
var transformer = transformers_1[_i];
val = transformer(val, eventDef, eventUi, view);
}
return val;
}
function computeEventStartResizable(context, eventDef, eventUi) {
return eventUi.durationEditable && context.options.eventResizableFromStart;
}
function computeEventEndResizable(context, eventDef, eventUi) {
return eventUi.durationEditable;
}
// applies the mutation to ALL defs/instances within the event store
function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) {
var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
var dest = createEmptyEventStore();
for (var defId in eventStore.defs) {
var def = eventStore.defs[defId];
dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, calendar.pluginSystem.hooks.eventDefMutationAppliers, calendar);
}
for (var instanceId in eventStore.instances) {
var instance = eventStore.instances[instanceId];
var def = dest.defs[instance.defId]; // important to grab the newly modified def
dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, calendar);
}
return dest;
}
function applyMutationToEventDef(eventDef, eventConfig, mutation, appliers, calendar) {
var standardProps = mutation.standardProps || {};
// if hasEnd has not been specified, guess a good value based on deltas.
// if duration will change, there's no way the default duration will persist,
// and thus, we need to mark the event as having a real end
if (standardProps.hasEnd == null &&
eventConfig.durationEditable &&
(mutation.startDelta || mutation.endDelta)) {
standardProps.hasEnd = true; // TODO: is this mutation okay?
}
var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) });
if (mutation.extendedProps) {
copy.extendedProps = __assign({}, copy.extendedProps, mutation.extendedProps);
}
for (var _i = 0, appliers_1 = appliers; _i < appliers_1.length; _i++) {
var applier = appliers_1[_i];
applier(copy, mutation, calendar);
}
if (!copy.hasEnd && calendar.opt('forceEventDuration')) {
copy.hasEnd = true;
}
return copy;
}
function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
eventConfig, mutation, calendar) {
var dateEnv = calendar.dateEnv;
var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
var copy = __assign({}, eventInstance);
if (forceAllDay) {
copy.range = computeAlignedDayRange(copy.range);
}
if (mutation.datesDelta && eventConfig.startEditable) {
copy.range = {
start: dateEnv.add(copy.range.start, mutation.datesDelta),
end: dateEnv.add(copy.range.end, mutation.datesDelta)
};
}
if (mutation.startDelta && eventConfig.durationEditable) {
copy.range = {
start: dateEnv.add(copy.range.start, mutation.startDelta),
end: copy.range.end
};
}
if (mutation.endDelta && eventConfig.durationEditable) {
copy.range = {
start: copy.range.start,
end: dateEnv.add(copy.range.end, mutation.endDelta)
};
}
if (clearEnd) {
copy.range = {
start: copy.range.start,
end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start)
};
}
// in case event was all-day but the supplied deltas were not
// better util for this?
if (eventDef.allDay) {
copy.range = {
start: startOfDay(copy.range.start),
end: startOfDay(copy.range.end)
};
}
// handle invalid durations
if (copy.range.end < copy.range.start) {
copy.range.end = calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start);
}
return copy;
}
function reduceEventStore (eventStore, action, eventSources, dateProfile, calendar) {
switch (action.type) {
case 'RECEIVE_EVENTS': // raw
return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, calendar);
case 'ADD_EVENTS': // already parsed, but not expanded
return addEvent(eventStore, action.eventStore, // new ones
dateProfile ? dateProfile.activeRange : null, calendar);
case 'MERGE_EVENTS': // already parsed and expanded
return mergeEventStores(eventStore, action.eventStore);
case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
case 'NEXT':
case 'SET_DATE':
case 'SET_VIEW_TYPE':
if (dateProfile) {
return expandRecurring(eventStore, dateProfile.activeRange, calendar);
}
else {
return eventStore;
}
case 'CHANGE_TIMEZONE':
return rezoneDates(eventStore, action.oldDateEnv, calendar.dateEnv);
case 'MUTATE_EVENTS':
return applyMutationToRelated(eventStore, action.instanceId, action.mutation, action.fromApi, calendar);
case 'REMOVE_EVENT_INSTANCES':
return excludeInstances(eventStore, action.instances);
case 'REMOVE_EVENT_DEF':
return filterEventStoreDefs(eventStore, function (eventDef) {
return eventDef.defId !== action.defId;
});
case 'REMOVE_EVENT_SOURCE':
return excludeEventsBySourceId(eventStore, action.sourceId);
case 'REMOVE_ALL_EVENT_SOURCES':
return filterEventStoreDefs(eventStore, function (eventDef) {
return !eventDef.sourceId; // only keep events with no source id
});
case 'REMOVE_ALL_EVENTS':
return createEmptyEventStore();
case 'RESET_EVENTS':
return {
defs: eventStore.defs,
instances: eventStore.instances
};
default:
return eventStore;
}
}
function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, calendar) {
if (eventSource && // not already removed
fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
) {
var subset = parseEvents(transformRawEvents(rawEvents, eventSource, calendar), eventSource.sourceId, calendar);
if (fetchRange) {
subset = expandRecurring(subset, fetchRange, calendar);
}
return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
}
return eventStore;
}
function addEvent(eventStore, subset, expandRange, calendar) {
if (expandRange) {
subset = expandRecurring(subset, expandRange, calendar);
}
return mergeEventStores(eventStore, subset);
}
function rezoneDates(eventStore, oldDateEnv, newDateEnv) {
var defs = eventStore.defs;
var instances = mapHash(eventStore.instances, function (instance) {
var def = defs[instance.defId];
if (def.allDay || def.recurringDef) {
return instance; // isn't dependent on timezone
}
else {
return __assign({}, instance, { range: {
start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo))
}, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
}
});
return { defs: defs, instances: instances };
}
function applyMutationToRelated(eventStore, instanceId, mutation, fromApi, calendar) {
var relevant = getRelevantEvents(eventStore, instanceId);
var eventConfigBase = fromApi ?
{ '': {
startEditable: true,
durationEditable: true,
constraints: [],
overlap: null,
allows: [],
backgroundColor: '',
borderColor: '',
textColor: '',
classNames: []
} } :
calendar.eventUiBases;
relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, calendar);
return mergeEventStores(eventStore, relevant);
}
function excludeEventsBySourceId(eventStore, sourceId) {
return filterEventStoreDefs(eventStore, function (eventDef) {
return eventDef.sourceId !== sourceId;
});
}
// QUESTION: why not just return instances? do a general object-property-exclusion util
function excludeInstances(eventStore, removals) {
return {
defs: eventStore.defs,
instances: filterHash(eventStore.instances, function (instance) {
return !removals[instance.instanceId];
})
};
}
// high-level segmenting-aware tester functions
// ------------------------------------------------------------------------------------------------------------------------
function isInteractionValid(interaction, calendar) {
return isNewPropsValid({ eventDrag: interaction }, calendar); // HACK: the eventDrag props is used for ALL interactions
}
function isDateSelectionValid(dateSelection, calendar) {
return isNewPropsValid({ dateSelection: dateSelection }, calendar);
}
function isNewPropsValid(newProps, calendar) {
var view = calendar.view;
var props = __assign({ businessHours: view ? view.props.businessHours : createEmptyEventStore(), dateSelection: '', eventStore: calendar.state.eventStore, eventUiBases: calendar.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
return (calendar.pluginSystem.hooks.isPropsValid || isPropsValid)(props, calendar);
}
function isPropsValid(state, calendar, dateSpanMeta, filterConfig) {
if (dateSpanMeta === void 0) { dateSpanMeta = {}; }
if (state.eventDrag && !isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig)) {
return false;
}
if (state.dateSelection && !isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig)) {
return false;
}
return true;
}
// Moving Event Validation
// ------------------------------------------------------------------------------------------------------------------------
function isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig) {
var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
var subjectEventStore = interaction.mutatedEvents;
var subjectDefs = subjectEventStore.defs;
var subjectInstances = subjectEventStore.instances;
var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
state.eventUiBases :
{ '': calendar.selectionConfig } // if not a real event, validate as a selection
);
if (filterConfig) {
subjectConfigs = mapHash(subjectConfigs, filterConfig);
}
var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too?
var otherDefs = otherEventStore.defs;
var otherInstances = otherEventStore.instances;
var otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
for (var subjectInstanceId in subjectInstances) {
var subjectInstance = subjectInstances[subjectInstanceId];
var subjectRange = subjectInstance.range;
var subjectConfig = subjectConfigs[subjectInstance.defId];
var subjectDef = subjectDefs[subjectInstance.defId];
// constraint
if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, calendar)) {
return false;
}
// overlap
var overlapFunc = calendar.opt('eventOverlap');
if (typeof overlapFunc !== 'function') {
overlapFunc = null;
}
for (var otherInstanceId in otherInstances) {
var otherInstance = otherInstances[otherInstanceId];
// intersect! evaluate
if (rangesIntersect(subjectRange, otherInstance.range)) {
var otherOverlap = otherConfigs[otherInstance.defId].overlap;
// consider the other event's overlap. only do this if the subject event is a "real" event
if (otherOverlap === false && interaction.isEvent) {
return false;
}
if (subjectConfig.overlap === false) {
return false;
}
if (overlapFunc && !overlapFunc(new EventApi(calendar, otherDefs[otherInstance.defId], otherInstance), // still event
new EventApi(calendar, subjectDef, subjectInstance) // moving event
)) {
return false;
}
}
}
// allow (a function)
var calendarEventStore = calendar.state.eventStore; // need global-to-calendar, not local to component (splittable)state
for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) {
var subjectAllow = _a[_i];
var subjectDateSpan = __assign({}, dateSpanMeta, { range: subjectInstance.range, allDay: subjectDef.allDay });
var origDef = calendarEventStore.defs[subjectDef.defId];
var origInstance = calendarEventStore.instances[subjectInstanceId];
var eventApi = void 0;
if (origDef) { // was previously in the calendar
eventApi = new EventApi(calendar, origDef, origInstance);
}
else { // was an external event
eventApi = new EventApi(calendar, subjectDef); // no instance, because had no dates
}
if (!subjectAllow(calendar.buildDateSpanApi(subjectDateSpan), eventApi)) {
return false;
}
}
}
return true;
}
// Date Selection Validation
// ------------------------------------------------------------------------------------------------------------------------
function isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig) {
var relevantEventStore = state.eventStore;
var relevantDefs = relevantEventStore.defs;
var relevantInstances = relevantEventStore.instances;
var selection = state.dateSelection;
var selectionRange = selection.range;
var selectionConfig = calendar.selectionConfig;
if (filterConfig) {
selectionConfig = filterConfig(selectionConfig);
}
// constraint
if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, calendar)) {
return false;
}
// overlap
var overlapFunc = calendar.opt('selectOverlap');
if (typeof overlapFunc !== 'function') {
overlapFunc = null;
}
for (var relevantInstanceId in relevantInstances) {
var relevantInstance = relevantInstances[relevantInstanceId];
// intersect! evaluate
if (rangesIntersect(selectionRange, relevantInstance.range)) {
if (selectionConfig.overlap === false) {
return false;
}
if (overlapFunc && !overlapFunc(new EventApi(calendar, relevantDefs[relevantInstance.defId], relevantInstance))) {
return false;
}
}
}
// allow (a function)
for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) {
var selectionAllow = _a[_i];
var fullDateSpan = __assign({}, dateSpanMeta, selection);
if (!selectionAllow(calendar.buildDateSpanApi(fullDateSpan), null)) {
return false;
}
}
return true;
}
// Constraint Utils
// ------------------------------------------------------------------------------------------------------------------------
function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, calendar) {
for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) {
var constraint = constraints_1[_i];
if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, calendar), subjectRange)) {
return false;
}
}
return true;
}
function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
otherEventStore, // for if constraint is an even group ID
businessHoursUnexpanded, // for if constraint is 'businessHours'
calendar // for expanding businesshours
) {
if (constraint === 'businessHours') {
return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, calendar));
}
else if (typeof constraint === 'string') { // an group ID
return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) {
return eventDef.groupId === constraint;
}));
}
else if (typeof constraint === 'object' && constraint) { // non-null object
return eventStoreToRanges(expandRecurring(constraint, subjectRange, calendar));
}
return []; // if it's false
}
// TODO: move to event-store file?
function eventStoreToRanges(eventStore) {
var instances = eventStore.instances;
var ranges = [];
for (var instanceId in instances) {
ranges.push(instances[instanceId].range);
}
return ranges;
}
// TODO: move to geom file?
function anyRangesContainRange(outerRanges, innerRange) {
for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) {
var outerRange = outerRanges_1[_i];
if (rangeContainsRange(outerRange, innerRange)) {
return true;
}
}
return false;
}
// Parsing
// ------------------------------------------------------------------------------------------------------------------------
function normalizeConstraint(input, calendar) {
if (Array.isArray(input)) {
return parseEvents(input, '', calendar, true); // allowOpenRange=true
}
else if (typeof input === 'object' && input) { // non-null object
return parseEvents([input], '', calendar, true); // allowOpenRange=true
}
else if (input != null) {
return String(input);
}
else {
return null;
}
}
function htmlEscape(s) {
return (s + '').replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&#039;')
.replace(/"/g, '&quot;')
.replace(/\n/g, '<br />');
}
// Given a hash of CSS properties, returns a string of CSS.
// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values.
function cssToStr(cssProps) {
var statements = [];
for (var name_1 in cssProps) {
var val = cssProps[name_1];
if (val != null && val !== '') {
statements.push(name_1 + ':' + val);
}
}
return statements.join(';');
}
// Given an object hash of HTML attribute names to values,
// generates a string that can be injected between < > in HTML
function attrsToStr(attrs) {
var parts = [];
for (var name_2 in attrs) {
var val = attrs[name_2];
if (val != null) {
parts.push(name_2 + '="' + htmlEscape(val) + '"');
}
}
return parts.join(' ');
}
function parseClassName(raw) {
if (Array.isArray(raw)) {
return raw;
}
else if (typeof raw === 'string') {
return raw.split(/\s+/);
}
else {
return [];
}
}
var UNSCOPED_EVENT_UI_PROPS = {
editable: Boolean,
startEditable: Boolean,
durationEditable: Boolean,
constraint: null,
overlap: null,
allow: null,
className: parseClassName,
classNames: parseClassName,
color: String,
backgroundColor: String,
borderColor: String,
textColor: String
};
function processUnscopedUiProps(rawProps, calendar, leftovers) {
var props = refineProps(rawProps, UNSCOPED_EVENT_UI_PROPS, {}, leftovers);
var constraint = normalizeConstraint(props.constraint, calendar);
return {
startEditable: props.startEditable != null ? props.startEditable : props.editable,
durationEditable: props.durationEditable != null ? props.durationEditable : props.editable,
constraints: constraint != null ? [constraint] : [],
overlap: props.overlap,
allows: props.allow != null ? [props.allow] : [],
backgroundColor: props.backgroundColor || props.color,
borderColor: props.borderColor || props.color,
textColor: props.textColor,
classNames: props.classNames.concat(props.className)
};
}
function processScopedUiProps(prefix, rawScoped, calendar, leftovers) {
var rawUnscoped = {};
var wasFound = {};
for (var key in UNSCOPED_EVENT_UI_PROPS) {
var scopedKey = prefix + capitaliseFirstLetter(key);
rawUnscoped[key] = rawScoped[scopedKey];
wasFound[scopedKey] = true;
}
if (prefix === 'event') {
rawUnscoped.editable = rawScoped.editable; // special case. there is no 'eventEditable', just 'editable'
}
if (leftovers) {
for (var key in rawScoped) {
if (!wasFound[key]) {
leftovers[key] = rawScoped[key];
}
}
}
return processUnscopedUiProps(rawUnscoped, calendar);
}
var EMPTY_EVENT_UI = {
startEditable: null,
durationEditable: null,
constraints: [],
overlap: null,
allows: [],
backgroundColor: '',
borderColor: '',
textColor: '',
classNames: []
};
// prevent against problems with <2 args!
function combineEventUis(uis) {
return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
}
function combineTwoEventUis(item0, item1) {
return {
startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
constraints: item0.constraints.concat(item1.constraints),
overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
allows: item0.allows.concat(item1.allows),
backgroundColor: item1.backgroundColor || item0.backgroundColor,
borderColor: item1.borderColor || item0.borderColor,
textColor: item1.textColor || item0.textColor,
classNames: item0.classNames.concat(item1.classNames)
};
}
var NON_DATE_PROPS = {
id: String,
groupId: String,
title: String,
url: String,
rendering: String,
extendedProps: null
};
var DATE_PROPS = {
start: null,
date: null,
end: null,
allDay: null
};
var uid = 0;
function parseEvent(raw, sourceId, calendar, allowOpenRange) {
var allDayDefault = computeIsAllDayDefault(sourceId, calendar);
var leftovers0 = {};
var recurringRes = parseRecurring(raw, // raw, but with single-event stuff stripped out
allDayDefault, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes, leftovers0 // will populate with non-recurring props
);
if (recurringRes) {
var def = parseEventDef(leftovers0, sourceId, recurringRes.allDay, Boolean(recurringRes.duration), calendar);
def.recurringDef = {
typeId: recurringRes.typeId,
typeData: recurringRes.typeData,
duration: recurringRes.duration
};
return { def: def, instance: null };
}
else {
var leftovers1 = {};
var singleRes = parseSingle(raw, allDayDefault, calendar, leftovers1, allowOpenRange);
if (singleRes) {
var def = parseEventDef(leftovers1, sourceId, singleRes.allDay, singleRes.hasEnd, calendar);
var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
return { def: def, instance: instance };
}
}
return null;
}
/*
Will NOT populate extendedProps with the leftover properties.
Will NOT populate date-related props.
The EventNonDateInput has been normalized (id => publicId, etc).
*/
function parseEventDef(raw, sourceId, allDay, hasEnd, calendar) {
var leftovers = {};
var def = pluckNonDateProps(raw, calendar, leftovers);
def.defId = String(uid++);
def.sourceId = sourceId;
def.allDay = allDay;
def.hasEnd = hasEnd;
for (var _i = 0, _a = calendar.pluginSystem.hooks.eventDefParsers; _i < _a.length; _i++) {
var eventDefParser = _a[_i];
var newLeftovers = {};
eventDefParser(def, leftovers, newLeftovers);
leftovers = newLeftovers;
}
def.extendedProps = __assign(leftovers, def.extendedProps || {});
// help out EventApi from having user modify props
Object.freeze(def.ui.classNames);
Object.freeze(def.extendedProps);
return def;
}
function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
return {
instanceId: String(uid++),
defId: defId,
range: range,
forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo
};
}
function parseSingle(raw, allDayDefault, calendar, leftovers, allowOpenRange) {
var props = pluckDateProps(raw, leftovers);
var allDay = props.allDay;
var startMeta;
var startMarker = null;
var hasEnd = false;
var endMeta;
var endMarker = null;
startMeta = calendar.dateEnv.createMarkerMeta(props.start);
if (startMeta) {
startMarker = startMeta.marker;
}
else if (!allowOpenRange) {
return null;
}
if (props.end != null) {
endMeta = calendar.dateEnv.createMarkerMeta(props.end);
}
if (allDay == null) {
if (allDayDefault != null) {
allDay = allDayDefault;
}
else {
// fall back to the date props LAST
allDay = (!startMeta || startMeta.isTimeUnspecified) &&
(!endMeta || endMeta.isTimeUnspecified);
}
}
if (allDay && startMarker) {
startMarker = startOfDay(startMarker);
}
if (endMeta) {
endMarker = endMeta.marker;
if (allDay) {
endMarker = startOfDay(endMarker);
}
if (startMarker && endMarker <= startMarker) {
endMarker = null;
}
}
if (endMarker) {
hasEnd = true;
}
else if (!allowOpenRange) {
hasEnd = calendar.opt('forceEventDuration') || false;
endMarker = calendar.dateEnv.add(startMarker, allDay ?
calendar.defaultAllDayEventDuration :
calendar.defaultTimedEventDuration);
}
return {
allDay: allDay,
hasEnd: hasEnd,
range: { start: startMarker, end: endMarker },
forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
forcedEndTzo: endMeta ? endMeta.forcedTzo : null
};
}
function pluckDateProps(raw, leftovers) {
var props = refineProps(raw, DATE_PROPS, {}, leftovers);
props.start = (props.start !== null) ? props.start : props.date;
delete props.date;
return props;
}
function pluckNonDateProps(raw, calendar, leftovers) {
var preLeftovers = {};
var props = refineProps(raw, NON_DATE_PROPS, {}, preLeftovers);
var ui = processUnscopedUiProps(preLeftovers, calendar, leftovers);
props.publicId = props.id;
delete props.id;
props.ui = ui;
return props;
}
function computeIsAllDayDefault(sourceId, calendar) {
var res = null;
if (sourceId) {
var source = calendar.state.eventSources[sourceId];
res = source.allDayDefault;
}
if (res == null) {
res = calendar.opt('allDayDefault');
}
return res;
}
var DEF_DEFAULTS = {
startTime: '09:00',
endTime: '17:00',
daysOfWeek: [1, 2, 3, 4, 5],
rendering: 'inverse-background',
classNames: 'fc-nonbusiness',
groupId: '_businessHours' // so multiple defs get grouped
};
/*
TODO: pass around as EventDefHash!!!
*/
function parseBusinessHours(input, calendar) {
return parseEvents(refineInputs(input), '', calendar);
}
function refineInputs(input) {
var rawDefs;
if (input === true) {
rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
}
else if (Array.isArray(input)) {
// if specifying an array, every sub-definition NEEDS a day-of-week
rawDefs = input.filter(function (rawDef) {
return rawDef.daysOfWeek;
});
}
else if (typeof input === 'object' && input) { // non-null object
rawDefs = [input];
}
else { // is probably false
rawDefs = [];
}
rawDefs = rawDefs.map(function (rawDef) {
return __assign({}, DEF_DEFAULTS, rawDef);
});
return rawDefs;
}
function memoizeRendering(renderFunc, unrenderFunc, dependencies) {
if (dependencies === void 0) { dependencies = []; }
var dependents = [];
var thisContext;
var prevArgs;
function unrender() {
if (prevArgs) {
for (var _i = 0, dependents_1 = dependents; _i < dependents_1.length; _i++) {
var dependent = dependents_1[_i];
dependent.unrender();
}
if (unrenderFunc) {
unrenderFunc.apply(thisContext, prevArgs);
}
prevArgs = null;
}
}
function res() {
if (!prevArgs || !isArraysEqual(prevArgs, arguments)) {
unrender();
thisContext = this;
prevArgs = arguments;
renderFunc.apply(this, arguments);
}
}
res.dependents = dependents;
res.unrender = unrender;
for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) {
var dependency = dependencies_1[_i];
dependency.dependents.push(res);
}
return res;
}
var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
var Splitter = /** @class */ (function () {
function Splitter() {
this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
this.splitDateSelection = memoize(this._splitDateSpan);
this.splitEventStore = memoize(this._splitEventStore);
this.splitIndividualUi = memoize(this._splitIndividualUi);
this.splitEventDrag = memoize(this._splitInteraction);
this.splitEventResize = memoize(this._splitInteraction);
this.eventUiBuilders = {}; // TODO: typescript protection
}
Splitter.prototype.splitProps = function (props) {
var _this = this;
var keyInfos = this.getKeyInfo(props);
var defKeys = this.getKeysForEventDefs(props.eventStore);
var dateSelections = this.splitDateSelection(props.dateSelection);
var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
var eventStores = this.splitEventStore(props.eventStore, defKeys);
var eventDrags = this.splitEventDrag(props.eventDrag);
var eventResizes = this.splitEventResize(props.eventResize);
var splitProps = {};
this.eventUiBuilders = mapHash(keyInfos, function (info, key) {
return _this.eventUiBuilders[key] || memoize(buildEventUiForKey);
});
for (var key in keyInfos) {
var keyInfo = keyInfos[key];
var eventStore = eventStores[key] || EMPTY_EVENT_STORE;
var buildEventUi = this.eventUiBuilders[key];
splitProps[key] = {
businessHours: keyInfo.businessHours || props.businessHours,
dateSelection: dateSelections[key] || null,
eventStore: eventStore,
eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
eventDrag: eventDrags[key] || null,
eventResize: eventResizes[key] || null
};
}
return splitProps;
};
Splitter.prototype._splitDateSpan = function (dateSpan) {
var dateSpans = {};
if (dateSpan) {
var keys = this.getKeysForDateSpan(dateSpan);
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
dateSpans[key] = dateSpan;
}
}
return dateSpans;
};
Splitter.prototype._getKeysForEventDefs = function (eventStore) {
var _this = this;
return mapHash(eventStore.defs, function (eventDef) {
return _this.getKeysForEventDef(eventDef);
});
};
Splitter.prototype._splitEventStore = function (eventStore, defKeys) {
var defs = eventStore.defs, instances = eventStore.instances;
var splitStores = {};
for (var defId in defs) {
for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) {
var key = _a[_i];
if (!splitStores[key]) {
splitStores[key] = createEmptyEventStore();
}
splitStores[key].defs[defId] = defs[defId];
}
}
for (var instanceId in instances) {
var instance = instances[instanceId];
for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) {
var key = _c[_b];
if (splitStores[key]) { // must have already been created
splitStores[key].instances[instanceId] = instance;
}
}
}
return splitStores;
};
Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) {
var splitHashes = {};
for (var defId in eventUiBases) {
if (defId) { // not the '' key
for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) {
var key = _a[_i];
if (!splitHashes[key]) {
splitHashes[key] = {};
}
splitHashes[key][defId] = eventUiBases[defId];
}
}
}
return splitHashes;
};
Splitter.prototype._splitInteraction = function (interaction) {
var splitStates = {};
if (interaction) {
var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar
);
// can't rely on defKeys because event data is mutated
var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
var populate = function (key) {
if (!splitStates[key]) {
splitStates[key] = {
affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE,
mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE,
isEvent: interaction.isEvent,
origSeg: interaction.origSeg
};
}
};
for (var key in affectedStores_1) {
populate(key);
}
for (var key in mutatedStores_1) {
populate(key);
}
}
return splitStates;
};
return Splitter;
}());
function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
var baseParts = [];
if (allUi) {
baseParts.push(allUi);
}
if (eventUiForKey) {
baseParts.push(eventUiForKey);
}
var stuff = {
'': combineEventUis(baseParts)
};
if (individualUi) {
__assign(stuff, individualUi);
}
return stuff;
}
// Generates HTML for an anchor to another view into the calendar.
// Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings.
// `gotoOptions` can either be a DateMarker, or an object with the form:
// { date, type, forceOff }
// `type` is a view-type like "day" or "week". default value is "day".
// `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
function buildGotoAnchorHtml(allOptions, dateEnv, gotoOptions, attrs, innerHtml) {
var date;
var type;
var forceOff;
var finalOptions;
if (gotoOptions instanceof Date) {
date = gotoOptions; // a single date-like input
}
else {
date = gotoOptions.date;
type = gotoOptions.type;
forceOff = gotoOptions.forceOff;
}
finalOptions = {
date: dateEnv.formatIso(date, { omitTime: true }),
type: type || 'day'
};
if (typeof attrs === 'string') {
innerHtml = attrs;
attrs = null;
}
attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space
innerHtml = innerHtml || '';
if (!forceOff && allOptions.navLinks) {
return '<a' + attrs +
' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
innerHtml +
'</a>';
}
else {
return '<span' + attrs + '>' +
innerHtml +
'</span>';
}
}
function getAllDayHtml(allOptions) {
return allOptions.allDayHtml || htmlEscape(allOptions.allDayText);
}
// Computes HTML classNames for a single-day element
function getDayClasses(date, dateProfile, context, noThemeHighlight) {
var calendar = context.calendar, options = context.options, theme = context.theme, dateEnv = context.dateEnv;
var classes = [];
var todayStart;
var todayEnd;
if (!rangeContainsMarker(dateProfile.activeRange, date)) {
classes.push('fc-disabled-day');
}
else {
classes.push('fc-' + DAY_IDS[date.getUTCDay()]);
if (options.monthMode &&
dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) {
classes.push('fc-other-month');
}
todayStart = startOfDay(calendar.getNow());
todayEnd = addDays(todayStart, 1);
if (date < todayStart) {
classes.push('fc-past');
}
else if (date >= todayEnd) {
classes.push('fc-future');
}
else {
classes.push('fc-today');
if (noThemeHighlight !== true) {
classes.push(theme.getClass('today'));
}
}
}
return classes;
}
// given a function that resolves a result asynchronously.
// the function can either call passed-in success and failure callbacks,
// or it can return a promise.
// if you need to pass additional params to func, bind them first.
function unpromisify(func, success, failure) {
// guard against success/failure callbacks being called more than once
// and guard against a promise AND callback being used together.
var isResolved = false;
var wrappedSuccess = function () {
if (!isResolved) {
isResolved = true;
success.apply(this, arguments);
}
};
var wrappedFailure = function () {
if (!isResolved) {
isResolved = true;
if (failure) {
failure.apply(this, arguments);
}
}
};
var res = func(wrappedSuccess, wrappedFailure);
if (res && typeof res.then === 'function') {
res.then(wrappedSuccess, wrappedFailure);
}
}
var Mixin = /** @class */ (function () {
function Mixin() {
}
// mix into a CLASS
Mixin.mixInto = function (destClass) {
this.mixIntoObj(destClass.prototype);
};
// mix into ANY object
Mixin.mixIntoObj = function (destObj) {
var _this = this;
Object.getOwnPropertyNames(this.prototype).forEach(function (name) {
if (!destObj[name]) { // if destination doesn't already define it
destObj[name] = _this.prototype[name];
}
});
};
/*
will override existing methods
TODO: remove! not used anymore
*/
Mixin.mixOver = function (destClass) {
var _this = this;
Object.getOwnPropertyNames(this.prototype).forEach(function (name) {
destClass.prototype[name] = _this.prototype[name];
});
};
return Mixin;
}());
/*
USAGE:
import { default as EmitterMixin, EmitterInterface } from './EmitterMixin'
in class:
on: EmitterInterface['on']
one: EmitterInterface['one']
off: EmitterInterface['off']
trigger: EmitterInterface['trigger']
triggerWith: EmitterInterface['triggerWith']
hasHandlers: EmitterInterface['hasHandlers']
after class:
EmitterMixin.mixInto(TheClass)
*/
var EmitterMixin = /** @class */ (function (_super) {
__extends(EmitterMixin, _super);
function EmitterMixin() {
return _super !== null && _super.apply(this, arguments) || this;
}
EmitterMixin.prototype.on = function (type, handler) {
addToHash(this._handlers || (this._handlers = {}), type, handler);
return this; // for chaining
};
// todo: add comments
EmitterMixin.prototype.one = function (type, handler) {
addToHash(this._oneHandlers || (this._oneHandlers = {}), type, handler);
return this; // for chaining
};
EmitterMixin.prototype.off = function (type, handler) {
if (this._handlers) {
removeFromHash(this._handlers, type, handler);
}
if (this._oneHandlers) {
removeFromHash(this._oneHandlers, type, handler);
}
return this; // for chaining
};
EmitterMixin.prototype.trigger = function (type) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
this.triggerWith(type, this, args);
return this; // for chaining
};
EmitterMixin.prototype.triggerWith = function (type, context, args) {
if (this._handlers) {
applyAll(this._handlers[type], context, args);
}
if (this._oneHandlers) {
applyAll(this._oneHandlers[type], context, args);
delete this._oneHandlers[type]; // will never fire again
}
return this; // for chaining
};
EmitterMixin.prototype.hasHandlers = function (type) {
return (this._handlers && this._handlers[type] && this._handlers[type].length) ||
(this._oneHandlers && this._oneHandlers[type] && this._oneHandlers[type].length);
};
return EmitterMixin;
}(Mixin));
function addToHash(hash, type, handler) {
(hash[type] || (hash[type] = []))
.push(handler);
}
function removeFromHash(hash, type, handler) {
if (handler) {
if (hash[type]) {
hash[type] = hash[type].filter(function (func) {
return func !== handler;
});
}
}
else {
delete hash[type]; // remove all handler funcs for this type
}
}
/*
Records offset information for a set of elements, relative to an origin element.
Can record the left/right OR the top/bottom OR both.
Provides methods for querying the cache by position.
*/
var PositionCache = /** @class */ (function () {
function PositionCache(originEl, els, isHorizontal, isVertical) {
this.originEl = originEl;
this.els = els;
this.isHorizontal = isHorizontal;
this.isVertical = isVertical;
}
// Queries the els for coordinates and stores them.
// Call this method before using and of the get* methods below.
PositionCache.prototype.build = function () {
var originEl = this.originEl;
var originClientRect = this.originClientRect =
originEl.getBoundingClientRect(); // relative to viewport top-left
if (this.isHorizontal) {
this.buildElHorizontals(originClientRect.left);
}
if (this.isVertical) {
this.buildElVerticals(originClientRect.top);
}
};
// Populates the left/right internal coordinate arrays
PositionCache.prototype.buildElHorizontals = function (originClientLeft) {
var lefts = [];
var rights = [];
for (var _i = 0, _a = this.els; _i < _a.length; _i++) {
var el = _a[_i];
var rect = el.getBoundingClientRect();
lefts.push(rect.left - originClientLeft);
rights.push(rect.right - originClientLeft);
}
this.lefts = lefts;
this.rights = rights;
};
// Populates the top/bottom internal coordinate arrays
PositionCache.prototype.buildElVerticals = function (originClientTop) {
var tops = [];
var bottoms = [];
for (var _i = 0, _a = this.els; _i < _a.length; _i++) {
var el = _a[_i];
var rect = el.getBoundingClientRect();
tops.push(rect.top - originClientTop);
bottoms.push(rect.bottom - originClientTop);
}
this.tops = tops;
this.bottoms = bottoms;
};
// Given a left offset (from document left), returns the index of the el that it horizontally intersects.
// If no intersection is made, returns undefined.
PositionCache.prototype.leftToIndex = function (leftPosition) {
var lefts = this.lefts;
var rights = this.rights;
var len = lefts.length;
var i;
for (i = 0; i < len; i++) {
if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
return i;
}
}
};
// Given a top offset (from document top), returns the index of the el that it vertically intersects.
// If no intersection is made, returns undefined.
PositionCache.prototype.topToIndex = function (topPosition) {
var tops = this.tops;
var bottoms = this.bottoms;
var len = tops.length;
var i;
for (i = 0; i < len; i++) {
if (topPosition >= tops[i] && topPosition < bottoms[i]) {
return i;
}
}
};
// Gets the width of the element at the given index
PositionCache.prototype.getWidth = function (leftIndex) {
return this.rights[leftIndex] - this.lefts[leftIndex];
};
// Gets the height of the element at the given index
PositionCache.prototype.getHeight = function (topIndex) {
return this.bottoms[topIndex] - this.tops[topIndex];
};
return PositionCache;
}());
/*
An object for getting/setting scroll-related information for an element.
Internally, this is done very differently for window versus DOM element,
so this object serves as a common interface.
*/
var ScrollController = /** @class */ (function () {
function ScrollController() {
}
ScrollController.prototype.getMaxScrollTop = function () {
return this.getScrollHeight() - this.getClientHeight();
};
ScrollController.prototype.getMaxScrollLeft = function () {
return this.getScrollWidth() - this.getClientWidth();
};
ScrollController.prototype.canScrollVertically = function () {
return this.getMaxScrollTop() > 0;
};
ScrollController.prototype.canScrollHorizontally = function () {
return this.getMaxScrollLeft() > 0;
};
ScrollController.prototype.canScrollUp = function () {
return this.getScrollTop() > 0;
};
ScrollController.prototype.canScrollDown = function () {
return this.getScrollTop() < this.getMaxScrollTop();
};
ScrollController.prototype.canScrollLeft = function () {
return this.getScrollLeft() > 0;
};
ScrollController.prototype.canScrollRight = function () {
return this.getScrollLeft() < this.getMaxScrollLeft();
};
return ScrollController;
}());
var ElementScrollController = /** @class */ (function (_super) {
__extends(ElementScrollController, _super);
function ElementScrollController(el) {
var _this = _super.call(this) || this;
_this.el = el;
return _this;
}
ElementScrollController.prototype.getScrollTop = function () {
return this.el.scrollTop;
};
ElementScrollController.prototype.getScrollLeft = function () {
return this.el.scrollLeft;
};
ElementScrollController.prototype.setScrollTop = function (top) {
this.el.scrollTop = top;
};
ElementScrollController.prototype.setScrollLeft = function (left) {
this.el.scrollLeft = left;
};
ElementScrollController.prototype.getScrollWidth = function () {
return this.el.scrollWidth;
};
ElementScrollController.prototype.getScrollHeight = function () {
return this.el.scrollHeight;
};
ElementScrollController.prototype.getClientHeight = function () {
return this.el.clientHeight;
};
ElementScrollController.prototype.getClientWidth = function () {
return this.el.clientWidth;
};
return ElementScrollController;
}(ScrollController));
var WindowScrollController = /** @class */ (function (_super) {
__extends(WindowScrollController, _super);
function WindowScrollController() {
return _super !== null && _super.apply(this, arguments) || this;
}
WindowScrollController.prototype.getScrollTop = function () {
return window.pageYOffset;
};
WindowScrollController.prototype.getScrollLeft = function () {
return window.pageXOffset;
};
WindowScrollController.prototype.setScrollTop = function (n) {
window.scroll(window.pageXOffset, n);
};
WindowScrollController.prototype.setScrollLeft = function (n) {
window.scroll(n, window.pageYOffset);
};
WindowScrollController.prototype.getScrollWidth = function () {
return document.documentElement.scrollWidth;
};
WindowScrollController.prototype.getScrollHeight = function () {
return document.documentElement.scrollHeight;
};
WindowScrollController.prototype.getClientHeight = function () {
return document.documentElement.clientHeight;
};
WindowScrollController.prototype.getClientWidth = function () {
return document.documentElement.clientWidth;
};
return WindowScrollController;
}(ScrollController));
/*
Embodies a div that has potential scrollbars
*/
var ScrollComponent = /** @class */ (function (_super) {
__extends(ScrollComponent, _super);
function ScrollComponent(overflowX, overflowY) {
var _this = _super.call(this, createElement('div', {
className: 'fc-scroller'
})) || this;
_this.overflowX = overflowX;
_this.overflowY = overflowY;
_this.applyOverflow();
return _this;
}
// sets to natural height, unlocks overflow
ScrollComponent.prototype.clear = function () {
this.setHeight('auto');
this.applyOverflow();
};
ScrollComponent.prototype.destroy = function () {
removeElement(this.el);
};
// Overflow
// -----------------------------------------------------------------------------------------------------------------
ScrollComponent.prototype.applyOverflow = function () {
applyStyle(this.el, {
overflowX: this.overflowX,
overflowY: this.overflowY
});
};
// Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.
// Useful for preserving scrollbar widths regardless of future resizes.
// Can pass in scrollbarWidths for optimization.
ScrollComponent.prototype.lockOverflow = function (scrollbarWidths) {
var overflowX = this.overflowX;
var overflowY = this.overflowY;
scrollbarWidths = scrollbarWidths || this.getScrollbarWidths();
if (overflowX === 'auto') {
overflowX = (scrollbarWidths.bottom || // horizontal scrollbars?
this.canScrollHorizontally() // OR scrolling pane with massless scrollbars?
) ? 'scroll' : 'hidden';
}
if (overflowY === 'auto') {
overflowY = (scrollbarWidths.left || scrollbarWidths.right || // horizontal scrollbars?
this.canScrollVertically() // OR scrolling pane with massless scrollbars?
) ? 'scroll' : 'hidden';
}
applyStyle(this.el, { overflowX: overflowX, overflowY: overflowY });
};
ScrollComponent.prototype.setHeight = function (height) {
applyStyleProp(this.el, 'height', height);
};
ScrollComponent.prototype.getScrollbarWidths = function () {
var edges = computeEdges(this.el);
return {
left: edges.scrollbarLeft,
right: edges.scrollbarRight,
bottom: edges.scrollbarBottom
};
};
return ScrollComponent;
}(ElementScrollController));
var Theme = /** @class */ (function () {
function Theme(calendarOptions) {
this.calendarOptions = calendarOptions;
this.processIconOverride();
}
Theme.prototype.processIconOverride = function () {
if (this.iconOverrideOption) {
this.setIconOverride(this.calendarOptions[this.iconOverrideOption]);
}
};
Theme.prototype.setIconOverride = function (iconOverrideHash) {
var iconClassesCopy;
var buttonName;
if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
iconClassesCopy = __assign({}, this.iconClasses);
for (buttonName in iconOverrideHash) {
iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
}
this.iconClasses = iconClassesCopy;
}
else if (iconOverrideHash === false) {
this.iconClasses = {};
}
};
Theme.prototype.applyIconOverridePrefix = function (className) {
var prefix = this.iconOverridePrefix;
if (prefix && className.indexOf(prefix) !== 0) { // if not already present
className = prefix + className;
}
return className;
};
Theme.prototype.getClass = function (key) {
return this.classes[key] || '';
};
Theme.prototype.getIconClass = function (buttonName) {
var className = this.iconClasses[buttonName];
if (className) {
return this.baseIconClass + ' ' + className;
}
return '';
};
Theme.prototype.getCustomButtonIconClass = function (customButtonProps) {
var className;
if (this.iconOverrideCustomButtonOption) {
className = customButtonProps[this.iconOverrideCustomButtonOption];
if (className) {
return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className);
}
}
return '';
};
return Theme;
}());
Theme.prototype.classes = {};
Theme.prototype.iconClasses = {};
Theme.prototype.baseIconClass = '';
Theme.prototype.iconOverridePrefix = '';
var guid = 0;
var ComponentContext = /** @class */ (function () {
function ComponentContext(calendar, theme, dateEnv, options, view) {
this.calendar = calendar;
this.theme = theme;
this.dateEnv = dateEnv;
this.options = options;
this.view = view;
this.isRtl = options.dir === 'rtl';
this.eventOrderSpecs = parseFieldSpecs(options.eventOrder);
this.nextDayThreshold = createDuration(options.nextDayThreshold);
}
ComponentContext.prototype.extend = function (options, view) {
return new ComponentContext(this.calendar, this.theme, this.dateEnv, options || this.options, view || this.view);
};
return ComponentContext;
}());
var Component = /** @class */ (function () {
function Component() {
this.everRendered = false;
this.uid = String(guid++);
}
Component.addEqualityFuncs = function (newFuncs) {
this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs);
};
Component.prototype.receiveProps = function (props, context) {
this.receiveContext(context);
var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps;
this.props = comboProps;
if (anyChanges) {
if (this.everRendered) {
this.beforeUpdate();
}
this.render(comboProps, context);
if (this.everRendered) {
this.afterUpdate();
}
}
this.everRendered = true;
};
Component.prototype.receiveContext = function (context) {
var oldContext = this.context;
this.context = context;
if (!oldContext) {
this.firstContext(context);
}
};
Component.prototype.render = function (props, context) {
};
Component.prototype.firstContext = function (context) {
};
Component.prototype.beforeUpdate = function () {
};
Component.prototype.afterUpdate = function () {
};
// after destroy is called, this component won't ever be used again
Component.prototype.destroy = function () {
};
return Component;
}());
Component.prototype.equalityFuncs = {};
/*
Reuses old values when equal. If anything is unequal, returns newProps as-is.
Great for PureComponent, but won't be feasible with React, so just eliminate and use React's DOM diffing.
*/
function recycleProps(oldProps, newProps, equalityFuncs) {
var comboProps = {}; // some old, some new
var anyChanges = false;
for (var key in newProps) {
if (key in oldProps && (oldProps[key] === newProps[key] ||
(equalityFuncs[key] && equalityFuncs[key](oldProps[key], newProps[key])))) {
// equal to old? use old prop
comboProps[key] = oldProps[key];
}
else {
comboProps[key] = newProps[key];
anyChanges = true;
}
}
for (var key in oldProps) {
if (!(key in newProps)) {
anyChanges = true;
break;
}
}
return { anyChanges: anyChanges, comboProps: comboProps };
}
/*
PURPOSES:
- hook up to fg, fill, and mirror renderers
- interface for dragging and hits
*/
var DateComponent = /** @class */ (function (_super) {
__extends(DateComponent, _super);
function DateComponent(el) {
var _this = _super.call(this) || this;
_this.el = el;
return _this;
}
DateComponent.prototype.destroy = function () {
_super.prototype.destroy.call(this);
removeElement(this.el);
};
// Hit System
// -----------------------------------------------------------------------------------------------------------------
DateComponent.prototype.buildPositionCaches = function () {
};
DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
return null; // this should be abstract
};
// Validation
// -----------------------------------------------------------------------------------------------------------------
DateComponent.prototype.isInteractionValid = function (interaction) {
var calendar = this.context.calendar;
var dateProfile = this.props.dateProfile; // HACK
var instances = interaction.mutatedEvents.instances;
if (dateProfile) { // HACK for DayTile
for (var instanceId in instances) {
if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
return false;
}
}
}
return isInteractionValid(interaction, calendar);
};
DateComponent.prototype.isDateSelectionValid = function (selection) {
var calendar = this.context.calendar;
var dateProfile = this.props.dateProfile; // HACK
if (dateProfile && // HACK for DayTile
!rangeContainsRange(dateProfile.validRange, selection.range)) {
return false;
}
return isDateSelectionValid(selection, calendar);
};
// Pointer Interaction Utils
// -----------------------------------------------------------------------------------------------------------------
DateComponent.prototype.isValidSegDownEl = function (el) {
return !this.props.eventDrag && // HACK
!this.props.eventResize && // HACK
!elementClosest(el, '.fc-mirror') &&
(this.isPopover() || !this.isInPopover(el));
// ^above line ensures we don't detect a seg interaction within a nested component.
// it's a HACK because it only supports a popover as the nested component.
};
DateComponent.prototype.isValidDateDownEl = function (el) {
var segEl = elementClosest(el, this.fgSegSelector);
return (!segEl || segEl.classList.contains('fc-mirror')) &&
!elementClosest(el, '.fc-more') && // a "more.." link
!elementClosest(el, 'a[data-goto]') && // a clickable nav link
!this.isInPopover(el);
};
DateComponent.prototype.isPopover = function () {
return this.el.classList.contains('fc-popover');
};
DateComponent.prototype.isInPopover = function (el) {
return Boolean(elementClosest(el, '.fc-popover'));
};
return DateComponent;
}(Component));
DateComponent.prototype.fgSegSelector = '.fc-event-container > *';
DateComponent.prototype.bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)';
var uid$1 = 0;
function createPlugin(input) {
return {
id: String(uid$1++),
deps: input.deps || [],
reducers: input.reducers || [],
eventDefParsers: input.eventDefParsers || [],
isDraggableTransformers: input.isDraggableTransformers || [],
eventDragMutationMassagers: input.eventDragMutationMassagers || [],
eventDefMutationAppliers: input.eventDefMutationAppliers || [],
dateSelectionTransformers: input.dateSelectionTransformers || [],
datePointTransforms: input.datePointTransforms || [],
dateSpanTransforms: input.dateSpanTransforms || [],
views: input.views || {},
viewPropsTransformers: input.viewPropsTransformers || [],
isPropsValid: input.isPropsValid || null,
externalDefTransforms: input.externalDefTransforms || [],
eventResizeJoinTransforms: input.eventResizeJoinTransforms || [],
viewContainerModifiers: input.viewContainerModifiers || [],
eventDropTransformers: input.eventDropTransformers || [],
componentInteractions: input.componentInteractions || [],
calendarInteractions: input.calendarInteractions || [],
themeClasses: input.themeClasses || {},
eventSourceDefs: input.eventSourceDefs || [],
cmdFormatter: input.cmdFormatter,
recurringTypes: input.recurringTypes || [],
namedTimeZonedImpl: input.namedTimeZonedImpl,
defaultView: input.defaultView || '',
elementDraggingImpl: input.elementDraggingImpl,
optionChangeHandlers: input.optionChangeHandlers || {}
};
}
var PluginSystem = /** @class */ (function () {
function PluginSystem() {
this.hooks = {
reducers: [],
eventDefParsers: [],
isDraggableTransformers: [],
eventDragMutationMassagers: [],
eventDefMutationAppliers: [],
dateSelectionTransformers: [],
datePointTransforms: [],
dateSpanTransforms: [],
views: {},
viewPropsTransformers: [],
isPropsValid: null,
externalDefTransforms: [],
eventResizeJoinTransforms: [],
viewContainerModifiers: [],
eventDropTransformers: [],
componentInteractions: [],
calendarInteractions: [],
themeClasses: {},
eventSourceDefs: [],
cmdFormatter: null,
recurringTypes: [],
namedTimeZonedImpl: null,
defaultView: '',
elementDraggingImpl: null,
optionChangeHandlers: {}
};
this.addedHash = {};
}
PluginSystem.prototype.add = function (plugin) {
if (!this.addedHash[plugin.id]) {
this.addedHash[plugin.id] = true;
for (var _i = 0, _a = plugin.deps; _i < _a.length; _i++) {
var dep = _a[_i];
this.add(dep);
}
this.hooks = combineHooks(this.hooks, plugin);
}
};
return PluginSystem;
}());
function combineHooks(hooks0, hooks1) {
return {
reducers: hooks0.reducers.concat(hooks1.reducers),
eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers),
isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
views: __assign({}, hooks0.views, hooks1.views),
viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms),
viewContainerModifiers: hooks0.viewContainerModifiers.concat(hooks1.viewContainerModifiers),
eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
themeClasses: __assign({}, hooks0.themeClasses, hooks1.themeClasses),
eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
defaultView: hooks0.defaultView || hooks1.defaultView,
elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
optionChangeHandlers: __assign({}, hooks0.optionChangeHandlers, hooks1.optionChangeHandlers)
};
}
var eventSourceDef = {
ignoreRange: true,
parseMeta: function (raw) {
if (Array.isArray(raw)) { // short form
return raw;
}
else if (Array.isArray(raw.events)) {
return raw.events;
}
return null;
},
fetch: function (arg, success) {
success({
rawEvents: arg.eventSource.meta
});
}
};
var ArrayEventSourcePlugin = createPlugin({
eventSourceDefs: [eventSourceDef]
});
var eventSourceDef$1 = {
parseMeta: function (raw) {
if (typeof raw === 'function') { // short form
return raw;
}
else if (typeof raw.events === 'function') {
return raw.events;
}
return null;
},
fetch: function (arg, success, failure) {
var dateEnv = arg.calendar.dateEnv;
var func = arg.eventSource.meta;
unpromisify(func.bind(null, {
start: dateEnv.toDate(arg.range.start),
end: dateEnv.toDate(arg.range.end),
startStr: dateEnv.formatIso(arg.range.start),
endStr: dateEnv.formatIso(arg.range.end),
timeZone: dateEnv.timeZone
}), function (rawEvents) {
success({ rawEvents: rawEvents }); // needs an object response
}, failure // send errorObj directly to failure callback
);
}
};
var FuncEventSourcePlugin = createPlugin({
eventSourceDefs: [eventSourceDef$1]
});
function requestJson(method, url, params, successCallback, failureCallback) {
method = method.toUpperCase();
var body = null;
if (method === 'GET') {
url = injectQueryStringParams(url, params);
}
else {
body = encodeParams(params);
}
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
if (method !== 'GET') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) {
try {
var res = JSON.parse(xhr.responseText);
successCallback(res, xhr);
}
catch (err) {
failureCallback('Failure parsing JSON', xhr);
}
}
else {
failureCallback('Request failed', xhr);
}
};
xhr.onerror = function () {
failureCallback('Request failed', xhr);
};
xhr.send(body);
}
function injectQueryStringParams(url, params) {
return url +
(url.indexOf('?') === -1 ? '?' : '&') +
encodeParams(params);
}
function encodeParams(params) {
var parts = [];
for (var key in params) {
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
}
return parts.join('&');
}
var eventSourceDef$2 = {
parseMeta: function (raw) {
if (typeof raw === 'string') { // short form
raw = { url: raw };
}
else if (!raw || typeof raw !== 'object' || !raw.url) {
return null;
}
return {
url: raw.url,
method: (raw.method || 'GET').toUpperCase(),
extraParams: raw.extraParams,
startParam: raw.startParam,
endParam: raw.endParam,
timeZoneParam: raw.timeZoneParam
};
},
fetch: function (arg, success, failure) {
var meta = arg.eventSource.meta;
var requestParams = buildRequestParams(meta, arg.range, arg.calendar);
requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) {
success({ rawEvents: rawEvents, xhr: xhr });
}, function (errorMessage, xhr) {
failure({ message: errorMessage, xhr: xhr });
});
}
};
var JsonFeedEventSourcePlugin = createPlugin({
eventSourceDefs: [eventSourceDef$2]
});
function buildRequestParams(meta, range, calendar) {
var dateEnv = calendar.dateEnv;
var startParam;
var endParam;
var timeZoneParam;
var customRequestParams;
var params = {};
startParam = meta.startParam;
if (startParam == null) {
startParam = calendar.opt('startParam');
}
endParam = meta.endParam;
if (endParam == null) {
endParam = calendar.opt('endParam');
}
timeZoneParam = meta.timeZoneParam;
if (timeZoneParam == null) {
timeZoneParam = calendar.opt('timeZoneParam');
}
// retrieve any outbound GET/POST data from the options
if (typeof meta.extraParams === 'function') {
// supplied as a function that returns a key/value object
customRequestParams = meta.extraParams();
}
else {
// probably supplied as a straight key/value object
customRequestParams = meta.extraParams || {};
}
__assign(params, customRequestParams);
params[startParam] = dateEnv.formatIso(range.start);
params[endParam] = dateEnv.formatIso(range.end);
if (dateEnv.timeZone !== 'local') {
params[timeZoneParam] = dateEnv.timeZone;
}
return params;
}
var recurring = {
parse: function (rawEvent, leftoverProps, dateEnv) {
var createMarker = dateEnv.createMarker.bind(dateEnv);
var processors = {
daysOfWeek: null,
startTime: createDuration,
endTime: createDuration,
startRecur: createMarker,
endRecur: createMarker
};
var props = refineProps(rawEvent, processors, {}, leftoverProps);
var anyValid = false;
for (var propName in props) {
if (props[propName] != null) {
anyValid = true;
break;
}
}
if (anyValid) {
var duration = null;
if ('duration' in leftoverProps) {
duration = createDuration(leftoverProps.duration);
delete leftoverProps.duration;
}
if (!duration && props.startTime && props.endTime) {
duration = subtractDurations(props.endTime, props.startTime);
}
return {
allDayGuess: Boolean(!props.startTime && !props.endTime),
duration: duration,
typeData: props // doesn't need endTime anymore but oh well
};
}
return null;
},
expand: function (typeData, framingRange, dateEnv) {
var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
if (clippedFramingRange) {
return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv);
}
else {
return [];
}
}
};
var SimpleRecurrencePlugin = createPlugin({
recurringTypes: [recurring]
});
function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) {
var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
var dayMarker = startOfDay(framingRange.start);
var endMarker = framingRange.end;
var instanceStarts = [];
while (dayMarker < endMarker) {
var instanceStart
// if everyday, or this particular day-of-week
= void 0;
// if everyday, or this particular day-of-week
if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
if (startTime) {
instanceStart = dateEnv.add(dayMarker, startTime);
}
else {
instanceStart = dayMarker;
}
instanceStarts.push(instanceStart);
}
dayMarker = addDays(dayMarker, 1);
}
return instanceStarts;
}
var DefaultOptionChangeHandlers = createPlugin({
optionChangeHandlers: {
events: function (events, calendar, deepEqual) {
handleEventSources([events], calendar, deepEqual);
},
eventSources: handleEventSources,
plugins: handlePlugins
}
});
function handleEventSources(inputs, calendar, deepEqual) {
var unfoundSources = hashValuesToArray(calendar.state.eventSources);
var newInputs = [];
for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) {
var input = inputs_1[_i];
var inputFound = false;
for (var i = 0; i < unfoundSources.length; i++) {
if (deepEqual(unfoundSources[i]._raw, input)) {
unfoundSources.splice(i, 1); // delete
inputFound = true;
break;
}
}
if (!inputFound) {
newInputs.push(input);
}
}
for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) {
var unfoundSource = unfoundSources_1[_a];
calendar.dispatch({
type: 'REMOVE_EVENT_SOURCE',
sourceId: unfoundSource.sourceId
});
}
for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) {
var newInput = newInputs_1[_b];
calendar.addEventSource(newInput);
}
}
// shortcoming: won't remove plugins
function handlePlugins(inputs, calendar) {
calendar.addPluginInputs(inputs); // will gracefully handle duplicates
}
var config = {}; // TODO: make these options
var globalDefaults = {
defaultRangeSeparator: ' - ',
titleRangeSeparator: ' \u2013 ',
defaultTimedEventDuration: '01:00:00',
defaultAllDayEventDuration: { day: 1 },
forceEventDuration: false,
nextDayThreshold: '00:00:00',
// display
columnHeader: true,
defaultView: '',
aspectRatio: 1.35,
header: {
left: 'title',
center: '',
right: 'today prev,next'
},
weekends: true,
weekNumbers: false,
weekNumberCalculation: 'local',
editable: false,
// nowIndicator: false,
scrollTime: '06:00:00',
minTime: '00:00:00',
maxTime: '24:00:00',
showNonCurrentDates: true,
// event ajax
lazyFetching: true,
startParam: 'start',
endParam: 'end',
timeZoneParam: 'timeZone',
timeZone: 'local',
// allDayDefault: undefined,
// locale
locales: [],
locale: '',
// dir: will get this from the default locale
// buttonIcons: null,
// allows setting a min-height to the event segment to prevent short events overlapping each other
timeGridEventMinHeight: 0,
themeSystem: 'standard',
// eventResizableFromStart: false,
dragRevertDuration: 500,
dragScroll: true,
allDayMaintainDuration: false,
// selectable: false,
unselectAuto: true,
// selectMinDistance: 0,
dropAccept: '*',
eventOrder: 'start,-duration,allDay,title',
// ^ if start tie, longer events go before shorter. final tie-breaker is title text
// rerenderDelay: null,
eventLimit: false,
eventLimitClick: 'popover',
dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
handleWindowResize: true,
windowResizeDelay: 100,
longPressDelay: 1000,
eventDragMinDistance: 5 // only applies to mouse
};
var rtlDefaults = {
header: {
left: 'next,prev today',
center: '',
right: 'title'
},
buttonIcons: {
// TODO: make RTL support the responibility of the theme
prev: 'fc-icon-chevron-right',
next: 'fc-icon-chevron-left',
prevYear: 'fc-icon-chevrons-right',
nextYear: 'fc-icon-chevrons-left'
}
};
var complexOptions = [
'header',
'footer',
'buttonText',
'buttonIcons'
];
// Merges an array of option objects into a single object
function mergeOptions(optionObjs) {
return mergeProps(optionObjs, complexOptions);
}
// TODO: move this stuff to a "plugin"-related file...
var INTERNAL_PLUGINS = [
ArrayEventSourcePlugin,
FuncEventSourcePlugin,
JsonFeedEventSourcePlugin,
SimpleRecurrencePlugin,
DefaultOptionChangeHandlers
];
function refinePluginDefs(pluginInputs) {
var plugins = [];
for (var _i = 0, pluginInputs_1 = pluginInputs; _i < pluginInputs_1.length; _i++) {
var pluginInput = pluginInputs_1[_i];
if (typeof pluginInput === 'string') {
var globalName = 'FullCalendar' + capitaliseFirstLetter(pluginInput);
if (!window[globalName]) {
console.warn('Plugin file not loaded for ' + pluginInput);
}
else {
plugins.push(window[globalName].default); // is an ES6 module
}
}
else {
plugins.push(pluginInput);
}
}
return INTERNAL_PLUGINS.concat(plugins);
}
var RAW_EN_LOCALE = {
code: 'en',
week: {
dow: 0,
doy: 4 // 4 days need to be within the year to be considered the first week
},
dir: 'ltr',
buttonText: {
prev: 'prev',
next: 'next',
prevYear: 'prev year',
nextYear: 'next year',
year: 'year',
today: 'today',
month: 'month',
week: 'week',
day: 'day',
list: 'list'
},
weekLabel: 'W',
allDayText: 'all-day',
eventLimitText: 'more',
noEventsMessage: 'No events to display'
};
function parseRawLocales(explicitRawLocales) {
var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
var globalArray = window['FullCalendarLocalesAll'] || []; // from locales-all.js
var globalObject = window['FullCalendarLocales'] || {}; // from locales/*.js. keys are meaningless
var allRawLocales = globalArray.concat(// globalArray is low prio
hashValuesToArray(globalObject), // medium prio
explicitRawLocales // highest prio
);
var rawLocaleMap = {
en: RAW_EN_LOCALE // necessary?
};
for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) {
var rawLocale = allRawLocales_1[_i];
rawLocaleMap[rawLocale.code] = rawLocale;
}
return {
map: rawLocaleMap,
defaultCode: defaultCode
};
}
function buildLocale(inputSingular, available) {
if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
}
else {
return queryLocale(inputSingular, available);
}
}
function queryLocale(codeArg, available) {
var codes = [].concat(codeArg || []); // will convert to array
var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
return parseLocale(codeArg, codes, raw);
}
function queryRawLocale(codes, available) {
for (var i = 0; i < codes.length; i++) {
var parts = codes[i].toLocaleLowerCase().split('-');
for (var j = parts.length; j > 0; j--) {
var simpleId = parts.slice(0, j).join('-');
if (available[simpleId]) {
return available[simpleId];
}
}
}
return null;
}
function parseLocale(codeArg, codes, raw) {
var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']);
delete merged.code; // don't want this part of the options
var week = merged.week;
delete merged.week;
return {
codeArg: codeArg,
codes: codes,
week: week,
simpleNumberFormat: new Intl.NumberFormat(codeArg),
options: merged
};
}
var OptionsManager = /** @class */ (function () {
function OptionsManager(overrides) {
this.overrides = __assign({}, overrides); // make a copy
this.dynamicOverrides = {};
this.compute();
}
OptionsManager.prototype.mutate = function (updates, removals, isDynamic) {
if (!Object.keys(updates).length && !removals.length) {
return;
}
var overrideHash = isDynamic ? this.dynamicOverrides : this.overrides;
__assign(overrideHash, updates);
for (var _i = 0, removals_1 = removals; _i < removals_1.length; _i++) {
var propName = removals_1[_i];
delete overrideHash[propName];
}
this.compute();
};
// Computes the flattened options hash for the calendar and assigns to `this.options`.
// Assumes this.overrides and this.dynamicOverrides have already been initialized.
OptionsManager.prototype.compute = function () {
// TODO: not a very efficient system
var locales = firstDefined(// explicit locale option given?
this.dynamicOverrides.locales, this.overrides.locales, globalDefaults.locales);
var locale = firstDefined(// explicit locales option given?
this.dynamicOverrides.locale, this.overrides.locale, globalDefaults.locale);
var available = parseRawLocales(locales);
var localeDefaults = buildLocale(locale || available.defaultCode, available.map).options;
var dir = firstDefined(// based on options computed so far, is direction RTL?
this.dynamicOverrides.dir, this.overrides.dir, localeDefaults.dir);
var dirDefaults = dir === 'rtl' ? rtlDefaults : {};
this.dirDefaults = dirDefaults;
this.localeDefaults = localeDefaults;
this.computed = mergeOptions([
globalDefaults,
dirDefaults,
localeDefaults,
this.overrides,
this.dynamicOverrides
]);
};
return OptionsManager;
}());
var calendarSystemClassMap = {};
function registerCalendarSystem(name, theClass) {
calendarSystemClassMap[name] = theClass;
}
function createCalendarSystem(name) {
return new calendarSystemClassMap[name]();
}
var GregorianCalendarSystem = /** @class */ (function () {
function GregorianCalendarSystem() {
}
GregorianCalendarSystem.prototype.getMarkerYear = function (d) {
return d.getUTCFullYear();
};
GregorianCalendarSystem.prototype.getMarkerMonth = function (d) {
return d.getUTCMonth();
};
GregorianCalendarSystem.prototype.getMarkerDay = function (d) {
return d.getUTCDate();
};
GregorianCalendarSystem.prototype.arrayToMarker = function (arr) {
return arrayToUtcDate(arr);
};
GregorianCalendarSystem.prototype.markerToArray = function (marker) {
return dateToUtcArray(marker);
};
return GregorianCalendarSystem;
}());
registerCalendarSystem('gregory', GregorianCalendarSystem);
var ISO_RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
function parse(str) {
var m = ISO_RE.exec(str);
if (m) {
var 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));
if (isValidDate(marker)) {
var timeZoneOffset = null;
if (m[13]) {
timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
Number(m[18] || 0));
}
return {
marker: marker,
isTimeUnspecified: !m[6],
timeZoneOffset: timeZoneOffset
};
}
}
return null;
}
var DateEnv = /** @class */ (function () {
function DateEnv(settings) {
var timeZone = this.timeZone = settings.timeZone;
var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
if (settings.namedTimeZoneImpl && isNamedTimeZone) {
this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
}
this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
this.calendarSystem = createCalendarSystem(settings.calendarSystem);
this.locale = settings.locale;
this.weekDow = settings.locale.week.dow;
this.weekDoy = settings.locale.week.doy;
if (settings.weekNumberCalculation === 'ISO') {
this.weekDow = 1;
this.weekDoy = 4;
}
if (typeof settings.firstDay === 'number') {
this.weekDow = settings.firstDay;
}
if (typeof settings.weekNumberCalculation === 'function') {
this.weekNumberFunc = settings.weekNumberCalculation;
}
this.weekLabel = settings.weekLabel != null ? settings.weekLabel : settings.locale.options.weekLabel;
this.cmdFormatter = settings.cmdFormatter;
}
// Creating / Parsing
DateEnv.prototype.createMarker = function (input) {
var meta = this.createMarkerMeta(input);
if (meta === null) {
return null;
}
return meta.marker;
};
DateEnv.prototype.createNowMarker = function () {
if (this.canComputeOffset) {
return this.timestampToMarker(new Date().valueOf());
}
else {
// if we can't compute the current date val for a timezone,
// better to give the current local date vals than UTC
return arrayToUtcDate(dateToLocalArray(new Date()));
}
};
DateEnv.prototype.createMarkerMeta = function (input) {
if (typeof input === 'string') {
return this.parse(input);
}
var marker = null;
if (typeof input === 'number') {
marker = this.timestampToMarker(input);
}
else if (input instanceof Date) {
input = input.valueOf();
if (!isNaN(input)) {
marker = this.timestampToMarker(input);
}
}
else if (Array.isArray(input)) {
marker = arrayToUtcDate(input);
}
if (marker === null || !isValidDate(marker)) {
return null;
}
return { marker: marker, isTimeUnspecified: false, forcedTzo: null };
};
DateEnv.prototype.parse = function (s) {
var parts = parse(s);
if (parts === null) {
return null;
}
var marker = parts.marker;
var forcedTzo = null;
if (parts.timeZoneOffset !== null) {
if (this.canComputeOffset) {
marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
}
else {
forcedTzo = parts.timeZoneOffset;
}
}
return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo };
};
// Accessors
DateEnv.prototype.getYear = function (marker) {
return this.calendarSystem.getMarkerYear(marker);
};
DateEnv.prototype.getMonth = function (marker) {
return this.calendarSystem.getMarkerMonth(marker);
};
// Adding / Subtracting
DateEnv.prototype.add = function (marker, dur) {
var a = this.calendarSystem.markerToArray(marker);
a[0] += dur.years;
a[1] += dur.months;
a[2] += dur.days;
a[6] += dur.milliseconds;
return this.calendarSystem.arrayToMarker(a);
};
DateEnv.prototype.subtract = function (marker, dur) {
var a = this.calendarSystem.markerToArray(marker);
a[0] -= dur.years;
a[1] -= dur.months;
a[2] -= dur.days;
a[6] -= dur.milliseconds;
return this.calendarSystem.arrayToMarker(a);
};
DateEnv.prototype.addYears = function (marker, n) {
var a = this.calendarSystem.markerToArray(marker);
a[0] += n;
return this.calendarSystem.arrayToMarker(a);
};
DateEnv.prototype.addMonths = function (marker, n) {
var a = this.calendarSystem.markerToArray(marker);
a[1] += n;
return this.calendarSystem.arrayToMarker(a);
};
// Diffing Whole Units
DateEnv.prototype.diffWholeYears = function (m0, m1) {
var calendarSystem = this.calendarSystem;
if (timeAsMs(m0) === timeAsMs(m1) &&
calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
}
return null;
};
DateEnv.prototype.diffWholeMonths = function (m0, m1) {
var calendarSystem = this.calendarSystem;
if (timeAsMs(m0) === timeAsMs(m1) &&
calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
(calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
}
return null;
};
// Range / Duration
DateEnv.prototype.greatestWholeUnit = function (m0, m1) {
var n = this.diffWholeYears(m0, m1);
if (n !== null) {
return { unit: 'year', value: n };
}
n = this.diffWholeMonths(m0, m1);
if (n !== null) {
return { unit: 'month', value: n };
}
n = diffWholeWeeks(m0, m1);
if (n !== null) {
return { unit: 'week', value: n };
}
n = diffWholeDays(m0, m1);
if (n !== null) {
return { unit: 'day', value: n };
}
n = diffHours(m0, m1);
if (isInt(n)) {
return { unit: 'hour', value: n };
}
n = diffMinutes(m0, m1);
if (isInt(n)) {
return { unit: 'minute', value: n };
}
n = diffSeconds(m0, m1);
if (isInt(n)) {
return { unit: 'second', value: n };
}
return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
};
DateEnv.prototype.countDurationsBetween = function (m0, m1, d) {
// TODO: can use greatestWholeUnit
var diff;
if (d.years) {
diff = this.diffWholeYears(m0, m1);
if (diff !== null) {
return diff / asRoughYears(d);
}
}
if (d.months) {
diff = this.diffWholeMonths(m0, m1);
if (diff !== null) {
return diff / asRoughMonths(d);
}
}
if (d.days) {
diff = diffWholeDays(m0, m1);
if (diff !== null) {
return diff / asRoughDays(d);
}
}
return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
};
// Start-Of
DateEnv.prototype.startOf = function (m, unit) {
if (unit === 'year') {
return this.startOfYear(m);
}
else if (unit === 'month') {
return this.startOfMonth(m);
}
else if (unit === 'week') {
return this.startOfWeek(m);
}
else if (unit === 'day') {
return startOfDay(m);
}
else if (unit === 'hour') {
return startOfHour(m);
}
else if (unit === 'minute') {
return startOfMinute(m);
}
else if (unit === 'second') {
return startOfSecond(m);
}
};
DateEnv.prototype.startOfYear = function (m) {
return this.calendarSystem.arrayToMarker([
this.calendarSystem.getMarkerYear(m)
]);
};
DateEnv.prototype.startOfMonth = function (m) {
return this.calendarSystem.arrayToMarker([
this.calendarSystem.getMarkerYear(m),
this.calendarSystem.getMarkerMonth(m)
]);
};
DateEnv.prototype.startOfWeek = function (m) {
return this.calendarSystem.arrayToMarker([
this.calendarSystem.getMarkerYear(m),
this.calendarSystem.getMarkerMonth(m),
m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7)
]);
};
// Week Number
DateEnv.prototype.computeWeekNumber = function (marker) {
if (this.weekNumberFunc) {
return this.weekNumberFunc(this.toDate(marker));
}
else {
return weekOfYear(marker, this.weekDow, this.weekDoy);
}
};
// TODO: choke on timeZoneName: long
DateEnv.prototype.format = function (marker, formatter, dateOptions) {
if (dateOptions === void 0) { dateOptions = {}; }
return formatter.format({
marker: marker,
timeZoneOffset: dateOptions.forcedTzo != null ?
dateOptions.forcedTzo :
this.offsetForMarker(marker)
}, this);
};
DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) {
if (dateOptions === void 0) { dateOptions = {}; }
if (dateOptions.isEndExclusive) {
end = addMs(end, -1);
}
return formatter.formatRange({
marker: start,
timeZoneOffset: dateOptions.forcedStartTzo != null ?
dateOptions.forcedStartTzo :
this.offsetForMarker(start)
}, {
marker: end,
timeZoneOffset: dateOptions.forcedEndTzo != null ?
dateOptions.forcedEndTzo :
this.offsetForMarker(end)
}, this);
};
DateEnv.prototype.formatIso = function (marker, extraOptions) {
if (extraOptions === void 0) { extraOptions = {}; }
var timeZoneOffset = null;
if (!extraOptions.omitTimeZoneOffset) {
if (extraOptions.forcedTzo != null) {
timeZoneOffset = extraOptions.forcedTzo;
}
else {
timeZoneOffset = this.offsetForMarker(marker);
}
}
return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
};
// TimeZone
DateEnv.prototype.timestampToMarker = function (ms) {
if (this.timeZone === 'local') {
return arrayToUtcDate(dateToLocalArray(new Date(ms)));
}
else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
return new Date(ms);
}
else {
return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
}
};
DateEnv.prototype.offsetForMarker = function (m) {
if (this.timeZone === 'local') {
return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
}
else if (this.timeZone === 'UTC') {
return 0;
}
else if (this.namedTimeZoneImpl) {
return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
}
return null;
};
// Conversion
DateEnv.prototype.toDate = function (m, forcedTzo) {
if (this.timeZone === 'local') {
return arrayToLocalDate(dateToUtcArray(m));
}
else if (this.timeZone === 'UTC') {
return new Date(m.valueOf()); // make sure it's a copy
}
else if (!this.namedTimeZoneImpl) {
return new Date(m.valueOf() - (forcedTzo || 0));
}
else {
return new Date(m.valueOf() -
this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms
);
}
};
return DateEnv;
}());
var SIMPLE_SOURCE_PROPS = {
id: String,
allDayDefault: Boolean,
eventDataTransform: Function,
success: Function,
failure: Function
};
var uid$2 = 0;
function doesSourceNeedRange(eventSource, calendar) {
var defs = calendar.pluginSystem.hooks.eventSourceDefs;
return !defs[eventSource.sourceDefId].ignoreRange;
}
function parseEventSource(raw, calendar) {
var defs = calendar.pluginSystem.hooks.eventSourceDefs;
for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence
var def = defs[i];
var meta = def.parseMeta(raw);
if (meta) {
var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar);
res._raw = raw;
return res;
}
}
return null;
}
function parseEventSourceProps(raw, meta, sourceDefId, calendar) {
var leftovers0 = {};
var props = refineProps(raw, SIMPLE_SOURCE_PROPS, {}, leftovers0);
var leftovers1 = {};
var ui = processUnscopedUiProps(leftovers0, calendar, leftovers1);
props.isFetching = false;
props.latestFetchId = '';
props.fetchRange = null;
props.publicId = String(raw.id || '');
props.sourceId = String(uid$2++);
props.sourceDefId = sourceDefId;
props.meta = meta;
props.ui = ui;
props.extendedProps = leftovers1;
return props;
}
function reduceEventSources (eventSources, action, dateProfile, calendar) {
switch (action.type) {
case 'ADD_EVENT_SOURCES': // already parsed
return addSources(eventSources, action.sources, dateProfile ? dateProfile.activeRange : null, calendar);
case 'REMOVE_EVENT_SOURCE':
return removeSource(eventSources, action.sourceId);
case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
case 'NEXT':
case 'SET_DATE':
case 'SET_VIEW_TYPE':
if (dateProfile) {
return fetchDirtySources(eventSources, dateProfile.activeRange, calendar);
}
else {
return eventSources;
}
case 'FETCH_EVENT_SOURCES':
case 'CHANGE_TIMEZONE':
return fetchSourcesByIds(eventSources, action.sourceIds ?
arrayToHash(action.sourceIds) :
excludeStaticSources(eventSources, calendar), dateProfile ? dateProfile.activeRange : null, calendar);
case 'RECEIVE_EVENTS':
case 'RECEIVE_EVENT_ERROR':
return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
case 'REMOVE_ALL_EVENT_SOURCES':
return {};
default:
return eventSources;
}
}
var uid$3 = 0;
function addSources(eventSourceHash, sources, fetchRange, calendar) {
var hash = {};
for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) {
var source = sources_1[_i];
hash[source.sourceId] = source;
}
if (fetchRange) {
hash = fetchDirtySources(hash, fetchRange, calendar);
}
return __assign({}, eventSourceHash, hash);
}
function removeSource(eventSourceHash, sourceId) {
return filterHash(eventSourceHash, function (eventSource) {
return eventSource.sourceId !== sourceId;
});
}
function fetchDirtySources(sourceHash, fetchRange, calendar) {
return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) {
return isSourceDirty(eventSource, fetchRange, calendar);
}), fetchRange, calendar);
}
function isSourceDirty(eventSource, fetchRange, calendar) {
if (!doesSourceNeedRange(eventSource, calendar)) {
return !eventSource.latestFetchId;
}
else {
return !calendar.opt('lazyFetching') ||
!eventSource.fetchRange ||
eventSource.isFetching || // always cancel outdated in-progress fetches
fetchRange.start < eventSource.fetchRange.start ||
fetchRange.end > eventSource.fetchRange.end;
}
}
function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, calendar) {
var nextSources = {};
for (var sourceId in prevSources) {
var source = prevSources[sourceId];
if (sourceIdHash[sourceId]) {
nextSources[sourceId] = fetchSource(source, fetchRange, calendar);
}
else {
nextSources[sourceId] = source;
}
}
return nextSources;
}
function fetchSource(eventSource, fetchRange, calendar) {
var sourceDef = calendar.pluginSystem.hooks.eventSourceDefs[eventSource.sourceDefId];
var fetchId = String(uid$3++);
sourceDef.fetch({
eventSource: eventSource,
calendar: calendar,
range: fetchRange
}, function (res) {
var rawEvents = res.rawEvents;
var calSuccess = calendar.opt('eventSourceSuccess');
var calSuccessRes;
var sourceSuccessRes;
if (eventSource.success) {
sourceSuccessRes = eventSource.success(rawEvents, res.xhr);
}
if (calSuccess) {
calSuccessRes = calSuccess(rawEvents, res.xhr);
}
rawEvents = sourceSuccessRes || calSuccessRes || rawEvents;
calendar.dispatch({
type: 'RECEIVE_EVENTS',
sourceId: eventSource.sourceId,
fetchId: fetchId,
fetchRange: fetchRange,
rawEvents: rawEvents
});
}, function (error) {
var callFailure = calendar.opt('eventSourceFailure');
console.warn(error.message, error);
if (eventSource.failure) {
eventSource.failure(error);
}
if (callFailure) {
callFailure(error);
}
calendar.dispatch({
type: 'RECEIVE_EVENT_ERROR',
sourceId: eventSource.sourceId,
fetchId: fetchId,
fetchRange: fetchRange,
error: error
});
});
return __assign({}, eventSource, { isFetching: true, latestFetchId: fetchId });
}
function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
var _a;
var eventSource = sourceHash[sourceId];
if (eventSource && // not already removed
fetchId === eventSource.latestFetchId) {
return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange // also serves as a marker that at least one fetch has completed
}), _a));
}
return sourceHash;
}
function excludeStaticSources(eventSources, calendar) {
return filterHash(eventSources, function (eventSource) {
return doesSourceNeedRange(eventSource, calendar);
});
}
var DateProfileGenerator = /** @class */ (function () {
function DateProfileGenerator(viewSpec, calendar) {
this.viewSpec = viewSpec;
this.options = viewSpec.options;
this.dateEnv = calendar.dateEnv;
this.calendar = calendar;
this.initHiddenDays();
}
/* Date Range Computation
------------------------------------------------------------------------------------------------------------------*/
// Builds a structure with info about what the dates/ranges will be for the "prev" view.
DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate) {
var dateEnv = this.dateEnv;
var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
currentDateProfile.dateIncrement);
return this.build(prevDate, -1);
};
// Builds a structure with info about what the dates/ranges will be for the "next" view.
DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate) {
var dateEnv = this.dateEnv;
var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
currentDateProfile.dateIncrement);
return this.build(nextDate, 1);
};
// Builds a structure holding dates/ranges for rendering around the given date.
// Optional direction param indicates whether the date is being incremented/decremented
// from its previous value. decremented = -1, incremented = 1 (default).
DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) {
if (forceToValid === void 0) { forceToValid = false; }
var validRange;
var minTime = null;
var maxTime = null;
var currentInfo;
var isRangeAllDay;
var renderRange;
var activeRange;
var isValid;
validRange = this.buildValidRange();
validRange = this.trimHiddenDays(validRange);
if (forceToValid) {
currentDate = constrainMarkerToRange(currentDate, validRange);
}
currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
renderRange = this.trimHiddenDays(renderRange);
activeRange = renderRange;
if (!this.options.showNonCurrentDates) {
activeRange = intersectRanges(activeRange, currentInfo.range);
}
minTime = createDuration(this.options.minTime);
maxTime = createDuration(this.options.maxTime);
activeRange = this.adjustActiveRange(activeRange, minTime, maxTime);
activeRange = intersectRanges(activeRange, validRange); // might return null
// it's invalid if the originally requested date is not contained,
// or if the range is completely outside of the valid range.
isValid = rangesIntersect(currentInfo.range, validRange);
return {
// constraint for where prev/next operations can go and where events can be dragged/resized to.
// an object with optional start and end properties.
validRange: validRange,
// range the view is formally responsible for.
// for example, a month view might have 1st-31st, excluding padded dates
currentRange: currentInfo.range,
// name of largest unit being displayed, like "month" or "week"
currentRangeUnit: currentInfo.unit,
isRangeAllDay: isRangeAllDay,
// dates that display events and accept drag-n-drop
// will be `null` if no dates accept events
activeRange: activeRange,
// date range with a rendered skeleton
// includes not-active days that need some sort of DOM
renderRange: renderRange,
// Duration object that denotes the first visible time of any given day
minTime: minTime,
// Duration object that denotes the exclusive visible end time of any given day
maxTime: maxTime,
isValid: isValid,
// how far the current date will move for a prev/next operation
dateIncrement: this.buildDateIncrement(currentInfo.duration)
// pass a fallback (might be null) ^
};
};
// Builds an object with optional start/end properties.
// Indicates the minimum/maximum dates to display.
// not responsible for trimming hidden days.
DateProfileGenerator.prototype.buildValidRange = function () {
return this.getRangeOption('validRange', this.calendar.getNow()) ||
{ start: null, end: null }; // completely open-ended
};
// Builds a structure with info about the "current" range, the range that is
// highlighted as being the current month for example.
// See build() for a description of `direction`.
// Guaranteed to have `range` and `unit` properties. `duration` is optional.
DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) {
var _a = this, viewSpec = _a.viewSpec, dateEnv = _a.dateEnv;
var duration = null;
var unit = null;
var range = null;
var dayCount;
if (viewSpec.duration) {
duration = viewSpec.duration;
unit = viewSpec.durationUnit;
range = this.buildRangeFromDuration(date, direction, duration, unit);
}
else if ((dayCount = this.options.dayCount)) {
unit = 'day';
range = this.buildRangeFromDayCount(date, direction, dayCount);
}
else if ((range = this.buildCustomVisibleRange(date))) {
unit = dateEnv.greatestWholeUnit(range.start, range.end).unit;
}
else {
duration = this.getFallbackDuration();
unit = greatestDurationDenominator(duration).unit;
range = this.buildRangeFromDuration(date, direction, duration, unit);
}
return { duration: duration, unit: unit, range: range };
};
DateProfileGenerator.prototype.getFallbackDuration = function () {
return createDuration({ day: 1 });
};
// Returns a new activeRange to have time values (un-ambiguate)
// minTime or maxTime causes the range to expand.
DateProfileGenerator.prototype.adjustActiveRange = function (range, minTime, maxTime) {
var dateEnv = this.dateEnv;
var start = range.start;
var end = range.end;
if (this.viewSpec.class.prototype.usesMinMaxTime) {
// expand active range if minTime is negative (why not when positive?)
if (asRoughDays(minTime) < 0) {
start = startOfDay(start); // necessary?
start = dateEnv.add(start, minTime);
}
// expand active range if maxTime is beyond one day (why not when positive?)
if (asRoughDays(maxTime) > 1) {
end = startOfDay(end); // necessary?
end = addDays(end, -1);
end = dateEnv.add(end, maxTime);
}
}
return { start: start, end: end };
};
// Builds the "current" range when it is specified as an explicit duration.
// `unit` is the already-computed greatestDurationDenominator unit of duration.
DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) {
var dateEnv = this.dateEnv;
var alignment = this.options.dateAlignment;
var dateIncrementInput;
var dateIncrementDuration;
var start;
var end;
var res;
// compute what the alignment should be
if (!alignment) {
dateIncrementInput = this.options.dateIncrement;
if (dateIncrementInput) {
dateIncrementDuration = createDuration(dateIncrementInput);
// use the smaller of the two units
if (asRoughMs(dateIncrementDuration) < asRoughMs(duration)) {
alignment = greatestDurationDenominator(dateIncrementDuration, !getWeeksFromInput(dateIncrementInput)).unit;
}
else {
alignment = unit;
}
}
else {
alignment = unit;
}
}
// if the view displays a single day or smaller
if (asRoughDays(duration) <= 1) {
if (this.isHiddenDay(start)) {
start = this.skipHiddenDays(start, direction);
start = startOfDay(start);
}
}
function computeRes() {
start = dateEnv.startOf(date, alignment);
end = dateEnv.add(start, duration);
res = { start: start, end: end };
}
computeRes();
// if range is completely enveloped by hidden days, go past the hidden days
if (!this.trimHiddenDays(res)) {
date = this.skipHiddenDays(date, direction);
computeRes();
}
return res;
};
// Builds the "current" range when a dayCount is specified.
DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) {
var dateEnv = this.dateEnv;
var customAlignment = this.options.dateAlignment;
var runningCount = 0;
var start = date;
var end;
if (customAlignment) {
start = dateEnv.startOf(start, customAlignment);
}
start = startOfDay(start);
start = this.skipHiddenDays(start, direction);
end = start;
do {
end = addDays(end, 1);
if (!this.isHiddenDay(end)) {
runningCount++;
}
} while (runningCount < dayCount);
return { start: start, end: end };
};
// Builds a normalized range object for the "visible" range,
// which is a way to define the currentRange and activeRange at the same time.
DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) {
var dateEnv = this.dateEnv;
var visibleRange = this.getRangeOption('visibleRange', dateEnv.toDate(date));
if (visibleRange && (visibleRange.start == null || visibleRange.end == null)) {
return null;
}
return visibleRange;
};
// Computes the range that will represent the element/cells for *rendering*,
// but which may have voided days/times.
// not responsible for trimming hidden days.
DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) {
return currentRange;
};
// Compute the duration value that should be added/substracted to the current date
// when a prev/next operation happens.
DateProfileGenerator.prototype.buildDateIncrement = function (fallback) {
var dateIncrementInput = this.options.dateIncrement;
var customAlignment;
if (dateIncrementInput) {
return createDuration(dateIncrementInput);
}
else if ((customAlignment = this.options.dateAlignment)) {
return createDuration(1, customAlignment);
}
else if (fallback) {
return fallback;
}
else {
return createDuration({ days: 1 });
}
};
// Arguments after name will be forwarded to a hypothetical function value
// WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects.
// Always clone your objects if you fear mutation.
DateProfileGenerator.prototype.getRangeOption = function (name) {
var otherArgs = [];
for (var _i = 1; _i < arguments.length; _i++) {
otherArgs[_i - 1] = arguments[_i];
}
var val = this.options[name];
if (typeof val === 'function') {
val = val.apply(null, otherArgs);
}
if (val) {
val = parseRange(val, this.dateEnv);
}
if (val) {
val = computeVisibleDayRange(val);
}
return val;
};
/* Hidden Days
------------------------------------------------------------------------------------------------------------------*/
// Initializes internal variables related to calculating hidden days-of-week
DateProfileGenerator.prototype.initHiddenDays = function () {
var hiddenDays = this.options.hiddenDays || []; // array of day-of-week indices that are hidden
var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
var dayCnt = 0;
var i;
if (this.options.weekends === false) {
hiddenDays.push(0, 6); // 0=sunday, 6=saturday
}
for (i = 0; i < 7; i++) {
if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
dayCnt++;
}
}
if (!dayCnt) {
throw new Error('invalid hiddenDays'); // all days were hidden? bad.
}
this.isHiddenDayHash = isHiddenDayHash;
};
// Remove days from the beginning and end of the range that are computed as hidden.
// If the whole range is trimmed off, returns null
DateProfileGenerator.prototype.trimHiddenDays = function (range) {
var start = range.start;
var end = range.end;
if (start) {
start = this.skipHiddenDays(start);
}
if (end) {
end = this.skipHiddenDays(end, -1, true);
}
if (start == null || end == null || start < end) {
return { start: start, end: end };
}
return null;
};
// Is the current day hidden?
// `day` is a day-of-week index (0-6), or a Date (used for UTC)
DateProfileGenerator.prototype.isHiddenDay = function (day) {
if (day instanceof Date) {
day = day.getUTCDay();
}
return this.isHiddenDayHash[day];
};
// Incrementing the current day until it is no longer a hidden day, returning a copy.
// DOES NOT CONSIDER validRange!
// If the initial value of `date` is not a hidden day, don't do anything.
// Pass `isExclusive` as `true` if you are dealing with an end date.
// `inc` defaults to `1` (increment one day forward each time)
DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) {
if (inc === void 0) { inc = 1; }
if (isExclusive === void 0) { isExclusive = false; }
while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
date = addDays(date, inc);
}
return date;
};
return DateProfileGenerator;
}());
// TODO: find a way to avoid comparing DateProfiles. it's tedious
function isDateProfilesEqual(p0, p1) {
return rangesEqual(p0.validRange, p1.validRange) &&
rangesEqual(p0.activeRange, p1.activeRange) &&
rangesEqual(p0.renderRange, p1.renderRange) &&
durationsEqual(p0.minTime, p1.minTime) &&
durationsEqual(p0.maxTime, p1.maxTime);
/*
TODO: compare more?
currentRange: DateRange
currentRangeUnit: string
isRangeAllDay: boolean
isValid: boolean
dateIncrement: Duration
*/
}
function reduce (state, action, calendar) {
var viewType = reduceViewType(state.viewType, action);
var dateProfile = reduceDateProfile(state.dateProfile, action, state.currentDate, viewType, calendar);
var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendar);
var nextState = __assign({}, state, { viewType: viewType,
dateProfile: dateProfile, currentDate: reduceCurrentDate(state.currentDate, action, dateProfile), eventSources: eventSources, eventStore: reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendar), dateSelection: reduceDateSelection(state.dateSelection, action, calendar), eventSelection: reduceSelectedEvent(state.eventSelection, action), eventDrag: reduceEventDrag(state.eventDrag, action, eventSources, calendar), eventResize: reduceEventResize(state.eventResize, action, eventSources, calendar), eventSourceLoadingLevel: computeLoadingLevel(eventSources), loadingLevel: computeLoadingLevel(eventSources) });
for (var _i = 0, _a = calendar.pluginSystem.hooks.reducers; _i < _a.length; _i++) {
var reducerFunc = _a[_i];
nextState = reducerFunc(nextState, action, calendar);
}
// console.log(action.type, nextState)
return nextState;
}
function reduceViewType(currentViewType, action) {
switch (action.type) {
case 'SET_VIEW_TYPE':
return action.viewType;
default:
return currentViewType;
}
}
function reduceDateProfile(currentDateProfile, action, currentDate, viewType, calendar) {
var newDateProfile;
switch (action.type) {
case 'PREV':
newDateProfile = calendar.dateProfileGenerators[viewType].buildPrev(currentDateProfile, currentDate);
break;
case 'NEXT':
newDateProfile = calendar.dateProfileGenerators[viewType].buildNext(currentDateProfile, currentDate);
break;
case 'SET_DATE':
if (!currentDateProfile.activeRange ||
!rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker)) {
newDateProfile = calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true // forceToValid
);
}
break;
case 'SET_VIEW_TYPE':
var generator = calendar.dateProfileGenerators[viewType];
if (!generator) {
throw new Error(viewType ?
'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' :
'No available FullCalendar view plugins.');
}
newDateProfile = generator.build(action.dateMarker || currentDate, undefined, true // forceToValid
);
break;
}
if (newDateProfile &&
newDateProfile.isValid &&
!(currentDateProfile && isDateProfilesEqual(currentDateProfile, newDateProfile))) {
return newDateProfile;
}
else {
return currentDateProfile;
}
}
function reduceCurrentDate(currentDate, action, dateProfile) {
switch (action.type) {
case 'PREV':
case 'NEXT':
if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) {
return dateProfile.currentRange.start;
}
else {
return currentDate;
}
case 'SET_DATE':
case 'SET_VIEW_TYPE':
var newDate = action.dateMarker || currentDate;
if (dateProfile.activeRange && !rangeContainsMarker(dateProfile.activeRange, newDate)) {
return dateProfile.currentRange.start;
}
else {
return newDate;
}
default:
return currentDate;
}
}
function reduceDateSelection(currentSelection, action, calendar) {
switch (action.type) {
case 'SELECT_DATES':
return action.selection;
case 'UNSELECT_DATES':
return null;
default:
return currentSelection;
}
}
function reduceSelectedEvent(currentInstanceId, action) {
switch (action.type) {
case 'SELECT_EVENT':
return action.eventInstanceId;
case 'UNSELECT_EVENT':
return '';
default:
return currentInstanceId;
}
}
function reduceEventDrag(currentDrag, action, sources, calendar) {
switch (action.type) {
case 'SET_EVENT_DRAG':
var newDrag = action.state;
return {
affectedEvents: newDrag.affectedEvents,
mutatedEvents: newDrag.mutatedEvents,
isEvent: newDrag.isEvent,
origSeg: newDrag.origSeg
};
case 'UNSET_EVENT_DRAG':
return null;
default:
return currentDrag;
}
}
function reduceEventResize(currentResize, action, sources, calendar) {
switch (action.type) {
case 'SET_EVENT_RESIZE':
var newResize = action.state;
return {
affectedEvents: newResize.affectedEvents,
mutatedEvents: newResize.mutatedEvents,
isEvent: newResize.isEvent,
origSeg: newResize.origSeg
};
case 'UNSET_EVENT_RESIZE':
return null;
default:
return currentResize;
}
}
function computeLoadingLevel(eventSources) {
var cnt = 0;
for (var sourceId in eventSources) {
if (eventSources[sourceId].isFetching) {
cnt++;
}
}
return cnt;
}
var STANDARD_PROPS = {
start: null,
end: null,
allDay: Boolean
};
function parseDateSpan(raw, dateEnv, defaultDuration) {
var span = parseOpenDateSpan(raw, dateEnv);
var range = span.range;
if (!range.start) {
return null;
}
if (!range.end) {
if (defaultDuration == null) {
return null;
}
else {
range.end = dateEnv.add(range.start, defaultDuration);
}
}
return span;
}
/*
TODO: somehow combine with parseRange?
Will return null if the start/end props were present but parsed invalidly.
*/
function parseOpenDateSpan(raw, dateEnv) {
var leftovers = {};
var standardProps = refineProps(raw, STANDARD_PROPS, {}, leftovers);
var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
var allDay = standardProps.allDay;
if (allDay == null) {
allDay = (startMeta && startMeta.isTimeUnspecified) &&
(!endMeta || endMeta.isTimeUnspecified);
}
// use this leftover object as the selection object
leftovers.range = {
start: startMeta ? startMeta.marker : null,
end: endMeta ? endMeta.marker : null
};
leftovers.allDay = allDay;
return leftovers;
}
function isDateSpansEqual(span0, span1) {
return rangesEqual(span0.range, span1.range) &&
span0.allDay === span1.allDay &&
isSpanPropsEqual(span0, span1);
}
// the NON-DATE-RELATED props
function isSpanPropsEqual(span0, span1) {
for (var propName in span1) {
if (propName !== 'range' && propName !== 'allDay') {
if (span0[propName] !== span1[propName]) {
return false;
}
}
}
// are there any props that span0 has that span1 DOESN'T have?
// both have range/allDay, so no need to special-case.
for (var propName in span0) {
if (!(propName in span1)) {
return false;
}
}
return true;
}
function buildDateSpanApi(span, dateEnv) {
return {
start: dateEnv.toDate(span.range.start),
end: dateEnv.toDate(span.range.end),
startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }),
allDay: span.allDay
};
}
function buildDatePointApi(span, dateEnv) {
return {
date: dateEnv.toDate(span.range.start),
dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
allDay: span.allDay
};
}
function fabricateEventRange(dateSpan, eventUiBases, calendar) {
var def = parseEventDef({ editable: false }, '', // sourceId
dateSpan.allDay, true, // hasEnd
calendar);
return {
def: def,
ui: compileEventUi(def, eventUiBases),
instance: createEventInstance(def.defId, dateSpan.range),
range: dateSpan.range,
isStart: true,
isEnd: true
};
}
function compileViewDefs(defaultConfigs, overrideConfigs) {
var hash = {};
var viewType;
for (viewType in defaultConfigs) {
ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
}
for (viewType in overrideConfigs) {
ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
}
return hash;
}
function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
if (hash[viewType]) {
return hash[viewType];
}
var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
if (viewDef) {
hash[viewType] = viewDef;
}
return viewDef;
}
function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
var defaultConfig = defaultConfigs[viewType];
var overrideConfig = overrideConfigs[viewType];
var queryProp = function (name) {
return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null);
};
var theClass = queryProp('class');
var superType = queryProp('superType');
if (!superType && theClass) {
superType =
findViewNameBySubclass(theClass, overrideConfigs) ||
findViewNameBySubclass(theClass, defaultConfigs);
}
var superDef = null;
if (superType) {
if (superType === viewType) {
throw new Error('Can\'t have a custom view type that references itself');
}
superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
}
if (!theClass && superDef) {
theClass = superDef.class;
}
if (!theClass) {
return null; // don't throw a warning, might be settings for a single-unit view
}
return {
type: viewType,
class: theClass,
defaults: __assign({}, (superDef ? superDef.defaults : {}), (defaultConfig ? defaultConfig.options : {})),
overrides: __assign({}, (superDef ? superDef.overrides : {}), (overrideConfig ? overrideConfig.options : {}))
};
}
function findViewNameBySubclass(viewSubclass, configs) {
var superProto = Object.getPrototypeOf(viewSubclass.prototype);
for (var viewType in configs) {
var parsed = configs[viewType];
// need DIRECT subclass, so instanceof won't do it
if (parsed.class && parsed.class.prototype === superProto) {
return viewType;
}
}
return '';
}
function parseViewConfigs(inputs) {
return mapHash(inputs, parseViewConfig);
}
var VIEW_DEF_PROPS = {
type: String,
class: null
};
function parseViewConfig(input) {
if (typeof input === 'function') {
input = { class: input };
}
var options = {};
var props = refineProps(input, VIEW_DEF_PROPS, {}, options);
return {
superType: props.type,
class: props.class,
options: options
};
}
function buildViewSpecs(defaultInputs, optionsManager) {
var defaultConfigs = parseViewConfigs(defaultInputs);
var overrideConfigs = parseViewConfigs(optionsManager.overrides.views);
var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
return mapHash(viewDefs, function (viewDef) {
return buildViewSpec(viewDef, overrideConfigs, optionsManager);
});
}
function buildViewSpec(viewDef, overrideConfigs, optionsManager) {
var durationInput = viewDef.overrides.duration ||
viewDef.defaults.duration ||
optionsManager.dynamicOverrides.duration ||
optionsManager.overrides.duration;
var duration = null;
var durationUnit = '';
var singleUnit = '';
var singleUnitOverrides = {};
if (durationInput) {
duration = createDuration(durationInput);
if (duration) { // valid?
var denom = greatestDurationDenominator(duration, !getWeeksFromInput(durationInput));
durationUnit = denom.unit;
if (denom.value === 1) {
singleUnit = durationUnit;
singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].options : {};
}
}
}
var queryButtonText = function (options) {
var buttonTextMap = options.buttonText || {};
var buttonTextKey = viewDef.defaults.buttonTextKey;
if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
return buttonTextMap[buttonTextKey];
}
if (buttonTextMap[viewDef.type] != null) {
return buttonTextMap[viewDef.type];
}
if (buttonTextMap[singleUnit] != null) {
return buttonTextMap[singleUnit];
}
};
return {
type: viewDef.type,
class: viewDef.class,
duration: duration,
durationUnit: durationUnit,
singleUnit: singleUnit,
options: __assign({}, globalDefaults, viewDef.defaults, optionsManager.dirDefaults, optionsManager.localeDefaults, optionsManager.overrides, singleUnitOverrides, viewDef.overrides, optionsManager.dynamicOverrides),
buttonTextOverride: queryButtonText(optionsManager.dynamicOverrides) ||
queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence
viewDef.overrides.buttonText,
buttonTextDefault: queryButtonText(optionsManager.localeDefaults) ||
queryButtonText(optionsManager.dirDefaults) ||
viewDef.defaults.buttonText ||
queryButtonText(globalDefaults) ||
viewDef.type // fall back to given view name
};
}
var Toolbar = /** @class */ (function (_super) {
__extends(Toolbar, _super);
function Toolbar(extraClassName) {
var _this = _super.call(this) || this;
_this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout);
_this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]);
_this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]);
_this._updateToday = memoizeRendering(_this.updateToday, null, [_this._renderLayout]);
_this._updatePrev = memoizeRendering(_this.updatePrev, null, [_this._renderLayout]);
_this._updateNext = memoizeRendering(_this.updateNext, null, [_this._renderLayout]);
_this.el = createElement('div', { className: 'fc-toolbar ' + extraClassName });
return _this;
}
Toolbar.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this._renderLayout.unrender(); // should unrender everything else
removeElement(this.el);
};
Toolbar.prototype.render = function (props) {
this._renderLayout(props.layout);
this._updateTitle(props.title);
this._updateActiveButton(props.activeButton);
this._updateToday(props.isTodayEnabled);
this._updatePrev(props.isPrevEnabled);
this._updateNext(props.isNextEnabled);
};
Toolbar.prototype.renderLayout = function (layout) {
var el = this.el;
this.viewsWithButtons = [];
appendToElement(el, this.renderSection('left', layout.left));
appendToElement(el, this.renderSection('center', layout.center));
appendToElement(el, this.renderSection('right', layout.right));
};
Toolbar.prototype.unrenderLayout = function () {
this.el.innerHTML = '';
};
Toolbar.prototype.renderSection = function (position, buttonStr) {
var _this = this;
var _a = this.context, theme = _a.theme, calendar = _a.calendar;
var optionsManager = calendar.optionsManager;
var viewSpecs = calendar.viewSpecs;
var sectionEl = createElement('div', { className: 'fc-' + position });
var calendarCustomButtons = optionsManager.computed.customButtons || {};
var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {};
var calendarButtonText = optionsManager.computed.buttonText || {};
if (buttonStr) {
buttonStr.split(' ').forEach(function (buttonGroupStr, i) {
var groupChildren = [];
var isOnlyButtons = true;
var groupEl;
buttonGroupStr.split(',').forEach(function (buttonName, j) {
var customButtonProps;
var viewSpec;
var buttonClick;
var buttonIcon; // only one of these will be set
var buttonText; // "
var buttonInnerHtml;
var buttonClasses;
var buttonEl;
var buttonAriaAttr;
if (buttonName === 'title') {
groupChildren.push(htmlToElement('<h2>&nbsp;</h2>')); // we always want it to take up height
isOnlyButtons = false;
}
else {
if ((customButtonProps = calendarCustomButtons[buttonName])) {
buttonClick = function (ev) {
if (customButtonProps.click) {
customButtonProps.click.call(buttonEl, ev);
}
};
(buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
(buttonIcon = theme.getIconClass(buttonName)) ||
(buttonText = customButtonProps.text);
}
else if ((viewSpec = viewSpecs[buttonName])) {
_this.viewsWithButtons.push(buttonName);
buttonClick = function () {
calendar.changeView(buttonName);
};
(buttonText = viewSpec.buttonTextOverride) ||
(buttonIcon = theme.getIconClass(buttonName)) ||
(buttonText = viewSpec.buttonTextDefault);
}
else if (calendar[buttonName]) { // a calendar method
buttonClick = function () {
calendar[buttonName]();
};
(buttonText = calendarButtonTextOverrides[buttonName]) ||
(buttonIcon = theme.getIconClass(buttonName)) ||
(buttonText = calendarButtonText[buttonName]);
// ^ everything else is considered default
}
if (buttonClick) {
buttonClasses = [
'fc-' + buttonName + '-button',
theme.getClass('button')
];
if (buttonText) {
buttonInnerHtml = htmlEscape(buttonText);
buttonAriaAttr = '';
}
else if (buttonIcon) {
buttonInnerHtml = "<span class='" + buttonIcon + "'></span>";
buttonAriaAttr = ' aria-label="' + buttonName + '"';
}
buttonEl = htmlToElement(// type="button" so that it doesn't submit a form
'<button type="button" class="' + buttonClasses.join(' ') + '"' +
buttonAriaAttr +
'>' + buttonInnerHtml + '</button>');
buttonEl.addEventListener('click', buttonClick);
groupChildren.push(buttonEl);
}
}
});
if (groupChildren.length > 1) {
groupEl = document.createElement('div');
var buttonGroupClassName = theme.getClass('buttonGroup');
if (isOnlyButtons && buttonGroupClassName) {
groupEl.classList.add(buttonGroupClassName);
}
appendToElement(groupEl, groupChildren);
sectionEl.appendChild(groupEl);
}
else {
appendToElement(sectionEl, groupChildren); // 1 or 0 children
}
});
}
return sectionEl;
};
Toolbar.prototype.updateToday = function (isTodayEnabled) {
this.toggleButtonEnabled('today', isTodayEnabled);
};
Toolbar.prototype.updatePrev = function (isPrevEnabled) {
this.toggleButtonEnabled('prev', isPrevEnabled);
};
Toolbar.prototype.updateNext = function (isNextEnabled) {
this.toggleButtonEnabled('next', isNextEnabled);
};
Toolbar.prototype.updateTitle = function (text) {
findElements(this.el, 'h2').forEach(function (titleEl) {
titleEl.innerText = text;
});
};
Toolbar.prototype.updateActiveButton = function (buttonName) {
var theme = this.context.theme;
var className = theme.getClass('buttonActive');
findElements(this.el, 'button').forEach(function (buttonEl) {
if (buttonName && buttonEl.classList.contains('fc-' + buttonName + '-button')) {
buttonEl.classList.add(className);
}
else {
buttonEl.classList.remove(className);
}
});
};
Toolbar.prototype.toggleButtonEnabled = function (buttonName, bool) {
findElements(this.el, '.fc-' + buttonName + '-button').forEach(function (buttonEl) {
buttonEl.disabled = !bool;
});
};
return Toolbar;
}(Component));
var CalendarComponent = /** @class */ (function (_super) {
__extends(CalendarComponent, _super);
function CalendarComponent(el) {
var _this = _super.call(this) || this;
_this.elClassNames = [];
_this.renderSkeleton = memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
_this.renderToolbars = memoizeRendering(_this._renderToolbars, _this._unrenderToolbars, [_this.renderSkeleton]);
_this.buildComponentContext = memoize(buildComponentContext);
_this.buildViewPropTransformers = memoize(buildViewPropTransformers);
_this.el = el;
_this.computeTitle = memoize(computeTitle);
_this.parseBusinessHours = memoize(function (input) {
return parseBusinessHours(input, _this.context.calendar);
});
return _this;
}
CalendarComponent.prototype.render = function (props, context) {
this.freezeHeight();
var title = this.computeTitle(props.dateProfile, props.viewSpec.options);
this.renderSkeleton(context);
this.renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, title);
this.renderView(props, title);
this.updateSize();
this.thawHeight();
};
CalendarComponent.prototype.destroy = function () {
if (this.header) {
this.header.destroy();
}
if (this.footer) {
this.footer.destroy();
}
this.renderSkeleton.unrender(); // will call destroyView
_super.prototype.destroy.call(this);
};
CalendarComponent.prototype._renderSkeleton = function (context) {
this.updateElClassNames(context);
prependToElement(this.el, this.contentEl = createElement('div', { className: 'fc-view-container' }));
var calendar = context.calendar;
for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) {
var modifyViewContainer = _a[_i];
modifyViewContainer(this.contentEl, calendar);
}
};
CalendarComponent.prototype._unrenderSkeleton = function () {
// weird to have this here
if (this.view) {
this.savedScroll = this.view.queryScroll();
this.view.destroy();
this.view = null;
}
removeElement(this.contentEl);
this.removeElClassNames();
};
CalendarComponent.prototype.removeElClassNames = function () {
var classList = this.el.classList;
for (var _i = 0, _a = this.elClassNames; _i < _a.length; _i++) {
var className = _a[_i];
classList.remove(className);
}
this.elClassNames = [];
};
CalendarComponent.prototype.updateElClassNames = function (context) {
this.removeElClassNames();
var theme = context.theme, options = context.options;
this.elClassNames = [
'fc',
'fc-' + options.dir,
theme.getClass('widget')
];
var classList = this.el.classList;
for (var _i = 0, _a = this.elClassNames; _i < _a.length; _i++) {
var className = _a[_i];
classList.add(className);
}
};
CalendarComponent.prototype._renderToolbars = function (viewSpec, dateProfile, currentDate, title) {
var _a = this, context = _a.context, header = _a.header, footer = _a.footer;
var options = context.options, calendar = context.calendar;
var headerLayout = options.header;
var footerLayout = options.footer;
var dateProfileGenerator = this.props.dateProfileGenerator;
var now = calendar.getNow();
var todayInfo = dateProfileGenerator.build(now);
var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate);
var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate);
var toolbarProps = {
title: title,
activeButton: viewSpec.type,
isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
isPrevEnabled: prevInfo.isValid,
isNextEnabled: nextInfo.isValid
};
if (headerLayout) {
if (!header) {
header = this.header = new Toolbar('fc-header-toolbar');
prependToElement(this.el, header.el);
}
header.receiveProps(__assign({ layout: headerLayout }, toolbarProps), context);
}
else if (header) {
header.destroy();
header = this.header = null;
}
if (footerLayout) {
if (!footer) {
footer = this.footer = new Toolbar('fc-footer-toolbar');
appendToElement(this.el, footer.el);
}
footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps), context);
}
else if (footer) {
footer.destroy();
footer = this.footer = null;
}
};
CalendarComponent.prototype._unrenderToolbars = function () {
if (this.header) {
this.header.destroy();
this.header = null;
}
if (this.footer) {
this.footer.destroy();
this.footer = null;
}
};
CalendarComponent.prototype.renderView = function (props, title) {
var view = this.view;
var _a = this.context, calendar = _a.calendar, options = _a.options;
var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator;
if (!view || view.viewSpec !== viewSpec) {
if (view) {
view.destroy();
}
view = this.view = new viewSpec['class'](viewSpec, this.contentEl);
if (this.savedScroll) {
view.addScroll(this.savedScroll, true);
this.savedScroll = null;
}
}
view.title = title; // for the API
var viewProps = {
dateProfileGenerator: dateProfileGenerator,
dateProfile: props.dateProfile,
businessHours: this.parseBusinessHours(viewSpec.options.businessHours),
eventStore: props.eventStore,
eventUiBases: props.eventUiBases,
dateSelection: props.dateSelection,
eventSelection: props.eventSelection,
eventDrag: props.eventDrag,
eventResize: props.eventResize
};
var transformers = this.buildViewPropTransformers(calendar.pluginSystem.hooks.viewPropsTransformers);
for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
var transformer = transformers_1[_i];
__assign(viewProps, transformer.transform(viewProps, viewSpec, props, options));
}
view.receiveProps(viewProps, this.buildComponentContext(this.context, viewSpec, view));
};
// Sizing
// -----------------------------------------------------------------------------------------------------------------
CalendarComponent.prototype.updateSize = function (isResize) {
if (isResize === void 0) { isResize = false; }
var view = this.view;
if (!view) {
return; // why?
}
if (isResize || this.isHeightAuto == null) {
this.computeHeightVars();
}
view.updateSize(isResize, this.viewHeight, this.isHeightAuto);
view.updateNowIndicator(); // we need to guarantee this will run after updateSize
view.popScroll(isResize);
};
CalendarComponent.prototype.computeHeightVars = function () {
var calendar = this.context.calendar; // yuck. need to handle dynamic options
var heightInput = calendar.opt('height');
var contentHeightInput = calendar.opt('contentHeight');
this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto';
if (typeof contentHeightInput === 'number') { // exists and not 'auto'
this.viewHeight = contentHeightInput;
}
else if (typeof contentHeightInput === 'function') { // exists and is a function
this.viewHeight = contentHeightInput();
}
else if (typeof heightInput === 'number') { // exists and not 'auto'
this.viewHeight = heightInput - this.queryToolbarsHeight();
}
else if (typeof heightInput === 'function') { // exists and is a function
this.viewHeight = heightInput() - this.queryToolbarsHeight();
}
else if (heightInput === 'parent') { // set to height of parent element
var parentEl = this.el.parentNode;
this.viewHeight = parentEl.getBoundingClientRect().height - this.queryToolbarsHeight();
}
else {
this.viewHeight = Math.round(this.contentEl.getBoundingClientRect().width /
Math.max(calendar.opt('aspectRatio'), .5));
}
};
CalendarComponent.prototype.queryToolbarsHeight = function () {
var height = 0;
if (this.header) {
height += computeHeightAndMargins(this.header.el);
}
if (this.footer) {
height += computeHeightAndMargins(this.footer.el);
}
return height;
};
// Height "Freezing"
// -----------------------------------------------------------------------------------------------------------------
CalendarComponent.prototype.freezeHeight = function () {
applyStyle(this.el, {
height: this.el.getBoundingClientRect().height,
overflow: 'hidden'
});
};
CalendarComponent.prototype.thawHeight = function () {
applyStyle(this.el, {
height: '',
overflow: ''
});
};
return CalendarComponent;
}(Component));
// Title and Date Formatting
// -----------------------------------------------------------------------------------------------------------------
// Computes what the title at the top of the calendar should be for this view
function computeTitle(dateProfile, viewOptions) {
var range;
// for views that span a large unit of time, show the proper interval, ignoring stray days before and after
if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
range = dateProfile.currentRange;
}
else { // for day units or smaller, use the actual day range
range = dateProfile.activeRange;
}
return this.context.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay });
}
// Generates the format string that should be used to generate the title for the current date range.
// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
function computeTitleFormat(dateProfile) {
var currentRangeUnit = dateProfile.currentRangeUnit;
if (currentRangeUnit === 'year') {
return { year: 'numeric' };
}
else if (currentRangeUnit === 'month') {
return { year: 'numeric', month: 'long' }; // like "September 2014"
}
else {
var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
if (days !== null && days > 1) {
// multi-day range. shorter, like "Sep 9 - 10 2014"
return { year: 'numeric', month: 'short', day: 'numeric' };
}
else {
// one day. longer, like "September 9 2014"
return { year: 'numeric', month: 'long', day: 'numeric' };
}
}
}
// build a context scoped to the view
function buildComponentContext(context, viewSpec, view) {
return context.extend(viewSpec.options, view);
}
// Plugin
// -----------------------------------------------------------------------------------------------------------------
function buildViewPropTransformers(theClasses) {
return theClasses.map(function (theClass) {
return new theClass();
});
}
var Interaction = /** @class */ (function () {
function Interaction(settings) {
this.component = settings.component;
}
Interaction.prototype.destroy = function () {
};
return Interaction;
}());
function parseInteractionSettings(component, input) {
return {
component: component,
el: input.el,
useEventCenter: input.useEventCenter != null ? input.useEventCenter : true
};
}
function interactionSettingsToStore(settings) {
var _a;
return _a = {},
_a[settings.component.uid] = settings,
_a;
}
// global state
var interactionSettingsStore = {};
/*
Detects when the user clicks on an event within a DateComponent
*/
var EventClicking = /** @class */ (function (_super) {
__extends(EventClicking, _super);
function EventClicking(settings) {
var _this = _super.call(this, settings) || this;
_this.handleSegClick = function (ev, segEl) {
var component = _this.component;
var _a = component.context, calendar = _a.calendar, view = _a.view;
var seg = getElSeg(segEl);
if (seg && // might be the <div> surrounding the more link
component.isValidSegDownEl(ev.target)) {
// our way to simulate a link click for elements that can't be <a> tags
// grab before trigger fired in case trigger trashes DOM thru rerendering
var hasUrlContainer = elementClosest(ev.target, '.fc-has-url');
var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
calendar.publiclyTrigger('eventClick', [
{
el: segEl,
event: new EventApi(component.context.calendar, seg.eventRange.def, seg.eventRange.instance),
jsEvent: ev,
view: view
}
]);
if (url && !ev.defaultPrevented) {
window.location.href = url;
}
}
};
var component = settings.component;
_this.destroy = listenBySelector(component.el, 'click', component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegClick);
return _this;
}
return EventClicking;
}(Interaction));
/*
Triggers events and adds/removes core classNames when the user's pointer
enters/leaves event-elements of a component.
*/
var EventHovering = /** @class */ (function (_super) {
__extends(EventHovering, _super);
function EventHovering(settings) {
var _this = _super.call(this, settings) || this;
// for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
_this.handleEventElRemove = function (el) {
if (el === _this.currentSegEl) {
_this.handleSegLeave(null, _this.currentSegEl);
}
};
_this.handleSegEnter = function (ev, segEl) {
if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
segEl.classList.add('fc-allow-mouse-resize');
_this.currentSegEl = segEl;
_this.triggerEvent('eventMouseEnter', ev, segEl);
}
};
_this.handleSegLeave = function (ev, segEl) {
if (_this.currentSegEl) {
segEl.classList.remove('fc-allow-mouse-resize');
_this.currentSegEl = null;
_this.triggerEvent('eventMouseLeave', ev, segEl);
}
};
var component = settings.component;
_this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave);
// how to make sure component already has context?
component.context.calendar.on('eventElRemove', _this.handleEventElRemove);
return _this;
}
EventHovering.prototype.destroy = function () {
this.removeHoverListeners();
this.component.context.calendar.off('eventElRemove', this.handleEventElRemove);
};
EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) {
var component = this.component;
var _a = component.context, calendar = _a.calendar, view = _a.view;
var seg = getElSeg(segEl);
if (!ev || component.isValidSegDownEl(ev.target)) {
calendar.publiclyTrigger(publicEvName, [
{
el: segEl,
event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
jsEvent: ev,
view: view
}
]);
}
};
return EventHovering;
}(Interaction));
var StandardTheme = /** @class */ (function (_super) {
__extends(StandardTheme, _super);
function StandardTheme() {
return _super !== null && _super.apply(this, arguments) || this;
}
return StandardTheme;
}(Theme));
StandardTheme.prototype.classes = {
widget: 'fc-unthemed',
widgetHeader: 'fc-widget-header',
widgetContent: 'fc-widget-content',
buttonGroup: 'fc-button-group',
button: 'fc-button fc-button-primary',
buttonActive: 'fc-button-active',
popoverHeader: 'fc-widget-header',
popoverContent: 'fc-widget-content',
// day grid
headerRow: 'fc-widget-header',
dayRow: 'fc-widget-content',
// list view
listView: 'fc-widget-content'
};
StandardTheme.prototype.baseIconClass = 'fc-icon';
StandardTheme.prototype.iconClasses = {
close: 'fc-icon-x',
prev: 'fc-icon-chevron-left',
next: 'fc-icon-chevron-right',
prevYear: 'fc-icon-chevrons-left',
nextYear: 'fc-icon-chevrons-right'
};
StandardTheme.prototype.iconOverrideOption = 'buttonIcons';
StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
var Calendar = /** @class */ (function () {
function Calendar(el, overrides) {
var _this = this;
this.buildComponentContext = memoize(buildComponentContext$1);
this.parseRawLocales = memoize(parseRawLocales);
this.buildLocale = memoize(buildLocale);
this.buildDateEnv = memoize(buildDateEnv);
this.buildTheme = memoize(buildTheme);
this.buildEventUiSingleBase = memoize(this._buildEventUiSingleBase);
this.buildSelectionConfig = memoize(this._buildSelectionConfig);
this.buildEventUiBySource = memoizeOutput(buildEventUiBySource, isPropsEqual);
this.buildEventUiBases = memoize(buildEventUiBases);
this.interactionsStore = {};
this.actionQueue = [];
this.isReducing = false;
// isDisplaying: boolean = false // installed in DOM? accepting renders?
this.needsRerender = false; // needs a render?
this.isRendering = false; // currently in the executeRender function?
this.renderingPauseDepth = 0;
this.buildDelayedRerender = memoize(buildDelayedRerender);
this.afterSizingTriggers = {};
this.isViewUpdated = false;
this.isDatesUpdated = false;
this.isEventsUpdated = false;
this.el = el;
this.optionsManager = new OptionsManager(overrides || {});
this.pluginSystem = new PluginSystem();
// only do once. don't do in handleOptions. because can't remove plugins
this.addPluginInputs(this.optionsManager.computed.plugins || []);
this.handleOptions(this.optionsManager.computed);
this.publiclyTrigger('_init'); // for tests
this.hydrate();
this.calendarInteractions = this.pluginSystem.hooks.calendarInteractions
.map(function (calendarInteractionClass) {
return new calendarInteractionClass(_this);
});
}
Calendar.prototype.addPluginInputs = function (pluginInputs) {
var pluginDefs = refinePluginDefs(pluginInputs);
for (var _i = 0, pluginDefs_1 = pluginDefs; _i < pluginDefs_1.length; _i++) {
var pluginDef = pluginDefs_1[_i];
this.pluginSystem.add(pluginDef);
}
};
Object.defineProperty(Calendar.prototype, "view", {
// public API
get: function () {
return this.component ? this.component.view : null;
},
enumerable: true,
configurable: true
});
// Public API for rendering
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.render = function () {
if (!this.component) {
this.component = new CalendarComponent(this.el);
this.renderableEventStore = createEmptyEventStore();
this.bindHandlers();
this.executeRender();
}
else {
this.requestRerender();
}
};
Calendar.prototype.destroy = function () {
if (this.component) {
this.unbindHandlers();
this.component.destroy(); // don't null-out. in case API needs access
this.component = null; // umm ???
for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) {
var interaction = _a[_i];
interaction.destroy();
}
this.publiclyTrigger('_destroyed');
}
};
// Handlers
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.bindHandlers = function () {
var _this = this;
// event delegation for nav links
this.removeNavLinkListener = listenBySelector(this.el, 'click', 'a[data-goto]', function (ev, anchorEl) {
var gotoOptions = anchorEl.getAttribute('data-goto');
gotoOptions = gotoOptions ? JSON.parse(gotoOptions) : {};
var dateEnv = _this.dateEnv;
var dateMarker = dateEnv.createMarker(gotoOptions.date);
var viewType = gotoOptions.type;
// property like "navLinkDayClick". might be a string or a function
var customAction = _this.viewOpt('navLink' + capitaliseFirstLetter(viewType) + 'Click');
if (typeof customAction === 'function') {
customAction(dateEnv.toDate(dateMarker), ev);
}
else {
if (typeof customAction === 'string') {
viewType = customAction;
}
_this.zoomTo(dateMarker, viewType);
}
});
if (this.opt('handleWindowResize')) {
window.addEventListener('resize', this.windowResizeProxy = debounce(// prevents rapid calls
this.windowResize.bind(this), this.opt('windowResizeDelay')));
}
};
Calendar.prototype.unbindHandlers = function () {
this.removeNavLinkListener();
if (this.windowResizeProxy) {
window.removeEventListener('resize', this.windowResizeProxy);
this.windowResizeProxy = null;
}
};
// Dispatcher
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.hydrate = function () {
var _this = this;
this.state = this.buildInitialState();
var rawSources = this.opt('eventSources') || [];
var singleRawSource = this.opt('events');
var sources = []; // parsed
if (singleRawSource) {
rawSources.unshift(singleRawSource);
}
for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) {
var rawSource = rawSources_1[_i];
var source = parseEventSource(rawSource, this);
if (source) {
sources.push(source);
}
}
this.batchRendering(function () {
_this.dispatch({ type: 'INIT' }); // pass in sources here?
_this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: sources });
_this.dispatch({
type: 'SET_VIEW_TYPE',
viewType: _this.opt('defaultView') || _this.pluginSystem.hooks.defaultView
});
});
};
Calendar.prototype.buildInitialState = function () {
return {
viewType: null,
loadingLevel: 0,
eventSourceLoadingLevel: 0,
currentDate: this.getInitialDate(),
dateProfile: null,
eventSources: {},
eventStore: createEmptyEventStore(),
dateSelection: null,
eventSelection: '',
eventDrag: null,
eventResize: null
};
};
Calendar.prototype.dispatch = function (action) {
this.actionQueue.push(action);
if (!this.isReducing) {
this.isReducing = true;
var oldState = this.state;
while (this.actionQueue.length) {
this.state = this.reduce(this.state, this.actionQueue.shift(), this);
}
var newState = this.state;
this.isReducing = false;
if (!oldState.loadingLevel && newState.loadingLevel) {
this.publiclyTrigger('loading', [true]);
}
else if (oldState.loadingLevel && !newState.loadingLevel) {
this.publiclyTrigger('loading', [false]);
}
var view = this.component && this.component.view;
if (oldState.eventStore !== newState.eventStore) {
if (oldState.eventStore) {
this.isEventsUpdated = true;
}
}
if (oldState.dateProfile !== newState.dateProfile) {
if (oldState.dateProfile && view) { // why would view be null!?
this.publiclyTrigger('datesDestroy', [
{
view: view,
el: view.el
}
]);
}
this.isDatesUpdated = true;
}
if (oldState.viewType !== newState.viewType) {
if (oldState.viewType && view) { // why would view be null!?
this.publiclyTrigger('viewSkeletonDestroy', [
{
view: view,
el: view.el
}
]);
}
this.isViewUpdated = true;
}
this.requestRerender();
}
};
Calendar.prototype.reduce = function (state, action, calendar) {
return reduce(state, action, calendar);
};
// Render Queue
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.requestRerender = function () {
this.needsRerender = true;
this.delayedRerender(); // will call a debounced-version of tryRerender
};
Calendar.prototype.tryRerender = function () {
if (this.component && // must be accepting renders
this.needsRerender && // indicates that a rerender was requested
!this.renderingPauseDepth && // not paused
!this.isRendering // not currently in the render loop
) {
this.executeRender();
}
};
Calendar.prototype.batchRendering = function (func) {
this.renderingPauseDepth++;
func();
this.renderingPauseDepth--;
if (this.needsRerender) {
this.requestRerender();
}
};
// Rendering
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.executeRender = function () {
// clear these BEFORE the render so that new values will accumulate during render
this.needsRerender = false;
this.isRendering = true;
this.renderComponent();
this.isRendering = false;
// received a rerender request while rendering
if (this.needsRerender) {
this.delayedRerender();
}
};
/*
don't call this directly. use executeRender instead
*/
Calendar.prototype.renderComponent = function () {
var _a = this, state = _a.state, component = _a.component;
var viewType = state.viewType;
var viewSpec = this.viewSpecs[viewType];
if (!viewSpec) {
throw new Error("View type \"" + viewType + "\" is not valid");
}
// if event sources are still loading and progressive rendering hasn't been enabled,
// keep rendering the last fully loaded set of events
var renderableEventStore = this.renderableEventStore =
(state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ?
this.renderableEventStore :
state.eventStore;
var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options);
var eventUiBySource = this.buildEventUiBySource(state.eventSources);
var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfileGenerator: this.dateProfileGenerators[viewType], dateProfile: state.dateProfile, eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize }), this.buildComponentContext(this.theme, this.dateEnv, this.optionsManager.computed));
if (this.isViewUpdated) {
this.isViewUpdated = false;
this.publiclyTrigger('viewSkeletonRender', [
{
view: component.view,
el: component.view.el
}
]);
}
if (this.isDatesUpdated) {
this.isDatesUpdated = false;
this.publiclyTrigger('datesRender', [
{
view: component.view,
el: component.view.el
}
]);
}
if (this.isEventsUpdated) {
this.isEventsUpdated = false;
}
this.releaseAfterSizingTriggers();
};
// Options
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.setOption = function (name, val) {
var _a;
this.mutateOptions((_a = {}, _a[name] = val, _a), [], true);
};
Calendar.prototype.getOption = function (name) {
return this.optionsManager.computed[name];
};
Calendar.prototype.opt = function (name) {
return this.optionsManager.computed[name];
};
Calendar.prototype.viewOpt = function (name) {
return this.viewOpts()[name];
};
Calendar.prototype.viewOpts = function () {
return this.viewSpecs[this.state.viewType].options;
};
/*
handles option changes (like a diff)
*/
Calendar.prototype.mutateOptions = function (updates, removals, isDynamic, deepEqual) {
var _this = this;
var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers;
var normalUpdates = {};
var specialUpdates = {};
var oldDateEnv = this.dateEnv; // do this before handleOptions
var isTimeZoneDirty = false;
var isSizeDirty = false;
var anyDifficultOptions = Boolean(removals.length);
for (var name_1 in updates) {
if (changeHandlers[name_1]) {
specialUpdates[name_1] = updates[name_1];
}
else {
normalUpdates[name_1] = updates[name_1];
}
}
for (var name_2 in normalUpdates) {
if (/^(height|contentHeight|aspectRatio)$/.test(name_2)) {
isSizeDirty = true;
}
else if (/^(defaultDate|defaultView)$/.test(name_2)) ;
else {
anyDifficultOptions = true;
if (name_2 === 'timeZone') {
isTimeZoneDirty = true;
}
}
}
this.optionsManager.mutate(normalUpdates, removals, isDynamic);
if (anyDifficultOptions) {
this.handleOptions(this.optionsManager.computed);
}
this.batchRendering(function () {
if (anyDifficultOptions) {
if (isTimeZoneDirty) {
_this.dispatch({
type: 'CHANGE_TIMEZONE',
oldDateEnv: oldDateEnv
});
}
/* HACK
has the same effect as calling this.requestRerender()
but recomputes the state's dateProfile
*/
_this.dispatch({
type: 'SET_VIEW_TYPE',
viewType: _this.state.viewType
});
}
else if (isSizeDirty) {
_this.updateSize();
}
// special updates
if (deepEqual) {
for (var name_3 in specialUpdates) {
changeHandlers[name_3](specialUpdates[name_3], _this, deepEqual);
}
}
});
};
/*
rebuilds things based off of a complete set of refined options
*/
Calendar.prototype.handleOptions = function (options) {
var _this = this;
var pluginHooks = this.pluginSystem.hooks;
this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration);
this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration);
this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay);
this.theme = this.buildTheme(options);
var available = this.parseRawLocales(options.locales);
this.availableRawLocales = available.map;
var locale = this.buildLocale(options.locale || available.defaultCode, available.map);
this.dateEnv = this.buildDateEnv(locale, options.timeZone, pluginHooks.namedTimeZonedImpl, options.firstDay, options.weekNumberCalculation, options.weekLabel, pluginHooks.cmdFormatter);
this.selectionConfig = this.buildSelectionConfig(options); // needs dateEnv. do after :(
// ineffecient to do every time?
this.viewSpecs = buildViewSpecs(pluginHooks.views, this.optionsManager);
// ineffecient to do every time?
this.dateProfileGenerators = mapHash(this.viewSpecs, function (viewSpec) {
return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, _this);
});
};
Calendar.prototype.getAvailableLocaleCodes = function () {
return Object.keys(this.availableRawLocales);
};
Calendar.prototype._buildSelectionConfig = function (rawOpts) {
return processScopedUiProps('select', rawOpts, this);
};
Calendar.prototype._buildEventUiSingleBase = function (rawOpts) {
if (rawOpts.editable) { // so 'editable' affected events
rawOpts = __assign({}, rawOpts, { eventEditable: true });
}
return processScopedUiProps('event', rawOpts, this);
};
// Trigger
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.hasPublicHandlers = function (name) {
return this.hasHandlers(name) ||
this.opt(name); // handler specified in options
};
Calendar.prototype.publiclyTrigger = function (name, args) {
var optHandler = this.opt(name);
this.triggerWith(name, this, args);
if (optHandler) {
return optHandler.apply(this, args);
}
};
Calendar.prototype.publiclyTriggerAfterSizing = function (name, args) {
var afterSizingTriggers = this.afterSizingTriggers;
(afterSizingTriggers[name] || (afterSizingTriggers[name] = [])).push(args);
};
Calendar.prototype.releaseAfterSizingTriggers = function () {
var afterSizingTriggers = this.afterSizingTriggers;
for (var name_4 in afterSizingTriggers) {
for (var _i = 0, _a = afterSizingTriggers[name_4]; _i < _a.length; _i++) {
var args = _a[_i];
this.publiclyTrigger(name_4, args);
}
}
this.afterSizingTriggers = {};
};
// View
// -----------------------------------------------------------------------------------------------------------------
// Returns a boolean about whether the view is okay to instantiate at some point
Calendar.prototype.isValidViewType = function (viewType) {
return Boolean(this.viewSpecs[viewType]);
};
Calendar.prototype.changeView = function (viewType, dateOrRange) {
var dateMarker = null;
if (dateOrRange) {
if (dateOrRange.start && dateOrRange.end) { // a range
this.optionsManager.mutate({ visibleRange: dateOrRange }, []); // will not rerender
this.handleOptions(this.optionsManager.computed); // ...but yuck
}
else { // a date
dateMarker = this.dateEnv.createMarker(dateOrRange); // just like gotoDate
}
}
this.unselect();
this.dispatch({
type: 'SET_VIEW_TYPE',
viewType: viewType,
dateMarker: dateMarker
});
};
// Forces navigation to a view for the given date.
// `viewType` can be a specific view name or a generic one like "week" or "day".
// needs to change
Calendar.prototype.zoomTo = function (dateMarker, viewType) {
var spec;
viewType = viewType || 'day'; // day is default zoom
spec = this.viewSpecs[viewType] ||
this.getUnitViewSpec(viewType);
this.unselect();
if (spec) {
this.dispatch({
type: 'SET_VIEW_TYPE',
viewType: spec.type,
dateMarker: dateMarker
});
}
else {
this.dispatch({
type: 'SET_DATE',
dateMarker: dateMarker
});
}
};
// Given a duration singular unit, like "week" or "day", finds a matching view spec.
// Preference is given to views that have corresponding buttons.
Calendar.prototype.getUnitViewSpec = function (unit) {
var component = this.component;
var viewTypes = [];
var i;
var spec;
// put views that have buttons first. there will be duplicates, but oh
if (component.header) {
viewTypes.push.apply(viewTypes, component.header.viewsWithButtons);
}
if (component.footer) {
viewTypes.push.apply(viewTypes, component.footer.viewsWithButtons);
}
for (var viewType in this.viewSpecs) {
viewTypes.push(viewType);
}
for (i = 0; i < viewTypes.length; i++) {
spec = this.viewSpecs[viewTypes[i]];
if (spec) {
if (spec.singleUnit === unit) {
return spec;
}
}
}
};
// Current Date
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.getInitialDate = function () {
var defaultDateInput = this.opt('defaultDate');
// compute the initial ambig-timezone date
if (defaultDateInput != null) {
return this.dateEnv.createMarker(defaultDateInput);
}
else {
return this.getNow(); // getNow already returns unzoned
}
};
Calendar.prototype.prev = function () {
this.unselect();
this.dispatch({ type: 'PREV' });
};
Calendar.prototype.next = function () {
this.unselect();
this.dispatch({ type: 'NEXT' });
};
Calendar.prototype.prevYear = function () {
this.unselect();
this.dispatch({
type: 'SET_DATE',
dateMarker: this.dateEnv.addYears(this.state.currentDate, -1)
});
};
Calendar.prototype.nextYear = function () {
this.unselect();
this.dispatch({
type: 'SET_DATE',
dateMarker: this.dateEnv.addYears(this.state.currentDate, 1)
});
};
Calendar.prototype.today = function () {
this.unselect();
this.dispatch({
type: 'SET_DATE',
dateMarker: this.getNow()
});
};
Calendar.prototype.gotoDate = function (zonedDateInput) {
this.unselect();
this.dispatch({
type: 'SET_DATE',
dateMarker: this.dateEnv.createMarker(zonedDateInput)
});
};
Calendar.prototype.incrementDate = function (deltaInput) {
var delta = createDuration(deltaInput);
if (delta) { // else, warn about invalid input?
this.unselect();
this.dispatch({
type: 'SET_DATE',
dateMarker: this.dateEnv.add(this.state.currentDate, delta)
});
}
};
// for external API
Calendar.prototype.getDate = function () {
return this.dateEnv.toDate(this.state.currentDate);
};
// Date Formatting Utils
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.formatDate = function (d, formatter) {
var dateEnv = this.dateEnv;
return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
};
// `settings` is for formatter AND isEndExclusive
Calendar.prototype.formatRange = function (d0, d1, settings) {
var dateEnv = this.dateEnv;
return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings, this.opt('defaultRangeSeparator')), settings);
};
Calendar.prototype.formatIso = function (d, omitTime) {
var dateEnv = this.dateEnv;
return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime });
};
// Sizing
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.windowResize = function (ev) {
if (!this.isHandlingWindowResize &&
this.component && // why?
ev.target === window // not a jqui resize event
) {
this.isHandlingWindowResize = true;
this.updateSize();
this.publiclyTrigger('windowResize', [this.view]);
this.isHandlingWindowResize = false;
}
};
Calendar.prototype.updateSize = function () {
if (this.component) { // when?
this.component.updateSize(true);
}
};
// Component Registration
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.registerInteractiveComponent = function (component, settingsInput) {
var settings = parseInteractionSettings(component, settingsInput);
var DEFAULT_INTERACTIONS = [
EventClicking,
EventHovering
];
var interactionClasses = DEFAULT_INTERACTIONS.concat(this.pluginSystem.hooks.componentInteractions);
var interactions = interactionClasses.map(function (interactionClass) {
return new interactionClass(settings);
});
this.interactionsStore[component.uid] = interactions;
interactionSettingsStore[component.uid] = settings;
};
Calendar.prototype.unregisterInteractiveComponent = function (component) {
for (var _i = 0, _a = this.interactionsStore[component.uid]; _i < _a.length; _i++) {
var listener = _a[_i];
listener.destroy();
}
delete this.interactionsStore[component.uid];
delete interactionSettingsStore[component.uid];
};
// Date Selection / Event Selection / DayClick
// -----------------------------------------------------------------------------------------------------------------
// this public method receives start/end dates in any format, with any timezone
// NOTE: args were changed from v3
Calendar.prototype.select = function (dateOrObj, endDate) {
var selectionInput;
if (endDate == null) {
if (dateOrObj.start != null) {
selectionInput = dateOrObj;
}
else {
selectionInput = {
start: dateOrObj,
end: null
};
}
}
else {
selectionInput = {
start: dateOrObj,
end: endDate
};
}
var selection = parseDateSpan(selectionInput, this.dateEnv, createDuration({ days: 1 }) // TODO: cache this?
);
if (selection) { // throw parse error otherwise?
this.dispatch({ type: 'SELECT_DATES', selection: selection });
this.triggerDateSelect(selection);
}
};
// public method
Calendar.prototype.unselect = function (pev) {
if (this.state.dateSelection) {
this.dispatch({ type: 'UNSELECT_DATES' });
this.triggerDateUnselect(pev);
}
};
Calendar.prototype.triggerDateSelect = function (selection, pev) {
var arg = __assign({}, this.buildDateSpanApi(selection), { jsEvent: pev ? pev.origEvent : null, view: this.view });
this.publiclyTrigger('select', [arg]);
};
Calendar.prototype.triggerDateUnselect = function (pev) {
this.publiclyTrigger('unselect', [
{
jsEvent: pev ? pev.origEvent : null,
view: this.view
}
]);
};
// TODO: receive pev?
Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) {
var arg = __assign({}, this.buildDatePointApi(dateSpan), { dayEl: dayEl, jsEvent: ev, // Is this always a mouse event? See #4655
view: view });
this.publiclyTrigger('dateClick', [arg]);
};
Calendar.prototype.buildDatePointApi = function (dateSpan) {
var props = {};
for (var _i = 0, _a = this.pluginSystem.hooks.datePointTransforms; _i < _a.length; _i++) {
var transform = _a[_i];
__assign(props, transform(dateSpan, this));
}
__assign(props, buildDatePointApi(dateSpan, this.dateEnv));
return props;
};
Calendar.prototype.buildDateSpanApi = function (dateSpan) {
var props = {};
for (var _i = 0, _a = this.pluginSystem.hooks.dateSpanTransforms; _i < _a.length; _i++) {
var transform = _a[_i];
__assign(props, transform(dateSpan, this));
}
__assign(props, buildDateSpanApi(dateSpan, this.dateEnv));
return props;
};
// Date Utils
// -----------------------------------------------------------------------------------------------------------------
// Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option
Calendar.prototype.getNow = function () {
var now = this.opt('now');
if (typeof now === 'function') {
now = now();
}
if (now == null) {
return this.dateEnv.createNowMarker();
}
return this.dateEnv.createMarker(now);
};
// Event-Date Utilities
// -----------------------------------------------------------------------------------------------------------------
// Given an event's allDay status and start date, return what its fallback end date should be.
// TODO: rename to computeDefaultEventEnd
Calendar.prototype.getDefaultEventEnd = function (allDay, marker) {
var end = marker;
if (allDay) {
end = startOfDay(end);
end = this.dateEnv.add(end, this.defaultAllDayEventDuration);
}
else {
end = this.dateEnv.add(end, this.defaultTimedEventDuration);
}
return end;
};
// Public Events API
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.addEvent = function (eventInput, sourceInput) {
if (eventInput instanceof EventApi) {
var def = eventInput._def;
var instance = eventInput._instance;
// not already present? don't want to add an old snapshot
if (!this.state.eventStore.defs[def.defId]) {
this.dispatch({
type: 'ADD_EVENTS',
eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args?
});
}
return eventInput;
}
var sourceId;
if (sourceInput instanceof EventSourceApi) {
sourceId = sourceInput.internalEventSource.sourceId;
}
else if (sourceInput != null) {
var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
if (!sourceApi) {
console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test
return null;
}
else {
sourceId = sourceApi.internalEventSource.sourceId;
}
}
var tuple = parseEvent(eventInput, sourceId, this);
if (tuple) {
this.dispatch({
type: 'ADD_EVENTS',
eventStore: eventTupleToStore(tuple)
});
return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
}
return null;
};
// TODO: optimize
Calendar.prototype.getEventById = function (id) {
var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances;
id = String(id);
for (var defId in defs) {
var def = defs[defId];
if (def.publicId === id) {
if (def.recurringDef) {
return new EventApi(this, def, null);
}
else {
for (var instanceId in instances) {
var instance = instances[instanceId];
if (instance.defId === def.defId) {
return new EventApi(this, def, instance);
}
}
}
}
}
return null;
};
Calendar.prototype.getEvents = function () {
var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances;
var eventApis = [];
for (var id in instances) {
var instance = instances[id];
var def = defs[instance.defId];
eventApis.push(new EventApi(this, def, instance));
}
return eventApis;
};
Calendar.prototype.removeAllEvents = function () {
this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
};
Calendar.prototype.rerenderEvents = function () {
this.dispatch({ type: 'RESET_EVENTS' });
};
// Public Event Sources API
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.getEventSources = function () {
var sourceHash = this.state.eventSources;
var sourceApis = [];
for (var internalId in sourceHash) {
sourceApis.push(new EventSourceApi(this, sourceHash[internalId]));
}
return sourceApis;
};
Calendar.prototype.getEventSourceById = function (id) {
var sourceHash = this.state.eventSources;
id = String(id);
for (var sourceId in sourceHash) {
if (sourceHash[sourceId].publicId === id) {
return new EventSourceApi(this, sourceHash[sourceId]);
}
}
return null;
};
Calendar.prototype.addEventSource = function (sourceInput) {
if (sourceInput instanceof EventSourceApi) {
// not already present? don't want to add an old snapshot
if (!this.state.eventSources[sourceInput.internalEventSource.sourceId]) {
this.dispatch({
type: 'ADD_EVENT_SOURCES',
sources: [sourceInput.internalEventSource]
});
}
return sourceInput;
}
var eventSource = parseEventSource(sourceInput, this);
if (eventSource) { // TODO: error otherwise?
this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
return new EventSourceApi(this, eventSource);
}
return null;
};
Calendar.prototype.removeAllEventSources = function () {
this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
};
Calendar.prototype.refetchEvents = function () {
this.dispatch({ type: 'FETCH_EVENT_SOURCES' });
};
// Scroll
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.scrollToTime = function (timeInput) {
var duration = createDuration(timeInput);
if (duration) {
this.component.view.scrollToDuration(duration);
}
};
return Calendar;
}());
EmitterMixin.mixInto(Calendar);
// for memoizers
// -----------------------------------------------------------------------------------------------------------------
function buildComponentContext$1(theme, dateEnv, options) {
return new ComponentContext(this, theme, dateEnv, options, null);
}
function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) {
return new DateEnv({
calendarSystem: 'gregory',
timeZone: timeZone,
namedTimeZoneImpl: namedTimeZoneImpl,
locale: locale,
weekNumberCalculation: weekNumberCalculation,
firstDay: firstDay,
weekLabel: weekLabel,
cmdFormatter: cmdFormatter
});
}
function buildTheme(calendarOptions) {
var themeClass = this.pluginSystem.hooks.themeClasses[calendarOptions.themeSystem] || StandardTheme;
return new themeClass(calendarOptions);
}
function buildDelayedRerender(wait) {
var func = this.tryRerender.bind(this);
if (wait != null) {
func = debounce(func, wait);
}
return func;
}
function buildEventUiBySource(eventSources) {
return mapHash(eventSources, function (eventSource) {
return eventSource.ui;
});
}
function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
var eventUiBases = { '': eventUiSingleBase };
for (var defId in eventDefs) {
var def = eventDefs[defId];
if (def.sourceId && eventUiBySource[def.sourceId]) {
eventUiBases[defId] = eventUiBySource[def.sourceId];
}
}
return eventUiBases;
}
var View = /** @class */ (function (_super) {
__extends(View, _super);
function View(viewSpec, parentEl) {
var _this = _super.call(this, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' })) || this;
_this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap);
_this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]);
_this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]);
_this.renderEventsMem = memoizeRendering(_this.renderEvents, _this.unrenderEvents, [_this.renderDatesMem]);
_this.renderEventSelectionMem = memoizeRendering(_this.renderEventSelectionWrap, _this.unrenderEventSelectionWrap, [_this.renderEventsMem]);
_this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]);
_this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]);
_this.viewSpec = viewSpec;
_this.type = viewSpec.type;
parentEl.appendChild(_this.el);
_this.initialize();
return _this;
}
View.prototype.initialize = function () {
};
Object.defineProperty(View.prototype, "activeStart", {
// Date Setting/Unsetting
// -----------------------------------------------------------------------------------------------------------------
get: function () {
return this.context.dateEnv.toDate(this.props.dateProfile.activeRange.start);
},
enumerable: true,
configurable: true
});
Object.defineProperty(View.prototype, "activeEnd", {
get: function () {
return this.context.dateEnv.toDate(this.props.dateProfile.activeRange.end);
},
enumerable: true,
configurable: true
});
Object.defineProperty(View.prototype, "currentStart", {
get: function () {
return this.context.dateEnv.toDate(this.props.dateProfile.currentRange.start);
},
enumerable: true,
configurable: true
});
Object.defineProperty(View.prototype, "currentEnd", {
get: function () {
return this.context.dateEnv.toDate(this.props.dateProfile.currentRange.end);
},
enumerable: true,
configurable: true
});
// General Rendering
// -----------------------------------------------------------------------------------------------------------------
View.prototype.render = function (props, context) {
this.renderDatesMem(props.dateProfile);
this.renderBusinessHoursMem(props.businessHours);
this.renderDateSelectionMem(props.dateSelection);
this.renderEventsMem(props.eventStore);
this.renderEventSelectionMem(props.eventSelection);
this.renderEventDragMem(props.eventDrag);
this.renderEventResizeMem(props.eventResize);
};
View.prototype.beforeUpdate = function () {
this.addScroll(this.queryScroll());
};
View.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderDatesMem.unrender(); // should unrender everything else
};
// Sizing
// -----------------------------------------------------------------------------------------------------------------
View.prototype.updateSize = function (isResize, viewHeight, isAuto) {
var calendar = this.context.calendar;
if (isResize) {
this.addScroll(this.queryScroll()); // NOTE: same code as in beforeUpdate
}
if (isResize || // HACKS...
calendar.isViewUpdated ||
calendar.isDatesUpdated ||
calendar.isEventsUpdated) {
// sort of the catch-all sizing
// anything that might cause dimension changes
this.updateBaseSize(isResize, viewHeight, isAuto);
}
// NOTE: popScroll is called by CalendarComponent
};
View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
};
// Date Rendering
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderDatesWrap = function (dateProfile) {
this.renderDates(dateProfile);
this.addScroll({
duration: createDuration(this.context.options.scrollTime)
});
};
View.prototype.unrenderDatesWrap = function () {
this.stopNowIndicator();
this.unrenderDates();
};
View.prototype.renderDates = function (dateProfile) { };
View.prototype.unrenderDates = function () { };
// Business Hours
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderBusinessHours = function (businessHours) { };
View.prototype.unrenderBusinessHours = function () { };
// Date Selection
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderDateSelectionWrap = function (selection) {
if (selection) {
this.renderDateSelection(selection);
}
};
View.prototype.unrenderDateSelectionWrap = function (selection) {
if (selection) {
this.unrenderDateSelection(selection);
}
};
View.prototype.renderDateSelection = function (selection) { };
View.prototype.unrenderDateSelection = function (selection) { };
// Event Rendering
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderEvents = function (eventStore) { };
View.prototype.unrenderEvents = function () { };
// util for subclasses
View.prototype.sliceEvents = function (eventStore, allDay) {
var props = this.props;
return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.context.nextDayThreshold : null).fg;
};
// Event Selection
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderEventSelectionWrap = function (instanceId) {
if (instanceId) {
this.renderEventSelection(instanceId);
}
};
View.prototype.unrenderEventSelectionWrap = function (instanceId) {
if (instanceId) {
this.unrenderEventSelection(instanceId);
}
};
View.prototype.renderEventSelection = function (instanceId) { };
View.prototype.unrenderEventSelection = function (instanceId) { };
// Event Drag
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderEventDragWrap = function (state) {
if (state) {
this.renderEventDrag(state);
}
};
View.prototype.unrenderEventDragWrap = function (state) {
if (state) {
this.unrenderEventDrag(state);
}
};
View.prototype.renderEventDrag = function (state) { };
View.prototype.unrenderEventDrag = function (state) { };
// Event Resize
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderEventResizeWrap = function (state) {
if (state) {
this.renderEventResize(state);
}
};
View.prototype.unrenderEventResizeWrap = function (state) {
if (state) {
this.unrenderEventResize(state);
}
};
View.prototype.renderEventResize = function (state) { };
View.prototype.unrenderEventResize = function (state) { };
/* Now Indicator
------------------------------------------------------------------------------------------------------------------*/
// Immediately render the current time indicator and begins re-rendering it at an interval,
// which is defined by this.getNowIndicatorUnit().
// TODO: somehow do this for the current whole day's background too
// USAGE: must be called manually from subclasses' render methods! don't need to call stopNowIndicator tho
View.prototype.startNowIndicator = function (dateProfile, dateProfileGenerator) {
var _this = this;
var _a = this.context, calendar = _a.calendar, dateEnv = _a.dateEnv, options = _a.options;
var unit;
var update;
var delay; // ms wait value
if (options.nowIndicator && !this.initialNowDate) {
unit = this.getNowIndicatorUnit(dateProfile, dateProfileGenerator);
if (unit) {
update = this.updateNowIndicator.bind(this);
this.initialNowDate = calendar.getNow();
this.initialNowQueriedMs = new Date().valueOf();
// wait until the beginning of the next interval
delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf();
// TODO: maybe always use setTimeout, waiting until start of next unit
this.nowIndicatorTimeoutID = setTimeout(function () {
_this.nowIndicatorTimeoutID = null;
update();
if (unit === 'second') {
delay = 1000; // every second
}
else {
delay = 1000 * 60; // otherwise, every minute
}
_this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval
}, delay);
}
// rendering will be initiated in updateSize
}
};
// rerenders the now indicator, computing the new current time from the amount of time that has passed
// since the initial getNow call.
View.prototype.updateNowIndicator = function () {
if (this.props.dateProfile && // a way to determine if dates were rendered yet
this.initialNowDate // activated before?
) {
this.unrenderNowIndicator(); // won't unrender if unnecessary
this.renderNowIndicator(addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs));
this.isNowIndicatorRendered = true;
}
};
// Immediately unrenders the view's current time indicator and stops any re-rendering timers.
// Won't cause side effects if indicator isn't rendered.
View.prototype.stopNowIndicator = function () {
if (this.nowIndicatorTimeoutID) {
clearTimeout(this.nowIndicatorTimeoutID);
this.nowIndicatorTimeoutID = null;
}
if (this.nowIndicatorIntervalID) {
clearInterval(this.nowIndicatorIntervalID);
this.nowIndicatorIntervalID = null;
}
if (this.isNowIndicatorRendered) {
this.unrenderNowIndicator();
this.isNowIndicatorRendered = false;
}
};
View.prototype.getNowIndicatorUnit = function (dateProfile, dateProfileGenerator) {
// subclasses should implement
};
// Renders a current time indicator at the given datetime
View.prototype.renderNowIndicator = function (date) {
// SUBCLASSES MUST PASS TO CHILDREN!
};
// Undoes the rendering actions from renderNowIndicator
View.prototype.unrenderNowIndicator = function () {
// SUBCLASSES MUST PASS TO CHILDREN!
};
/* Scroller
------------------------------------------------------------------------------------------------------------------*/
View.prototype.addScroll = function (scroll, isForced) {
if (isForced) {
scroll.isForced = isForced;
}
__assign(this.queuedScroll || (this.queuedScroll = {}), scroll);
};
View.prototype.popScroll = function (isResize) {
this.applyQueuedScroll(isResize);
this.queuedScroll = null;
};
View.prototype.applyQueuedScroll = function (isResize) {
if (this.queuedScroll) {
this.applyScroll(this.queuedScroll, isResize);
}
};
View.prototype.queryScroll = function () {
var scroll = {};
if (this.props.dateProfile) { // dates rendered yet?
__assign(scroll, this.queryDateScroll());
}
return scroll;
};
View.prototype.applyScroll = function (scroll, isResize) {
var duration = scroll.duration, isForced = scroll.isForced;
if (duration != null && !isForced) {
delete scroll.duration;
if (this.props.dateProfile) { // dates rendered yet?
__assign(scroll, this.computeDateScroll(duration));
}
}
if (this.props.dateProfile) { // dates rendered yet?
this.applyDateScroll(scroll);
}
};
View.prototype.computeDateScroll = function (duration) {
return {}; // subclasses must implement
};
View.prototype.queryDateScroll = function () {
return {}; // subclasses must implement
};
View.prototype.applyDateScroll = function (scroll) {
// subclasses must implement
};
// for API
View.prototype.scrollToDuration = function (duration) {
this.applyScroll({ duration: duration }, false);
};
return View;
}(DateComponent));
EmitterMixin.mixInto(View);
View.prototype.usesMinMaxTime = false;
View.prototype.dateProfileGeneratorClass = DateProfileGenerator;
var FgEventRenderer = /** @class */ (function () {
function FgEventRenderer() {
this.segs = [];
this.isSizeDirty = false;
}
FgEventRenderer.prototype.renderSegs = function (context, segs, mirrorInfo) {
this.context = context;
this.rangeUpdated(); // called too frequently :(
// render an `.el` on each seg
// returns a subset of the segs. segs that were actually rendered
segs = this.renderSegEls(segs, mirrorInfo);
this.segs = segs;
this.attachSegs(segs, mirrorInfo);
this.isSizeDirty = true;
triggerRenderedSegs(this.context, this.segs, Boolean(mirrorInfo));
};
FgEventRenderer.prototype.unrender = function (context, _segs, mirrorInfo) {
triggerWillRemoveSegs(this.context, this.segs, Boolean(mirrorInfo));
this.detachSegs(this.segs);
this.segs = [];
};
// Updates values that rely on options and also relate to range
FgEventRenderer.prototype.rangeUpdated = function () {
var options = this.context.options;
var displayEventTime;
var displayEventEnd;
this.eventTimeFormat = createFormatter(options.eventTimeFormat || this.computeEventTimeFormat(), options.defaultRangeSeparator);
displayEventTime = options.displayEventTime;
if (displayEventTime == null) {
displayEventTime = this.computeDisplayEventTime(); // might be based off of range
}
displayEventEnd = options.displayEventEnd;
if (displayEventEnd == null) {
displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range
}
this.displayEventTime = displayEventTime;
this.displayEventEnd = displayEventEnd;
};
// Renders and assigns an `el` property for each foreground event segment.
// Only returns segments that successfully rendered.
FgEventRenderer.prototype.renderSegEls = function (segs, mirrorInfo) {
var html = '';
var i;
if (segs.length) { // don't build an empty html string
// build a large concatenation of event segment HTML
for (i = 0; i < segs.length; i++) {
html += this.renderSegHtml(segs[i], mirrorInfo);
}
// Grab individual elements from the combined HTML string. Use each as the default rendering.
// Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
htmlToElements(html).forEach(function (el, i) {
var seg = segs[i];
if (el) {
seg.el = el;
}
});
segs = filterSegsViaEls(this.context, segs, Boolean(mirrorInfo));
}
return segs;
};
// Generic utility for generating the HTML classNames for an event segment's element
FgEventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable, mirrorInfo) {
var classes = [
'fc-event',
seg.isStart ? 'fc-start' : 'fc-not-start',
seg.isEnd ? 'fc-end' : 'fc-not-end'
].concat(seg.eventRange.ui.classNames);
if (isDraggable) {
classes.push('fc-draggable');
}
if (isResizable) {
classes.push('fc-resizable');
}
if (mirrorInfo) {
classes.push('fc-mirror');
if (mirrorInfo.isDragging) {
classes.push('fc-dragging');
}
if (mirrorInfo.isResizing) {
classes.push('fc-resizing');
}
}
return classes;
};
// Compute the text that should be displayed on an event's element.
// `range` can be the Event object itself, or something range-like, with at least a `start`.
// If event times are disabled, or the event has no time, will return a blank string.
// If not specified, formatter will default to the eventTimeFormat setting,
// and displayEnd will default to the displayEventEnd setting.
FgEventRenderer.prototype.getTimeText = function (eventRange, formatter, displayEnd) {
var def = eventRange.def, instance = eventRange.instance;
return this._getTimeText(instance.range.start, def.hasEnd ? instance.range.end : null, def.allDay, formatter, displayEnd, instance.forcedStartTzo, instance.forcedEndTzo);
};
FgEventRenderer.prototype._getTimeText = function (start, end, allDay, formatter, displayEnd, forcedStartTzo, forcedEndTzo) {
var dateEnv = this.context.dateEnv;
if (formatter == null) {
formatter = this.eventTimeFormat;
}
if (displayEnd == null) {
displayEnd = this.displayEventEnd;
}
if (this.displayEventTime && !allDay) {
if (displayEnd && end) {
return dateEnv.formatRange(start, end, formatter, {
forcedStartTzo: forcedStartTzo,
forcedEndTzo: forcedEndTzo
});
}
else {
return dateEnv.format(start, formatter, {
forcedTzo: forcedStartTzo
});
}
}
return '';
};
FgEventRenderer.prototype.computeEventTimeFormat = function () {
return {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true
};
};
FgEventRenderer.prototype.computeDisplayEventTime = function () {
return true;
};
FgEventRenderer.prototype.computeDisplayEventEnd = function () {
return true;
};
// Utility for generating event skin-related CSS properties
FgEventRenderer.prototype.getSkinCss = function (ui) {
return {
'background-color': ui.backgroundColor,
'border-color': ui.borderColor,
color: ui.textColor
};
};
FgEventRenderer.prototype.sortEventSegs = function (segs) {
var specs = this.context.eventOrderSpecs;
var objs = segs.map(buildSegCompareObj);
objs.sort(function (obj0, obj1) {
return compareByFieldSpecs(obj0, obj1, specs);
});
return objs.map(function (c) {
return c._seg;
});
};
FgEventRenderer.prototype.computeSizes = function (force) {
if (force || this.isSizeDirty) {
this.computeSegSizes(this.segs);
}
};
FgEventRenderer.prototype.assignSizes = function (force) {
if (force || this.isSizeDirty) {
this.assignSegSizes(this.segs);
this.isSizeDirty = false;
}
};
FgEventRenderer.prototype.computeSegSizes = function (segs) {
};
FgEventRenderer.prototype.assignSegSizes = function (segs) {
};
// Manipulation on rendered segs
FgEventRenderer.prototype.hideByHash = function (hash) {
if (hash) {
for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
var seg = _a[_i];
if (hash[seg.eventRange.instance.instanceId]) {
seg.el.style.visibility = 'hidden';
}
}
}
};
FgEventRenderer.prototype.showByHash = function (hash) {
if (hash) {
for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
var seg = _a[_i];
if (hash[seg.eventRange.instance.instanceId]) {
seg.el.style.visibility = '';
}
}
}
};
FgEventRenderer.prototype.selectByInstanceId = function (instanceId) {
if (instanceId) {
for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
var seg = _a[_i];
var eventInstance = seg.eventRange.instance;
if (eventInstance && eventInstance.instanceId === instanceId &&
seg.el // necessary?
) {
seg.el.classList.add('fc-selected');
}
}
}
};
FgEventRenderer.prototype.unselectByInstanceId = function (instanceId) {
if (instanceId) {
for (var _i = 0, _a = this.segs; _i < _a.length; _i++) {
var seg = _a[_i];
if (seg.el) { // necessary?
seg.el.classList.remove('fc-selected');
}
}
}
};
return FgEventRenderer;
}());
// returns a object with all primitive props that can be compared
function buildSegCompareObj(seg) {
var eventDef = seg.eventRange.def;
var range = seg.eventRange.instance.range;
var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
var end = range.end ? range.end.valueOf() : 0; // "
return __assign({}, eventDef.extendedProps, eventDef, { id: eventDef.publicId, start: start,
end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval
});
}
/*
TODO: when refactoring this class, make a new FillRenderer instance for each `type`
*/
var FillRenderer = /** @class */ (function () {
function FillRenderer() {
this.fillSegTag = 'div';
this.dirtySizeFlags = {};
this.containerElsByType = {};
this.segsByType = {};
}
FillRenderer.prototype.getSegsByType = function (type) {
return this.segsByType[type] || [];
};
FillRenderer.prototype.renderSegs = function (type, context, segs) {
var _a;
this.context = context;
var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs
var containerEls = this.attachSegs(type, renderedSegs);
if (containerEls) {
(_a = (this.containerElsByType[type] || (this.containerElsByType[type] = []))).push.apply(_a, containerEls);
}
this.segsByType[type] = renderedSegs;
if (type === 'bgEvent') {
triggerRenderedSegs(context, renderedSegs, false); // isMirror=false
}
this.dirtySizeFlags[type] = true;
};
// Unrenders a specific type of fill that is currently rendered on the grid
FillRenderer.prototype.unrender = function (type, context) {
var segs = this.segsByType[type];
if (segs) {
if (type === 'bgEvent') {
triggerWillRemoveSegs(context, segs, false); // isMirror=false
}
this.detachSegs(type, segs);
}
};
// Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.
// Only returns segments that successfully rendered.
FillRenderer.prototype.renderSegEls = function (type, segs) {
var _this = this;
var html = '';
var i;
if (segs.length) {
// build a large concatenation of segment HTML
for (i = 0; i < segs.length; i++) {
html += this.renderSegHtml(type, segs[i]);
}
// Grab individual elements from the combined HTML string. Use each as the default rendering.
// Then, compute the 'el' for each segment.
htmlToElements(html).forEach(function (el, i) {
var seg = segs[i];
if (el) {
seg.el = el;
}
});
if (type === 'bgEvent') {
segs = filterSegsViaEls(this.context, segs, false // isMirror. background events can never be mirror elements
);
}
// correct element type? (would be bad if a non-TD were inserted into a table for example)
segs = segs.filter(function (seg) {
return elementMatches(seg.el, _this.fillSegTag);
});
}
return segs;
};
// Builds the HTML needed for one fill segment. Generic enough to work with different types.
FillRenderer.prototype.renderSegHtml = function (type, seg) {
var css = null;
var classNames = [];
if (type !== 'highlight' && type !== 'businessHours') {
css = {
'background-color': seg.eventRange.ui.backgroundColor
};
}
if (type !== 'highlight') {
classNames = classNames.concat(seg.eventRange.ui.classNames);
}
if (type === 'businessHours') {
classNames.push('fc-bgevent');
}
else {
classNames.push('fc-' + type.toLowerCase());
}
return '<' + this.fillSegTag +
(classNames.length ? ' class="' + classNames.join(' ') + '"' : '') +
(css ? ' style="' + cssToStr(css) + '"' : '') +
'></' + this.fillSegTag + '>';
};
FillRenderer.prototype.detachSegs = function (type, segs) {
var containerEls = this.containerElsByType[type];
if (containerEls) {
containerEls.forEach(removeElement);
delete this.containerElsByType[type];
}
};
FillRenderer.prototype.computeSizes = function (force) {
for (var type in this.segsByType) {
if (force || this.dirtySizeFlags[type]) {
this.computeSegSizes(this.segsByType[type]);
}
}
};
FillRenderer.prototype.assignSizes = function (force) {
for (var type in this.segsByType) {
if (force || this.dirtySizeFlags[type]) {
this.assignSegSizes(this.segsByType[type]);
}
}
this.dirtySizeFlags = {};
};
FillRenderer.prototype.computeSegSizes = function (segs) {
};
FillRenderer.prototype.assignSegSizes = function (segs) {
};
return FillRenderer;
}());
var NamedTimeZoneImpl = /** @class */ (function () {
function NamedTimeZoneImpl(timeZoneName) {
this.timeZoneName = timeZoneName;
}
return NamedTimeZoneImpl;
}());
/*
An abstraction for a dragging interaction originating on an event.
Does higher-level things than PointerDragger, such as possibly:
- a "mirror" that moves with the pointer
- a minimum number of pixels or other criteria for a true drag to begin
subclasses must emit:
- pointerdown
- dragstart
- dragmove
- pointerup
- dragend
*/
var ElementDragging = /** @class */ (function () {
function ElementDragging(el) {
this.emitter = new EmitterMixin();
}
ElementDragging.prototype.destroy = function () {
};
ElementDragging.prototype.setMirrorIsVisible = function (bool) {
// optional if subclass doesn't want to support a mirror
};
ElementDragging.prototype.setMirrorNeedsRevert = function (bool) {
// optional if subclass doesn't want to support a mirror
};
ElementDragging.prototype.setAutoScrollEnabled = function (bool) {
// optional
};
return ElementDragging;
}());
function formatDate(dateInput, settings) {
if (settings === void 0) { settings = {}; }
var dateEnv = buildDateEnv$1(settings);
var formatter = createFormatter(settings);
var dateMeta = dateEnv.createMarkerMeta(dateInput);
if (!dateMeta) { // TODO: warning?
return '';
}
return dateEnv.format(dateMeta.marker, formatter, {
forcedTzo: dateMeta.forcedTzo
});
}
function formatRange(startInput, endInput, settings // mixture of env and formatter settings
) {
var dateEnv = buildDateEnv$1(typeof settings === 'object' && settings ? settings : {}); // pass in if non-null object
var formatter = createFormatter(settings, globalDefaults.defaultRangeSeparator);
var startMeta = dateEnv.createMarkerMeta(startInput);
var endMeta = dateEnv.createMarkerMeta(endInput);
if (!startMeta || !endMeta) { // TODO: warning?
return '';
}
return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
forcedStartTzo: startMeta.forcedTzo,
forcedEndTzo: endMeta.forcedTzo,
isEndExclusive: settings.isEndExclusive
});
}
// TODO: more DRY and optimized
function buildDateEnv$1(settings) {
var locale = buildLocale(settings.locale || 'en', parseRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
// ensure required settings
settings = __assign({ timeZone: globalDefaults.timeZone, calendarSystem: 'gregory' }, settings, { locale: locale });
return new DateEnv(settings);
}
var DRAG_META_PROPS = {
startTime: createDuration,
duration: createDuration,
create: Boolean,
sourceId: String
};
var DRAG_META_DEFAULTS = {
create: true
};
function parseDragMeta(raw) {
var leftoverProps = {};
var refined = refineProps(raw, DRAG_META_PROPS, DRAG_META_DEFAULTS, leftoverProps);
refined.leftoverProps = leftoverProps;
return refined;
}
// Computes a default column header formatting string if `colFormat` is not explicitly defined
function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
// if more than one week row, or if there are a lot of columns with not much space,
// put just the day numbers will be in each cell
if (!datesRepDistinctDays || dayCnt > 10) {
return { weekday: 'short' }; // "Sat"
}
else if (dayCnt > 1) {
return { weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }; // "Sat 11/12"
}
else {
return { weekday: 'long' }; // "Saturday"
}
}
function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) {
var dateEnv = context.dateEnv, theme = context.theme, options = context.options;
var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow.
var classNames = [
'fc-day-header',
theme.getClass('widgetHeader')
];
var innerHtml;
if (typeof options.columnHeaderHtml === 'function') {
innerHtml = options.columnHeaderHtml(dateEnv.toDate(dateMarker));
}
else if (typeof options.columnHeaderText === 'function') {
innerHtml = htmlEscape(options.columnHeaderText(dateEnv.toDate(dateMarker)));
}
else {
innerHtml = htmlEscape(dateEnv.format(dateMarker, colHeadFormat));
}
// if only one row of days, the classNames on the header can represent the specific days beneath
if (datesRepDistinctDays) {
classNames = classNames.concat(
// includes the day-of-week class
// noThemeHighlight=true (don't highlight the header)
getDayClasses(dateMarker, dateProfile, context, true));
}
else {
classNames.push('fc-' + DAY_IDS[dateMarker.getUTCDay()]); // only add the day-of-week class
}
return '' +
'<th class="' + classNames.join(' ') + '"' +
((isDateValid && datesRepDistinctDays) ?
' data-date="' + dateEnv.formatIso(dateMarker, { omitTime: true }) + '"' :
'') +
(colspan > 1 ?
' colspan="' + colspan + '"' :
'') +
(otherAttrs ?
' ' + otherAttrs :
'') +
'>' +
(isDateValid ?
// don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
buildGotoAnchorHtml(options, dateEnv, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
// if not valid, display text, but no link
innerHtml) +
'</th>';
}
var DayHeader = /** @class */ (function (_super) {
__extends(DayHeader, _super);
function DayHeader(parentEl) {
var _this = _super.call(this) || this;
_this.renderSkeleton = memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
_this.parentEl = parentEl;
return _this;
}
DayHeader.prototype.render = function (props, context) {
var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays;
var parts = [];
this.renderSkeleton(context);
if (props.renderIntroHtml) {
parts.push(props.renderIntroHtml());
}
var colHeadFormat = createFormatter(context.options.columnHeaderFormat ||
computeFallbackHeaderFormat(datesRepDistinctDays, dates.length));
for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) {
var date = dates_1[_i];
parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, context));
}
if (context.isRtl) {
parts.reverse();
}
this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>';
};
DayHeader.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderSkeleton.unrender();
};
DayHeader.prototype._renderSkeleton = function (context) {
var theme = context.theme;
var parentEl = this.parentEl;
parentEl.innerHTML = ''; // because might be nbsp
parentEl.appendChild(this.el = htmlToElement('<div class="fc-row ' + theme.getClass('headerRow') + '">' +
'<table class="' + theme.getClass('tableGrid') + '">' +
'<thead></thead>' +
'</table>' +
'</div>'));
this.thead = this.el.querySelector('thead');
};
DayHeader.prototype._unrenderSkeleton = function () {
removeElement(this.el);
};
return DayHeader;
}(Component));
var DaySeries = /** @class */ (function () {
function DaySeries(range, dateProfileGenerator) {
var date = range.start;
var end = range.end;
var indices = [];
var dates = [];
var dayIndex = -1;
while (date < end) { // loop each day from start to end
if (dateProfileGenerator.isHiddenDay(date)) {
indices.push(dayIndex + 0.5); // mark that it's between indices
}
else {
dayIndex++;
indices.push(dayIndex);
dates.push(date);
}
date = addDays(date, 1);
}
this.dates = dates;
this.indices = indices;
this.cnt = dates.length;
}
DaySeries.prototype.sliceRange = function (range) {
var firstIndex = this.getDateDayIndex(range.start); // inclusive first index
var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
var clippedFirstIndex = Math.max(0, firstIndex);
var clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
// deal with in-between indices
clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
if (clippedFirstIndex <= clippedLastIndex) {
return {
firstIndex: clippedFirstIndex,
lastIndex: clippedLastIndex,
isStart: firstIndex === clippedFirstIndex,
isEnd: lastIndex === clippedLastIndex
};
}
else {
return null;
}
};
// Given a date, returns its chronolocial cell-index from the first cell of the grid.
// If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
// If before the first offset, returns a negative number.
// If after the last offset, returns an offset past the last cell offset.
// Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
DaySeries.prototype.getDateDayIndex = function (date) {
var indices = this.indices;
var dayOffset = Math.floor(diffDays(this.dates[0], date));
if (dayOffset < 0) {
return indices[0] - 1;
}
else if (dayOffset >= indices.length) {
return indices[indices.length - 1] + 1;
}
else {
return indices[dayOffset];
}
};
return DaySeries;
}());
var DayTable = /** @class */ (function () {
function DayTable(daySeries, breakOnWeeks) {
var dates = daySeries.dates;
var daysPerRow;
var firstDay;
var rowCnt;
if (breakOnWeeks) {
// count columns until the day-of-week repeats
firstDay = dates[0].getUTCDay();
for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) {
if (dates[daysPerRow].getUTCDay() === firstDay) {
break;
}
}
rowCnt = Math.ceil(dates.length / daysPerRow);
}
else {
rowCnt = 1;
daysPerRow = dates.length;
}
this.rowCnt = rowCnt;
this.colCnt = daysPerRow;
this.daySeries = daySeries;
this.cells = this.buildCells();
this.headerDates = this.buildHeaderDates();
}
DayTable.prototype.buildCells = function () {
var rows = [];
for (var row = 0; row < this.rowCnt; row++) {
var cells = [];
for (var col = 0; col < this.colCnt; col++) {
cells.push(this.buildCell(row, col));
}
rows.push(cells);
}
return rows;
};
DayTable.prototype.buildCell = function (row, col) {
return {
date: this.daySeries.dates[row * this.colCnt + col]
};
};
DayTable.prototype.buildHeaderDates = function () {
var dates = [];
for (var col = 0; col < this.colCnt; col++) {
dates.push(this.cells[0][col].date);
}
return dates;
};
DayTable.prototype.sliceRange = function (range) {
var colCnt = this.colCnt;
var seriesSeg = this.daySeries.sliceRange(range);
var segs = [];
if (seriesSeg) {
var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex;
var index = firstIndex;
while (index <= lastIndex) {
var row = Math.floor(index / colCnt);
var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
segs.push({
row: row,
firstCol: index % colCnt,
lastCol: (nextIndex - 1) % colCnt,
isStart: seriesSeg.isStart && index === firstIndex,
isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex
});
index = nextIndex;
}
}
return segs;
};
return DayTable;
}());
var Slicer = /** @class */ (function () {
function Slicer() {
this.sliceBusinessHours = memoize(this._sliceBusinessHours);
this.sliceDateSelection = memoize(this._sliceDateSpan);
this.sliceEventStore = memoize(this._sliceEventStore);
this.sliceEventDrag = memoize(this._sliceInteraction);
this.sliceEventResize = memoize(this._sliceInteraction);
}
Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, calendar, component) {
var extraArgs = [];
for (var _i = 5; _i < arguments.length; _i++) {
extraArgs[_i - 5] = arguments[_i];
}
var eventUiBases = props.eventUiBases;
var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs));
return {
dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)),
businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, calendar, component].concat(extraArgs)),
fgEventSegs: eventSegs.fg,
bgEventSegs: eventSegs.bg,
eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)),
eventResize: this.sliceEventResize.apply(this, [props.eventResize, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)),
eventSelection: props.eventSelection
}; // TODO: give interactionSegs?
};
Slicer.prototype.sliceNowDate = function (// does not memoize
date, component) {
var extraArgs = [];
for (var _i = 2; _i < arguments.length; _i++) {
extraArgs[_i - 2] = arguments[_i];
}
return this._sliceDateSpan.apply(this, [{ range: { start: date, end: addMs(date, 1) }, allDay: false },
{},
component].concat(extraArgs));
};
Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, calendar, component) {
var extraArgs = [];
for (var _i = 5; _i < arguments.length; _i++) {
extraArgs[_i - 5] = arguments[_i];
}
if (!businessHours) {
return [];
}
return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), calendar),
{},
dateProfile,
nextDayThreshold,
component].concat(extraArgs)).bg;
};
Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold, component) {
var extraArgs = [];
for (var _i = 5; _i < arguments.length; _i++) {
extraArgs[_i - 5] = arguments[_i];
}
if (eventStore) {
var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
return {
bg: this.sliceEventRanges(rangeRes.bg, component, extraArgs),
fg: this.sliceEventRanges(rangeRes.fg, component, extraArgs)
};
}
else {
return { bg: [], fg: [] };
}
};
Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold, component) {
var extraArgs = [];
for (var _i = 5; _i < arguments.length; _i++) {
extraArgs[_i - 5] = arguments[_i];
}
if (!interaction) {
return null;
}
var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
return {
segs: this.sliceEventRanges(rangeRes.fg, component, extraArgs),
affectedInstances: interaction.affectedEvents.instances,
isEvent: interaction.isEvent,
sourceSeg: interaction.origSeg
};
};
Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, component) {
var extraArgs = [];
for (var _i = 3; _i < arguments.length; _i++) {
extraArgs[_i - 3] = arguments[_i];
}
if (!dateSpan) {
return [];
}
var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.context.calendar);
var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs));
for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) {
var seg = segs_1[_a];
seg.component = component;
seg.eventRange = eventRange;
}
return segs;
};
/*
"complete" seg means it has component and eventRange
*/
Slicer.prototype.sliceEventRanges = function (eventRanges, component, // TODO: kill
extraArgs) {
var segs = [];
for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) {
var eventRange = eventRanges_1[_i];
segs.push.apply(segs, this.sliceEventRange(eventRange, component, extraArgs));
}
return segs;
};
/*
"complete" seg means it has component and eventRange
*/
Slicer.prototype.sliceEventRange = function (eventRange, component, // TODO: kill
extraArgs) {
var segs = this.sliceRange.apply(this, [eventRange.range].concat(extraArgs));
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
seg.component = component;
seg.eventRange = eventRange;
seg.isStart = eventRange.isStart && seg.isStart;
seg.isEnd = eventRange.isEnd && seg.isEnd;
}
return segs;
};
return Slicer;
}());
/*
for incorporating minTime/maxTime if appropriate
TODO: should be part of DateProfile!
TimelineDateProfile already does this btw
*/
function computeActiveRange(dateProfile, isComponentAllDay) {
var range = dateProfile.activeRange;
if (isComponentAllDay) {
return range;
}
return {
start: addMs(range.start, dateProfile.minTime.milliseconds),
end: addMs(range.end, dateProfile.maxTime.milliseconds - 864e5) // 864e5 = ms in a day
};
}
// exports
// --------------------------------------------------------------------------------------------------
var version = '4.4.2';
/***/ }),
/***/ "./node_modules/@fullcalendar/daygrid/main.css":
/*!*****************************************************!*\
!*** ./node_modules/@fullcalendar/daygrid/main.css ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "./node_modules/@fullcalendar/daygrid/main.esm.js":
/*!********************************************************!*\
!*** ./node_modules/@fullcalendar/daygrid/main.esm.js ***!
\********************************************************/
/*! exports provided: default, AbstractDayGridView, DayBgRow, DayGrid, DayGridSlicer, DayGridView, SimpleDayGrid, buildBasicDayTable */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractDayGridView", function() { return AbstractDayGridView; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DayBgRow", function() { return DayBgRow; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DayGrid", function() { return DayGrid; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DayGridSlicer", function() { return DayGridSlicer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DayGridView", function() { return DayGridView; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SimpleDayGrid", function() { return SimpleDayGrid; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildBasicDayTable", function() { return buildDayTable; });
/* harmony import */ var _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @fullcalendar/core */ "./node_modules/@fullcalendar/core/main.esm.js");
/*!
FullCalendar Day Grid Plugin v4.4.2
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var DayGridDateProfileGenerator = /** @class */ (function (_super) {
__extends(DayGridDateProfileGenerator, _super);
function DayGridDateProfileGenerator() {
return _super !== null && _super.apply(this, arguments) || this;
}
// Computes the date range that will be rendered.
DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) {
var dateEnv = this.dateEnv;
var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay);
var start = renderRange.start;
var end = renderRange.end;
var endOfWeek;
// year and month views should be aligned with weeks. this is already done for week
if (/^(year|month)$/.test(currentRangeUnit)) {
start = dateEnv.startOfWeek(start);
// make end-of-week if not already
endOfWeek = dateEnv.startOfWeek(end);
if (endOfWeek.valueOf() !== end.valueOf()) {
end = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["addWeeks"])(endOfWeek, 1);
}
}
// ensure 6 weeks
if (this.options.monthMode &&
this.options.fixedWeekCount) {
var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffWeeks"])(start, end));
end = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["addWeeks"])(end, 6 - rowCnt);
}
return { start: start, end: end };
};
return DayGridDateProfileGenerator;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DateProfileGenerator"]));
/* A rectangular panel that is absolutely positioned over other content
------------------------------------------------------------------------------------------------------------------------
Options:
- className (string)
- content (HTML string, element, or element array)
- parentEl
- top
- left
- right (the x coord of where the right edge should be. not a "CSS" right)
- autoHide (boolean)
- show (callback)
- hide (callback)
*/
var Popover = /** @class */ (function () {
function Popover(options) {
var _this = this;
this.isHidden = true;
this.margin = 10; // the space required between the popover and the edges of the scroll container
// Triggered when the user clicks *anywhere* in the document, for the autoHide feature
this.documentMousedown = function (ev) {
// only hide the popover if the click happened outside the popover
if (_this.el && !_this.el.contains(ev.target)) {
_this.hide();
}
};
this.options = options;
}
// Shows the popover on the specified position. Renders it if not already
Popover.prototype.show = function () {
if (this.isHidden) {
if (!this.el) {
this.render();
}
this.el.style.display = '';
this.position();
this.isHidden = false;
this.trigger('show');
}
};
// Hides the popover, through CSS, but does not remove it from the DOM
Popover.prototype.hide = function () {
if (!this.isHidden) {
this.el.style.display = 'none';
this.isHidden = true;
this.trigger('hide');
}
};
// Creates `this.el` and renders content inside of it
Popover.prototype.render = function () {
var _this = this;
var options = this.options;
var el = this.el = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('div', {
className: 'fc-popover ' + (options.className || ''),
style: {
top: '0',
left: '0'
}
});
if (typeof options.content === 'function') {
options.content(el);
}
options.parentEl.appendChild(el);
// when a click happens on anything inside with a 'fc-close' className, hide the popover
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["listenBySelector"])(el, 'click', '.fc-close', function (ev) {
_this.hide();
});
if (options.autoHide) {
document.addEventListener('mousedown', this.documentMousedown);
}
};
// Hides and unregisters any handlers
Popover.prototype.destroy = function () {
this.hide();
if (this.el) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["removeElement"])(this.el);
this.el = null;
}
document.removeEventListener('mousedown', this.documentMousedown);
};
// Positions the popover optimally, using the top/left/right options
Popover.prototype.position = function () {
var options = this.options;
var el = this.el;
var elDims = el.getBoundingClientRect(); // only used for width,height
var origin = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(el.offsetParent);
var clippingRect = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeClippingRect"])(options.parentEl);
var top; // the "position" (not "offset") values for the popover
var left; //
// compute top and left
top = options.top || 0;
if (options.left !== undefined) {
left = options.left;
}
else if (options.right !== undefined) {
left = options.right - elDims.width; // derive the left value from the right value
}
else {
left = 0;
}
// constrain to the view port. if constrained by two edges, give precedence to top/left
top = Math.min(top, clippingRect.bottom - elDims.height - this.margin);
top = Math.max(top, clippingRect.top + this.margin);
left = Math.min(left, clippingRect.right - elDims.width - this.margin);
left = Math.max(left, clippingRect.left + this.margin);
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyStyle"])(el, {
top: top - origin.top,
left: left - origin.left
});
};
// Triggers a callback. Calls a function in the option hash of the same name.
// Arguments beyond the first `name` are forwarded on.
// TODO: better code reuse for this. Repeat code
// can kill this???
Popover.prototype.trigger = function (name) {
if (this.options[name]) {
this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
}
};
return Popover;
}());
/* Event-rendering methods for the DayGrid class
----------------------------------------------------------------------------------------------------------------------*/
// "Simple" is bad a name. has nothing to do with SimpleDayGrid
var SimpleDayGridEventRenderer = /** @class */ (function (_super) {
__extends(SimpleDayGridEventRenderer, _super);
function SimpleDayGridEventRenderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
// Builds the HTML to be used for the default element for an individual segment
SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
var context = this.context;
var eventRange = seg.eventRange;
var eventDef = eventRange.def;
var eventUi = eventRange.ui;
var allDay = eventDef.allDay;
var isDraggable = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeEventDraggable"])(context, eventDef, eventUi);
var isResizableFromStart = allDay && seg.isStart && Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeEventStartResizable"])(context, eventDef, eventUi);
var isResizableFromEnd = allDay && seg.isEnd && Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeEventEndResizable"])(context, eventDef, eventUi);
var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
var skinCss = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["cssToStr"])(this.getSkinCss(eventUi));
var timeHtml = '';
var timeText;
var titleHtml;
classes.unshift('fc-day-grid-event', 'fc-h-event');
// Only display a timed events time if it is the starting segment
if (seg.isStart) {
timeText = this.getTimeText(eventRange);
if (timeText) {
timeHtml = '<span class="fc-time">' + Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(timeText) + '</span>';
}
}
titleHtml =
'<span class="fc-title">' +
(Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(eventDef.title || '') || '&nbsp;') + // we always want one line of height
'</span>';
return '<a class="' + classes.join(' ') + '"' +
(eventDef.url ?
' href="' + Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(eventDef.url) + '"' :
'') +
(skinCss ?
' style="' + skinCss + '"' :
'') +
'>' +
'<div class="fc-content">' +
(context.options.dir === 'rtl' ?
titleHtml + ' ' + timeHtml : // put a natural space in between
timeHtml + ' ' + titleHtml //
) +
'</div>' +
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
'') +
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
'') +
'</a>';
};
// Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () {
return {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow'
};
};
SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
return false; // TODO: somehow consider the originating DayGrid's column count
};
return SimpleDayGridEventRenderer;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["FgEventRenderer"]));
/* Event-rendering methods for the DayGrid class
----------------------------------------------------------------------------------------------------------------------*/
var DayGridEventRenderer = /** @class */ (function (_super) {
__extends(DayGridEventRenderer, _super);
function DayGridEventRenderer(dayGrid) {
var _this = _super.call(this) || this;
_this.dayGrid = dayGrid;
return _this;
}
// Renders the given foreground event segments onto the grid
DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
var rowStructs = this.rowStructs = this.renderSegRows(segs);
// append to each row's content skeleton
this.dayGrid.rowEls.forEach(function (rowNode, i) {
rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl);
});
// removes the "more.." events popover
if (!mirrorInfo) {
this.dayGrid.removeSegPopover();
}
};
// Unrenders all currently rendered foreground event segments
DayGridEventRenderer.prototype.detachSegs = function () {
var rowStructs = this.rowStructs || [];
var rowStruct;
while ((rowStruct = rowStructs.pop())) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["removeElement"])(rowStruct.tbodyEl);
}
this.rowStructs = null;
};
// Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton.
// Returns an array of rowStruct objects (see the bottom of `renderSegRow`).
// PRECONDITION: each segment shoud already have a rendered and assigned `.el`
DayGridEventRenderer.prototype.renderSegRows = function (segs) {
var rowStructs = [];
var segRows;
var row;
segRows = this.groupSegRows(segs); // group into nested arrays
// iterate each row of segment groupings
for (row = 0; row < segRows.length; row++) {
rowStructs.push(this.renderSegRow(row, segRows[row]));
}
return rowStructs;
};
// Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains
// the segments. Returns object with a bunch of internal data about how the render was calculated.
// NOTE: modifies rowSegs
DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) {
var isRtl = this.context.isRtl;
var dayGrid = this.dayGrid;
var colCnt = dayGrid.colCnt;
var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels
var levelCnt = Math.max(1, segLevels.length); // ensure at least one level
var tbody = document.createElement('tbody');
var segMatrix = []; // lookup for which segments are rendered into which level+col cells
var cellMatrix = []; // lookup for all <td> elements of the level+col matrix
var loneCellMatrix = []; // lookup for <td> elements that only take up a single column
var i;
var levelSegs;
var col;
var tr;
var j;
var seg;
var td;
// populates empty cells from the current column (`col`) to `endCol`
function emptyCellsUntil(endCol) {
while (col < endCol) {
// try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell
td = (loneCellMatrix[i - 1] || [])[col];
if (td) {
td.rowSpan = (td.rowSpan || 1) + 1;
}
else {
td = document.createElement('td');
tr.appendChild(td);
}
cellMatrix[i][col] = td;
loneCellMatrix[i][col] = td;
col++;
}
}
for (i = 0; i < levelCnt; i++) { // iterate through all levels
levelSegs = segLevels[i];
col = 0;
tr = document.createElement('tr');
segMatrix.push([]);
cellMatrix.push([]);
loneCellMatrix.push([]);
// levelCnt might be 1 even though there are no actual levels. protect against this.
// this single empty row is useful for styling.
if (levelSegs) {
for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level
seg = levelSegs[j];
var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
emptyCellsUntil(leftCol);
// create a container that occupies or more columns. append the event element.
td = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('td', { className: 'fc-event-container' }, seg.el);
if (leftCol !== rightCol) {
td.colSpan = rightCol - leftCol + 1;
}
else { // a single-column segment
loneCellMatrix[i][col] = td;
}
while (col <= rightCol) {
cellMatrix[i][col] = td;
segMatrix[i][col] = seg;
col++;
}
tr.appendChild(td);
}
}
emptyCellsUntil(colCnt); // finish off the row
var introHtml = dayGrid.renderProps.renderIntroHtml();
if (introHtml) {
if (isRtl) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["appendToElement"])(tr, introHtml);
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["prependToElement"])(tr, introHtml);
}
}
tbody.appendChild(tr);
}
return {
row: row,
tbodyEl: tbody,
cellMatrix: cellMatrix,
segMatrix: segMatrix,
segLevels: segLevels,
segs: rowSegs
};
};
// Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.
// NOTE: modifies segs
DayGridEventRenderer.prototype.buildSegLevels = function (segs) {
var isRtl = this.context.isRtl;
var colCnt = this.dayGrid.colCnt;
var levels = [];
var i;
var seg;
var j;
// Give preference to elements with certain criteria, so they have
// a chance to be closer to the top.
segs = this.sortEventSegs(segs);
for (i = 0; i < segs.length; i++) {
seg = segs[i];
// loop through levels, starting with the topmost, until the segment doesn't collide with other segments
for (j = 0; j < levels.length; j++) {
if (!isDaySegCollision(seg, levels[j])) {
break;
}
}
// `j` now holds the desired subrow index
seg.level = j;
seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only
seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only
;
(levels[j] || (levels[j] = [])).push(seg);
}
// order segments left-to-right. very important if calendar is RTL
for (j = 0; j < levels.length; j++) {
levels[j].sort(compareDaySegCols);
}
return levels;
};
// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row
DayGridEventRenderer.prototype.groupSegRows = function (segs) {
var segRows = [];
var i;
for (i = 0; i < this.dayGrid.rowCnt; i++) {
segRows.push([]);
}
for (i = 0; i < segs.length; i++) {
segRows[segs[i].row].push(segs[i]);
}
return segRows;
};
// Computes a default `displayEventEnd` value if one is not expliclty defined
DayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day
};
return DayGridEventRenderer;
}(SimpleDayGridEventRenderer));
// Computes whether two segments' columns collide. They are assumed to be in the same row.
function isDaySegCollision(seg, otherSegs) {
var i;
var otherSeg;
for (i = 0; i < otherSegs.length; i++) {
otherSeg = otherSegs[i];
if (otherSeg.firstCol <= seg.lastCol &&
otherSeg.lastCol >= seg.firstCol) {
return true;
}
}
return false;
}
// A cmp function for determining the leftmost event
function compareDaySegCols(a, b) {
return a.leftCol - b.leftCol;
}
var DayGridMirrorRenderer = /** @class */ (function (_super) {
__extends(DayGridMirrorRenderer, _super);
function DayGridMirrorRenderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
var sourceSeg = mirrorInfo.sourceSeg;
var rowStructs = this.rowStructs = this.renderSegRows(segs);
// inject each new event skeleton into each associated row
this.dayGrid.rowEls.forEach(function (rowNode, row) {
var skeletonEl = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlToElement"])('<div class="fc-mirror-skeleton"><table></table></div>'); // will be absolutely positioned
var skeletonTopEl;
var skeletonTop;
// If there is an original segment, match the top position. Otherwise, put it at the row's top level
if (sourceSeg && sourceSeg.row === row) {
skeletonTopEl = sourceSeg.el;
}
else {
skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody');
if (!skeletonTopEl) { // when no events
skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table');
}
}
skeletonTop = skeletonTopEl.getBoundingClientRect().top -
rowNode.getBoundingClientRect().top; // the offsetParent origin
skeletonEl.style.top = skeletonTop + 'px';
skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl);
rowNode.appendChild(skeletonEl);
});
};
return DayGridMirrorRenderer;
}(DayGridEventRenderer));
var EMPTY_CELL_HTML = '<td style="pointer-events:none"></td>';
var DayGridFillRenderer = /** @class */ (function (_super) {
__extends(DayGridFillRenderer, _super);
function DayGridFillRenderer(dayGrid) {
var _this = _super.call(this) || this;
_this.fillSegTag = 'td'; // override the default tag name
_this.dayGrid = dayGrid;
return _this;
}
DayGridFillRenderer.prototype.renderSegs = function (type, context, segs) {
// don't render timed background events
if (type === 'bgEvent') {
segs = segs.filter(function (seg) {
return seg.eventRange.def.allDay;
});
}
_super.prototype.renderSegs.call(this, type, context, segs);
};
DayGridFillRenderer.prototype.attachSegs = function (type, segs) {
var els = [];
var i;
var seg;
var skeletonEl;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
skeletonEl = this.renderFillRow(type, seg);
this.dayGrid.rowEls[seg.row].appendChild(skeletonEl);
els.push(skeletonEl);
}
return els;
};
// Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
DayGridFillRenderer.prototype.renderFillRow = function (type, seg) {
var dayGrid = this.dayGrid;
var isRtl = this.context.isRtl;
var colCnt = dayGrid.colCnt;
var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
var startCol = leftCol;
var endCol = rightCol + 1;
var className;
var skeletonEl;
var trEl;
if (type === 'businessHours') {
className = 'bgevent';
}
else {
className = type.toLowerCase();
}
skeletonEl = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlToElement"])('<div class="fc-' + className + '-skeleton">' +
'<table><tr></tr></table>' +
'</div>');
trEl = skeletonEl.getElementsByTagName('tr')[0];
if (startCol > 0) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["appendToElement"])(trEl,
// will create (startCol + 1) td's
new Array(startCol + 1).join(EMPTY_CELL_HTML));
}
seg.el.colSpan = endCol - startCol;
trEl.appendChild(seg.el);
if (endCol < colCnt) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["appendToElement"])(trEl,
// will create (colCnt - endCol) td's
new Array(colCnt - endCol + 1).join(EMPTY_CELL_HTML));
}
var introHtml = dayGrid.renderProps.renderIntroHtml();
if (introHtml) {
if (isRtl) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["appendToElement"])(trEl, introHtml);
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["prependToElement"])(trEl, introHtml);
}
}
return skeletonEl;
};
return DayGridFillRenderer;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["FillRenderer"]));
var DayTile = /** @class */ (function (_super) {
__extends(DayTile, _super);
function DayTile(el) {
var _this = _super.call(this, el) || this;
var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this);
var renderFrame = _this.renderFrame = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(_this._renderFrame);
_this.renderFgEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]);
_this.renderEventSelection = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
_this.renderEventDrag = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]);
_this.renderEventResize = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]);
return _this;
}
DayTile.prototype.firstContext = function (context) {
context.calendar.registerInteractiveComponent(this, {
el: this.el,
useEventCenter: false
});
};
DayTile.prototype.render = function (props, context) {
this.renderFrame(props.date);
this.renderFgEvents(context, props.fgSegs);
this.renderEventSelection(props.eventSelection);
this.renderEventDrag(props.eventDragInstances);
this.renderEventResize(props.eventResizeInstances);
};
DayTile.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderFrame.unrender(); // should unrender everything else
this.context.calendar.unregisterInteractiveComponent(this);
};
DayTile.prototype._renderFrame = function (date) {
var _a = this.context, theme = _a.theme, dateEnv = _a.dateEnv, options = _a.options;
var title = dateEnv.format(date, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createFormatter"])(options.dayPopoverFormat) // TODO: cache
);
this.el.innerHTML =
'<div class="fc-header ' + theme.getClass('popoverHeader') + '">' +
'<span class="fc-title">' +
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(title) +
'</span>' +
'<span class="fc-close ' + theme.getIconClass('close') + '"></span>' +
'</div>' +
'<div class="fc-body ' + theme.getClass('popoverContent') + '">' +
'<div class="fc-event-container"></div>' +
'</div>';
this.segContainerEl = this.el.querySelector('.fc-event-container');
};
DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
var date = this.props.date; // HACK
if (positionLeft < elWidth && positionTop < elHeight) {
return {
component: this,
dateSpan: {
allDay: true,
range: { start: date, end: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["addDays"])(date, 1) }
},
dayEl: this.el,
rect: {
left: 0,
top: 0,
right: elWidth,
bottom: elHeight
},
layer: 1
};
}
};
return DayTile;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DateComponent"]));
var DayTileEventRenderer = /** @class */ (function (_super) {
__extends(DayTileEventRenderer, _super);
function DayTileEventRenderer(dayTile) {
var _this = _super.call(this) || this;
_this.dayTile = dayTile;
return _this;
}
DayTileEventRenderer.prototype.attachSegs = function (segs) {
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
this.dayTile.segContainerEl.appendChild(seg.el);
}
};
DayTileEventRenderer.prototype.detachSegs = function (segs) {
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["removeElement"])(seg.el);
}
};
return DayTileEventRenderer;
}(SimpleDayGridEventRenderer));
var DayBgRow = /** @class */ (function () {
function DayBgRow(context) {
this.context = context;
}
DayBgRow.prototype.renderHtml = function (props) {
var parts = [];
if (props.renderIntroHtml) {
parts.push(props.renderIntroHtml());
}
for (var _i = 0, _a = props.cells; _i < _a.length; _i++) {
var cell = _a[_i];
parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs));
}
if (!props.cells.length) {
parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>');
}
if (this.context.options.dir === 'rtl') {
parts.reverse();
}
return '<tr>' + parts.join('') + '</tr>';
};
return DayBgRow;
}());
function renderCellHtml(date, dateProfile, context, otherAttrs) {
var dateEnv = context.dateEnv, theme = context.theme;
var isDateValid = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["rangeContainsMarker"])(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
var classes = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getDayClasses"])(date, dateProfile, context);
classes.unshift('fc-day', theme.getClass('widgetContent'));
return '<td class="' + classes.join(' ') + '"' +
(isDateValid ?
' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
'') +
(otherAttrs ?
' ' + otherAttrs :
'') +
'></td>';
}
var DAY_NUM_FORMAT = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createFormatter"])({ day: 'numeric' });
var WEEK_NUM_FORMAT = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createFormatter"])({ week: 'numeric' });
var DayGrid = /** @class */ (function (_super) {
__extends(DayGrid, _super);
function DayGrid(el, renderProps) {
var _this = _super.call(this, el) || this;
_this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid
_this.isCellSizesDirty = false;
_this.renderProps = renderProps;
var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this);
var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this);
_this.mirrorRenderer = new DayGridMirrorRenderer(_this);
var renderCells = _this.renderCells = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(_this._renderCells, _this._unrenderCells);
_this.renderBusinessHours = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]);
_this.renderDateSelection = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]);
_this.renderBgEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]);
_this.renderFgEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]);
_this.renderEventSelection = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
_this.renderEventDrag = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]);
_this.renderEventResize = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(_this._renderEventResize, _this._unrenderEventResize, [renderCells]);
return _this;
}
DayGrid.prototype.render = function (props, context) {
var cells = props.cells;
this.rowCnt = cells.length;
this.colCnt = cells[0].length;
this.renderCells(cells, props.isRigid);
this.renderBusinessHours(context, props.businessHourSegs);
this.renderDateSelection(context, props.dateSelectionSegs);
this.renderBgEvents(context, props.bgEventSegs);
this.renderFgEvents(context, props.fgEventSegs);
this.renderEventSelection(props.eventSelection);
this.renderEventDrag(props.eventDrag);
this.renderEventResize(props.eventResize);
if (this.segPopoverTile) {
this.updateSegPopoverTile();
}
};
DayGrid.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderCells.unrender(); // will unrender everything else
};
DayGrid.prototype.getCellRange = function (row, col) {
var start = this.props.cells[row][col].date;
var end = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["addDays"])(start, 1);
return { start: start, end: end };
};
DayGrid.prototype.updateSegPopoverTile = function (date, segs) {
var ownProps = this.props;
this.segPopoverTile.receiveProps({
date: date || this.segPopoverTile.props.date,
fgSegs: segs || this.segPopoverTile.props.fgSegs,
eventSelection: ownProps.eventSelection,
eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null,
eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null
}, this.context);
};
/* Date Rendering
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype._renderCells = function (cells, isRigid) {
var _a = this.context, calendar = _a.calendar, view = _a.view, isRtl = _a.isRtl, dateEnv = _a.dateEnv;
var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt;
var html = '';
var row;
var col;
for (row = 0; row < rowCnt; row++) {
html += this.renderDayRowHtml(row, isRigid);
}
this.el.innerHTML = html;
this.rowEls = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["findElements"])(this.el, '.fc-row');
this.cellEls = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["findElements"])(this.el, '.fc-day, .fc-disabled-day');
if (isRtl) {
this.cellEls.reverse();
}
this.rowPositions = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["PositionCache"](this.el, this.rowEls, false, true // vertical
);
this.colPositions = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["PositionCache"](this.el, this.cellEls.slice(0, colCnt), // only the first row
true, false // horizontal
);
// trigger dayRender with each cell's element
for (row = 0; row < rowCnt; row++) {
for (col = 0; col < colCnt; col++) {
calendar.publiclyTrigger('dayRender', [
{
date: dateEnv.toDate(cells[row][col].date),
el: this.getCellEl(row, col),
view: view
}
]);
}
}
this.isCellSizesDirty = true;
};
DayGrid.prototype._unrenderCells = function () {
this.removeSegPopover();
};
// Generates the HTML for a single row, which is a div that wraps a table.
// `row` is the row number.
DayGrid.prototype.renderDayRowHtml = function (row, isRigid) {
var theme = this.context.theme;
var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')];
if (isRigid) {
classes.push('fc-rigid');
}
var bgRow = new DayBgRow(this.context);
return '' +
'<div class="' + classes.join(' ') + '">' +
'<div class="fc-bg">' +
'<table class="' + theme.getClass('tableGrid') + '">' +
bgRow.renderHtml({
cells: this.props.cells[row],
dateProfile: this.props.dateProfile,
renderIntroHtml: this.renderProps.renderBgIntroHtml
}) +
'</table>' +
'</div>' +
'<div class="fc-content-skeleton">' +
'<table>' +
(this.getIsNumbersVisible() ?
'<thead>' +
this.renderNumberTrHtml(row) +
'</thead>' :
'') +
'</table>' +
'</div>' +
'</div>';
};
DayGrid.prototype.getIsNumbersVisible = function () {
return this.getIsDayNumbersVisible() ||
this.renderProps.cellWeekNumbersVisible ||
this.renderProps.colWeekNumbersVisible;
};
DayGrid.prototype.getIsDayNumbersVisible = function () {
return this.rowCnt > 1;
};
/* Grid Number Rendering
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype.renderNumberTrHtml = function (row) {
var isRtl = this.context.isRtl;
var intro = this.renderProps.renderNumberIntroHtml(row, this);
return '' +
'<tr>' +
(isRtl ? '' : intro) +
this.renderNumberCellsHtml(row) +
(isRtl ? intro : '') +
'</tr>';
};
DayGrid.prototype.renderNumberCellsHtml = function (row) {
var htmls = [];
var col;
var date;
for (col = 0; col < this.colCnt; col++) {
date = this.props.cells[row][col].date;
htmls.push(this.renderNumberCellHtml(date));
}
if (this.context.isRtl) {
htmls.reverse();
}
return htmls.join('');
};
// Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton.
// The number row will only exist if either day numbers or week numbers are turned on.
DayGrid.prototype.renderNumberCellHtml = function (date) {
var _a = this.context, dateEnv = _a.dateEnv, options = _a.options;
var html = '';
var isDateValid = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["rangeContainsMarker"])(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid;
var classes;
var weekCalcFirstDow;
if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) {
// no numbers in day cell (week number must be along the side)
return '<td></td>'; // will create an empty space above events :(
}
classes = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getDayClasses"])(date, this.props.dateProfile, this.context);
classes.unshift('fc-day-top');
if (this.renderProps.cellWeekNumbersVisible) {
weekCalcFirstDow = dateEnv.weekDow;
}
html += '<td class="' + classes.join(' ') + '"' +
(isDateValid ?
' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
'') +
'>';
if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) {
html += Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["buildGotoAnchorHtml"])(options, dateEnv, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML
);
}
if (isDayNumberVisible) {
html += Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["buildGotoAnchorHtml"])(options, dateEnv, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML
);
}
html += '</td>';
return html;
};
/* Sizing
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype.updateSize = function (isResize) {
var calendar = this.context.calendar;
var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
if (isResize ||
this.isCellSizesDirty ||
calendar.isEventsUpdated // hack
) {
this.buildPositionCaches();
this.isCellSizesDirty = false;
}
fillRenderer.computeSizes(isResize);
eventRenderer.computeSizes(isResize);
mirrorRenderer.computeSizes(isResize);
fillRenderer.assignSizes(isResize);
eventRenderer.assignSizes(isResize);
mirrorRenderer.assignSizes(isResize);
};
DayGrid.prototype.buildPositionCaches = function () {
this.buildColPositions();
this.buildRowPositions();
};
DayGrid.prototype.buildColPositions = function () {
this.colPositions.build();
};
DayGrid.prototype.buildRowPositions = function () {
this.rowPositions.build();
this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack
};
/* Hit System
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype.positionToHit = function (leftPosition, topPosition) {
var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions;
var col = colPositions.leftToIndex(leftPosition);
var row = rowPositions.topToIndex(topPosition);
if (row != null && col != null) {
return {
row: row,
col: col,
dateSpan: {
range: this.getCellRange(row, col),
allDay: true
},
dayEl: this.getCellEl(row, col),
relativeRect: {
left: colPositions.lefts[col],
right: colPositions.rights[col],
top: rowPositions.tops[row],
bottom: rowPositions.bottoms[row]
}
};
}
};
/* Cell System
------------------------------------------------------------------------------------------------------------------*/
// FYI: the first column is the leftmost column, regardless of date
DayGrid.prototype.getCellEl = function (row, col) {
return this.cellEls[row * this.colCnt + col];
};
/* Event Drag Visualization
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype._renderEventDrag = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
this.fillRenderer.renderSegs('highlight', this.context, state.segs);
}
};
DayGrid.prototype._unrenderEventDrag = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.fillRenderer.unrender('highlight', this.context);
}
};
/* Event Resize Visualization
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype._renderEventResize = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
this.fillRenderer.renderSegs('highlight', this.context, state.segs);
this.mirrorRenderer.renderSegs(this.context, state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
}
};
DayGrid.prototype._unrenderEventResize = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.fillRenderer.unrender('highlight', this.context);
this.mirrorRenderer.unrender(this.context, state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
}
};
/* More+ Link Popover
------------------------------------------------------------------------------------------------------------------*/
DayGrid.prototype.removeSegPopover = function () {
if (this.segPopover) {
this.segPopover.hide(); // in handler, will call segPopover's removeElement
}
};
// Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
// `levelLimit` can be false (don't limit), a number, or true (should be computed).
DayGrid.prototype.limitRows = function (levelLimit) {
var rowStructs = this.eventRenderer.rowStructs || [];
var row; // row #
var rowLevelLimit;
for (row = 0; row < rowStructs.length; row++) {
this.unlimitRow(row);
if (!levelLimit) {
rowLevelLimit = false;
}
else if (typeof levelLimit === 'number') {
rowLevelLimit = levelLimit;
}
else {
rowLevelLimit = this.computeRowLevelLimit(row);
}
if (rowLevelLimit !== false) {
this.limitRow(row, rowLevelLimit);
}
}
};
// Computes the number of levels a row will accomodate without going outside its bounds.
// Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
// `row` is the row number.
DayGrid.prototype.computeRowLevelLimit = function (row) {
var rowEl = this.rowEls[row]; // the containing "fake" row div
var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport!
var trEls = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["findChildren"])(this.eventRenderer.rowStructs[row].tbodyEl);
var i;
var trEl;
// Reveal one level <tr> at a time and stop when we find one out of bounds
for (i = 0; i < trEls.length; i++) {
trEl = trEls[i];
trEl.classList.remove('fc-limited'); // reset to original state (reveal)
if (trEl.getBoundingClientRect().bottom > rowBottom) {
return i;
}
}
return false; // should not limit at all
};
// Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
// `row` is the row number.
// `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
DayGrid.prototype.limitRow = function (row, levelLimit) {
var _this = this;
var colCnt = this.colCnt;
var isRtl = this.context.isRtl;
var rowStruct = this.eventRenderer.rowStructs[row];
var moreNodes = []; // array of "more" <a> links and <td> DOM nodes
var col = 0; // col #, left-to-right (not chronologically)
var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
var cellMatrix; // a matrix (by level, then column) of all <td> elements in the row
var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes
var i;
var seg;
var segsBelow; // array of segment objects below `seg` in the current `col`
var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
var td;
var rowSpan;
var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell
var j;
var moreTd;
var moreWrap;
var moreLink;
// Iterates through empty level cells and places "more" links inside if need be
var emptyCellsUntil = function (endCol) {
while (col < endCol) {
segsBelow = _this.getCellSegs(row, col, levelLimit);
if (segsBelow.length) {
td = cellMatrix[levelLimit - 1][col];
moreLink = _this.renderMoreLink(row, col, segsBelow);
moreWrap = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('div', null, moreLink);
td.appendChild(moreWrap);
moreNodes.push(moreWrap);
}
col++;
}
};
if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
levelSegs = rowStruct.segLevels[levelLimit - 1];
cellMatrix = rowStruct.cellMatrix;
limitedNodes = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["findChildren"])(rowStruct.tbodyEl).slice(levelLimit); // get level <tr> elements past the limit
limitedNodes.forEach(function (node) {
node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array
});
// iterate though segments in the last allowable level
for (i = 0; i < levelSegs.length; i++) {
seg = levelSegs[i];
var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
emptyCellsUntil(leftCol); // process empty cells before the segment
// determine *all* segments below `seg` that occupy the same columns
colSegsBelow = [];
totalSegsBelow = 0;
while (col <= rightCol) {
segsBelow = this.getCellSegs(row, col, levelLimit);
colSegsBelow.push(segsBelow);
totalSegsBelow += segsBelow.length;
col++;
}
if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell
rowSpan = td.rowSpan || 1;
segMoreNodes = [];
// make a replacement <td> for each column the segment occupies. will be one for each colspan
for (j = 0; j < colSegsBelow.length; j++) {
moreTd = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('td', { className: 'fc-more-cell', rowSpan: rowSpan });
segsBelow = colSegsBelow[j];
moreLink = this.renderMoreLink(row, leftCol + j, [seg].concat(segsBelow) // count seg as hidden too
);
moreWrap = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('div', null, moreLink);
moreTd.appendChild(moreWrap);
segMoreNodes.push(moreTd);
moreNodes.push(moreTd);
}
td.classList.add('fc-limited');
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["insertAfterElement"])(td, segMoreNodes);
limitedNodes.push(td);
}
}
emptyCellsUntil(this.colCnt); // finish off the level
rowStruct.moreEls = moreNodes; // for easy undoing later
rowStruct.limitedEls = limitedNodes; // for easy undoing later
}
};
// Reveals all levels and removes all "more"-related elements for a grid's row.
// `row` is a row number.
DayGrid.prototype.unlimitRow = function (row) {
var rowStruct = this.eventRenderer.rowStructs[row];
if (rowStruct.moreEls) {
rowStruct.moreEls.forEach(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["removeElement"]);
rowStruct.moreEls = null;
}
if (rowStruct.limitedEls) {
rowStruct.limitedEls.forEach(function (limitedEl) {
limitedEl.classList.remove('fc-limited');
});
rowStruct.limitedEls = null;
}
};
// Renders an <a> element that represents hidden event element for a cell.
// Responsible for attaching click handler as well.
DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) {
var _this = this;
var _a = this.context, calendar = _a.calendar, view = _a.view, dateEnv = _a.dateEnv, options = _a.options, isRtl = _a.isRtl;
var a = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('a', { className: 'fc-more' });
a.innerText = this.getMoreLinkText(hiddenSegs.length);
a.addEventListener('click', function (ev) {
var clickOption = options.eventLimitClick;
var _col = isRtl ? _this.colCnt - col - 1 : col; // HACK: props.cells has different dir system?
var date = _this.props.cells[row][_col].date;
var moreEl = ev.currentTarget;
var dayEl = _this.getCellEl(row, col);
var allSegs = _this.getCellSegs(row, col);
// rescope the segments to be within the cell's date
var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);
if (typeof clickOption === 'function') {
// the returned value can be an atomic option
clickOption = calendar.publiclyTrigger('eventLimitClick', [
{
date: dateEnv.toDate(date),
allDay: true,
dayEl: dayEl,
moreEl: moreEl,
segs: reslicedAllSegs,
hiddenSegs: reslicedHiddenSegs,
jsEvent: ev,
view: view
}
]);
}
if (clickOption === 'popover') {
_this.showSegPopover(row, col, moreEl, reslicedAllSegs);
}
else if (typeof clickOption === 'string') { // a view name
calendar.zoomTo(date, clickOption);
}
});
return a;
};
// Reveals the popover that displays all events within a cell
DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) {
var _this = this;
var _a = this.context, calendar = _a.calendar, view = _a.view, theme = _a.theme, isRtl = _a.isRtl;
var _col = isRtl ? this.colCnt - col - 1 : col; // HACK: props.cells has different dir system?
var moreWrap = moreLink.parentNode; // the <div> wrapper around the <a>
var topEl; // the element we want to match the top coordinate of
var options;
if (this.rowCnt === 1) {
topEl = view.el; // will cause the popover to cover any sort of header
}
else {
topEl = this.rowEls[row]; // will align with top of row
}
options = {
className: 'fc-more-popover ' + theme.getClass('popover'),
parentEl: view.el,
top: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(topEl).top,
autoHide: true,
content: function (el) {
_this.segPopoverTile = new DayTile(el);
_this.updateSegPopoverTile(_this.props.cells[row][_col].date, segs);
},
hide: function () {
_this.segPopoverTile.destroy();
_this.segPopoverTile = null;
_this.segPopover.destroy();
_this.segPopover = null;
}
};
// Determine horizontal coordinate.
// We use the moreWrap instead of the <td> to avoid border confusion.
if (isRtl) {
options.right = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(moreWrap).right + 1; // +1 to be over cell border
}
else {
options.left = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(moreWrap).left - 1; // -1 to be over cell border
}
this.segPopover = new Popover(options);
this.segPopover.show();
calendar.releaseAfterSizingTriggers(); // hack for eventPositioned
};
// Given the events within an array of segment objects, reslice them to be in a single day
DayGrid.prototype.resliceDaySegs = function (segs, dayDate) {
var dayStart = dayDate;
var dayEnd = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["addDays"])(dayStart, 1);
var dayRange = { start: dayStart, end: dayEnd };
var newSegs = [];
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
var eventRange = seg.eventRange;
var origRange = eventRange.range;
var slicedRange = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["intersectRanges"])(origRange, dayRange);
if (slicedRange) {
newSegs.push(__assign({}, seg, { eventRange: {
def: eventRange.def,
ui: __assign({}, eventRange.ui, { durationEditable: false }),
instance: eventRange.instance,
range: slicedRange
}, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() }));
}
}
return newSegs;
};
// Generates the text that should be inside a "more" link, given the number of events it represents
DayGrid.prototype.getMoreLinkText = function (num) {
var opt = this.context.options.eventLimitText;
if (typeof opt === 'function') {
return opt(num);
}
else {
return '+' + num + ' ' + opt;
}
};
// Returns segments within a given cell.
// If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
DayGrid.prototype.getCellSegs = function (row, col, startLevel) {
var segMatrix = this.eventRenderer.rowStructs[row].segMatrix;
var level = startLevel || 0;
var segs = [];
var seg;
while (level < segMatrix.length) {
seg = segMatrix[level][col];
if (seg) {
segs.push(seg);
}
level++;
}
return segs;
};
return DayGrid;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DateComponent"]));
var WEEK_NUM_FORMAT$1 = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createFormatter"])({ week: 'numeric' });
/* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
----------------------------------------------------------------------------------------------------------------------*/
// It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
// It is responsible for managing width/height.
var AbstractDayGridView = /** @class */ (function (_super) {
__extends(AbstractDayGridView, _super);
function AbstractDayGridView() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.processOptions = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoize"])(_this._processOptions);
_this.renderSkeleton = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoizeRendering"])(_this._renderSkeleton, _this._unrenderSkeleton);
/* Header Rendering
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that will go before the day-of week header cells
_this.renderHeadIntroHtml = function () {
var _a = _this.context, theme = _a.theme, options = _a.options;
if (_this.colWeekNumbersVisible) {
return '' +
'<th class="fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.weekNumberStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(options.weekLabel) +
'</span>' +
'</th>';
}
return '';
};
/* Day Grid Rendering
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that will go before content-skeleton cells that display the day/week numbers
_this.renderDayGridNumberIntroHtml = function (row, dayGrid) {
var _a = _this.context, options = _a.options, dateEnv = _a.dateEnv;
var weekStart = dayGrid.props.cells[row][0].date;
if (_this.colWeekNumbersVisible) {
return '' +
'<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '>' +
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["buildGotoAnchorHtml"])(// aside from link, important for matchCellWidths
options, dateEnv, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML
) +
'</td>';
}
return '';
};
// Generates the HTML that goes before the day bg cells for each day-row
_this.renderDayGridBgIntroHtml = function () {
var theme = _this.context.theme;
if (_this.colWeekNumbersVisible) {
return '<td class="fc-week-number ' + theme.getClass('widgetContent') + '" ' + _this.weekNumberStyleAttr() + '></td>';
}
return '';
};
// Generates the HTML that goes before every other type of row generated by DayGrid.
// Affects mirror-skeleton and highlight-skeleton rows.
_this.renderDayGridIntroHtml = function () {
if (_this.colWeekNumbersVisible) {
return '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '></td>';
}
return '';
};
return _this;
}
AbstractDayGridView.prototype._processOptions = function (options) {
if (options.weekNumbers) {
if (options.weekNumbersWithinDays) {
this.cellWeekNumbersVisible = true;
this.colWeekNumbersVisible = false;
}
else {
this.cellWeekNumbersVisible = false;
this.colWeekNumbersVisible = true;
}
}
else {
this.colWeekNumbersVisible = false;
this.cellWeekNumbersVisible = false;
}
};
AbstractDayGridView.prototype.render = function (props, context) {
_super.prototype.render.call(this, props, context);
this.processOptions(context.options);
this.renderSkeleton(context);
};
AbstractDayGridView.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderSkeleton.unrender();
};
AbstractDayGridView.prototype._renderSkeleton = function (context) {
this.el.classList.add('fc-dayGrid-view');
this.el.innerHTML = this.renderSkeletonHtml();
this.scroller = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["ScrollComponent"]('hidden', // overflow x
'auto' // overflow y
);
var dayGridContainerEl = this.scroller.el;
this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl);
dayGridContainerEl.classList.add('fc-day-grid-container');
var dayGridEl = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createElement"])('div', { className: 'fc-day-grid' });
dayGridContainerEl.appendChild(dayGridEl);
this.dayGrid = new DayGrid(dayGridEl, {
renderNumberIntroHtml: this.renderDayGridNumberIntroHtml,
renderBgIntroHtml: this.renderDayGridBgIntroHtml,
renderIntroHtml: this.renderDayGridIntroHtml,
colWeekNumbersVisible: this.colWeekNumbersVisible,
cellWeekNumbersVisible: this.cellWeekNumbersVisible
});
};
AbstractDayGridView.prototype._unrenderSkeleton = function () {
this.el.classList.remove('fc-dayGrid-view');
this.dayGrid.destroy();
this.scroller.destroy();
};
// Builds the HTML skeleton for the view.
// The day-grid component will render inside of a container defined by this HTML.
AbstractDayGridView.prototype.renderSkeletonHtml = function () {
var _a = this.context, theme = _a.theme, options = _a.options;
return '' +
'<table class="' + theme.getClass('tableGrid') + '">' +
(options.columnHeader ?
'<thead class="fc-head">' +
'<tr>' +
'<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
'</tr>' +
'</thead>' :
'') +
'<tbody class="fc-body">' +
'<tr>' +
'<td class="' + theme.getClass('widgetContent') + '"></td>' +
'</tr>' +
'</tbody>' +
'</table>';
};
// Generates an HTML attribute string for setting the width of the week number column, if it is known
AbstractDayGridView.prototype.weekNumberStyleAttr = function () {
if (this.weekNumberWidth != null) {
return 'style="width:' + this.weekNumberWidth + 'px"';
}
return '';
};
// Determines whether each row should have a constant height
AbstractDayGridView.prototype.hasRigidRows = function () {
var eventLimit = this.context.options.eventLimit;
return eventLimit && typeof eventLimit !== 'number';
};
/* Dimensions
------------------------------------------------------------------------------------------------------------------*/
AbstractDayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
_super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
this.dayGrid.updateSize(isResize);
};
// Refreshes the horizontal dimensions of the view
AbstractDayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
var dayGrid = this.dayGrid;
var eventLimit = this.context.options.eventLimit;
var headRowEl = this.header ? this.header.el : null; // HACK
var scrollerHeight;
var scrollbarWidths;
// hack to give the view some height prior to dayGrid's columns being rendered
// TODO: separate setting height from scroller VS dayGrid.
if (!dayGrid.rowEls) {
if (!isAuto) {
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
}
return;
}
if (this.colWeekNumbersVisible) {
// Make sure all week number cells running down the side have the same width.
this.weekNumberWidth = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["matchCellWidths"])(Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["findElements"])(this.el, '.fc-week-number'));
}
// reset all heights to be natural
this.scroller.clear();
if (headRowEl) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["uncompensateScroll"])(headRowEl);
}
dayGrid.removeSegPopover(); // kill the "more" popover if displayed
// is the event limit a constant level number?
if (eventLimit && typeof eventLimit === 'number') {
dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
}
// distribute the height to the rows
// (viewHeight is a "recommended" value if isAuto)
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.setGridHeight(scrollerHeight, isAuto);
// is the event limit dynamically calculated?
if (eventLimit && typeof eventLimit !== 'number') {
dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
}
if (!isAuto) { // should we force dimensions of the scroll container?
this.scroller.setHeight(scrollerHeight);
scrollbarWidths = this.scroller.getScrollbarWidths();
if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
if (headRowEl) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["compensateScroll"])(headRowEl, scrollbarWidths);
}
// doing the scrollbar compensation might have created text overflow which created more height. redo
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
}
// guarantees the same scrollbar widths
this.scroller.lockOverflow(scrollbarWidths);
}
};
// given a desired total height of the view, returns what the height of the scroller should be
AbstractDayGridView.prototype.computeScrollerHeight = function (viewHeight) {
return viewHeight -
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["subtractInnerElHeight"])(this.el, this.scroller.el); // everything that's NOT the scroller
};
// Sets the height of just the DayGrid component in this view
AbstractDayGridView.prototype.setGridHeight = function (height, isAuto) {
if (this.context.options.monthMode) {
// if auto, make the height of each row the height that it would be if there were 6 weeks
if (isAuto) {
height *= this.dayGrid.rowCnt / 6;
}
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["distributeHeight"])(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows
}
else {
if (isAuto) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["undistributeHeight"])(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["distributeHeight"])(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
}
}
};
/* Scroll
------------------------------------------------------------------------------------------------------------------*/
AbstractDayGridView.prototype.computeDateScroll = function (duration) {
return { top: 0 };
};
AbstractDayGridView.prototype.queryDateScroll = function () {
return { top: this.scroller.getScrollTop() };
};
AbstractDayGridView.prototype.applyDateScroll = function (scroll) {
if (scroll.top !== undefined) {
this.scroller.setScrollTop(scroll.top);
}
};
return AbstractDayGridView;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["View"]));
AbstractDayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator;
var SimpleDayGrid = /** @class */ (function (_super) {
__extends(SimpleDayGrid, _super);
function SimpleDayGrid(dayGrid) {
var _this = _super.call(this, dayGrid.el) || this;
_this.slicer = new DayGridSlicer();
_this.dayGrid = dayGrid;
return _this;
}
SimpleDayGrid.prototype.firstContext = function (context) {
context.calendar.registerInteractiveComponent(this, { el: this.dayGrid.el });
};
SimpleDayGrid.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.context.calendar.unregisterInteractiveComponent(this);
};
SimpleDayGrid.prototype.render = function (props, context) {
var dayGrid = this.dayGrid;
var dateProfile = props.dateProfile, dayTable = props.dayTable;
dayGrid.receiveContext(context); // hack because context is used in sliceProps
dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, context.calendar, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid }), context);
};
SimpleDayGrid.prototype.buildPositionCaches = function () {
this.dayGrid.buildPositionCaches();
};
SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) {
var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop);
if (rawHit) {
return {
component: this.dayGrid,
dateSpan: rawHit.dateSpan,
dayEl: rawHit.dayEl,
rect: {
left: rawHit.relativeRect.left,
right: rawHit.relativeRect.right,
top: rawHit.relativeRect.top,
bottom: rawHit.relativeRect.bottom
},
layer: 0
};
}
};
return SimpleDayGrid;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DateComponent"]));
var DayGridSlicer = /** @class */ (function (_super) {
__extends(DayGridSlicer, _super);
function DayGridSlicer() {
return _super !== null && _super.apply(this, arguments) || this;
}
DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) {
return dayTable.sliceRange(dateRange);
};
return DayGridSlicer;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Slicer"]));
var DayGridView = /** @class */ (function (_super) {
__extends(DayGridView, _super);
function DayGridView() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.buildDayTable = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["memoize"])(buildDayTable);
return _this;
}
DayGridView.prototype.render = function (props, context) {
_super.prototype.render.call(this, props, context); // will call _renderSkeleton/_unrenderSkeleton
var dateProfile = this.props.dateProfile;
var dayTable = this.dayTable =
this.buildDayTable(dateProfile, props.dateProfileGenerator);
if (this.header) {
this.header.receiveProps({
dateProfile: dateProfile,
dates: dayTable.headerDates,
datesRepDistinctDays: dayTable.rowCnt === 1,
renderIntroHtml: this.renderHeadIntroHtml
}, context);
}
this.simpleDayGrid.receiveProps({
dateProfile: dateProfile,
dayTable: dayTable,
businessHours: props.businessHours,
dateSelection: props.dateSelection,
eventStore: props.eventStore,
eventUiBases: props.eventUiBases,
eventSelection: props.eventSelection,
eventDrag: props.eventDrag,
eventResize: props.eventResize,
isRigid: this.hasRigidRows(),
nextDayThreshold: this.context.nextDayThreshold
}, context);
};
DayGridView.prototype._renderSkeleton = function (context) {
_super.prototype._renderSkeleton.call(this, context);
if (context.options.columnHeader) {
this.header = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DayHeader"](this.el.querySelector('.fc-head-container'));
}
this.simpleDayGrid = new SimpleDayGrid(this.dayGrid);
};
DayGridView.prototype._unrenderSkeleton = function () {
_super.prototype._unrenderSkeleton.call(this);
if (this.header) {
this.header.destroy();
}
this.simpleDayGrid.destroy();
};
return DayGridView;
}(AbstractDayGridView));
function buildDayTable(dateProfile, dateProfileGenerator) {
var daySeries = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DaySeries"](dateProfile.renderRange, dateProfileGenerator);
return new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["DayTable"](daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
}
var main = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createPlugin"])({
defaultView: 'dayGridMonth',
views: {
dayGrid: DayGridView,
dayGridDay: {
type: 'dayGrid',
duration: { days: 1 }
},
dayGridWeek: {
type: 'dayGrid',
duration: { weeks: 1 }
},
dayGridMonth: {
type: 'dayGrid',
duration: { months: 1 },
monthMode: true,
fixedWeekCount: true
}
}
});
/* harmony default export */ __webpack_exports__["default"] = (main);
/***/ }),
/***/ "./node_modules/@fullcalendar/interaction/main.esm.js":
/*!************************************************************!*\
!*** ./node_modules/@fullcalendar/interaction/main.esm.js ***!
\************************************************************/
/*! exports provided: default, Draggable, FeaturefulElementDragging, PointerDragging, ThirdPartyDraggable */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Draggable", function() { return ExternalDraggable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FeaturefulElementDragging", function() { return FeaturefulElementDragging; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PointerDragging", function() { return PointerDragging; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ThirdPartyDraggable", function() { return ThirdPartyDraggable; });
/* harmony import */ var _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @fullcalendar/core */ "./node_modules/@fullcalendar/core/main.esm.js");
/*!
FullCalendar Interaction Plugin v4.4.2
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["config"].touchMouseIgnoreWait = 500;
var ignoreMouseDepth = 0;
var listenerCnt = 0;
var isWindowTouchMoveCancelled = false;
/*
Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
Tracks when the pointer "drags" on a certain element, meaning down+move+up.
Also, tracks if there was touch-scrolling.
Also, can prevent touch-scrolling from happening.
Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
emits:
- pointerdown
- pointermove
- pointerup
*/
var PointerDragging = /** @class */ (function () {
function PointerDragging(containerEl) {
var _this = this;
this.subjectEl = null;
this.downEl = null;
// options that can be directly assigned by caller
this.selector = ''; // will cause subjectEl in all emitted events to be this element
this.handleSelector = '';
this.shouldIgnoreMove = false;
this.shouldWatchScroll = true; // for simulating pointermove on scroll
// internal states
this.isDragging = false;
this.isTouchDragging = false;
this.wasTouchScroll = false;
// Mouse
// ----------------------------------------------------------------------------------------------------
this.handleMouseDown = function (ev) {
if (!_this.shouldIgnoreMouse() &&
isPrimaryMouseButton(ev) &&
_this.tryStart(ev)) {
var pev = _this.createEventFromMouse(ev, true);
_this.emitter.trigger('pointerdown', pev);
_this.initScrollWatch(pev);
if (!_this.shouldIgnoreMove) {
document.addEventListener('mousemove', _this.handleMouseMove);
}
document.addEventListener('mouseup', _this.handleMouseUp);
}
};
this.handleMouseMove = function (ev) {
var pev = _this.createEventFromMouse(ev);
_this.recordCoords(pev);
_this.emitter.trigger('pointermove', pev);
};
this.handleMouseUp = function (ev) {
document.removeEventListener('mousemove', _this.handleMouseMove);
document.removeEventListener('mouseup', _this.handleMouseUp);
_this.emitter.trigger('pointerup', _this.createEventFromMouse(ev));
_this.cleanup(); // call last so that pointerup has access to props
};
// Touch
// ----------------------------------------------------------------------------------------------------
this.handleTouchStart = function (ev) {
if (_this.tryStart(ev)) {
_this.isTouchDragging = true;
var pev = _this.createEventFromTouch(ev, true);
_this.emitter.trigger('pointerdown', pev);
_this.initScrollWatch(pev);
// unlike mouse, need to attach to target, not document
// https://stackoverflow.com/a/45760014
var target = ev.target;
if (!_this.shouldIgnoreMove) {
target.addEventListener('touchmove', _this.handleTouchMove);
}
target.addEventListener('touchend', _this.handleTouchEnd);
target.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end
// attach a handler to get called when ANY scroll action happens on the page.
// this was impossible to do with normal on/off because 'scroll' doesn't bubble.
// http://stackoverflow.com/a/32954565/96342
window.addEventListener('scroll', _this.handleTouchScroll, true // useCapture
);
}
};
this.handleTouchMove = function (ev) {
var pev = _this.createEventFromTouch(ev);
_this.recordCoords(pev);
_this.emitter.trigger('pointermove', pev);
};
this.handleTouchEnd = function (ev) {
if (_this.isDragging) { // done to guard against touchend followed by touchcancel
var target = ev.target;
target.removeEventListener('touchmove', _this.handleTouchMove);
target.removeEventListener('touchend', _this.handleTouchEnd);
target.removeEventListener('touchcancel', _this.handleTouchEnd);
window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true
_this.emitter.trigger('pointerup', _this.createEventFromTouch(ev));
_this.cleanup(); // call last so that pointerup has access to props
_this.isTouchDragging = false;
startIgnoringMouse();
}
};
this.handleTouchScroll = function () {
_this.wasTouchScroll = true;
};
this.handleScroll = function (ev) {
if (!_this.shouldIgnoreMove) {
var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX;
var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY;
_this.emitter.trigger('pointermove', {
origEvent: ev,
isTouch: _this.isTouchDragging,
subjectEl: _this.subjectEl,
pageX: pageX,
pageY: pageY,
deltaX: pageX - _this.origPageX,
deltaY: pageY - _this.origPageY
});
}
};
this.containerEl = containerEl;
this.emitter = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EmitterMixin"]();
containerEl.addEventListener('mousedown', this.handleMouseDown);
containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
listenerCreated();
}
PointerDragging.prototype.destroy = function () {
this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
listenerDestroyed();
};
PointerDragging.prototype.tryStart = function (ev) {
var subjectEl = this.querySubjectEl(ev);
var downEl = ev.target;
if (subjectEl &&
(!this.handleSelector || Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(downEl, this.handleSelector))) {
this.subjectEl = subjectEl;
this.downEl = downEl;
this.isDragging = true; // do this first so cancelTouchScroll will work
this.wasTouchScroll = false;
return true;
}
return false;
};
PointerDragging.prototype.cleanup = function () {
isWindowTouchMoveCancelled = false;
this.isDragging = false;
this.subjectEl = null;
this.downEl = null;
// keep wasTouchScroll around for later access
this.destroyScrollWatch();
};
PointerDragging.prototype.querySubjectEl = function (ev) {
if (this.selector) {
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(ev.target, this.selector);
}
else {
return this.containerEl;
}
};
PointerDragging.prototype.shouldIgnoreMouse = function () {
return ignoreMouseDepth || this.isTouchDragging;
};
// can be called by user of this class, to cancel touch-based scrolling for the current drag
PointerDragging.prototype.cancelTouchScroll = function () {
if (this.isDragging) {
isWindowTouchMoveCancelled = true;
}
};
// Scrolling that simulates pointermoves
// ----------------------------------------------------------------------------------------------------
PointerDragging.prototype.initScrollWatch = function (ev) {
if (this.shouldWatchScroll) {
this.recordCoords(ev);
window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
}
};
PointerDragging.prototype.recordCoords = function (ev) {
if (this.shouldWatchScroll) {
this.prevPageX = ev.pageX;
this.prevPageY = ev.pageY;
this.prevScrollX = window.pageXOffset;
this.prevScrollY = window.pageYOffset;
}
};
PointerDragging.prototype.destroyScrollWatch = function () {
if (this.shouldWatchScroll) {
window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
}
};
// Event Normalization
// ----------------------------------------------------------------------------------------------------
PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) {
var deltaX = 0;
var deltaY = 0;
// TODO: repeat code
if (isFirst) {
this.origPageX = ev.pageX;
this.origPageY = ev.pageY;
}
else {
deltaX = ev.pageX - this.origPageX;
deltaY = ev.pageY - this.origPageY;
}
return {
origEvent: ev,
isTouch: false,
subjectEl: this.subjectEl,
pageX: ev.pageX,
pageY: ev.pageY,
deltaX: deltaX,
deltaY: deltaY
};
};
PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) {
var touches = ev.touches;
var pageX;
var pageY;
var deltaX = 0;
var deltaY = 0;
// if touch coords available, prefer,
// because FF would give bad ev.pageX ev.pageY
if (touches && touches.length) {
pageX = touches[0].pageX;
pageY = touches[0].pageY;
}
else {
pageX = ev.pageX;
pageY = ev.pageY;
}
// TODO: repeat code
if (isFirst) {
this.origPageX = pageX;
this.origPageY = pageY;
}
else {
deltaX = pageX - this.origPageX;
deltaY = pageY - this.origPageY;
}
return {
origEvent: ev,
isTouch: true,
subjectEl: this.subjectEl,
pageX: pageX,
pageY: pageY,
deltaX: deltaX,
deltaY: deltaY
};
};
return PointerDragging;
}());
// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
function isPrimaryMouseButton(ev) {
return ev.button === 0 && !ev.ctrlKey;
}
// Ignoring fake mouse events generated by touch
// ----------------------------------------------------------------------------------------------------
function startIgnoringMouse() {
ignoreMouseDepth++;
setTimeout(function () {
ignoreMouseDepth--;
}, _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["config"].touchMouseIgnoreWait);
}
// We want to attach touchmove as early as possible for Safari
// ----------------------------------------------------------------------------------------------------
function listenerCreated() {
if (!(listenerCnt++)) {
window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
}
}
function listenerDestroyed() {
if (!(--listenerCnt)) {
window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
}
}
function onWindowTouchMove(ev) {
if (isWindowTouchMoveCancelled) {
ev.preventDefault();
}
}
/*
An effect in which an element follows the movement of a pointer across the screen.
The moving element is a clone of some other element.
Must call start + handleMove + stop.
*/
var ElementMirror = /** @class */ (function () {
function ElementMirror() {
this.isVisible = false; // must be explicitly enabled
this.sourceEl = null;
this.mirrorEl = null;
this.sourceElRect = null; // screen coords relative to viewport
// options that can be set directly by caller
this.parentNode = document.body;
this.zIndex = 9999;
this.revertDuration = 0;
}
ElementMirror.prototype.start = function (sourceEl, pageX, pageY) {
this.sourceEl = sourceEl;
this.sourceElRect = this.sourceEl.getBoundingClientRect();
this.origScreenX = pageX - window.pageXOffset;
this.origScreenY = pageY - window.pageYOffset;
this.deltaX = 0;
this.deltaY = 0;
this.updateElPosition();
};
ElementMirror.prototype.handleMove = function (pageX, pageY) {
this.deltaX = (pageX - window.pageXOffset) - this.origScreenX;
this.deltaY = (pageY - window.pageYOffset) - this.origScreenY;
this.updateElPosition();
};
// can be called before start
ElementMirror.prototype.setIsVisible = function (bool) {
if (bool) {
if (!this.isVisible) {
if (this.mirrorEl) {
this.mirrorEl.style.display = '';
}
this.isVisible = bool; // needs to happen before updateElPosition
this.updateElPosition(); // because was not updating the position while invisible
}
}
else {
if (this.isVisible) {
if (this.mirrorEl) {
this.mirrorEl.style.display = 'none';
}
this.isVisible = bool;
}
}
};
// always async
ElementMirror.prototype.stop = function (needsRevertAnimation, callback) {
var _this = this;
var done = function () {
_this.cleanup();
callback();
};
if (needsRevertAnimation &&
this.mirrorEl &&
this.isVisible &&
this.revertDuration && // if 0, transition won't work
(this.deltaX || this.deltaY) // if same coords, transition won't work
) {
this.doRevertAnimation(done, this.revertDuration);
}
else {
setTimeout(done, 0);
}
};
ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) {
var mirrorEl = this.mirrorEl;
var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
mirrorEl.style.transition =
'top ' + revertDuration + 'ms,' +
'left ' + revertDuration + 'ms';
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyStyle"])(mirrorEl, {
left: finalSourceElRect.left,
top: finalSourceElRect.top
});
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["whenTransitionDone"])(mirrorEl, function () {
mirrorEl.style.transition = '';
callback();
});
};
ElementMirror.prototype.cleanup = function () {
if (this.mirrorEl) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["removeElement"])(this.mirrorEl);
this.mirrorEl = null;
}
this.sourceEl = null;
};
ElementMirror.prototype.updateElPosition = function () {
if (this.sourceEl && this.isVisible) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyStyle"])(this.getMirrorEl(), {
left: this.sourceElRect.left + this.deltaX,
top: this.sourceElRect.top + this.deltaY
});
}
};
ElementMirror.prototype.getMirrorEl = function () {
var sourceElRect = this.sourceElRect;
var mirrorEl = this.mirrorEl;
if (!mirrorEl) {
mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
// we don't want long taps or any mouse interaction causing selection/menus.
// would use preventSelection(), but that prevents selectstart, causing problems.
mirrorEl.classList.add('fc-unselectable');
mirrorEl.classList.add('fc-dragging');
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyStyle"])(mirrorEl, {
position: 'fixed',
zIndex: this.zIndex,
visibility: '',
boxSizing: 'border-box',
width: sourceElRect.right - sourceElRect.left,
height: sourceElRect.bottom - sourceElRect.top,
right: 'auto',
bottom: 'auto',
margin: 0
});
this.parentNode.appendChild(mirrorEl);
}
return mirrorEl;
};
return ElementMirror;
}());
/*
Is a cache for a given element's scroll information (all the info that ScrollController stores)
in addition the "client rectangle" of the element.. the area within the scrollbars.
The cache can be in one of two modes:
- doesListening:false - ignores when the container is scrolled by someone else
- doesListening:true - watch for scrolling and update the cache
*/
var ScrollGeomCache = /** @class */ (function (_super) {
__extends(ScrollGeomCache, _super);
function ScrollGeomCache(scrollController, doesListening) {
var _this = _super.call(this) || this;
_this.handleScroll = function () {
_this.scrollTop = _this.scrollController.getScrollTop();
_this.scrollLeft = _this.scrollController.getScrollLeft();
_this.handleScrollChange();
};
_this.scrollController = scrollController;
_this.doesListening = doesListening;
_this.scrollTop = _this.origScrollTop = scrollController.getScrollTop();
_this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft();
_this.scrollWidth = scrollController.getScrollWidth();
_this.scrollHeight = scrollController.getScrollHeight();
_this.clientWidth = scrollController.getClientWidth();
_this.clientHeight = scrollController.getClientHeight();
_this.clientRect = _this.computeClientRect(); // do last in case it needs cached values
if (_this.doesListening) {
_this.getEventTarget().addEventListener('scroll', _this.handleScroll);
}
return _this;
}
ScrollGeomCache.prototype.destroy = function () {
if (this.doesListening) {
this.getEventTarget().removeEventListener('scroll', this.handleScroll);
}
};
ScrollGeomCache.prototype.getScrollTop = function () {
return this.scrollTop;
};
ScrollGeomCache.prototype.getScrollLeft = function () {
return this.scrollLeft;
};
ScrollGeomCache.prototype.setScrollTop = function (top) {
this.scrollController.setScrollTop(top);
if (!this.doesListening) {
// we are not relying on the element to normalize out-of-bounds scroll values
// so we need to sanitize ourselves
this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
this.handleScrollChange();
}
};
ScrollGeomCache.prototype.setScrollLeft = function (top) {
this.scrollController.setScrollLeft(top);
if (!this.doesListening) {
// we are not relying on the element to normalize out-of-bounds scroll values
// so we need to sanitize ourselves
this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
this.handleScrollChange();
}
};
ScrollGeomCache.prototype.getClientWidth = function () {
return this.clientWidth;
};
ScrollGeomCache.prototype.getClientHeight = function () {
return this.clientHeight;
};
ScrollGeomCache.prototype.getScrollWidth = function () {
return this.scrollWidth;
};
ScrollGeomCache.prototype.getScrollHeight = function () {
return this.scrollHeight;
};
ScrollGeomCache.prototype.handleScrollChange = function () {
};
return ScrollGeomCache;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["ScrollController"]));
var ElementScrollGeomCache = /** @class */ (function (_super) {
__extends(ElementScrollGeomCache, _super);
function ElementScrollGeomCache(el, doesListening) {
return _super.call(this, new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["ElementScrollController"](el), doesListening) || this;
}
ElementScrollGeomCache.prototype.getEventTarget = function () {
return this.scrollController.el;
};
ElementScrollGeomCache.prototype.computeClientRect = function () {
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeInnerRect"])(this.scrollController.el);
};
return ElementScrollGeomCache;
}(ScrollGeomCache));
var WindowScrollGeomCache = /** @class */ (function (_super) {
__extends(WindowScrollGeomCache, _super);
function WindowScrollGeomCache(doesListening) {
return _super.call(this, new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["WindowScrollController"](), doesListening) || this;
}
WindowScrollGeomCache.prototype.getEventTarget = function () {
return window;
};
WindowScrollGeomCache.prototype.computeClientRect = function () {
return {
left: this.scrollLeft,
right: this.scrollLeft + this.clientWidth,
top: this.scrollTop,
bottom: this.scrollTop + this.clientHeight
};
};
// the window is the only scroll object that changes it's rectangle relative
// to the document's topleft as it scrolls
WindowScrollGeomCache.prototype.handleScrollChange = function () {
this.clientRect = this.computeClientRect();
};
return WindowScrollGeomCache;
}(ScrollGeomCache));
// If available we are using native "performance" API instead of "Date"
// Read more about it on MDN:
// https://developer.mozilla.org/en-US/docs/Web/API/Performance
var getTime = typeof performance === 'function' ? performance.now : Date.now;
/*
For a pointer interaction, automatically scrolls certain scroll containers when the pointer
approaches the edge.
The caller must call start + handleMove + stop.
*/
var AutoScroller = /** @class */ (function () {
function AutoScroller() {
var _this = this;
// options that can be set by caller
this.isEnabled = true;
this.scrollQuery = [window, '.fc-scroller'];
this.edgeThreshold = 50; // pixels
this.maxVelocity = 300; // pixels per second
// internal state
this.pointerScreenX = null;
this.pointerScreenY = null;
this.isAnimating = false;
this.scrollCaches = null;
// protect against the initial pointerdown being too close to an edge and starting the scroll
this.everMovedUp = false;
this.everMovedDown = false;
this.everMovedLeft = false;
this.everMovedRight = false;
this.animate = function () {
if (_this.isAnimating) { // wasn't cancelled between animation calls
var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset);
if (edge) {
var now = getTime();
_this.handleSide(edge, (now - _this.msSinceRequest) / 1000);
_this.requestAnimation(now);
}
else {
_this.isAnimating = false; // will stop animation
}
}
};
}
AutoScroller.prototype.start = function (pageX, pageY) {
if (this.isEnabled) {
this.scrollCaches = this.buildCaches();
this.pointerScreenX = null;
this.pointerScreenY = null;
this.everMovedUp = false;
this.everMovedDown = false;
this.everMovedLeft = false;
this.everMovedRight = false;
this.handleMove(pageX, pageY);
}
};
AutoScroller.prototype.handleMove = function (pageX, pageY) {
if (this.isEnabled) {
var pointerScreenX = pageX - window.pageXOffset;
var pointerScreenY = pageY - window.pageYOffset;
var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
if (yDelta < 0) {
this.everMovedUp = true;
}
else if (yDelta > 0) {
this.everMovedDown = true;
}
if (xDelta < 0) {
this.everMovedLeft = true;
}
else if (xDelta > 0) {
this.everMovedRight = true;
}
this.pointerScreenX = pointerScreenX;
this.pointerScreenY = pointerScreenY;
if (!this.isAnimating) {
this.isAnimating = true;
this.requestAnimation(getTime());
}
}
};
AutoScroller.prototype.stop = function () {
if (this.isEnabled) {
this.isAnimating = false; // will stop animation
for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
var scrollCache = _a[_i];
scrollCache.destroy();
}
this.scrollCaches = null;
}
};
AutoScroller.prototype.requestAnimation = function (now) {
this.msSinceRequest = now;
requestAnimationFrame(this.animate);
};
AutoScroller.prototype.handleSide = function (edge, seconds) {
var scrollCache = edge.scrollCache;
var edgeThreshold = this.edgeThreshold;
var invDistance = edgeThreshold - edge.distance;
var velocity = // the closer to the edge, the faster we scroll
(invDistance * invDistance) / (edgeThreshold * edgeThreshold) * // quadratic
this.maxVelocity * seconds;
var sign = 1;
switch (edge.name) {
case 'left':
sign = -1;
// falls through
case 'right':
scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
break;
case 'top':
sign = -1;
// falls through
case 'bottom':
scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
break;
}
};
// left/top are relative to document topleft
AutoScroller.prototype.computeBestEdge = function (left, top) {
var edgeThreshold = this.edgeThreshold;
var bestSide = null;
for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
var scrollCache = _a[_i];
var rect = scrollCache.clientRect;
var leftDist = left - rect.left;
var rightDist = rect.right - left;
var topDist = top - rect.top;
var bottomDist = rect.bottom - top;
// completely within the rect?
if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
(!bestSide || bestSide.distance > topDist)) {
bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist };
}
if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
(!bestSide || bestSide.distance > bottomDist)) {
bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist };
}
if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
(!bestSide || bestSide.distance > leftDist)) {
bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist };
}
if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
(!bestSide || bestSide.distance > rightDist)) {
bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist };
}
}
}
return bestSide;
};
AutoScroller.prototype.buildCaches = function () {
return this.queryScrollEls().map(function (el) {
if (el === window) {
return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
}
else {
return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
}
});
};
AutoScroller.prototype.queryScrollEls = function () {
var els = [];
for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) {
var query = _a[_i];
if (typeof query === 'object') {
els.push(query);
}
else {
els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query)));
}
}
return els;
};
return AutoScroller;
}());
/*
Monitors dragging on an element. Has a number of high-level features:
- minimum distance required before dragging
- minimum wait time ("delay") before dragging
- a mirror element that follows the pointer
*/
var FeaturefulElementDragging = /** @class */ (function (_super) {
__extends(FeaturefulElementDragging, _super);
function FeaturefulElementDragging(containerEl) {
var _this = _super.call(this, containerEl) || this;
// options that can be directly set by caller
// the caller can also set the PointerDragging's options as well
_this.delay = null;
_this.minDistance = 0;
_this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
_this.mirrorNeedsRevert = false;
_this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
_this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
_this.isDelayEnded = false;
_this.isDistanceSurpassed = false;
_this.delayTimeoutId = null;
_this.onPointerDown = function (ev) {
if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going
_this.isInteracting = true;
_this.isDelayEnded = false;
_this.isDistanceSurpassed = false;
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["preventSelection"])(document.body);
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["preventContextMenu"])(document.body);
// prevent links from being visited if there's an eventual drag.
// also prevents selection in older browsers (maybe?).
// not necessary for touch, besides, browser would complain about passiveness.
if (!ev.isTouch) {
ev.origEvent.preventDefault();
}
_this.emitter.trigger('pointerdown', ev);
if (!_this.pointer.shouldIgnoreMove) {
// actions related to initiating dragstart+dragmove+dragend...
_this.mirror.setIsVisible(false); // reset. caller must set-visible
_this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
_this.startDelay(ev);
if (!_this.minDistance) {
_this.handleDistanceSurpassed(ev);
}
}
}
};
_this.onPointerMove = function (ev) {
if (_this.isInteracting) { // if false, still waiting for previous drag's revert
_this.emitter.trigger('pointermove', ev);
if (!_this.isDistanceSurpassed) {
var minDistance = _this.minDistance;
var distanceSq = void 0; // current distance from the origin, squared
var deltaX = ev.deltaX, deltaY = ev.deltaY;
distanceSq = deltaX * deltaX + deltaY * deltaY;
if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
_this.handleDistanceSurpassed(ev);
}
}
if (_this.isDragging) {
// a real pointer move? (not one simulated by scrolling)
if (ev.origEvent.type !== 'scroll') {
_this.mirror.handleMove(ev.pageX, ev.pageY);
_this.autoScroller.handleMove(ev.pageX, ev.pageY);
}
_this.emitter.trigger('dragmove', ev);
}
}
};
_this.onPointerUp = function (ev) {
if (_this.isInteracting) { // if false, still waiting for previous drag's revert
_this.isInteracting = false;
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["allowSelection"])(document.body);
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["allowContextMenu"])(document.body);
_this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
if (_this.isDragging) {
_this.autoScroller.stop();
_this.tryStopDrag(ev); // which will stop the mirror
}
if (_this.delayTimeoutId) {
clearTimeout(_this.delayTimeoutId);
_this.delayTimeoutId = null;
}
}
};
var pointer = _this.pointer = new PointerDragging(containerEl);
pointer.emitter.on('pointerdown', _this.onPointerDown);
pointer.emitter.on('pointermove', _this.onPointerMove);
pointer.emitter.on('pointerup', _this.onPointerUp);
_this.mirror = new ElementMirror();
_this.autoScroller = new AutoScroller();
return _this;
}
FeaturefulElementDragging.prototype.destroy = function () {
this.pointer.destroy();
};
FeaturefulElementDragging.prototype.startDelay = function (ev) {
var _this = this;
if (typeof this.delay === 'number') {
this.delayTimeoutId = setTimeout(function () {
_this.delayTimeoutId = null;
_this.handleDelayEnd(ev);
}, this.delay); // not assignable to number!
}
else {
this.handleDelayEnd(ev);
}
};
FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) {
this.isDelayEnded = true;
this.tryStartDrag(ev);
};
FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) {
this.isDistanceSurpassed = true;
this.tryStartDrag(ev);
};
FeaturefulElementDragging.prototype.tryStartDrag = function (ev) {
if (this.isDelayEnded && this.isDistanceSurpassed) {
if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
this.isDragging = true;
this.mirrorNeedsRevert = false;
this.autoScroller.start(ev.pageX, ev.pageY);
this.emitter.trigger('dragstart', ev);
if (this.touchScrollAllowed === false) {
this.pointer.cancelTouchScroll();
}
}
}
};
FeaturefulElementDragging.prototype.tryStopDrag = function (ev) {
// .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
// that come from the document to fire beforehand. much more convenient this way.
this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev) // bound with args
);
};
FeaturefulElementDragging.prototype.stopDrag = function (ev) {
this.isDragging = false;
this.emitter.trigger('dragend', ev);
};
// fill in the implementations...
FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) {
this.pointer.shouldIgnoreMove = bool;
};
FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) {
this.mirror.setIsVisible(bool);
};
FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) {
this.mirrorNeedsRevert = bool;
};
FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) {
this.autoScroller.isEnabled = bool;
};
return FeaturefulElementDragging;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["ElementDragging"]));
/*
When this class is instantiated, it records the offset of an element (relative to the document topleft),
and continues to monitor scrolling, updating the cached coordinates if it needs to.
Does not access the DOM after instantiation, so highly performant.
Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
and an determine if a given point is inside the combined clipping rectangle.
*/
var OffsetTracker = /** @class */ (function () {
function OffsetTracker(el) {
this.origRect = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(el);
// will work fine for divs that have overflow:hidden
this.scrollCaches = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getClippingParents"])(el).map(function (el) {
return new ElementScrollGeomCache(el, true); // listen=true
});
}
OffsetTracker.prototype.destroy = function () {
for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
var scrollCache = _a[_i];
scrollCache.destroy();
}
};
OffsetTracker.prototype.computeLeft = function () {
var left = this.origRect.left;
for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
var scrollCache = _a[_i];
left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
}
return left;
};
OffsetTracker.prototype.computeTop = function () {
var top = this.origRect.top;
for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
var scrollCache = _a[_i];
top += scrollCache.origScrollTop - scrollCache.getScrollTop();
}
return top;
};
OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) {
var point = { left: pageX, top: pageY };
for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
var scrollCache = _a[_i];
if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
!Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["pointInsideRect"])(point, scrollCache.clientRect)) {
return false;
}
}
return true;
};
return OffsetTracker;
}());
// certain clipping containers should never constrain interactions, like <html> and <body>
// https://github.com/fullcalendar/fullcalendar/issues/3615
function isIgnoredClipping(node) {
var tagName = node.tagName;
return tagName === 'HTML' || tagName === 'BODY';
}
/*
Tracks movement over multiple droppable areas (aka "hits")
that exist in one or more DateComponents.
Relies on an existing draggable.
emits:
- pointerdown
- dragstart
- hitchange - fires initially, even if not over a hit
- pointerup
- (hitchange - again, to null, if ended over a hit)
- dragend
*/
var HitDragging = /** @class */ (function () {
function HitDragging(dragging, droppableStore) {
var _this = this;
// options that can be set by caller
this.useSubjectCenter = false;
this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
this.initialHit = null;
this.movingHit = null;
this.finalHit = null; // won't ever be populated if shouldIgnoreMove
this.handlePointerDown = function (ev) {
var dragging = _this.dragging;
_this.initialHit = null;
_this.movingHit = null;
_this.finalHit = null;
_this.prepareHits();
_this.processFirstCoord(ev);
if (_this.initialHit || !_this.requireInitial) {
dragging.setIgnoreMove(false);
_this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
}
else {
dragging.setIgnoreMove(true);
}
};
this.handleDragStart = function (ev) {
_this.emitter.trigger('dragstart', ev);
_this.handleMove(ev, true); // force = fire even if initially null
};
this.handleDragMove = function (ev) {
_this.emitter.trigger('dragmove', ev);
_this.handleMove(ev);
};
this.handlePointerUp = function (ev) {
_this.releaseHits();
_this.emitter.trigger('pointerup', ev);
};
this.handleDragEnd = function (ev) {
if (_this.movingHit) {
_this.emitter.trigger('hitupdate', null, true, ev);
}
_this.finalHit = _this.movingHit;
_this.movingHit = null;
_this.emitter.trigger('dragend', ev);
};
this.droppableStore = droppableStore;
dragging.emitter.on('pointerdown', this.handlePointerDown);
dragging.emitter.on('dragstart', this.handleDragStart);
dragging.emitter.on('dragmove', this.handleDragMove);
dragging.emitter.on('pointerup', this.handlePointerUp);
dragging.emitter.on('dragend', this.handleDragEnd);
this.dragging = dragging;
this.emitter = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EmitterMixin"]();
}
// sets initialHit
// sets coordAdjust
HitDragging.prototype.processFirstCoord = function (ev) {
var origPoint = { left: ev.pageX, top: ev.pageY };
var adjustedPoint = origPoint;
var subjectEl = ev.subjectEl;
var subjectRect;
if (subjectEl !== document) {
subjectRect = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(subjectEl);
adjustedPoint = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["constrainPoint"])(adjustedPoint, subjectRect);
}
var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
if (initialHit) {
if (this.useSubjectCenter && subjectRect) {
var slicedSubjectRect = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["intersectRects"])(subjectRect, initialHit.rect);
if (slicedSubjectRect) {
adjustedPoint = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getRectCenter"])(slicedSubjectRect);
}
}
this.coordAdjust = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffPoints"])(adjustedPoint, origPoint);
}
else {
this.coordAdjust = { left: 0, top: 0 };
}
};
HitDragging.prototype.handleMove = function (ev, forceHandle) {
var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
this.movingHit = hit;
this.emitter.trigger('hitupdate', hit, false, ev);
}
};
HitDragging.prototype.prepareHits = function () {
this.offsetTrackers = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["mapHash"])(this.droppableStore, function (interactionSettings) {
interactionSettings.component.buildPositionCaches();
return new OffsetTracker(interactionSettings.el);
});
};
HitDragging.prototype.releaseHits = function () {
var offsetTrackers = this.offsetTrackers;
for (var id in offsetTrackers) {
offsetTrackers[id].destroy();
}
this.offsetTrackers = {};
};
HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) {
var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers;
var bestHit = null;
for (var id in droppableStore) {
var component = droppableStore[id].component;
var offsetTracker = offsetTrackers[id];
if (offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
var originLeft = offsetTracker.computeLeft();
var originTop = offsetTracker.computeTop();
var positionLeft = offsetLeft - originLeft;
var positionTop = offsetTop - originTop;
var origRect = offsetTracker.origRect;
var width = origRect.right - origRect.left;
var height = origRect.bottom - origRect.top;
if (
// must be within the element's bounds
positionLeft >= 0 && positionLeft < width &&
positionTop >= 0 && positionTop < height) {
var hit = component.queryHit(positionLeft, positionTop, width, height);
if (hit &&
(
// make sure the hit is within activeRange, meaning it's not a deal cell
!component.props.dateProfile || // hack for DayTile
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["rangeContainsRange"])(component.props.dateProfile.activeRange, hit.dateSpan.range)) &&
(!bestHit || hit.layer > bestHit.layer)) {
// TODO: better way to re-orient rectangle
hit.rect.left += originLeft;
hit.rect.right += originLeft;
hit.rect.top += originTop;
hit.rect.bottom += originTop;
bestHit = hit;
}
}
}
}
return bestHit;
};
return HitDragging;
}());
function isHitsEqual(hit0, hit1) {
if (!hit0 && !hit1) {
return true;
}
if (Boolean(hit0) !== Boolean(hit1)) {
return false;
}
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["isDateSpansEqual"])(hit0.dateSpan, hit1.dateSpan);
}
/*
Monitors when the user clicks on a specific date/time of a component.
A pointerdown+pointerup on the same "hit" constitutes a click.
*/
var DateClicking = /** @class */ (function (_super) {
__extends(DateClicking, _super);
function DateClicking(settings) {
var _this = _super.call(this, settings) || this;
_this.handlePointerDown = function (ev) {
var dragging = _this.dragging;
// do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
dragging.setIgnoreMove(!_this.component.isValidDateDownEl(dragging.pointer.downEl));
};
// won't even fire if moving was ignored
_this.handleDragEnd = function (ev) {
var component = _this.component;
var _a = component.context, calendar = _a.calendar, view = _a.view;
var pointer = _this.dragging.pointer;
if (!pointer.wasTouchScroll) {
var _b = _this.hitDragging, initialHit = _b.initialHit, finalHit = _b.finalHit;
if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
calendar.triggerDateClick(initialHit.dateSpan, initialHit.dayEl, view, ev.origEvent);
}
}
};
var component = settings.component;
// we DO want to watch pointer moves because otherwise finalHit won't get populated
_this.dragging = new FeaturefulElementDragging(component.el);
_this.dragging.autoScroller.isEnabled = false;
var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsToStore"])(settings));
hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
hitDragging.emitter.on('dragend', _this.handleDragEnd);
return _this;
}
DateClicking.prototype.destroy = function () {
this.dragging.destroy();
};
return DateClicking;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"]));
/*
Tracks when the user selects a portion of time of a component,
constituted by a drag over date cells, with a possible delay at the beginning of the drag.
*/
var DateSelecting = /** @class */ (function (_super) {
__extends(DateSelecting, _super);
function DateSelecting(settings) {
var _this = _super.call(this, settings) || this;
_this.dragSelection = null;
_this.handlePointerDown = function (ev) {
var _a = _this, component = _a.component, dragging = _a.dragging;
var options = component.context.options;
var canSelect = options.selectable &&
component.isValidDateDownEl(ev.origEvent.target);
// don't bother to watch expensive moves if component won't do selection
dragging.setIgnoreMove(!canSelect);
// if touch, require user to hold down
dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null;
};
_this.handleDragStart = function (ev) {
_this.component.context.calendar.unselect(ev); // unselect previous selections
};
_this.handleHitUpdate = function (hit, isFinal) {
var calendar = _this.component.context.calendar;
var dragSelection = null;
var isInvalid = false;
if (hit) {
dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, calendar.pluginSystem.hooks.dateSelectionTransformers);
if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) {
isInvalid = true;
dragSelection = null;
}
}
if (dragSelection) {
calendar.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
}
else if (!isFinal) { // only unselect if moved away while dragging
calendar.dispatch({ type: 'UNSELECT_DATES' });
}
if (!isInvalid) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])();
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])();
}
if (!isFinal) {
_this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
}
};
_this.handlePointerUp = function (pev) {
if (_this.dragSelection) {
// selection is already rendered, so just need to report selection
_this.component.context.calendar.triggerDateSelect(_this.dragSelection, pev);
_this.dragSelection = null;
}
};
var component = settings.component;
var options = component.context.options;
var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
dragging.touchScrollAllowed = false;
dragging.minDistance = options.selectMinDistance || 0;
dragging.autoScroller.isEnabled = options.dragScroll;
var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsToStore"])(settings));
hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
hitDragging.emitter.on('dragstart', _this.handleDragStart);
hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
hitDragging.emitter.on('pointerup', _this.handlePointerUp);
return _this;
}
DateSelecting.prototype.destroy = function () {
this.dragging.destroy();
};
return DateSelecting;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"]));
function getComponentTouchDelay(component) {
var options = component.context.options;
var delay = options.selectLongPressDelay;
if (delay == null) {
delay = options.longPressDelay;
}
return delay;
}
function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
var dateSpan0 = hit0.dateSpan;
var dateSpan1 = hit1.dateSpan;
var ms = [
dateSpan0.range.start,
dateSpan0.range.end,
dateSpan1.range.start,
dateSpan1.range.end
];
ms.sort(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["compareNumbers"]);
var props = {};
for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) {
var transformer = dateSelectionTransformers_1[_i];
var res = transformer(hit0, hit1);
if (res === false) {
return null;
}
else if (res) {
__assign(props, res);
}
}
props.range = { start: ms[0], end: ms[3] };
props.allDay = dateSpan0.allDay;
return props;
}
var EventDragging = /** @class */ (function (_super) {
__extends(EventDragging, _super);
function EventDragging(settings) {
var _this = _super.call(this, settings) || this;
// internal state
_this.subjectSeg = null; // the seg being selected/dragged
_this.isDragging = false;
_this.eventRange = null;
_this.relevantEvents = null; // the events being dragged
_this.receivingCalendar = null;
_this.validMutation = null;
_this.mutatedRelevantEvents = null;
_this.handlePointerDown = function (ev) {
var origTarget = ev.origEvent.target;
var _a = _this, component = _a.component, dragging = _a.dragging;
var mirror = dragging.mirror;
var options = component.context.options;
var initialCalendar = component.context.calendar;
var subjectSeg = _this.subjectSeg = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getElSeg"])(ev.subjectEl);
var eventRange = _this.eventRange = subjectSeg.eventRange;
var eventInstanceId = eventRange.instance.instanceId;
_this.relevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getRelevantEvents"])(initialCalendar.state.eventStore, eventInstanceId);
dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
dragging.delay =
// only do a touch delay if touch and this event hasn't been selected yet
(ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
getComponentTouchDelay$1(component) :
null;
mirror.parentNode = initialCalendar.el;
mirror.revertDuration = options.dragRevertDuration;
var isValid = component.isValidSegDownEl(origTarget) &&
!Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(origTarget, '.fc-resizer'); // NOT on a resizer
dragging.setIgnoreMove(!isValid);
// disable dragging for elements that are resizable (ie, selectable)
// but are not draggable
_this.isDragging = isValid &&
ev.subjectEl.classList.contains('fc-draggable');
};
_this.handleDragStart = function (ev) {
var context = _this.component.context;
var initialCalendar = context.calendar;
var eventRange = _this.eventRange;
var eventInstanceId = eventRange.instance.instanceId;
if (ev.isTouch) {
// need to select a different event?
if (eventInstanceId !== _this.component.props.eventSelection) {
initialCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId });
}
}
else {
// if now using mouse, but was previous touch interaction, clear selected event
initialCalendar.dispatch({ type: 'UNSELECT_EVENT' });
}
if (_this.isDragging) {
initialCalendar.unselect(ev); // unselect *date* selection
initialCalendar.publiclyTrigger('eventDragStart', [
{
el: _this.subjectSeg.el,
event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](initialCalendar, eventRange.def, eventRange.instance),
jsEvent: ev.origEvent,
view: context.view
}
]);
}
};
_this.handleHitUpdate = function (hit, isFinal) {
if (!_this.isDragging) {
return;
}
var relevantEvents = _this.relevantEvents;
var initialHit = _this.hitDragging.initialHit;
var initialCalendar = _this.component.context.calendar;
// states based on new hit
var receivingCalendar = null;
var mutation = null;
var mutatedRelevantEvents = null;
var isInvalid = false;
var interaction = {
affectedEvents: relevantEvents,
mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(),
isEvent: true,
origSeg: _this.subjectSeg
};
if (hit) {
var receivingComponent = hit.component;
receivingCalendar = receivingComponent.context.calendar;
var receivingOptions = receivingComponent.context.options;
if (initialCalendar === receivingCalendar ||
receivingOptions.editable && receivingOptions.droppable) {
mutation = computeEventMutation(initialHit, hit, receivingCalendar.pluginSystem.hooks.eventDragMutationMassagers);
if (mutation) {
mutatedRelevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyMutationToEventStore"])(relevantEvents, receivingCalendar.eventUiBases, mutation, receivingCalendar);
interaction.mutatedEvents = mutatedRelevantEvents;
if (!receivingComponent.isInteractionValid(interaction)) {
isInvalid = true;
mutation = null;
mutatedRelevantEvents = null;
interaction.mutatedEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])();
}
}
}
else {
receivingCalendar = null;
}
}
_this.displayDrag(receivingCalendar, interaction);
if (!isInvalid) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])();
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])();
}
if (!isFinal) {
if (initialCalendar === receivingCalendar && // TODO: write test for this
isHitsEqual(initialHit, hit)) {
mutation = null;
}
_this.dragging.setMirrorNeedsRevert(!mutation);
// render the mirror if no already-rendered mirror
// TODO: wish we could somehow wait for dispatch to guarantee render
_this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-mirror'));
// assign states based on new hit
_this.receivingCalendar = receivingCalendar;
_this.validMutation = mutation;
_this.mutatedRelevantEvents = mutatedRelevantEvents;
}
};
_this.handlePointerUp = function () {
if (!_this.isDragging) {
_this.cleanup(); // because handleDragEnd won't fire
}
};
_this.handleDragEnd = function (ev) {
if (_this.isDragging) {
var context = _this.component.context;
var initialCalendar_1 = context.calendar;
var initialView = context.view;
var _a = _this, receivingCalendar = _a.receivingCalendar, validMutation = _a.validMutation;
var eventDef = _this.eventRange.def;
var eventInstance = _this.eventRange.instance;
var eventApi = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](initialCalendar_1, eventDef, eventInstance);
var relevantEvents_1 = _this.relevantEvents;
var mutatedRelevantEvents = _this.mutatedRelevantEvents;
var finalHit = _this.hitDragging.finalHit;
_this.clearDrag(); // must happen after revert animation
initialCalendar_1.publiclyTrigger('eventDragStop', [
{
el: _this.subjectSeg.el,
event: eventApi,
jsEvent: ev.origEvent,
view: initialView
}
]);
if (validMutation) {
// dropped within same calendar
if (receivingCalendar === initialCalendar_1) {
initialCalendar_1.dispatch({
type: 'MERGE_EVENTS',
eventStore: mutatedRelevantEvents
});
var transformed = {};
for (var _i = 0, _b = initialCalendar_1.pluginSystem.hooks.eventDropTransformers; _i < _b.length; _i++) {
var transformer = _b[_i];
__assign(transformed, transformer(validMutation, initialCalendar_1));
}
var eventDropArg = __assign({}, transformed, { el: ev.subjectEl, delta: validMutation.datesDelta, oldEvent: eventApi, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](// the data AFTER the mutation
initialCalendar_1, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () {
initialCalendar_1.dispatch({
type: 'MERGE_EVENTS',
eventStore: relevantEvents_1
});
}, jsEvent: ev.origEvent, view: initialView });
initialCalendar_1.publiclyTrigger('eventDrop', [eventDropArg]);
// dropped in different calendar
}
else if (receivingCalendar) {
initialCalendar_1.publiclyTrigger('eventLeave', [
{
draggedEl: ev.subjectEl,
event: eventApi,
view: initialView
}
]);
initialCalendar_1.dispatch({
type: 'REMOVE_EVENT_INSTANCES',
instances: _this.mutatedRelevantEvents.instances
});
receivingCalendar.dispatch({
type: 'MERGE_EVENTS',
eventStore: _this.mutatedRelevantEvents
});
if (ev.isTouch) {
receivingCalendar.dispatch({
type: 'SELECT_EVENT',
eventInstanceId: eventInstance.instanceId
});
}
var dropArg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component // should this be finalHit.component.view? See #4644
});
receivingCalendar.publiclyTrigger('drop', [dropArg]);
receivingCalendar.publiclyTrigger('eventReceive', [
{
draggedEl: ev.subjectEl,
event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](// the data AFTER the mutation
receivingCalendar, mutatedRelevantEvents.defs[eventDef.defId], mutatedRelevantEvents.instances[eventInstance.instanceId]),
view: finalHit.component // should this be finalHit.component.view? See #4644
}
]);
}
}
else {
initialCalendar_1.publiclyTrigger('_noEventDrop');
}
}
_this.cleanup();
};
var component = _this.component;
var options = component.context.options;
var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
dragging.pointer.selector = EventDragging.SELECTOR;
dragging.touchScrollAllowed = false;
dragging.autoScroller.isEnabled = options.dragScroll;
var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsStore"]);
hitDragging.useSubjectCenter = settings.useEventCenter;
hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
hitDragging.emitter.on('dragstart', _this.handleDragStart);
hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
hitDragging.emitter.on('pointerup', _this.handlePointerUp);
hitDragging.emitter.on('dragend', _this.handleDragEnd);
return _this;
}
EventDragging.prototype.destroy = function () {
this.dragging.destroy();
};
// render a drag state on the next receivingCalendar
EventDragging.prototype.displayDrag = function (nextCalendar, state) {
var initialCalendar = this.component.context.calendar;
var prevCalendar = this.receivingCalendar;
// does the previous calendar need to be cleared?
if (prevCalendar && prevCalendar !== nextCalendar) {
// does the initial calendar need to be cleared?
// if so, don't clear all the way. we still need to to hide the affectedEvents
if (prevCalendar === initialCalendar) {
prevCalendar.dispatch({
type: 'SET_EVENT_DRAG',
state: {
affectedEvents: state.affectedEvents,
mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(),
isEvent: true,
origSeg: state.origSeg
}
});
// completely clear the old calendar if it wasn't the initial
}
else {
prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
}
}
if (nextCalendar) {
nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state });
}
};
EventDragging.prototype.clearDrag = function () {
var initialCalendar = this.component.context.calendar;
var receivingCalendar = this.receivingCalendar;
if (receivingCalendar) {
receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
}
// the initial calendar might have an dummy drag state from displayDrag
if (initialCalendar !== receivingCalendar) {
initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
}
};
EventDragging.prototype.cleanup = function () {
this.subjectSeg = null;
this.isDragging = false;
this.eventRange = null;
this.relevantEvents = null;
this.receivingCalendar = null;
this.validMutation = null;
this.mutatedRelevantEvents = null;
};
EventDragging.SELECTOR = '.fc-draggable, .fc-resizable'; // TODO: test this in IE11
return EventDragging;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"]));
function computeEventMutation(hit0, hit1, massagers) {
var dateSpan0 = hit0.dateSpan;
var dateSpan1 = hit1.dateSpan;
var date0 = dateSpan0.range.start;
var date1 = dateSpan1.range.start;
var standardProps = {};
if (dateSpan0.allDay !== dateSpan1.allDay) {
standardProps.allDay = dateSpan1.allDay;
standardProps.hasEnd = hit1.component.context.options.allDayMaintainDuration;
if (dateSpan1.allDay) {
// means date1 is already start-of-day,
// but date0 needs to be converted
date0 = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["startOfDay"])(date0);
}
}
var delta = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffDates"])(date0, date1, hit0.component.context.dateEnv, hit0.component === hit1.component ?
hit0.component.largeUnit :
null);
if (delta.milliseconds) { // has hours/minutes/seconds
standardProps.allDay = false;
}
var mutation = {
datesDelta: delta,
standardProps: standardProps
};
for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) {
var massager = massagers_1[_i];
massager(mutation, hit0, hit1);
}
return mutation;
}
function getComponentTouchDelay$1(component) {
var options = component.context.options;
var delay = options.eventLongPressDelay;
if (delay == null) {
delay = options.longPressDelay;
}
return delay;
}
var EventDragging$1 = /** @class */ (function (_super) {
__extends(EventDragging, _super);
function EventDragging(settings) {
var _this = _super.call(this, settings) || this;
// internal state
_this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
_this.eventRange = null;
_this.relevantEvents = null;
_this.validMutation = null;
_this.mutatedRelevantEvents = null;
_this.handlePointerDown = function (ev) {
var component = _this.component;
var seg = _this.querySeg(ev);
var eventRange = _this.eventRange = seg.eventRange;
_this.dragging.minDistance = component.context.options.eventDragMinDistance;
// if touch, need to be working with a selected event
_this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) ||
(ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId));
};
_this.handleDragStart = function (ev) {
var _a = _this.component.context, calendar = _a.calendar, view = _a.view;
var eventRange = _this.eventRange;
_this.relevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getRelevantEvents"])(calendar.state.eventStore, _this.eventRange.instance.instanceId);
_this.draggingSeg = _this.querySeg(ev);
calendar.unselect();
calendar.publiclyTrigger('eventResizeStart', [
{
el: _this.draggingSeg.el,
event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](calendar, eventRange.def, eventRange.instance),
jsEvent: ev.origEvent,
view: view
}
]);
};
_this.handleHitUpdate = function (hit, isFinal, ev) {
var calendar = _this.component.context.calendar;
var relevantEvents = _this.relevantEvents;
var initialHit = _this.hitDragging.initialHit;
var eventInstance = _this.eventRange.instance;
var mutation = null;
var mutatedRelevantEvents = null;
var isInvalid = false;
var interaction = {
affectedEvents: relevantEvents,
mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(),
isEvent: true,
origSeg: _this.draggingSeg
};
if (hit) {
mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-start-resizer'), eventInstance.range, calendar.pluginSystem.hooks.eventResizeJoinTransforms);
}
if (mutation) {
mutatedRelevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyMutationToEventStore"])(relevantEvents, calendar.eventUiBases, mutation, calendar);
interaction.mutatedEvents = mutatedRelevantEvents;
if (!_this.component.isInteractionValid(interaction)) {
isInvalid = true;
mutation = null;
mutatedRelevantEvents = null;
interaction.mutatedEvents = null;
}
}
if (mutatedRelevantEvents) {
calendar.dispatch({
type: 'SET_EVENT_RESIZE',
state: interaction
});
}
else {
calendar.dispatch({ type: 'UNSET_EVENT_RESIZE' });
}
if (!isInvalid) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])();
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])();
}
if (!isFinal) {
if (mutation && isHitsEqual(initialHit, hit)) {
mutation = null;
}
_this.validMutation = mutation;
_this.mutatedRelevantEvents = mutatedRelevantEvents;
}
};
_this.handleDragEnd = function (ev) {
var _a = _this.component.context, calendar = _a.calendar, view = _a.view;
var eventDef = _this.eventRange.def;
var eventInstance = _this.eventRange.instance;
var eventApi = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](calendar, eventDef, eventInstance);
var relevantEvents = _this.relevantEvents;
var mutatedRelevantEvents = _this.mutatedRelevantEvents;
calendar.publiclyTrigger('eventResizeStop', [
{
el: _this.draggingSeg.el,
event: eventApi,
jsEvent: ev.origEvent,
view: view
}
]);
if (_this.validMutation) {
calendar.dispatch({
type: 'MERGE_EVENTS',
eventStore: mutatedRelevantEvents
});
calendar.publiclyTrigger('eventResize', [
{
el: _this.draggingSeg.el,
startDelta: _this.validMutation.startDelta || Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createDuration"])(0),
endDelta: _this.validMutation.endDelta || Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createDuration"])(0),
prevEvent: eventApi,
event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](// the data AFTER the mutation
calendar, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null),
revert: function () {
calendar.dispatch({
type: 'MERGE_EVENTS',
eventStore: relevantEvents
});
},
jsEvent: ev.origEvent,
view: view
}
]);
}
else {
calendar.publiclyTrigger('_noEventResize');
}
// reset all internal state
_this.draggingSeg = null;
_this.relevantEvents = null;
_this.validMutation = null;
// okay to keep eventInstance around. useful to set it in handlePointerDown
};
var component = settings.component;
var dragging = _this.dragging = new FeaturefulElementDragging(component.el);
dragging.pointer.selector = '.fc-resizer';
dragging.touchScrollAllowed = false;
dragging.autoScroller.isEnabled = component.context.options.dragScroll;
var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsToStore"])(settings));
hitDragging.emitter.on('pointerdown', _this.handlePointerDown);
hitDragging.emitter.on('dragstart', _this.handleDragStart);
hitDragging.emitter.on('hitupdate', _this.handleHitUpdate);
hitDragging.emitter.on('dragend', _this.handleDragEnd);
return _this;
}
EventDragging.prototype.destroy = function () {
this.dragging.destroy();
};
EventDragging.prototype.querySeg = function (ev) {
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getElSeg"])(Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(ev.subjectEl, this.component.fgSegSelector));
};
return EventDragging;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"]));
function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) {
var dateEnv = hit0.component.context.dateEnv;
var date0 = hit0.dateSpan.range.start;
var date1 = hit1.dateSpan.range.start;
var delta = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffDates"])(date0, date1, dateEnv, hit0.component.largeUnit);
var props = {};
for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) {
var transform = transforms_1[_i];
var res = transform(hit0, hit1);
if (res === false) {
return null;
}
else if (res) {
__assign(props, res);
}
}
if (isFromStart) {
if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
props.startDelta = delta;
return props;
}
}
else {
if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
props.endDelta = delta;
return props;
}
}
return null;
}
var UnselectAuto = /** @class */ (function () {
function UnselectAuto(calendar) {
var _this = this;
this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
this.onSelect = function (selectInfo) {
if (selectInfo.jsEvent) {
_this.isRecentPointerDateSelect = true;
}
};
this.onDocumentPointerUp = function (pev) {
var _a = _this, calendar = _a.calendar, documentPointer = _a.documentPointer;
var state = calendar.state;
// touch-scrolling should never unfocus any type of selection
if (!documentPointer.wasTouchScroll) {
if (state.dateSelection && // an existing date selection?
!_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
) {
var unselectAuto = calendar.viewOpt('unselectAuto');
var unselectCancel = calendar.viewOpt('unselectCancel');
if (unselectAuto && (!unselectAuto || !Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(documentPointer.downEl, unselectCancel))) {
calendar.unselect(pev);
}
}
if (state.eventSelection && // an existing event selected?
!Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(documentPointer.downEl, EventDragging.SELECTOR) // interaction DIDN'T start on an event
) {
calendar.dispatch({ type: 'UNSELECT_EVENT' });
}
}
_this.isRecentPointerDateSelect = false;
};
this.calendar = calendar;
var documentPointer = this.documentPointer = new PointerDragging(document);
documentPointer.shouldIgnoreMove = true;
documentPointer.shouldWatchScroll = false;
documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
/*
TODO: better way to know about whether there was a selection with the pointer
*/
calendar.on('select', this.onSelect);
}
UnselectAuto.prototype.destroy = function () {
this.calendar.off('select', this.onSelect);
this.documentPointer.destroy();
};
return UnselectAuto;
}());
/*
Given an already instantiated draggable object for one-or-more elements,
Interprets any dragging as an attempt to drag an events that lives outside
of a calendar onto a calendar.
*/
var ExternalElementDragging = /** @class */ (function () {
function ExternalElementDragging(dragging, suppliedDragMeta) {
var _this = this;
this.receivingCalendar = null;
this.droppableEvent = null; // will exist for all drags, even if create:false
this.suppliedDragMeta = null;
this.dragMeta = null;
this.handleDragStart = function (ev) {
_this.dragMeta = _this.buildDragMeta(ev.subjectEl);
};
this.handleHitUpdate = function (hit, isFinal, ev) {
var dragging = _this.hitDragging.dragging;
var receivingCalendar = null;
var droppableEvent = null;
var isInvalid = false;
var interaction = {
affectedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(),
mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(),
isEvent: _this.dragMeta.create,
origSeg: null
};
if (hit) {
receivingCalendar = hit.component.context.calendar;
if (_this.canDropElOnCalendar(ev.subjectEl, receivingCalendar)) {
droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingCalendar);
interaction.mutatedEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["eventTupleToStore"])(droppableEvent);
isInvalid = !Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["isInteractionValid"])(interaction, receivingCalendar);
if (isInvalid) {
interaction.mutatedEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])();
droppableEvent = null;
}
}
}
_this.displayDrag(receivingCalendar, interaction);
// show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
// TODO: wish we could somehow wait for dispatch to guarantee render
dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-mirror'));
if (!isInvalid) {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])();
}
else {
Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])();
}
if (!isFinal) {
dragging.setMirrorNeedsRevert(!droppableEvent);
_this.receivingCalendar = receivingCalendar;
_this.droppableEvent = droppableEvent;
}
};
this.handleDragEnd = function (pev) {
var _a = _this, receivingCalendar = _a.receivingCalendar, droppableEvent = _a.droppableEvent;
_this.clearDrag();
if (receivingCalendar && droppableEvent) {
var finalHit = _this.hitDragging.finalHit;
var finalView = finalHit.component.context.view;
var dragMeta = _this.dragMeta;
var arg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView });
receivingCalendar.publiclyTrigger('drop', [arg]);
if (dragMeta.create) {
receivingCalendar.dispatch({
type: 'MERGE_EVENTS',
eventStore: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["eventTupleToStore"])(droppableEvent)
});
if (pev.isTouch) {
receivingCalendar.dispatch({
type: 'SELECT_EVENT',
eventInstanceId: droppableEvent.instance.instanceId
});
}
// signal that an external event landed
receivingCalendar.publiclyTrigger('eventReceive', [
{
draggedEl: pev.subjectEl,
event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](receivingCalendar, droppableEvent.def, droppableEvent.instance),
view: finalView
}
]);
}
}
_this.receivingCalendar = null;
_this.droppableEvent = null;
};
var hitDragging = this.hitDragging = new HitDragging(dragging, _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsStore"]);
hitDragging.requireInitial = false; // will start outside of a component
hitDragging.emitter.on('dragstart', this.handleDragStart);
hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
hitDragging.emitter.on('dragend', this.handleDragEnd);
this.suppliedDragMeta = suppliedDragMeta;
}
ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) {
if (typeof this.suppliedDragMeta === 'object') {
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseDragMeta"])(this.suppliedDragMeta);
}
else if (typeof this.suppliedDragMeta === 'function') {
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseDragMeta"])(this.suppliedDragMeta(subjectEl));
}
else {
return getDragMetaFromEl(subjectEl);
}
};
ExternalElementDragging.prototype.displayDrag = function (nextCalendar, state) {
var prevCalendar = this.receivingCalendar;
if (prevCalendar && prevCalendar !== nextCalendar) {
prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
}
if (nextCalendar) {
nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state });
}
};
ExternalElementDragging.prototype.clearDrag = function () {
if (this.receivingCalendar) {
this.receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
}
};
ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingCalendar) {
var dropAccept = receivingCalendar.opt('dropAccept');
if (typeof dropAccept === 'function') {
return dropAccept(el);
}
else if (typeof dropAccept === 'string' && dropAccept) {
return Boolean(Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementMatches"])(el, dropAccept));
}
return true;
};
return ExternalElementDragging;
}());
// Utils for computing event store from the DragMeta
// ----------------------------------------------------------------------------------------------------
function computeEventForDateSpan(dateSpan, dragMeta, calendar) {
var defProps = __assign({}, dragMeta.leftoverProps);
for (var _i = 0, _a = calendar.pluginSystem.hooks.externalDefTransforms; _i < _a.length; _i++) {
var transform = _a[_i];
__assign(defProps, transform(dateSpan, dragMeta));
}
var def = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseEventDef"])(defProps, dragMeta.sourceId, dateSpan.allDay, calendar.opt('forceEventDuration') || Boolean(dragMeta.duration), // hasEnd
calendar);
var start = dateSpan.range.start;
// only rely on time info if drop zone is all-day,
// otherwise, we already know the time
if (dateSpan.allDay && dragMeta.startTime) {
start = calendar.dateEnv.add(start, dragMeta.startTime);
}
var end = dragMeta.duration ?
calendar.dateEnv.add(start, dragMeta.duration) :
calendar.getDefaultEventEnd(dateSpan.allDay, start);
var instance = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEventInstance"])(def.defId, { start: start, end: end });
return { def: def, instance: instance };
}
// Utils for extracting data from element
// ----------------------------------------------------------------------------------------------------
function getDragMetaFromEl(el) {
var str = getEmbeddedElData(el, 'event');
var obj = str ?
JSON.parse(str) :
{ create: false }; // if no embedded data, assume no event creation
return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseDragMeta"])(obj);
}
_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["config"].dataAttrPrefix = '';
function getEmbeddedElData(el, name) {
var prefix = _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["config"].dataAttrPrefix;
var prefixedName = (prefix ? prefix + '-' : '') + name;
return el.getAttribute('data-' + prefixedName) || '';
}
/*
Makes an element (that is *external* to any calendar) draggable.
Can pass in data that determines how an event will be created when dropped onto a calendar.
Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
*/
var ExternalDraggable = /** @class */ (function () {
function ExternalDraggable(el, settings) {
var _this = this;
if (settings === void 0) { settings = {}; }
this.handlePointerDown = function (ev) {
var dragging = _this.dragging;
var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay;
dragging.minDistance =
minDistance != null ?
minDistance :
(ev.isTouch ? 0 : _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["globalDefaults"].eventDragMinDistance);
dragging.delay =
ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
(longPressDelay != null ? longPressDelay : _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["globalDefaults"].longPressDelay) :
0;
};
this.handleDragStart = function (ev) {
if (ev.isTouch &&
_this.dragging.delay &&
ev.subjectEl.classList.contains('fc-event')) {
_this.dragging.mirror.getMirrorEl().classList.add('fc-selected');
}
};
this.settings = settings;
var dragging = this.dragging = new FeaturefulElementDragging(el);
dragging.touchScrollAllowed = false;
if (settings.itemSelector != null) {
dragging.pointer.selector = settings.itemSelector;
}
if (settings.appendTo != null) {
dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
}
dragging.emitter.on('pointerdown', this.handlePointerDown);
dragging.emitter.on('dragstart', this.handleDragStart);
new ExternalElementDragging(dragging, settings.eventData);
}
ExternalDraggable.prototype.destroy = function () {
this.dragging.destroy();
};
return ExternalDraggable;
}());
/*
Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
The third-party system is responsible for drawing the visuals effects of the drag.
This class simply monitors for pointer movements and fires events.
It also has the ability to hide the moving element (the "mirror") during the drag.
*/
var InferredElementDragging = /** @class */ (function (_super) {
__extends(InferredElementDragging, _super);
function InferredElementDragging(containerEl) {
var _this = _super.call(this, containerEl) || this;
_this.shouldIgnoreMove = false;
_this.mirrorSelector = '';
_this.currentMirrorEl = null;
_this.handlePointerDown = function (ev) {
_this.emitter.trigger('pointerdown', ev);
if (!_this.shouldIgnoreMove) {
// fire dragstart right away. does not support delay or min-distance
_this.emitter.trigger('dragstart', ev);
}
};
_this.handlePointerMove = function (ev) {
if (!_this.shouldIgnoreMove) {
_this.emitter.trigger('dragmove', ev);
}
};
_this.handlePointerUp = function (ev) {
_this.emitter.trigger('pointerup', ev);
if (!_this.shouldIgnoreMove) {
// fire dragend right away. does not support a revert animation
_this.emitter.trigger('dragend', ev);
}
};
var pointer = _this.pointer = new PointerDragging(containerEl);
pointer.emitter.on('pointerdown', _this.handlePointerDown);
pointer.emitter.on('pointermove', _this.handlePointerMove);
pointer.emitter.on('pointerup', _this.handlePointerUp);
return _this;
}
InferredElementDragging.prototype.destroy = function () {
this.pointer.destroy();
};
InferredElementDragging.prototype.setIgnoreMove = function (bool) {
this.shouldIgnoreMove = bool;
};
InferredElementDragging.prototype.setMirrorIsVisible = function (bool) {
if (bool) {
// restore a previously hidden element.
// use the reference in case the selector class has already been removed.
if (this.currentMirrorEl) {
this.currentMirrorEl.style.visibility = '';
this.currentMirrorEl = null;
}
}
else {
var mirrorEl = this.mirrorSelector ?
document.querySelector(this.mirrorSelector) :
null;
if (mirrorEl) {
this.currentMirrorEl = mirrorEl;
mirrorEl.style.visibility = 'hidden';
}
}
};
return InferredElementDragging;
}(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["ElementDragging"]));
/*
Bridges third-party drag-n-drop systems with FullCalendar.
Must be instantiated and destroyed by caller.
*/
var ThirdPartyDraggable = /** @class */ (function () {
function ThirdPartyDraggable(containerOrSettings, settings) {
var containerEl = document;
if (
// wish we could just test instanceof EventTarget, but doesn't work in IE11
containerOrSettings === document ||
containerOrSettings instanceof Element) {
containerEl = containerOrSettings;
settings = settings || {};
}
else {
settings = (containerOrSettings || {});
}
var dragging = this.dragging = new InferredElementDragging(containerEl);
if (typeof settings.itemSelector === 'string') {
dragging.pointer.selector = settings.itemSelector;
}
else if (containerEl === document) {
dragging.pointer.selector = '[data-event]';
}
if (typeof settings.mirrorSelector === 'string') {
dragging.mirrorSelector = settings.mirrorSelector;
}
new ExternalElementDragging(dragging, settings.eventData);
}
ThirdPartyDraggable.prototype.destroy = function () {
this.dragging.destroy();
};
return ThirdPartyDraggable;
}());
var main = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createPlugin"])({
componentInteractions: [DateClicking, DateSelecting, EventDragging, EventDragging$1],
calendarInteractions: [UnselectAuto],
elementDraggingImpl: FeaturefulElementDragging
});
/* harmony default export */ __webpack_exports__["default"] = (main);
/***/ }),
/***/ "./node_modules/core-js/internals/a-callable.js":
/*!******************************************************!*\
!*** ./node_modules/core-js/internals/a-callable.js ***!
\******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var tryToString = __webpack_require__(/*! ../internals/try-to-string */ "./node_modules/core-js/internals/try-to-string.js");
var $TypeError = TypeError;
// `Assert: IsCallable(argument) is true`
module.exports = function (argument) {
if (isCallable(argument)) return argument;
throw new $TypeError(tryToString(argument) + ' is not a function');
};
/***/ }),
/***/ "./node_modules/core-js/internals/an-object.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/an-object.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
var $String = String;
var $TypeError = TypeError;
// `Assert: Type(argument) is Object`
module.exports = function (argument) {
if (isObject(argument)) return argument;
throw new $TypeError($String(argument) + ' is not an object');
};
/***/ }),
/***/ "./node_modules/core-js/internals/classof-raw.js":
/*!*******************************************************!*\
!*** ./node_modules/core-js/internals/classof-raw.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
var toString = uncurryThis({}.toString);
var stringSlice = uncurryThis(''.slice);
module.exports = function (it) {
return stringSlice(toString(it), 8, -1);
};
/***/ }),
/***/ "./node_modules/core-js/internals/classof.js":
/*!***************************************************!*\
!*** ./node_modules/core-js/internals/classof.js ***!
\***************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var classofRaw = __webpack_require__(/*! ../internals/classof-raw */ "./node_modules/core-js/internals/classof-raw.js");
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ "./node_modules/core-js/internals/well-known-symbol.js");
var TO_STRING_TAG = wellKnownSymbol('toStringTag');
var $Object = Object;
// ES3 wrong here
var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) === 'Arguments';
// fallback for IE11 Script Access Denied error
var tryGet = function (it, key) {
try {
return it[key];
} catch (error) { /* empty */ }
};
// getting tag from ES6+ `Object.prototype.toString`
module.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {
var O, tag, result;
return it === undefined ? 'Undefined' : it === null ? 'Null'
// @@toStringTag case
: typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag
// builtinTag case
: CORRECT_ARGUMENTS ? classofRaw(O)
// ES3 arguments fallback
: (result = classofRaw(O)) === 'Object' && isCallable(O.callee) ? 'Arguments' : result;
};
/***/ }),
/***/ "./node_modules/core-js/internals/create-non-enumerable-property.js":
/*!**************************************************************************!*\
!*** ./node_modules/core-js/internals/create-non-enumerable-property.js ***!
\**************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js");
var definePropertyModule = __webpack_require__(/*! ../internals/object-define-property */ "./node_modules/core-js/internals/object-define-property.js");
var createPropertyDescriptor = __webpack_require__(/*! ../internals/create-property-descriptor */ "./node_modules/core-js/internals/create-property-descriptor.js");
module.exports = DESCRIPTORS ? function (object, key, value) {
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
} : function (object, key, value) {
object[key] = value;
return object;
};
/***/ }),
/***/ "./node_modules/core-js/internals/create-property-descriptor.js":
/*!**********************************************************************!*\
!*** ./node_modules/core-js/internals/create-property-descriptor.js ***!
\**********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value: value
};
};
/***/ }),
/***/ "./node_modules/core-js/internals/define-built-in.js":
/*!***********************************************************!*\
!*** ./node_modules/core-js/internals/define-built-in.js ***!
\***********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var definePropertyModule = __webpack_require__(/*! ../internals/object-define-property */ "./node_modules/core-js/internals/object-define-property.js");
var makeBuiltIn = __webpack_require__(/*! ../internals/make-built-in */ "./node_modules/core-js/internals/make-built-in.js");
var defineGlobalProperty = __webpack_require__(/*! ../internals/define-global-property */ "./node_modules/core-js/internals/define-global-property.js");
module.exports = function (O, key, value, options) {
if (!options) options = {};
var simple = options.enumerable;
var name = options.name !== undefined ? options.name : key;
if (isCallable(value)) makeBuiltIn(value, name, options);
if (options.global) {
if (simple) O[key] = value;
else defineGlobalProperty(key, value);
} else {
try {
if (!options.unsafe) delete O[key];
else if (O[key]) simple = true;
} catch (error) { /* empty */ }
if (simple) O[key] = value;
else definePropertyModule.f(O, key, {
value: value,
enumerable: false,
configurable: !options.nonConfigurable,
writable: !options.nonWritable
});
} return O;
};
/***/ }),
/***/ "./node_modules/core-js/internals/define-global-property.js":
/*!******************************************************************!*\
!*** ./node_modules/core-js/internals/define-global-property.js ***!
\******************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
// eslint-disable-next-line es/no-object-defineproperty -- safe
var defineProperty = Object.defineProperty;
module.exports = function (key, value) {
try {
defineProperty(global, key, { value: value, configurable: true, writable: true });
} catch (error) {
global[key] = value;
} return value;
};
/***/ }),
/***/ "./node_modules/core-js/internals/descriptors.js":
/*!*******************************************************!*\
!*** ./node_modules/core-js/internals/descriptors.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
// Detect IE8's incomplete defineProperty implementation
module.exports = !fails(function () {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] !== 7;
});
/***/ }),
/***/ "./node_modules/core-js/internals/document-create-element.js":
/*!*******************************************************************!*\
!*** ./node_modules/core-js/internals/document-create-element.js ***!
\*******************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
var document = global.document;
// typeof document.createElement is 'object' in old IE
var EXISTS = isObject(document) && isObject(document.createElement);
module.exports = function (it) {
return EXISTS ? document.createElement(it) : {};
};
/***/ }),
/***/ "./node_modules/core-js/internals/engine-user-agent.js":
/*!*************************************************************!*\
!*** ./node_modules/core-js/internals/engine-user-agent.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = typeof navigator != 'undefined' && String(navigator.userAgent) || '';
/***/ }),
/***/ "./node_modules/core-js/internals/engine-v8-version.js":
/*!*************************************************************!*\
!*** ./node_modules/core-js/internals/engine-v8-version.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var userAgent = __webpack_require__(/*! ../internals/engine-user-agent */ "./node_modules/core-js/internals/engine-user-agent.js");
var process = global.process;
var Deno = global.Deno;
var versions = process && process.versions || Deno && Deno.version;
var v8 = versions && versions.v8;
var match, version;
if (v8) {
match = v8.split('.');
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
// but their correct versions are not interesting for us
version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
}
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
// so check `userAgent` even if `.v8` exists, but 0
if (!version && userAgent) {
match = userAgent.match(/Edge\/(\d+)/);
if (!match || match[1] >= 74) {
match = userAgent.match(/Chrome\/(\d+)/);
if (match) version = +match[1];
}
}
module.exports = version;
/***/ }),
/***/ "./node_modules/core-js/internals/fails.js":
/*!*************************************************!*\
!*** ./node_modules/core-js/internals/fails.js ***!
\*************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (exec) {
try {
return !!exec();
} catch (error) {
return true;
}
};
/***/ }),
/***/ "./node_modules/core-js/internals/function-bind-native.js":
/*!****************************************************************!*\
!*** ./node_modules/core-js/internals/function-bind-native.js ***!
\****************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
module.exports = !fails(function () {
// eslint-disable-next-line es/no-function-prototype-bind -- safe
var test = (function () { /* empty */ }).bind();
// eslint-disable-next-line no-prototype-builtins -- safe
return typeof test != 'function' || test.hasOwnProperty('prototype');
});
/***/ }),
/***/ "./node_modules/core-js/internals/function-call.js":
/*!*********************************************************!*\
!*** ./node_modules/core-js/internals/function-call.js ***!
\*********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var NATIVE_BIND = __webpack_require__(/*! ../internals/function-bind-native */ "./node_modules/core-js/internals/function-bind-native.js");
var call = Function.prototype.call;
module.exports = NATIVE_BIND ? call.bind(call) : function () {
return call.apply(call, arguments);
};
/***/ }),
/***/ "./node_modules/core-js/internals/function-name.js":
/*!*********************************************************!*\
!*** ./node_modules/core-js/internals/function-name.js ***!
\*********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js");
var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js");
var FunctionPrototype = Function.prototype;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor;
var EXISTS = hasOwn(FunctionPrototype, 'name');
// additional protection from minified / mangled / dropped function names
var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
var CONFIGURABLE = EXISTS && (!DESCRIPTORS || (DESCRIPTORS && getDescriptor(FunctionPrototype, 'name').configurable));
module.exports = {
EXISTS: EXISTS,
PROPER: PROPER,
CONFIGURABLE: CONFIGURABLE
};
/***/ }),
/***/ "./node_modules/core-js/internals/function-uncurry-this.js":
/*!*****************************************************************!*\
!*** ./node_modules/core-js/internals/function-uncurry-this.js ***!
\*****************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var NATIVE_BIND = __webpack_require__(/*! ../internals/function-bind-native */ "./node_modules/core-js/internals/function-bind-native.js");
var FunctionPrototype = Function.prototype;
var call = FunctionPrototype.call;
var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call);
module.exports = NATIVE_BIND ? uncurryThisWithBind : function (fn) {
return function () {
return call.apply(fn, arguments);
};
};
/***/ }),
/***/ "./node_modules/core-js/internals/get-built-in.js":
/*!********************************************************!*\
!*** ./node_modules/core-js/internals/get-built-in.js ***!
\********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var aFunction = function (argument) {
return isCallable(argument) ? argument : undefined;
};
module.exports = function (namespace, method) {
return arguments.length < 2 ? aFunction(global[namespace]) : global[namespace] && global[namespace][method];
};
/***/ }),
/***/ "./node_modules/core-js/internals/get-method.js":
/*!******************************************************!*\
!*** ./node_modules/core-js/internals/get-method.js ***!
\******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var aCallable = __webpack_require__(/*! ../internals/a-callable */ "./node_modules/core-js/internals/a-callable.js");
var isNullOrUndefined = __webpack_require__(/*! ../internals/is-null-or-undefined */ "./node_modules/core-js/internals/is-null-or-undefined.js");
// `GetMethod` abstract operation
// https://tc39.es/ecma262/#sec-getmethod
module.exports = function (V, P) {
var func = V[P];
return isNullOrUndefined(func) ? undefined : aCallable(func);
};
/***/ }),
/***/ "./node_modules/core-js/internals/global.js":
/*!**************************************************!*\
!*** ./node_modules/core-js/internals/global.js ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(global) {
var check = function (it) {
return it && it.Math === Math && it;
};
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
module.exports =
// eslint-disable-next-line es/no-global-this -- safe
check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
// eslint-disable-next-line no-restricted-globals -- safe
check(typeof self == 'object' && self) ||
check(typeof global == 'object' && global) ||
check(typeof this == 'object' && this) ||
// eslint-disable-next-line no-new-func -- fallback
(function () { return this; })() || Function('return this')();
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js")))
/***/ }),
/***/ "./node_modules/core-js/internals/has-own-property.js":
/*!************************************************************!*\
!*** ./node_modules/core-js/internals/has-own-property.js ***!
\************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
var toObject = __webpack_require__(/*! ../internals/to-object */ "./node_modules/core-js/internals/to-object.js");
var hasOwnProperty = uncurryThis({}.hasOwnProperty);
// `HasOwnProperty` abstract operation
// https://tc39.es/ecma262/#sec-hasownproperty
// eslint-disable-next-line es/no-object-hasown -- safe
module.exports = Object.hasOwn || function hasOwn(it, key) {
return hasOwnProperty(toObject(it), key);
};
/***/ }),
/***/ "./node_modules/core-js/internals/hidden-keys.js":
/*!*******************************************************!*\
!*** ./node_modules/core-js/internals/hidden-keys.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = {};
/***/ }),
/***/ "./node_modules/core-js/internals/ie8-dom-define.js":
/*!**********************************************************!*\
!*** ./node_modules/core-js/internals/ie8-dom-define.js ***!
\**********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js");
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
var createElement = __webpack_require__(/*! ../internals/document-create-element */ "./node_modules/core-js/internals/document-create-element.js");
// Thanks to IE8 for its funny defineProperty
module.exports = !DESCRIPTORS && !fails(function () {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object.defineProperty(createElement('div'), 'a', {
get: function () { return 7; }
}).a !== 7;
});
/***/ }),
/***/ "./node_modules/core-js/internals/inspect-source.js":
/*!**********************************************************!*\
!*** ./node_modules/core-js/internals/inspect-source.js ***!
\**********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var store = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js");
var functionToString = uncurryThis(Function.toString);
// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
if (!isCallable(store.inspectSource)) {
store.inspectSource = function (it) {
return functionToString(it);
};
}
module.exports = store.inspectSource;
/***/ }),
/***/ "./node_modules/core-js/internals/internal-state.js":
/*!**********************************************************!*\
!*** ./node_modules/core-js/internals/internal-state.js ***!
\**********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var NATIVE_WEAK_MAP = __webpack_require__(/*! ../internals/weak-map-basic-detection */ "./node_modules/core-js/internals/weak-map-basic-detection.js");
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
var createNonEnumerableProperty = __webpack_require__(/*! ../internals/create-non-enumerable-property */ "./node_modules/core-js/internals/create-non-enumerable-property.js");
var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js");
var shared = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js");
var sharedKey = __webpack_require__(/*! ../internals/shared-key */ "./node_modules/core-js/internals/shared-key.js");
var hiddenKeys = __webpack_require__(/*! ../internals/hidden-keys */ "./node_modules/core-js/internals/hidden-keys.js");
var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
var TypeError = global.TypeError;
var WeakMap = global.WeakMap;
var set, get, has;
var enforce = function (it) {
return has(it) ? get(it) : set(it, {});
};
var getterFor = function (TYPE) {
return function (it) {
var state;
if (!isObject(it) || (state = get(it)).type !== TYPE) {
throw new TypeError('Incompatible receiver, ' + TYPE + ' required');
} return state;
};
};
if (NATIVE_WEAK_MAP || shared.state) {
var store = shared.state || (shared.state = new WeakMap());
/* eslint-disable no-self-assign -- prototype methods protection */
store.get = store.get;
store.has = store.has;
store.set = store.set;
/* eslint-enable no-self-assign -- prototype methods protection */
set = function (it, metadata) {
if (store.has(it)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
metadata.facade = it;
store.set(it, metadata);
return metadata;
};
get = function (it) {
return store.get(it) || {};
};
has = function (it) {
return store.has(it);
};
} else {
var STATE = sharedKey('state');
hiddenKeys[STATE] = true;
set = function (it, metadata) {
if (hasOwn(it, STATE)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
metadata.facade = it;
createNonEnumerableProperty(it, STATE, metadata);
return metadata;
};
get = function (it) {
return hasOwn(it, STATE) ? it[STATE] : {};
};
has = function (it) {
return hasOwn(it, STATE);
};
}
module.exports = {
set: set,
get: get,
has: has,
enforce: enforce,
getterFor: getterFor
};
/***/ }),
/***/ "./node_modules/core-js/internals/is-callable.js":
/*!*******************************************************!*\
!*** ./node_modules/core-js/internals/is-callable.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
var documentAll = typeof document == 'object' && document.all;
// `IsCallable` abstract operation
// https://tc39.es/ecma262/#sec-iscallable
// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
module.exports = typeof documentAll == 'undefined' && documentAll !== undefined ? function (argument) {
return typeof argument == 'function' || argument === documentAll;
} : function (argument) {
return typeof argument == 'function';
};
/***/ }),
/***/ "./node_modules/core-js/internals/is-null-or-undefined.js":
/*!****************************************************************!*\
!*** ./node_modules/core-js/internals/is-null-or-undefined.js ***!
\****************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// we can't use just `it == null` since of `document.all` special case
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
module.exports = function (it) {
return it === null || it === undefined;
};
/***/ }),
/***/ "./node_modules/core-js/internals/is-object.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/is-object.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
module.exports = function (it) {
return typeof it == 'object' ? it !== null : isCallable(it);
};
/***/ }),
/***/ "./node_modules/core-js/internals/is-pure.js":
/*!***************************************************!*\
!*** ./node_modules/core-js/internals/is-pure.js ***!
\***************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = false;
/***/ }),
/***/ "./node_modules/core-js/internals/is-symbol.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/is-symbol.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var getBuiltIn = __webpack_require__(/*! ../internals/get-built-in */ "./node_modules/core-js/internals/get-built-in.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var isPrototypeOf = __webpack_require__(/*! ../internals/object-is-prototype-of */ "./node_modules/core-js/internals/object-is-prototype-of.js");
var USE_SYMBOL_AS_UID = __webpack_require__(/*! ../internals/use-symbol-as-uid */ "./node_modules/core-js/internals/use-symbol-as-uid.js");
var $Object = Object;
module.exports = USE_SYMBOL_AS_UID ? function (it) {
return typeof it == 'symbol';
} : function (it) {
var $Symbol = getBuiltIn('Symbol');
return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it));
};
/***/ }),
/***/ "./node_modules/core-js/internals/make-built-in.js":
/*!*********************************************************!*\
!*** ./node_modules/core-js/internals/make-built-in.js ***!
\*********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js");
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js");
var CONFIGURABLE_FUNCTION_NAME = __webpack_require__(/*! ../internals/function-name */ "./node_modules/core-js/internals/function-name.js").CONFIGURABLE;
var inspectSource = __webpack_require__(/*! ../internals/inspect-source */ "./node_modules/core-js/internals/inspect-source.js");
var InternalStateModule = __webpack_require__(/*! ../internals/internal-state */ "./node_modules/core-js/internals/internal-state.js");
var enforceInternalState = InternalStateModule.enforce;
var getInternalState = InternalStateModule.get;
var $String = String;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var defineProperty = Object.defineProperty;
var stringSlice = uncurryThis(''.slice);
var replace = uncurryThis(''.replace);
var join = uncurryThis([].join);
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () {
return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8;
});
var TEMPLATE = String(String).split('String');
var makeBuiltIn = module.exports = function (value, name, options) {
if (stringSlice($String(name), 0, 7) === 'Symbol(') {
name = '[' + replace($String(name), /^Symbol\(([^)]*)\).*$/, '$1') + ']';
}
if (options && options.getter) name = 'get ' + name;
if (options && options.setter) name = 'set ' + name;
if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) {
if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true });
else value.name = name;
}
if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) {
defineProperty(value, 'length', { value: options.arity });
}
try {
if (options && hasOwn(options, 'constructor') && options.constructor) {
if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false });
// in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable
} else if (value.prototype) value.prototype = undefined;
} catch (error) { /* empty */ }
var state = enforceInternalState(value);
if (!hasOwn(state, 'source')) {
state.source = join(TEMPLATE, typeof name == 'string' ? name : '');
} return value;
};
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
// eslint-disable-next-line no-extend-native -- required
Function.prototype.toString = makeBuiltIn(function toString() {
return isCallable(this) && getInternalState(this).source || inspectSource(this);
}, 'toString');
/***/ }),
/***/ "./node_modules/core-js/internals/object-define-property.js":
/*!******************************************************************!*\
!*** ./node_modules/core-js/internals/object-define-property.js ***!
\******************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js");
var IE8_DOM_DEFINE = __webpack_require__(/*! ../internals/ie8-dom-define */ "./node_modules/core-js/internals/ie8-dom-define.js");
var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(/*! ../internals/v8-prototype-define-bug */ "./node_modules/core-js/internals/v8-prototype-define-bug.js");
var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js");
var toPropertyKey = __webpack_require__(/*! ../internals/to-property-key */ "./node_modules/core-js/internals/to-property-key.js");
var $TypeError = TypeError;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var $defineProperty = Object.defineProperty;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
var ENUMERABLE = 'enumerable';
var CONFIGURABLE = 'configurable';
var WRITABLE = 'writable';
// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) {
anObject(O);
P = toPropertyKey(P);
anObject(Attributes);
if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
var current = $getOwnPropertyDescriptor(O, P);
if (current && current[WRITABLE]) {
O[P] = Attributes.value;
Attributes = {
configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE],
enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
writable: false
};
}
} return $defineProperty(O, P, Attributes);
} : $defineProperty : function defineProperty(O, P, Attributes) {
anObject(O);
P = toPropertyKey(P);
anObject(Attributes);
if (IE8_DOM_DEFINE) try {
return $defineProperty(O, P, Attributes);
} catch (error) { /* empty */ }
if ('get' in Attributes || 'set' in Attributes) throw new $TypeError('Accessors not supported');
if ('value' in Attributes) O[P] = Attributes.value;
return O;
};
/***/ }),
/***/ "./node_modules/core-js/internals/object-is-prototype-of.js":
/*!******************************************************************!*\
!*** ./node_modules/core-js/internals/object-is-prototype-of.js ***!
\******************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
module.exports = uncurryThis({}.isPrototypeOf);
/***/ }),
/***/ "./node_modules/core-js/internals/object-to-string.js":
/*!************************************************************!*\
!*** ./node_modules/core-js/internals/object-to-string.js ***!
\************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js");
var classof = __webpack_require__(/*! ../internals/classof */ "./node_modules/core-js/internals/classof.js");
// `Object.prototype.toString` method implementation
// https://tc39.es/ecma262/#sec-object.prototype.tostring
module.exports = TO_STRING_TAG_SUPPORT ? {}.toString : function toString() {
return '[object ' + classof(this) + ']';
};
/***/ }),
/***/ "./node_modules/core-js/internals/ordinary-to-primitive.js":
/*!*****************************************************************!*\
!*** ./node_modules/core-js/internals/ordinary-to-primitive.js ***!
\*****************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var call = __webpack_require__(/*! ../internals/function-call */ "./node_modules/core-js/internals/function-call.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
var $TypeError = TypeError;
// `OrdinaryToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-ordinarytoprimitive
module.exports = function (input, pref) {
var fn, val;
if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
throw new $TypeError("Can't convert object to primitive value");
};
/***/ }),
/***/ "./node_modules/core-js/internals/regexp-flags.js":
/*!********************************************************!*\
!*** ./node_modules/core-js/internals/regexp-flags.js ***!
\********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js");
// `RegExp.prototype.flags` getter implementation
// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
module.exports = function () {
var that = anObject(this);
var result = '';
if (that.hasIndices) result += 'd';
if (that.global) result += 'g';
if (that.ignoreCase) result += 'i';
if (that.multiline) result += 'm';
if (that.dotAll) result += 's';
if (that.unicode) result += 'u';
if (that.unicodeSets) result += 'v';
if (that.sticky) result += 'y';
return result;
};
/***/ }),
/***/ "./node_modules/core-js/internals/regexp-get-flags.js":
/*!************************************************************!*\
!*** ./node_modules/core-js/internals/regexp-get-flags.js ***!
\************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var call = __webpack_require__(/*! ../internals/function-call */ "./node_modules/core-js/internals/function-call.js");
var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js");
var isPrototypeOf = __webpack_require__(/*! ../internals/object-is-prototype-of */ "./node_modules/core-js/internals/object-is-prototype-of.js");
var regExpFlags = __webpack_require__(/*! ../internals/regexp-flags */ "./node_modules/core-js/internals/regexp-flags.js");
var RegExpPrototype = RegExp.prototype;
module.exports = function (R) {
var flags = R.flags;
return flags === undefined && !('flags' in RegExpPrototype) && !hasOwn(R, 'flags') && isPrototypeOf(RegExpPrototype, R)
? call(regExpFlags, R) : flags;
};
/***/ }),
/***/ "./node_modules/core-js/internals/require-object-coercible.js":
/*!********************************************************************!*\
!*** ./node_modules/core-js/internals/require-object-coercible.js ***!
\********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var isNullOrUndefined = __webpack_require__(/*! ../internals/is-null-or-undefined */ "./node_modules/core-js/internals/is-null-or-undefined.js");
var $TypeError = TypeError;
// `RequireObjectCoercible` abstract operation
// https://tc39.es/ecma262/#sec-requireobjectcoercible
module.exports = function (it) {
if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it);
return it;
};
/***/ }),
/***/ "./node_modules/core-js/internals/shared-key.js":
/*!******************************************************!*\
!*** ./node_modules/core-js/internals/shared-key.js ***!
\******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var shared = __webpack_require__(/*! ../internals/shared */ "./node_modules/core-js/internals/shared.js");
var uid = __webpack_require__(/*! ../internals/uid */ "./node_modules/core-js/internals/uid.js");
var keys = shared('keys');
module.exports = function (key) {
return keys[key] || (keys[key] = uid(key));
};
/***/ }),
/***/ "./node_modules/core-js/internals/shared-store.js":
/*!********************************************************!*\
!*** ./node_modules/core-js/internals/shared-store.js ***!
\********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var IS_PURE = __webpack_require__(/*! ../internals/is-pure */ "./node_modules/core-js/internals/is-pure.js");
var globalThis = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var defineGlobalProperty = __webpack_require__(/*! ../internals/define-global-property */ "./node_modules/core-js/internals/define-global-property.js");
var SHARED = '__core-js_shared__';
var store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});
(store.versions || (store.versions = [])).push({
version: '3.37.1',
mode: IS_PURE ? 'pure' : 'global',
copyright: '© 2014-2024 Denis Pushkarev (zloirock.ru)',
license: 'https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE',
source: 'https://github.com/zloirock/core-js'
});
/***/ }),
/***/ "./node_modules/core-js/internals/shared.js":
/*!**************************************************!*\
!*** ./node_modules/core-js/internals/shared.js ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var store = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js");
module.exports = function (key, value) {
return store[key] || (store[key] = value || {});
};
/***/ }),
/***/ "./node_modules/core-js/internals/symbol-constructor-detection.js":
/*!************************************************************************!*\
!*** ./node_modules/core-js/internals/symbol-constructor-detection.js ***!
\************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* eslint-disable es/no-symbol -- required for testing */
var V8_VERSION = __webpack_require__(/*! ../internals/engine-v8-version */ "./node_modules/core-js/internals/engine-v8-version.js");
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var $String = global.String;
// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
module.exports = !!Object.getOwnPropertySymbols && !fails(function () {
var symbol = Symbol('symbol detection');
// Chrome 38 Symbol has incorrect toString conversion
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
// of course, fail.
return !$String(symbol) || !(Object(symbol) instanceof Symbol) ||
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
});
/***/ }),
/***/ "./node_modules/core-js/internals/to-object.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/to-object.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ "./node_modules/core-js/internals/require-object-coercible.js");
var $Object = Object;
// `ToObject` abstract operation
// https://tc39.es/ecma262/#sec-toobject
module.exports = function (argument) {
return $Object(requireObjectCoercible(argument));
};
/***/ }),
/***/ "./node_modules/core-js/internals/to-primitive.js":
/*!********************************************************!*\
!*** ./node_modules/core-js/internals/to-primitive.js ***!
\********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var call = __webpack_require__(/*! ../internals/function-call */ "./node_modules/core-js/internals/function-call.js");
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
var isSymbol = __webpack_require__(/*! ../internals/is-symbol */ "./node_modules/core-js/internals/is-symbol.js");
var getMethod = __webpack_require__(/*! ../internals/get-method */ "./node_modules/core-js/internals/get-method.js");
var ordinaryToPrimitive = __webpack_require__(/*! ../internals/ordinary-to-primitive */ "./node_modules/core-js/internals/ordinary-to-primitive.js");
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ "./node_modules/core-js/internals/well-known-symbol.js");
var $TypeError = TypeError;
var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
// `ToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-toprimitive
module.exports = function (input, pref) {
if (!isObject(input) || isSymbol(input)) return input;
var exoticToPrim = getMethod(input, TO_PRIMITIVE);
var result;
if (exoticToPrim) {
if (pref === undefined) pref = 'default';
result = call(exoticToPrim, input, pref);
if (!isObject(result) || isSymbol(result)) return result;
throw new $TypeError("Can't convert object to primitive value");
}
if (pref === undefined) pref = 'number';
return ordinaryToPrimitive(input, pref);
};
/***/ }),
/***/ "./node_modules/core-js/internals/to-property-key.js":
/*!***********************************************************!*\
!*** ./node_modules/core-js/internals/to-property-key.js ***!
\***********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var toPrimitive = __webpack_require__(/*! ../internals/to-primitive */ "./node_modules/core-js/internals/to-primitive.js");
var isSymbol = __webpack_require__(/*! ../internals/is-symbol */ "./node_modules/core-js/internals/is-symbol.js");
// `ToPropertyKey` abstract operation
// https://tc39.es/ecma262/#sec-topropertykey
module.exports = function (argument) {
var key = toPrimitive(argument, 'string');
return isSymbol(key) ? key : key + '';
};
/***/ }),
/***/ "./node_modules/core-js/internals/to-string-tag-support.js":
/*!*****************************************************************!*\
!*** ./node_modules/core-js/internals/to-string-tag-support.js ***!
\*****************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ "./node_modules/core-js/internals/well-known-symbol.js");
var TO_STRING_TAG = wellKnownSymbol('toStringTag');
var test = {};
test[TO_STRING_TAG] = 'z';
module.exports = String(test) === '[object z]';
/***/ }),
/***/ "./node_modules/core-js/internals/to-string.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/to-string.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var classof = __webpack_require__(/*! ../internals/classof */ "./node_modules/core-js/internals/classof.js");
var $String = String;
module.exports = function (argument) {
if (classof(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string');
return $String(argument);
};
/***/ }),
/***/ "./node_modules/core-js/internals/try-to-string.js":
/*!*********************************************************!*\
!*** ./node_modules/core-js/internals/try-to-string.js ***!
\*********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $String = String;
module.exports = function (argument) {
try {
return $String(argument);
} catch (error) {
return 'Object';
}
};
/***/ }),
/***/ "./node_modules/core-js/internals/uid.js":
/*!***********************************************!*\
!*** ./node_modules/core-js/internals/uid.js ***!
\***********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
var id = 0;
var postfix = Math.random();
var toString = uncurryThis(1.0.toString);
module.exports = function (key) {
return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36);
};
/***/ }),
/***/ "./node_modules/core-js/internals/use-symbol-as-uid.js":
/*!*************************************************************!*\
!*** ./node_modules/core-js/internals/use-symbol-as-uid.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* eslint-disable es/no-symbol -- required for testing */
var NATIVE_SYMBOL = __webpack_require__(/*! ../internals/symbol-constructor-detection */ "./node_modules/core-js/internals/symbol-constructor-detection.js");
module.exports = NATIVE_SYMBOL
&& !Symbol.sham
&& typeof Symbol.iterator == 'symbol';
/***/ }),
/***/ "./node_modules/core-js/internals/v8-prototype-define-bug.js":
/*!*******************************************************************!*\
!*** ./node_modules/core-js/internals/v8-prototype-define-bug.js ***!
\*******************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js");
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
// V8 ~ Chrome 36-
// https://bugs.chromium.org/p/v8/issues/detail?id=3334
module.exports = DESCRIPTORS && fails(function () {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object.defineProperty(function () { /* empty */ }, 'prototype', {
value: 42,
writable: false
}).prototype !== 42;
});
/***/ }),
/***/ "./node_modules/core-js/internals/weak-map-basic-detection.js":
/*!********************************************************************!*\
!*** ./node_modules/core-js/internals/weak-map-basic-detection.js ***!
\********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js");
var WeakMap = global.WeakMap;
module.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap));
/***/ }),
/***/ "./node_modules/core-js/internals/well-known-symbol.js":
/*!*************************************************************!*\
!*** ./node_modules/core-js/internals/well-known-symbol.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var shared = __webpack_require__(/*! ../internals/shared */ "./node_modules/core-js/internals/shared.js");
var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js");
var uid = __webpack_require__(/*! ../internals/uid */ "./node_modules/core-js/internals/uid.js");
var NATIVE_SYMBOL = __webpack_require__(/*! ../internals/symbol-constructor-detection */ "./node_modules/core-js/internals/symbol-constructor-detection.js");
var USE_SYMBOL_AS_UID = __webpack_require__(/*! ../internals/use-symbol-as-uid */ "./node_modules/core-js/internals/use-symbol-as-uid.js");
var Symbol = global.Symbol;
var WellKnownSymbolsStore = shared('wks');
var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol['for'] || Symbol : Symbol && Symbol.withoutSetter || uid;
module.exports = function (name) {
if (!hasOwn(WellKnownSymbolsStore, name)) {
WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol, name)
? Symbol[name]
: createWellKnownSymbol('Symbol.' + name);
} return WellKnownSymbolsStore[name];
};
/***/ }),
/***/ "./node_modules/core-js/modules/es.date.to-string.js":
/*!***********************************************************!*\
!*** ./node_modules/core-js/modules/es.date.to-string.js ***!
\***********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// TODO: Remove from `core-js@4`
var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js");
var defineBuiltIn = __webpack_require__(/*! ../internals/define-built-in */ "./node_modules/core-js/internals/define-built-in.js");
var DatePrototype = Date.prototype;
var INVALID_DATE = 'Invalid Date';
var TO_STRING = 'toString';
var nativeDateToString = uncurryThis(DatePrototype[TO_STRING]);
var thisTimeValue = uncurryThis(DatePrototype.getTime);
// `Date.prototype.toString` method
// https://tc39.es/ecma262/#sec-date.prototype.tostring
if (String(new Date(NaN)) !== INVALID_DATE) {
defineBuiltIn(DatePrototype, TO_STRING, function toString() {
var value = thisTimeValue(this);
// eslint-disable-next-line no-self-compare -- NaN check
return value === value ? nativeDateToString(this) : INVALID_DATE;
});
}
/***/ }),
/***/ "./node_modules/core-js/modules/es.object.to-string.js":
/*!*************************************************************!*\
!*** ./node_modules/core-js/modules/es.object.to-string.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js");
var defineBuiltIn = __webpack_require__(/*! ../internals/define-built-in */ "./node_modules/core-js/internals/define-built-in.js");
var toString = __webpack_require__(/*! ../internals/object-to-string */ "./node_modules/core-js/internals/object-to-string.js");
// `Object.prototype.toString` method
// https://tc39.es/ecma262/#sec-object.prototype.tostring
if (!TO_STRING_TAG_SUPPORT) {
defineBuiltIn(Object.prototype, 'toString', toString, { unsafe: true });
}
/***/ }),
/***/ "./node_modules/core-js/modules/es.regexp.to-string.js":
/*!*************************************************************!*\
!*** ./node_modules/core-js/modules/es.regexp.to-string.js ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var PROPER_FUNCTION_NAME = __webpack_require__(/*! ../internals/function-name */ "./node_modules/core-js/internals/function-name.js").PROPER;
var defineBuiltIn = __webpack_require__(/*! ../internals/define-built-in */ "./node_modules/core-js/internals/define-built-in.js");
var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js");
var $toString = __webpack_require__(/*! ../internals/to-string */ "./node_modules/core-js/internals/to-string.js");
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
var getRegExpFlags = __webpack_require__(/*! ../internals/regexp-get-flags */ "./node_modules/core-js/internals/regexp-get-flags.js");
var TO_STRING = 'toString';
var RegExpPrototype = RegExp.prototype;
var nativeToString = RegExpPrototype[TO_STRING];
var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) !== '/a/b'; });
// FF44- RegExp#toString has a wrong name
var INCORRECT_NAME = PROPER_FUNCTION_NAME && nativeToString.name !== TO_STRING;
// `RegExp.prototype.toString` method
// https://tc39.es/ecma262/#sec-regexp.prototype.tostring
if (NOT_GENERIC || INCORRECT_NAME) {
defineBuiltIn(RegExpPrototype, TO_STRING, function toString() {
var R = anObject(this);
var pattern = $toString(R.source);
var flags = $toString(getRegExpFlags(R));
return '/' + pattern + '/' + flags;
}, { unsafe: true });
}
/***/ }),
/***/ "./node_modules/webpack/buildin/global.js":
/*!***********************************!*\
!*** (webpack)/buildin/global.js ***!
\***********************************/
/*! no static exports found */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || new Function("return this")();
} catch (e) {
// This works if the window reference is available
if (typeof window === "object") g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ })
}]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL2xvY2FsZXMvZnIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvY29yZS9tYWluLmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL21haW4uZXNtLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2RheWdyaWQvbWFpbi5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvZGF5Z3JpZC9tYWluLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9pbnRlcmFjdGlvbi9tYWluLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvYS1jYWxsYWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvYW4tb2JqZWN0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9jbGFzc29mLXJhdy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvY2xhc3NvZi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvY3JlYXRlLW5vbi1lbnVtZXJhYmxlLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9jcmVhdGUtcHJvcGVydHktZGVzY3JpcHRvci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZGVmaW5lLWJ1aWx0LWluLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9kZWZpbmUtZ2xvYmFsLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9kZXNjcmlwdG9ycy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZG9jdW1lbnQtY3JlYXRlLWVsZW1lbnQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2VuZ2luZS11c2VyLWFnZW50LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9lbmdpbmUtdjgtdmVyc2lvbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZmFpbHMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2Z1bmN0aW9uLWJpbmQtbmF0aXZlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mdW5jdGlvbi1jYWxsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mdW5jdGlvbi1uYW1lLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mdW5jdGlvbi11bmN1cnJ5LXRoaXMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2dldC1idWlsdC1pbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZ2V0LW1ldGhvZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9oYXMtb3duLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9oaWRkZW4ta2V5cy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvaWU4LWRvbS1kZWZpbmUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2luc3BlY3Qtc291cmNlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9pbnRlcm5hbC1zdGF0ZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvaXMtY2FsbGFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLW51bGwtb3ItdW5kZWZpbmVkLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9pcy1vYmplY3QuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLXB1cmUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLXN5bWJvbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvbWFrZS1idWlsdC1pbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LWRlZmluZS1wcm9wZXJ0eS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LWlzLXByb3RvdHlwZS1vZi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LXRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb3JkaW5hcnktdG8tcHJpbWl0aXZlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9yZWdleHAtZmxhZ3MuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3JlZ2V4cC1nZXQtZmxhZ3MuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3JlcXVpcmUtb2JqZWN0LWNvZXJjaWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2hhcmVkLWtleS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2hhcmVkLXN0b3JlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9zaGFyZWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3N5bWJvbC1jb25zdHJ1Y3Rvci1kZXRlY3Rpb24uanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RvLW9iamVjdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvdG8tcHJpbWl0aXZlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy90by1wcm9wZXJ0eS1rZXkuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvdG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy90cnktdG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy91aWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3VzZS1zeW1ib2wtYXMtdWlkLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy92OC1wcm90b3R5cGUtZGVmaW5lLWJ1Zy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvd2Vhay1tYXAtYmFzaWMtZGV0ZWN0aW9uLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy93ZWxsLWtub3duLXN5bWJvbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmRhdGUudG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMub2JqZWN0LnRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnJlZ2V4cC50by1zdHJpbmcuanMiLCJ3ZWJwYWNrOi8vLyh3ZWJwYWNrKS9idWlsZGluL2dsb2JhbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBLElBQUksS0FBNEQ7QUFDaEUsSUFBSSxTQUNxSTtBQUN6SSxDQUFDLG9CQUFvQjs7QUFFckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDOzs7Ozs7Ozs7Ozs7QUM5QkQsdUM7Ozs7Ozs7Ozs7OztBQ0FBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Q7QUFDbEQ7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsMkJBQTJCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBLG9CQUFv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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0EsZUFBZSxTQUFTO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEMsb0JBQW9CO0FBQ3BCO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHFCQUFxQjtBQUN4RCxrQ0FBa0Msb0JBQW9CO0FBQ3REO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0EsbUNBQW1DO0FBQ25DLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRDtBQUN0RDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSx5REFBeUQ7QUFDekQ7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0EsOEJBQThCLDhCQUE4QjtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyx1QkFBdUI7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixlQUFlO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkMsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DO0FBQ25DLFNBQVM7QUFDVDtBQUNBO0FBQ0EsaUNBQWlDLGNBQWM7QUFDL0M7QUFDQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBLGlHQUFpRztBQUNqRztBQUNBLDZCQUE2Qix5QkFBeUI7QUFDdEQ7QUFDQTtBQUNBLDZCQUE2Qix5QkFBeUI7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsY0FBYztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIscUJBQXFCO0FBQ2xEO0FBQ0E7QUFDQSw2QkFBNkIsaUJBQWlCLGdCQUFnQixFQUFFO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLGNBQWM7QUFDL0M7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLHVEQUF1RDtBQUN4RjtBQUNBO0FBQ0EsaUNBQWlDLDJFQUEyRTtBQUM1RztBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0EsNkJBQTZCLHVEQUF1RDtBQUNwRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCLHlCQUF5QixvQkFBb0I7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEIseUJBQXlCLGtCQUFrQjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQix5QkFBeUIsb0JBQW9CO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxjQUFjO0FBQy9DLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQiwrQkFBK0I7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQiwyQkFBMkIsRUFBRTtBQUN2RDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsMEJBQTBCLDBCQUEwQixFQUFFO0FBQ3REO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSwwQkFBMEIseUJBQXlCLEVBQUU7QUFDckQ7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLDBCQUEwQix3QkFBd0IsRUFBRTtBQUNwRDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsMEJBQTBCLHNCQUFzQixFQUFFO0FBQ2xEO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSwwQkFBMEIsNEJBQTRCLEVBQUU7QUFDeEQ7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLDBCQUEwQixtQ0FBbUMsRUFBRTtBQUMvRDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsMEJBQTBCLHNDQUFzQyxFQUFFO0FBQ2xFO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSwwQkFBMEIsNENBQTRDLEVBQUU7QUFDeEU7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLDBCQUEwQiw2QkFBNkIsRUFBRTtBQUN6RDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsMEJBQTBCLHVDQUF1QyxFQUFFO0FBQ25FO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSwwQkFBMEIscUNBQXFDLEVBQUU7QUFDakU7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLDBCQUEwQixpQ0FBaUMsRUFBRTtBQUM3RDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsMEJBQTBCLCtCQUErQixFQUFFO0FBQzNEO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLDBCQUEwQixnQ0FBZ0MsRUFBRTtBQUM1RDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsMEJBQTBCLGdDQUFnQyxFQUFFO0FBQzVEO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQSwyREFBMkQsOEJBQThCO0FBQ3pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsOEJBQThCO0FBQ3pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxtQ0FBbUMsb0JBQW9CO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxvQkFBb0I7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Q7QUFDbEQsZ0VBQWdFO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLG9CQUFvQjtBQUN2RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxvQkFBb0I7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCw0QkFBNEI7QUFDL0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQSwwQkFBMEIsNEJBQTRCLGdCQUFnQixrQ0FBa0M7QUFDeEc7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQSwyQ0FBMkMsd0JBQXdCO0FBQ25FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7QUFDMUMsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQSw4QkFBOEIsYUFBYTtBQUMzQztBQUNBO0FBQ0EsaUJBQWlCLDBKQUEwSjtBQUMzSztBQUNBLEtBQUs7QUFDTCxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxFQUFFO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEIseUJBQXlCLFlBQVk7QUFDakU7QUFDQTtBQUNBLDRCQUE0QiwrQkFBK0I7QUFDM0Q7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLGtPQUFrTztBQUM1UDtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsbUJBQW1CO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsK0JBQStCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUdBQW1HO0FBQ25HO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkRBQTJEO0FBQzNELG1EQUFtRCxnQkFBZ0I7QUFDbkU7QUFDQSw2Q0FBNkMsaUJBQWlCLDBEQUEwRDtBQUN4SDtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQiw4REFBOEQ7QUFDOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELGdCQUFnQjtBQUNqRTtBQUNBLHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsMkJBQTJCO0FBQzVFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsNERBQTREO0FBQzVEO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELDJCQUEyQjtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0RBQXNEO0FBQ3REO0FBQ0Esa0RBQWtEO0FBQ2xELHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0NBQXdDO0FBQ3hDLDRCQUE0QjtBQUM1Qiw0QkFBNEI7QUFDNUIsOEJBQThCO0FBQzlCLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFLGdCQUFnQjtBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUVBQW1FO0FBQ25FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixxQ0FBcUM7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLEVBQUU7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQixLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyxtQkFBbUI7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RCwwQkFBMEI7QUFDakY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsNEJBQTRCO0FBQy9FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0M7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0VBQStFO0FBQy9FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLG9CQUFvQjtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELGdCQUFnQjtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsZ0JBQWdCO0FBQzFFO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QixxREFBcUQsZ0JBQWdCO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsaUJBQWlCO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLFVBQVUsNENBQTRDO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hELG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQsb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHVCQUF1QjtBQUMvQztBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsZ0JBQWdCO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxnQkFBZ0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2Qiw2Q0FBNkM7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUVBQXVFO0FBQ3ZFLHlDQUF5QztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBLHNCQUFzQixFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsUUFBUSxFQUFFO0FBQzlHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTCxzQkFBc0IsZ0JBQWdCLDJDQUEyQztBQUNqRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsc0JBQXNCLDRCQUE0QixnQkFBZ0I7QUFDNUYsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxzQkFBc0I7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0RBQStEO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQ7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVELHdCQUF3QjtBQUMvRSxtREFBbUQsd0JBQXdCO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQztBQUNuQyxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnRUFBZ0U7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFT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M0Q7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQ7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQ7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLGlCQUFpQjtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLDhCQUE4QixlQUFlO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLG9CQUFv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QTtBQUNBLEdBQUcsR0FBRyxlQUFlO0FBQ3JCOzs7Ozs7Ozs7Ozs7QUN6QkE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0Q0FBNEM7O0FBRTVDIiwiZmlsZSI6InZlbmRvcnN+ZnVsbGNhbGVuZGFyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG4gICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcbiAgICAoZ2xvYmFsID0gZ2xvYmFsIHx8IHNlbGYsIChnbG9iYWwuRnVsbENhbGVuZGFyTG9jYWxlcyA9IGdsb2JhbC5GdWxsQ2FsZW5kYXJMb2NhbGVzIHx8IHt9LCBnbG9iYWwuRnVsbENhbGVuZGFyTG9jYWxlcy5mciA9IGZhY3RvcnkoKSkpO1xufSh0aGlzLCBmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuICAgIHZhciBmciA9IHtcbiAgICAgICAgY29kZTogXCJmclwiLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsXG4gICAgICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgICAgICBidXR0b25UZXh0OiB7XG4gICAgICAgICAgICBwcmV2OiBcIlByw6ljw6lkZW50XCIsXG4gICAgICAgICAgICBuZXh0OiBcIlN1aXZhbnRcIixcbiAgICAgICAgICAgIHRvZGF5OiBcIkF1am91cmQnaHVpXCIsXG4gICAgICAgICAgICB5ZWFyOiBcIkFubsOpZVwiLFxuICAgICAgICAgICAgbW9udGg6IFwiTW9pc1wiLFxuICAgICAgICAgICAgd2VlazogXCJTZW1haW5lXCIsXG4gICAgICAgICAgICBkYXk6IFwiSm91clwiLFxuICAgICAgICAgICAgbGlzdDogXCJQbGFubmluZ1wiXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtMYWJlbDogXCJTZW0uXCIsXG4gICAgICAgIGFsbERheUh0bWw6IFwiVG91dGUgbGE8YnIvPmpvdXJuw6llXCIsXG4gICAgICAgIGV2ZW50TGltaXRUZXh0OiBcImVuIHBsdXNcIixcbiAgICAgICAgbm9FdmVudHNNZXNzYWdlOiBcIkF1Y3VuIMOpdsOpbmVtZW50IMOgIGFmZmljaGVyXCJcbiAgICB9O1xuXG4gICAgcmV0dXJuIGZyO1xuXG59KSk7XG4iLCIvLyBleHRyYWN0ZWQgYnkgbWluaS1jc3MtZXh0cmFjdC1wbHVnaW4iLCIvKiFcbkZ1bGxDYWxlbmRhciBDb3JlIFBhY2thZ2UgdjQuNC4yXG5Eb2NzICYgTGljZW5zZTogaHR0cHM6Ly9mdWxsY2FsZW5kYXIuaW8vXG4oYykgMjAxOSBBZGFtIFNoYXdcbiovXG5cbi8vIENyZWF0aW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG52YXIgZWxlbWVudFByb3BIYXNoID0ge1xuICAgIGNsYXNzTmFtZTogdHJ1ZSxcbiAgICBjb2xTcGFuOiB0cnVlLFxuICAgIHJvd1NwYW46IHRydWVcbn07XG52YXIgY29udGFpbmVyVGFnSGFzaCA9IHtcbiAgICAnPHRyJzogJ3Rib2R5JyxcbiAgICAnPHRkJzogJ3RyJ1xufTtcbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnTmFtZSwgYXR0cnMsIGNvbnRlbnQpIHtcbiAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZ05hbWUpO1xuICAgIGlmIChhdHRycykge1xuICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBhdHRycykge1xuICAgICAgICAgICAgaWYgKGF0dHJOYW1lID09PSAnc3R5bGUnKSB7XG4gICAgICAgICAgICAgICAgYXBwbHlTdHlsZShlbCwgYXR0cnNbYXR0ck5hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGVsZW1lbnRQcm9wSGFzaFthdHRyTmFtZV0pIHtcbiAgICAgICAgICAgICAgICBlbFthdHRyTmFtZV0gPSBhdHRyc1thdHRyTmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJzW2F0dHJOYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICBlbC5pbm5lckhUTUwgPSBjb250ZW50OyAvLyBzaG9ydGN1dC4gbm8gbmVlZCB0byBwcm9jZXNzIEhUTUwgaW4gYW55IHdheVxuICAgIH1cbiAgICBlbHNlIGlmIChjb250ZW50ICE9IG51bGwpIHtcbiAgICAgICAgYXBwZW5kVG9FbGVtZW50KGVsLCBjb250ZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGVsO1xufVxuZnVuY3Rpb24gaHRtbFRvRWxlbWVudChodG1sKSB7XG4gICAgaHRtbCA9IGh0bWwudHJpbSgpO1xuICAgIHZhciBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGNvbXB1dGVDb250YWluZXJUYWcoaHRtbCkpO1xuICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSBodG1sO1xuICAgIHJldHVybiBjb250YWluZXIuZmlyc3RDaGlsZDtcbn1cbmZ1bmN0aW9uIGh0bWxUb0VsZW1lbnRzKGh0bWwpIHtcbiAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoaHRtbFRvTm9kZUxpc3QoaHRtbCkpO1xufVxuZnVuY3Rpb24gaHRtbFRvTm9kZUxpc3QoaHRtbCkge1xuICAgIGh0bWwgPSBodG1sLnRyaW0oKTtcbiAgICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChjb21wdXRlQ29udGFpbmVyVGFnKGh0bWwpKTtcbiAgICBjb250YWluZXIuaW5uZXJIVE1MID0gaHRtbDtcbiAgICByZXR1cm4gY29udGFpbmVyLmNoaWxkTm9kZXM7XG59XG4vLyBhc3N1bWVzIGh0bWwgYWxyZWFkeSB0cmltbWVkIGFuZCB0YWcgbmFtZXMgYXJlIGxvd2VyY2FzZVxuZnVuY3Rpb24gY29tcHV0ZUNvbnRhaW5lclRhZyhodG1sKSB7XG4gICAgcmV0dXJuIGNvbnRhaW5lclRhZ0hhc2hbaHRtbC5zdWJzdHIoMCwgMykgLy8gZmFzdGVyIHRoYW4gdXNpbmcgcmVnZXhcbiAgICBdIHx8ICdkaXYnO1xufVxuZnVuY3Rpb24gYXBwZW5kVG9FbGVtZW50KGVsLCBjb250ZW50KSB7XG4gICAgdmFyIGNoaWxkTm9kZXMgPSBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBlbC5hcHBlbmRDaGlsZChjaGlsZE5vZGVzW2ldKTtcbiAgICB9XG59XG5mdW5jdGlvbiBwcmVwZW5kVG9FbGVtZW50KHBhcmVudCwgY29udGVudCkge1xuICAgIHZhciBuZXdFbHMgPSBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpO1xuICAgIHZhciBhZnRlckVsID0gcGFyZW50LmZpcnN0Q2hpbGQgfHwgbnVsbDsgLy8gaWYgbm8gZmlyc3RDaGlsZCwgd2lsbCBhcHBlbmQgdG8gZW5kLCBidXQgdGhhdCdzIG9rYXksIGIvYyB0aGVyZSB3ZXJlIG5vIGNoaWxkcmVuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuZXdFbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShuZXdFbHNbaV0sIGFmdGVyRWwpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGluc2VydEFmdGVyRWxlbWVudChyZWZFbCwgY29udGVudCkge1xuICAgIHZhciBuZXdFbHMgPSBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpO1xuICAgIHZhciBhZnRlckVsID0gcmVmRWwubmV4dFNpYmxpbmcgfHwgbnVsbDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5ld0Vscy5sZW5ndGg7IGkrKykge1xuICAgICAgICByZWZFbC5wYXJlbnROb2RlLmluc2VydEJlZm9yZShuZXdFbHNbaV0sIGFmdGVyRWwpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG5vcm1hbGl6ZUNvbnRlbnQoY29udGVudCkge1xuICAgIHZhciBlbHM7XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICBlbHMgPSBodG1sVG9FbGVtZW50cyhjb250ZW50KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoY29udGVudCBpbnN0YW5jZW9mIE5vZGUpIHtcbiAgICAgICAgZWxzID0gW2NvbnRlbnRdO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gTm9kZVtdIG9yIE5vZGVMaXN0XG4gICAgICAgIGVscyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNvbnRlbnQpO1xuICAgIH1cbiAgICByZXR1cm4gZWxzO1xufVxuZnVuY3Rpb24gcmVtb3ZlRWxlbWVudChlbCkge1xuICAgIGlmIChlbC5wYXJlbnROb2RlKSB7XG4gICAgICAgIGVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZWwpO1xuICAgIH1cbn1cbi8vIFF1ZXJ5aW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBmcm9tIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FbGVtZW50L2Nsb3Nlc3RcbnZhciBtYXRjaGVzTWV0aG9kID0gRWxlbWVudC5wcm90b3R5cGUubWF0Y2hlcyB8fFxuICAgIEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXNTZWxlY3RvciB8fFxuICAgIEVsZW1lbnQucHJvdG90eXBlLm1zTWF0Y2hlc1NlbGVjdG9yO1xudmFyIGNsb3Nlc3RNZXRob2QgPSBFbGVtZW50LnByb3RvdHlwZS5jbG9zZXN0IHx8IGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgIC8vIHBvbHlmaWxsXG4gICAgdmFyIGVsID0gdGhpcztcbiAgICBpZiAoIWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jb250YWlucyhlbCkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRvIHtcbiAgICAgICAgaWYgKGVsZW1lbnRNYXRjaGVzKGVsLCBzZWxlY3RvcikpIHtcbiAgICAgICAgICAgIHJldHVybiBlbDtcbiAgICAgICAgfVxuICAgICAgICBlbCA9IGVsLnBhcmVudEVsZW1lbnQgfHwgZWwucGFyZW50Tm9kZTtcbiAgICB9IHdoaWxlIChlbCAhPT0gbnVsbCAmJiBlbC5ub2RlVHlwZSA9PT0gMSk7XG4gICAgcmV0dXJuIG51bGw7XG59O1xuZnVuY3Rpb24gZWxlbWVudENsb3Nlc3QoZWwsIHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIGNsb3Nlc3RNZXRob2QuY2FsbChlbCwgc2VsZWN0b3IpO1xufVxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXMoZWwsIHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIG1hdGNoZXNNZXRob2QuY2FsbChlbCwgc2VsZWN0b3IpO1xufVxuLy8gYWNjZXB0cyBtdWx0aXBsZSBzdWJqZWN0IGVsc1xuLy8gcmV0dXJucyBhIHJlYWwgYXJyYXkuIGdvb2QgZm9yIG1ldGhvZHMgbGlrZSBmb3JFYWNoXG5mdW5jdGlvbiBmaW5kRWxlbWVudHMoY29udGFpbmVyLCBzZWxlY3Rvcikge1xuICAgIHZhciBjb250YWluZXJzID0gY29udGFpbmVyIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQgPyBbY29udGFpbmVyXSA6IGNvbnRhaW5lcjtcbiAgICB2YXIgYWxsTWF0Y2hlcyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29udGFpbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbWF0Y2hlcyA9IGNvbnRhaW5lcnNbaV0ucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWF0Y2hlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgYWxsTWF0Y2hlcy5wdXNoKG1hdGNoZXNbal0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhbGxNYXRjaGVzO1xufVxuLy8gYWNjZXB0cyBtdWx0aXBsZSBzdWJqZWN0IGVsc1xuLy8gb25seSBxdWVyaWVzIGRpcmVjdCBjaGlsZCBlbGVtZW50c1xuZnVuY3Rpb24gZmluZENoaWxkcmVuKHBhcmVudCwgc2VsZWN0b3IpIHtcbiAgICB2YXIgcGFyZW50cyA9IHBhcmVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ID8gW3BhcmVudF0gOiBwYXJlbnQ7XG4gICAgdmFyIGFsbE1hdGNoZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBwYXJlbnRzW2ldLmNoaWxkcmVuOyAvLyBvbmx5IGV2ZXIgZWxlbWVudHNcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY2hpbGROb2Rlc1tqXTtcbiAgICAgICAgICAgIGlmICghc2VsZWN0b3IgfHwgZWxlbWVudE1hdGNoZXMoY2hpbGROb2RlLCBzZWxlY3RvcikpIHtcbiAgICAgICAgICAgICAgICBhbGxNYXRjaGVzLnB1c2goY2hpbGROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYWxsTWF0Y2hlcztcbn1cbi8vIEF0dHJpYnV0ZXNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGZvcmNlQ2xhc3NOYW1lKGVsLCBjbGFzc05hbWUsIGJvb2wpIHtcbiAgICBpZiAoYm9vbCkge1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBlbC5jbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSk7XG4gICAgfVxufVxuLy8gU3R5bGVcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbnZhciBQSVhFTF9QUk9QX1JFID0gLyh0b3B8bGVmdHxyaWdodHxib3R0b218d2lkdGh8aGVpZ2h0KSQvaTtcbmZ1bmN0aW9uIGFwcGx5U3R5bGUoZWwsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgYXBwbHlTdHlsZVByb3AoZWwsIHByb3BOYW1lLCBwcm9wc1twcm9wTmFtZV0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFwcGx5U3R5bGVQcm9wKGVsLCBuYW1lLCB2YWwpIHtcbiAgICBpZiAodmFsID09IG51bGwpIHtcbiAgICAgICAgZWwuc3R5bGVbbmFtZV0gPSAnJztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicgJiYgUElYRUxfUFJPUF9SRS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gdmFsICsgJ3B4JztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gdmFsO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcG9pbnRJbnNpZGVSZWN0KHBvaW50LCByZWN0KSB7XG4gICAgcmV0dXJuIHBvaW50LmxlZnQgPj0gcmVjdC5sZWZ0ICYmXG4gICAgICAgIHBvaW50LmxlZnQgPCByZWN0LnJpZ2h0ICYmXG4gICAgICAgIHBvaW50LnRvcCA+PSByZWN0LnRvcCAmJlxuICAgICAgICBwb2ludC50b3AgPCByZWN0LmJvdHRvbTtcbn1cbi8vIFJldHVybnMgYSBuZXcgcmVjdGFuZ2xlIHRoYXQgaXMgdGhlIGludGVyc2VjdGlvbiBvZiB0aGUgdHdvIHJlY3RhbmdsZXMuIElmIHRoZXkgZG9uJ3QgaW50ZXJzZWN0LCByZXR1cm5zIGZhbHNlXG5mdW5jdGlvbiBpbnRlcnNlY3RSZWN0cyhyZWN0MSwgcmVjdDIpIHtcbiAgICB2YXIgcmVzID0ge1xuICAgICAgICBsZWZ0OiBNYXRoLm1heChyZWN0MS5sZWZ0LCByZWN0Mi5sZWZ0KSxcbiAgICAgICAgcmlnaHQ6IE1hdGgubWluKHJlY3QxLnJpZ2h0LCByZWN0Mi5yaWdodCksXG4gICAgICAgIHRvcDogTWF0aC5tYXgocmVjdDEudG9wLCByZWN0Mi50b3ApLFxuICAgICAgICBib3R0b206IE1hdGgubWluKHJlY3QxLmJvdHRvbSwgcmVjdDIuYm90dG9tKVxuICAgIH07XG4gICAgaWYgKHJlcy5sZWZ0IDwgcmVzLnJpZ2h0ICYmIHJlcy50b3AgPCByZXMuYm90dG9tKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIHRyYW5zbGF0ZVJlY3QocmVjdCwgZGVsdGFYLCBkZWx0YVkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiByZWN0LmxlZnQgKyBkZWx0YVgsXG4gICAgICAgIHJpZ2h0OiByZWN0LnJpZ2h0ICsgZGVsdGFYLFxuICAgICAgICB0b3A6IHJlY3QudG9wICsgZGVsdGFZLFxuICAgICAgICBib3R0b206IHJlY3QuYm90dG9tICsgZGVsdGFZXG4gICAgfTtcbn1cbi8vIFJldHVybnMgYSBuZXcgcG9pbnQgdGhhdCB3aWxsIGhhdmUgYmVlbiBtb3ZlZCB0byByZXNpZGUgd2l0aGluIHRoZSBnaXZlbiByZWN0YW5nbGVcbmZ1bmN0aW9uIGNvbnN0cmFpblBvaW50KHBvaW50LCByZWN0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogTWF0aC5taW4oTWF0aC5tYXgocG9pbnQubGVmdCwgcmVjdC5sZWZ0KSwgcmVjdC5yaWdodCksXG4gICAgICAgIHRvcDogTWF0aC5taW4oTWF0aC5tYXgocG9pbnQudG9wLCByZWN0LnRvcCksIHJlY3QuYm90dG9tKVxuICAgIH07XG59XG4vLyBSZXR1cm5zIGEgcG9pbnQgdGhhdCBpcyB0aGUgY2VudGVyIG9mIHRoZSBnaXZlbiByZWN0YW5nbGVcbmZ1bmN0aW9uIGdldFJlY3RDZW50ZXIocmVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IChyZWN0LmxlZnQgKyByZWN0LnJpZ2h0KSAvIDIsXG4gICAgICAgIHRvcDogKHJlY3QudG9wICsgcmVjdC5ib3R0b20pIC8gMlxuICAgIH07XG59XG4vLyBTdWJ0cmFjdHMgcG9pbnQyJ3MgY29vcmRpbmF0ZXMgZnJvbSBwb2ludDEncyBjb29yZGluYXRlcywgcmV0dXJuaW5nIGEgZGVsdGFcbmZ1bmN0aW9uIGRpZmZQb2ludHMocG9pbnQxLCBwb2ludDIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiBwb2ludDEubGVmdCAtIHBvaW50Mi5sZWZ0LFxuICAgICAgICB0b3A6IHBvaW50MS50b3AgLSBwb2ludDIudG9wXG4gICAgfTtcbn1cblxuLy8gTG9naWMgZm9yIGRldGVybWluaW5nIGlmLCB3aGVuIHRoZSBlbGVtZW50IGlzIHJpZ2h0LXRvLWxlZnQsIHRoZSBzY3JvbGxiYXIgYXBwZWFycyBvbiB0aGUgbGVmdCBzaWRlXG52YXIgaXNSdGxTY3JvbGxiYXJPbkxlZnQgPSBudWxsO1xuZnVuY3Rpb24gZ2V0SXNSdGxTY3JvbGxiYXJPbkxlZnQoKSB7XG4gICAgaWYgKGlzUnRsU2Nyb2xsYmFyT25MZWZ0ID09PSBudWxsKSB7XG4gICAgICAgIGlzUnRsU2Nyb2xsYmFyT25MZWZ0ID0gY29tcHV0ZUlzUnRsU2Nyb2xsYmFyT25MZWZ0KCk7XG4gICAgfVxuICAgIHJldHVybiBpc1J0bFNjcm9sbGJhck9uTGVmdDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVJc1J0bFNjcm9sbGJhck9uTGVmdCgpIHtcbiAgICB2YXIgb3V0ZXJFbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHtcbiAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgdG9wOiAtMTAwMCxcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICBib3JkZXI6IDAsXG4gICAgICAgICAgICBwYWRkaW5nOiAwLFxuICAgICAgICAgICAgb3ZlcmZsb3c6ICdzY3JvbGwnLFxuICAgICAgICAgICAgZGlyZWN0aW9uOiAncnRsJ1xuICAgICAgICB9XG4gICAgfSwgJzxkaXY+PC9kaXY+Jyk7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChvdXRlckVsKTtcbiAgICB2YXIgaW5uZXJFbCA9IG91dGVyRWwuZmlyc3RDaGlsZDtcbiAgICB2YXIgcmVzID0gaW5uZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ID4gb3V0ZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuICAgIHJlbW92ZUVsZW1lbnQob3V0ZXJFbCk7XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIFRoZSBzY3JvbGxiYXIgd2lkdGggY29tcHV0YXRpb25zIGluIGNvbXB1dGVFZGdlcyBhcmUgc29tZXRpbWVzIGZsYXdlZCB3aGVuIGl0IGNvbWVzIHRvXG4vLyByZXRpbmEgZGlzcGxheXMsIHJvdW5kaW5nLCBhbmQgSUUxMS4gTWFzc2FnZSB0aGVtIGludG8gYSB1c2FibGUgdmFsdWUuXG5mdW5jdGlvbiBzYW5pdGl6ZVNjcm9sbGJhcldpZHRoKHdpZHRoKSB7XG4gICAgd2lkdGggPSBNYXRoLm1heCgwLCB3aWR0aCk7IC8vIG5vIG5lZ2F0aXZlc1xuICAgIHdpZHRoID0gTWF0aC5yb3VuZCh3aWR0aCk7XG4gICAgcmV0dXJuIHdpZHRoO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlRWRnZXMoZWwsIGdldFBhZGRpbmcpIHtcbiAgICBpZiAoZ2V0UGFkZGluZyA9PT0gdm9pZCAwKSB7IGdldFBhZGRpbmcgPSBmYWxzZTsgfVxuICAgIHZhciBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIHZhciBib3JkZXJMZWZ0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5ib3JkZXJMZWZ0V2lkdGgsIDEwKSB8fCAwO1xuICAgIHZhciBib3JkZXJSaWdodCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUuYm9yZGVyUmlnaHRXaWR0aCwgMTApIHx8IDA7XG4gICAgdmFyIGJvcmRlclRvcCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUuYm9yZGVyVG9wV2lkdGgsIDEwKSB8fCAwO1xuICAgIHZhciBib3JkZXJCb3R0b20gPSBwYXJzZUludChjb21wdXRlZFN0eWxlLmJvcmRlckJvdHRvbVdpZHRoLCAxMCkgfHwgMDtcbiAgICAvLyBtdXN0IHVzZSBvZmZzZXQoV2lkdGh8SGVpZ2h0KSBiZWNhdXNlIGNvbXBhdGlibGUgd2l0aCBjbGllbnQoV2lkdGh8SGVpZ2h0KVxuICAgIHZhciBzY3JvbGxiYXJMZWZ0UmlnaHQgPSBzYW5pdGl6ZVNjcm9sbGJhcldpZHRoKGVsLm9mZnNldFdpZHRoIC0gZWwuY2xpZW50V2lkdGggLSBib3JkZXJMZWZ0IC0gYm9yZGVyUmlnaHQpO1xuICAgIHZhciBzY3JvbGxiYXJCb3R0b20gPSBzYW5pdGl6ZVNjcm9sbGJhcldpZHRoKGVsLm9mZnNldEhlaWdodCAtIGVsLmNsaWVudEhlaWdodCAtIGJvcmRlclRvcCAtIGJvcmRlckJvdHRvbSk7XG4gICAgdmFyIHJlcyA9IHtcbiAgICAgICAgYm9yZGVyTGVmdDogYm9yZGVyTGVmdCxcbiAgICAgICAgYm9yZGVyUmlnaHQ6IGJvcmRlclJpZ2h0LFxuICAgICAgICBib3JkZXJUb3A6IGJvcmRlclRvcCxcbiAgICAgICAgYm9yZGVyQm90dG9tOiBib3JkZXJCb3R0b20sXG4gICAgICAgIHNjcm9sbGJhckJvdHRvbTogc2Nyb2xsYmFyQm90dG9tLFxuICAgICAgICBzY3JvbGxiYXJMZWZ0OiAwLFxuICAgICAgICBzY3JvbGxiYXJSaWdodDogMFxuICAgIH07XG4gICAgaWYgKGdldElzUnRsU2Nyb2xsYmFyT25MZWZ0KCkgJiYgY29tcHV0ZWRTdHlsZS5kaXJlY3Rpb24gPT09ICdydGwnKSB7IC8vIGlzIHRoZSBzY3JvbGxiYXIgb24gdGhlIGxlZnQgc2lkZT9cbiAgICAgICAgcmVzLnNjcm9sbGJhckxlZnQgPSBzY3JvbGxiYXJMZWZ0UmlnaHQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXMuc2Nyb2xsYmFyUmlnaHQgPSBzY3JvbGxiYXJMZWZ0UmlnaHQ7XG4gICAgfVxuICAgIGlmIChnZXRQYWRkaW5nKSB7XG4gICAgICAgIHJlcy5wYWRkaW5nTGVmdCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUucGFkZGluZ0xlZnQsIDEwKSB8fCAwO1xuICAgICAgICByZXMucGFkZGluZ1JpZ2h0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nUmlnaHQsIDEwKSB8fCAwO1xuICAgICAgICByZXMucGFkZGluZ1RvcCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUucGFkZGluZ1RvcCwgMTApIHx8IDA7XG4gICAgICAgIHJlcy5wYWRkaW5nQm90dG9tID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nQm90dG9tLCAxMCkgfHwgMDtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGNvbXB1dGVJbm5lclJlY3QoZWwsIGdvV2l0aGluUGFkZGluZykge1xuICAgIGlmIChnb1dpdGhpblBhZGRpbmcgPT09IHZvaWQgMCkgeyBnb1dpdGhpblBhZGRpbmcgPSBmYWxzZTsgfVxuICAgIHZhciBvdXRlclJlY3QgPSBjb21wdXRlUmVjdChlbCk7XG4gICAgdmFyIGVkZ2VzID0gY29tcHV0ZUVkZ2VzKGVsLCBnb1dpdGhpblBhZGRpbmcpO1xuICAgIHZhciByZXMgPSB7XG4gICAgICAgIGxlZnQ6IG91dGVyUmVjdC5sZWZ0ICsgZWRnZXMuYm9yZGVyTGVmdCArIGVkZ2VzLnNjcm9sbGJhckxlZnQsXG4gICAgICAgIHJpZ2h0OiBvdXRlclJlY3QucmlnaHQgLSBlZGdlcy5ib3JkZXJSaWdodCAtIGVkZ2VzLnNjcm9sbGJhclJpZ2h0LFxuICAgICAgICB0b3A6IG91dGVyUmVjdC50b3AgKyBlZGdlcy5ib3JkZXJUb3AsXG4gICAgICAgIGJvdHRvbTogb3V0ZXJSZWN0LmJvdHRvbSAtIGVkZ2VzLmJvcmRlckJvdHRvbSAtIGVkZ2VzLnNjcm9sbGJhckJvdHRvbVxuICAgIH07XG4gICAgaWYgKGdvV2l0aGluUGFkZGluZykge1xuICAgICAgICByZXMubGVmdCArPSBlZGdlcy5wYWRkaW5nTGVmdDtcbiAgICAgICAgcmVzLnJpZ2h0IC09IGVkZ2VzLnBhZGRpbmdSaWdodDtcbiAgICAgICAgcmVzLnRvcCArPSBlZGdlcy5wYWRkaW5nVG9wO1xuICAgICAgICByZXMuYm90dG9tIC09IGVkZ2VzLnBhZGRpbmdCb3R0b207XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBjb21wdXRlUmVjdChlbCkge1xuICAgIHZhciByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogcmVjdC5sZWZ0ICsgd2luZG93LnBhZ2VYT2Zmc2V0LFxuICAgICAgICB0b3A6IHJlY3QudG9wICsgd2luZG93LnBhZ2VZT2Zmc2V0LFxuICAgICAgICByaWdodDogcmVjdC5yaWdodCArIHdpbmRvdy5wYWdlWE9mZnNldCxcbiAgICAgICAgYm90dG9tOiByZWN0LmJvdHRvbSArIHdpbmRvdy5wYWdlWU9mZnNldFxuICAgIH07XG59XG5mdW5jdGlvbiBjb21wdXRlVmlld3BvcnRSZWN0KCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IHdpbmRvdy5wYWdlWE9mZnNldCxcbiAgICAgICAgcmlnaHQ6IHdpbmRvdy5wYWdlWE9mZnNldCArIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCxcbiAgICAgICAgdG9wOiB3aW5kb3cucGFnZVlPZmZzZXQsXG4gICAgICAgIGJvdHRvbTogd2luZG93LnBhZ2VZT2Zmc2V0ICsgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodFxuICAgIH07XG59XG5mdW5jdGlvbiBjb21wdXRlSGVpZ2h0QW5kTWFyZ2lucyhlbCkge1xuICAgIHJldHVybiBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgKyBjb21wdXRlVk1hcmdpbnMoZWwpO1xufVxuZnVuY3Rpb24gY29tcHV0ZVZNYXJnaW5zKGVsKSB7XG4gICAgdmFyIGNvbXB1dGVkID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIHJldHVybiBwYXJzZUludChjb21wdXRlZC5tYXJnaW5Ub3AsIDEwKSArXG4gICAgICAgIHBhcnNlSW50KGNvbXB1dGVkLm1hcmdpbkJvdHRvbSwgMTApO1xufVxuLy8gZG9lcyBub3QgcmV0dXJuIHdpbmRvd1xuZnVuY3Rpb24gZ2V0Q2xpcHBpbmdQYXJlbnRzKGVsKSB7XG4gICAgdmFyIHBhcmVudHMgPSBbXTtcbiAgICB3aGlsZSAoZWwgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgeyAvLyB3aWxsIHN0b3Agd2hlbiBnZXRzIHRvIGRvY3VtZW50IG9yIG51bGxcbiAgICAgICAgdmFyIGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICAgIGlmIChjb21wdXRlZFN0eWxlLnBvc2l0aW9uID09PSAnZml4ZWQnKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoKC8oYXV0b3xzY3JvbGwpLykudGVzdChjb21wdXRlZFN0eWxlLm92ZXJmbG93ICsgY29tcHV0ZWRTdHlsZS5vdmVyZmxvd1kgKyBjb21wdXRlZFN0eWxlLm92ZXJmbG93WCkpIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaChlbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWwgPSBlbC5wYXJlbnROb2RlO1xuICAgIH1cbiAgICByZXR1cm4gcGFyZW50cztcbn1cbmZ1bmN0aW9uIGNvbXB1dGVDbGlwcGluZ1JlY3QoZWwpIHtcbiAgICByZXR1cm4gZ2V0Q2xpcHBpbmdQYXJlbnRzKGVsKVxuICAgICAgICAubWFwKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gY29tcHV0ZUlubmVyUmVjdChlbCk7XG4gICAgfSlcbiAgICAgICAgLmNvbmNhdChjb21wdXRlVmlld3BvcnRSZWN0KCkpXG4gICAgICAgIC5yZWR1Y2UoZnVuY3Rpb24gKHJlY3QwLCByZWN0MSkge1xuICAgICAgICByZXR1cm4gaW50ZXJzZWN0UmVjdHMocmVjdDAsIHJlY3QxKSB8fCByZWN0MTsgLy8gc2hvdWxkIGFsd2F5cyBpbnRlcnNlY3RcbiAgICB9KTtcbn1cblxuLy8gU3RvcHMgYSBtb3VzZS90b3VjaCBldmVudCBmcm9tIGRvaW5nIGl0J3MgbmF0aXZlIGJyb3dzZXIgYWN0aW9uXG5mdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChldikge1xuICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG59XG4vLyBFdmVudCBEZWxlZ2F0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBsaXN0ZW5CeVNlbGVjdG9yKGNvbnRhaW5lciwgZXZlbnRUeXBlLCBzZWxlY3RvciwgaGFuZGxlcikge1xuICAgIGZ1bmN0aW9uIHJlYWxIYW5kbGVyKGV2KSB7XG4gICAgICAgIHZhciBtYXRjaGVkQ2hpbGQgPSBlbGVtZW50Q2xvc2VzdChldi50YXJnZXQsIHNlbGVjdG9yKTtcbiAgICAgICAgaWYgKG1hdGNoZWRDaGlsZCkge1xuICAgICAgICAgICAgaGFuZGxlci5jYWxsKG1hdGNoZWRDaGlsZCwgZXYsIG1hdGNoZWRDaGlsZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCByZWFsSGFuZGxlcik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCByZWFsSGFuZGxlcik7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGxpc3RlblRvSG92ZXJCeVNlbGVjdG9yKGNvbnRhaW5lciwgc2VsZWN0b3IsIG9uTW91c2VFbnRlciwgb25Nb3VzZUxlYXZlKSB7XG4gICAgdmFyIGN1cnJlbnRNYXRjaGVkQ2hpbGQ7XG4gICAgcmV0dXJuIGxpc3RlbkJ5U2VsZWN0b3IoY29udGFpbmVyLCAnbW91c2VvdmVyJywgc2VsZWN0b3IsIGZ1bmN0aW9uIChldiwgbWF0Y2hlZENoaWxkKSB7XG4gICAgICAgIGlmIChtYXRjaGVkQ2hpbGQgIT09IGN1cnJlbnRNYXRjaGVkQ2hpbGQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRNYXRjaGVkQ2hpbGQgPSBtYXRjaGVkQ2hpbGQ7XG4gICAgICAgICAgICBvbk1vdXNlRW50ZXIoZXYsIG1hdGNoZWRDaGlsZCk7XG4gICAgICAgICAgICB2YXIgcmVhbE9uTW91c2VMZWF2ZV8xID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudE1hdGNoZWRDaGlsZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgb25Nb3VzZUxlYXZlKGV2LCBtYXRjaGVkQ2hpbGQpO1xuICAgICAgICAgICAgICAgIG1hdGNoZWRDaGlsZC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgcmVhbE9uTW91c2VMZWF2ZV8xKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBsaXN0ZW4gdG8gdGhlIG5leHQgbW91c2VsZWF2ZSwgYW5kIHRoZW4gdW5hdHRhY2hcbiAgICAgICAgICAgIG1hdGNoZWRDaGlsZC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgcmVhbE9uTW91c2VMZWF2ZV8xKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLy8gQW5pbWF0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG52YXIgdHJhbnNpdGlvbkV2ZW50TmFtZXMgPSBbXG4gICAgJ3dlYmtpdFRyYW5zaXRpb25FbmQnLFxuICAgICdvdHJhbnNpdGlvbmVuZCcsXG4gICAgJ29UcmFuc2l0aW9uRW5kJyxcbiAgICAnbXNUcmFuc2l0aW9uRW5kJyxcbiAgICAndHJhbnNpdGlvbmVuZCdcbl07XG4vLyB0cmlnZ2VyZWQgb25seSB3aGVuIHRoZSBuZXh0IHNpbmdsZSBzdWJzZXF1ZW50IHRyYW5zaXRpb24gZmluaXNoZXNcbmZ1bmN0aW9uIHdoZW5UcmFuc2l0aW9uRG9uZShlbCwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVhbENhbGxiYWNrID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGNhbGxiYWNrKGV2KTtcbiAgICAgICAgdHJhbnNpdGlvbkV2ZW50TmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgcmVhbENhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICB0cmFuc2l0aW9uRXZlbnROYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChldmVudE5hbWUpIHtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIHJlYWxDYWxsYmFjayk7IC8vIGNyb3NzLWJyb3dzZXIgd2F5IHRvIGRldGVybWluZSB3aGVuIHRoZSB0cmFuc2l0aW9uIGZpbmlzaGVzXG4gICAgfSk7XG59XG5cbnZhciBEQVlfSURTID0gWydzdW4nLCAnbW9uJywgJ3R1ZScsICd3ZWQnLCAndGh1JywgJ2ZyaScsICdzYXQnXTtcbi8vIEFkZGluZ1xuZnVuY3Rpb24gYWRkV2Vla3MobSwgbikge1xuICAgIHZhciBhID0gZGF0ZVRvVXRjQXJyYXkobSk7XG4gICAgYVsyXSArPSBuICogNztcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoYSk7XG59XG5mdW5jdGlvbiBhZGREYXlzKG0sIG4pIHtcbiAgICB2YXIgYSA9IGRhdGVUb1V0Y0FycmF5KG0pO1xuICAgIGFbMl0gKz0gbjtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoYSk7XG59XG5mdW5jdGlvbiBhZGRNcyhtLCBuKSB7XG4gICAgdmFyIGEgPSBkYXRlVG9VdGNBcnJheShtKTtcbiAgICBhWzZdICs9IG47XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGEpO1xufVxuLy8gRGlmZmluZyAoYWxsIHJldHVybiBmbG9hdHMpXG5mdW5jdGlvbiBkaWZmV2Vla3MobTAsIG0xKSB7XG4gICAgcmV0dXJuIGRpZmZEYXlzKG0wLCBtMSkgLyA3O1xufVxuZnVuY3Rpb24gZGlmZkRheXMobTAsIG0xKSB7XG4gICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gKDEwMDAgKiA2MCAqIDYwICogMjQpO1xufVxuZnVuY3Rpb24gZGlmZkhvdXJzKG0wLCBtMSkge1xuICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvICgxMDAwICogNjAgKiA2MCk7XG59XG5mdW5jdGlvbiBkaWZmTWludXRlcyhtMCwgbTEpIHtcbiAgICByZXR1cm4gKG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSkgLyAoMTAwMCAqIDYwKTtcbn1cbmZ1bmN0aW9uIGRpZmZTZWNvbmRzKG0wLCBtMSkge1xuICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvIDEwMDA7XG59XG5mdW5jdGlvbiBkaWZmRGF5QW5kVGltZShtMCwgbTEpIHtcbiAgICB2YXIgbTBkYXkgPSBzdGFydE9mRGF5KG0wKTtcbiAgICB2YXIgbTFkYXkgPSBzdGFydE9mRGF5KG0xKTtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogMCxcbiAgICAgICAgbW9udGhzOiAwLFxuICAgICAgICBkYXlzOiBNYXRoLnJvdW5kKGRpZmZEYXlzKG0wZGF5LCBtMWRheSkpLFxuICAgICAgICBtaWxsaXNlY29uZHM6IChtMS52YWx1ZU9mKCkgLSBtMWRheS52YWx1ZU9mKCkpIC0gKG0wLnZhbHVlT2YoKSAtIG0wZGF5LnZhbHVlT2YoKSlcbiAgICB9O1xufVxuLy8gRGlmZmluZyBXaG9sZSBVbml0c1xuZnVuY3Rpb24gZGlmZldob2xlV2Vla3MobTAsIG0xKSB7XG4gICAgdmFyIGQgPSBkaWZmV2hvbGVEYXlzKG0wLCBtMSk7XG4gICAgaWYgKGQgIT09IG51bGwgJiYgZCAlIDcgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGQgLyA3O1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIGRpZmZXaG9sZURheXMobTAsIG0xKSB7XG4gICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKGRpZmZEYXlzKG0wLCBtMSkpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbi8vIFN0YXJ0LU9mXG5mdW5jdGlvbiBzdGFydE9mRGF5KG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKClcbiAgICBdKTtcbn1cbmZ1bmN0aW9uIHN0YXJ0T2ZIb3VyKG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgICAgIG0uZ2V0VVRDSG91cnMoKVxuICAgIF0pO1xufVxuZnVuY3Rpb24gc3RhcnRPZk1pbnV0ZShtKSB7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKFtcbiAgICAgICAgbS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBtLmdldFVUQ01vbnRoKCksXG4gICAgICAgIG0uZ2V0VVRDRGF0ZSgpLFxuICAgICAgICBtLmdldFVUQ0hvdXJzKCksXG4gICAgICAgIG0uZ2V0VVRDTWludXRlcygpXG4gICAgXSk7XG59XG5mdW5jdGlvbiBzdGFydE9mU2Vjb25kKG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgICAgIG0uZ2V0VVRDSG91cnMoKSxcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCksXG4gICAgICAgIG0uZ2V0VVRDU2Vjb25kcygpXG4gICAgXSk7XG59XG4vLyBXZWVrIENvbXB1dGF0aW9uXG5mdW5jdGlvbiB3ZWVrT2ZZZWFyKG1hcmtlciwgZG93LCBkb3kpIHtcbiAgICB2YXIgeSA9IG1hcmtlci5nZXRVVENGdWxsWWVhcigpO1xuICAgIHZhciB3ID0gd2Vla09mR2l2ZW5ZZWFyKG1hcmtlciwgeSwgZG93LCBkb3kpO1xuICAgIGlmICh3IDwgMSkge1xuICAgICAgICByZXR1cm4gd2Vla09mR2l2ZW5ZZWFyKG1hcmtlciwgeSAtIDEsIGRvdywgZG95KTtcbiAgICB9XG4gICAgdmFyIG5leHRXID0gd2Vla09mR2l2ZW5ZZWFyKG1hcmtlciwgeSArIDEsIGRvdywgZG95KTtcbiAgICBpZiAobmV4dFcgPj0gMSkge1xuICAgICAgICByZXR1cm4gTWF0aC5taW4odywgbmV4dFcpO1xuICAgIH1cbiAgICByZXR1cm4gdztcbn1cbmZ1bmN0aW9uIHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHllYXIsIGRvdywgZG95KSB7XG4gICAgdmFyIGZpcnN0V2Vla1N0YXJ0ID0gYXJyYXlUb1V0Y0RhdGUoW3llYXIsIDAsIDEgKyBmaXJzdFdlZWtPZmZzZXQoeWVhciwgZG93LCBkb3kpXSk7XG4gICAgdmFyIGRheVN0YXJ0ID0gc3RhcnRPZkRheShtYXJrZXIpO1xuICAgIHZhciBkYXlzID0gTWF0aC5yb3VuZChkaWZmRGF5cyhmaXJzdFdlZWtTdGFydCwgZGF5U3RhcnQpKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihkYXlzIC8gNykgKyAxOyAvLyB6ZXJvLWluZGV4ZWRcbn1cbi8vIHN0YXJ0LW9mLWZpcnN0LXdlZWsgLSBzdGFydC1vZi15ZWFyXG5mdW5jdGlvbiBmaXJzdFdlZWtPZmZzZXQoeWVhciwgZG93LCBkb3kpIHtcbiAgICAvLyBmaXJzdC13ZWVrIGRheSAtLSB3aGljaCBqYW51YXJ5IGlzIGFsd2F5cyBpbiB0aGUgZmlyc3Qgd2VlayAoNCBmb3IgaXNvLCAxIGZvciBvdGhlcilcbiAgICB2YXIgZndkID0gNyArIGRvdyAtIGRveTtcbiAgICAvLyBmaXJzdC13ZWVrIGRheSBsb2NhbCB3ZWVrZGF5IC0tIHdoaWNoIGxvY2FsIHdlZWtkYXkgaXMgZndkXG4gICAgdmFyIGZ3ZGx3ID0gKDcgKyBhcnJheVRvVXRjRGF0ZShbeWVhciwgMCwgZndkXSkuZ2V0VVRDRGF5KCkgLSBkb3cpICUgNztcbiAgICByZXR1cm4gLWZ3ZGx3ICsgZndkIC0gMTtcbn1cbi8vIEFycmF5IENvbnZlcnNpb25cbmZ1bmN0aW9uIGRhdGVUb0xvY2FsQXJyYXkoZGF0ZSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgICBkYXRlLmdldERhdGUoKSxcbiAgICAgICAgZGF0ZS5nZXRIb3VycygpLFxuICAgICAgICBkYXRlLmdldE1pbnV0ZXMoKSxcbiAgICAgICAgZGF0ZS5nZXRTZWNvbmRzKCksXG4gICAgICAgIGRhdGUuZ2V0TWlsbGlzZWNvbmRzKClcbiAgICBdO1xufVxuZnVuY3Rpb24gYXJyYXlUb0xvY2FsRGF0ZShhKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKGFbMF0sIGFbMV0gfHwgMCwgYVsyXSA9PSBudWxsID8gMSA6IGFbMl0sIC8vIGRheSBvZiBtb250aFxuICAgIGFbM10gfHwgMCwgYVs0XSB8fCAwLCBhWzVdIHx8IDApO1xufVxuZnVuY3Rpb24gZGF0ZVRvVXRjQXJyYXkoZGF0ZSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGRhdGUuZ2V0VVRDRnVsbFllYXIoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENNb250aCgpLFxuICAgICAgICBkYXRlLmdldFVUQ0RhdGUoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENIb3VycygpLFxuICAgICAgICBkYXRlLmdldFVUQ01pbnV0ZXMoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENTZWNvbmRzKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDTWlsbGlzZWNvbmRzKClcbiAgICBdO1xufVxuZnVuY3Rpb24gYXJyYXlUb1V0Y0RhdGUoYSkge1xuICAgIC8vIGFjY29yZGluZyB0byB3ZWIgc3RhbmRhcmRzIChhbmQgU2FmYXJpKSwgYSBtb250aCBpbmRleCBpcyByZXF1aXJlZC5cbiAgICAvLyBtYXNzYWdlIGlmIG9ubHkgZ2l2ZW4gYSB5ZWFyLlxuICAgIGlmIChhLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBhID0gYS5jb25jYXQoWzBdKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDLmFwcGx5KERhdGUsIGEpKTtcbn1cbi8vIE90aGVyIFV0aWxzXG5mdW5jdGlvbiBpc1ZhbGlkRGF0ZShtKSB7XG4gICAgcmV0dXJuICFpc05hTihtLnZhbHVlT2YoKSk7XG59XG5mdW5jdGlvbiB0aW1lQXNNcyhtKSB7XG4gICAgcmV0dXJuIG0uZ2V0VVRDSG91cnMoKSAqIDEwMDAgKiA2MCAqIDYwICtcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCkgKiAxMDAwICogNjAgK1xuICAgICAgICBtLmdldFVUQ1NlY29uZHMoKSAqIDEwMDAgK1xuICAgICAgICBtLmdldFVUQ01pbGxpc2Vjb25kcygpO1xufVxuXG52YXIgSU5URVJOQUxfVU5JVFMgPSBbJ3llYXJzJywgJ21vbnRocycsICdkYXlzJywgJ21pbGxpc2Vjb25kcyddO1xudmFyIFBBUlNFX1JFID0gL14oLT8pKD86KFxcZCspXFwuKT8oXFxkKyk6KFxcZFxcZCkoPzo6KFxcZFxcZCkoPzpcXC4oXFxkXFxkXFxkKSk/KT8vO1xuLy8gUGFyc2luZyBhbmQgQ3JlYXRpb25cbmZ1bmN0aW9uIGNyZWF0ZUR1cmF0aW9uKGlucHV0LCB1bml0KSB7XG4gICAgdmFyIF9hO1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVN0cmluZyhpbnB1dCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgaW5wdXQpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgIHJldHVybiBub3JtYWxpemVPYmplY3QoaW5wdXQpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiBub3JtYWxpemVPYmplY3QoKF9hID0ge30sIF9hW3VuaXQgfHwgJ21pbGxpc2Vjb25kcyddID0gaW5wdXQsIF9hKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59XG5mdW5jdGlvbiBwYXJzZVN0cmluZyhzKSB7XG4gICAgdmFyIG0gPSBQQVJTRV9SRS5leGVjKHMpO1xuICAgIGlmIChtKSB7XG4gICAgICAgIHZhciBzaWduID0gbVsxXSA/IC0xIDogMTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHllYXJzOiAwLFxuICAgICAgICAgICAgbW9udGhzOiAwLFxuICAgICAgICAgICAgZGF5czogc2lnbiAqIChtWzJdID8gcGFyc2VJbnQobVsyXSwgMTApIDogMCksXG4gICAgICAgICAgICBtaWxsaXNlY29uZHM6IHNpZ24gKiAoKG1bM10gPyBwYXJzZUludChtWzNdLCAxMCkgOiAwKSAqIDYwICogNjAgKiAxMDAwICsgLy8gaG91cnNcbiAgICAgICAgICAgICAgICAobVs0XSA/IHBhcnNlSW50KG1bNF0sIDEwKSA6IDApICogNjAgKiAxMDAwICsgLy8gbWludXRlc1xuICAgICAgICAgICAgICAgIChtWzVdID8gcGFyc2VJbnQobVs1XSwgMTApIDogMCkgKiAxMDAwICsgLy8gc2Vjb25kc1xuICAgICAgICAgICAgICAgIChtWzZdID8gcGFyc2VJbnQobVs2XSwgMTApIDogMCkgLy8gbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBub3JtYWxpemVPYmplY3Qob2JqKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IG9iai55ZWFycyB8fCBvYmoueWVhciB8fCAwLFxuICAgICAgICBtb250aHM6IG9iai5tb250aHMgfHwgb2JqLm1vbnRoIHx8IDAsXG4gICAgICAgIGRheXM6IChvYmouZGF5cyB8fCBvYmouZGF5IHx8IDApICtcbiAgICAgICAgICAgIGdldFdlZWtzRnJvbUlucHV0KG9iaikgKiA3LFxuICAgICAgICBtaWxsaXNlY29uZHM6IChvYmouaG91cnMgfHwgb2JqLmhvdXIgfHwgMCkgKiA2MCAqIDYwICogMTAwMCArIC8vIGhvdXJzXG4gICAgICAgICAgICAob2JqLm1pbnV0ZXMgfHwgb2JqLm1pbnV0ZSB8fCAwKSAqIDYwICogMTAwMCArIC8vIG1pbnV0ZXNcbiAgICAgICAgICAgIChvYmouc2Vjb25kcyB8fCBvYmouc2Vjb25kIHx8IDApICogMTAwMCArIC8vIHNlY29uZHNcbiAgICAgICAgICAgIChvYmoubWlsbGlzZWNvbmRzIHx8IG9iai5taWxsaXNlY29uZCB8fCBvYmoubXMgfHwgMCkgLy8gbXNcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0V2Vla3NGcm9tSW5wdXQob2JqKSB7XG4gICAgcmV0dXJuIG9iai53ZWVrcyB8fCBvYmoud2VlayB8fCAwO1xufVxuLy8gRXF1YWxpdHlcbmZ1bmN0aW9uIGR1cmF0aW9uc0VxdWFsKGQwLCBkMSkge1xuICAgIHJldHVybiBkMC55ZWFycyA9PT0gZDEueWVhcnMgJiZcbiAgICAgICAgZDAubW9udGhzID09PSBkMS5tb250aHMgJiZcbiAgICAgICAgZDAuZGF5cyA9PT0gZDEuZGF5cyAmJlxuICAgICAgICBkMC5taWxsaXNlY29uZHMgPT09IGQxLm1pbGxpc2Vjb25kcztcbn1cbmZ1bmN0aW9uIGlzU2luZ2xlRGF5KGR1cikge1xuICAgIHJldHVybiBkdXIueWVhcnMgPT09IDAgJiYgZHVyLm1vbnRocyA9PT0gMCAmJiBkdXIuZGF5cyA9PT0gMSAmJiBkdXIubWlsbGlzZWNvbmRzID09PSAwO1xufVxuLy8gU2ltcGxlIE1hdGhcbmZ1bmN0aW9uIGFkZER1cmF0aW9ucyhkMCwgZDEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZDAueWVhcnMgKyBkMS55ZWFycyxcbiAgICAgICAgbW9udGhzOiBkMC5tb250aHMgKyBkMS5tb250aHMsXG4gICAgICAgIGRheXM6IGQwLmRheXMgKyBkMS5kYXlzLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQwLm1pbGxpc2Vjb25kcyArIGQxLm1pbGxpc2Vjb25kc1xuICAgIH07XG59XG5mdW5jdGlvbiBzdWJ0cmFjdER1cmF0aW9ucyhkMSwgZDApIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZDEueWVhcnMgLSBkMC55ZWFycyxcbiAgICAgICAgbW9udGhzOiBkMS5tb250aHMgLSBkMC5tb250aHMsXG4gICAgICAgIGRheXM6IGQxLmRheXMgLSBkMC5kYXlzLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQxLm1pbGxpc2Vjb25kcyAtIGQwLm1pbGxpc2Vjb25kc1xuICAgIH07XG59XG5mdW5jdGlvbiBtdWx0aXBseUR1cmF0aW9uKGQsIG4pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZC55ZWFycyAqIG4sXG4gICAgICAgIG1vbnRoczogZC5tb250aHMgKiBuLFxuICAgICAgICBkYXlzOiBkLmRheXMgKiBuLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQubWlsbGlzZWNvbmRzICogblxuICAgIH07XG59XG4vLyBDb252ZXJzaW9uc1xuLy8gXCJSb3VnaFwiIGJlY2F1c2UgdGhleSBhcmUgYmFzZWQgb24gYXZlcmFnZS1jYXNlIEdyZWdvcmlhbiBtb250aHMveWVhcnNcbmZ1bmN0aW9uIGFzUm91Z2hZZWFycyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaERheXMoZHVyKSAvIDM2NTtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hNb250aHMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hEYXlzKGR1cikgLyAzMDtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hEYXlzKGR1cikge1xuICAgIHJldHVybiBhc1JvdWdoTXMoZHVyKSAvIDg2NGU1O1xufVxuZnVuY3Rpb24gYXNSb3VnaE1pbnV0ZXMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hNcyhkdXIpIC8gKDEwMDAgKiA2MCk7XG59XG5mdW5jdGlvbiBhc1JvdWdoU2Vjb25kcyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaE1zKGR1cikgLyAxMDAwO1xufVxuZnVuY3Rpb24gYXNSb3VnaE1zKGR1cikge1xuICAgIHJldHVybiBkdXIueWVhcnMgKiAoMzY1ICogODY0ZTUpICtcbiAgICAgICAgZHVyLm1vbnRocyAqICgzMCAqIDg2NGU1KSArXG4gICAgICAgIGR1ci5kYXlzICogODY0ZTUgK1xuICAgICAgICBkdXIubWlsbGlzZWNvbmRzO1xufVxuLy8gQWR2YW5jZWQgTWF0aFxuZnVuY3Rpb24gd2hvbGVEaXZpZGVEdXJhdGlvbnMobnVtZXJhdG9yLCBkZW5vbWluYXRvcikge1xuICAgIHZhciByZXMgPSBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgSU5URVJOQUxfVU5JVFMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHVuaXQgPSBJTlRFUk5BTF9VTklUU1tpXTtcbiAgICAgICAgaWYgKGRlbm9taW5hdG9yW3VuaXRdKSB7XG4gICAgICAgICAgICB2YXIgbG9jYWxSZXMgPSBudW1lcmF0b3JbdW5pdF0gLyBkZW5vbWluYXRvclt1bml0XTtcbiAgICAgICAgICAgIGlmICghaXNJbnQobG9jYWxSZXMpIHx8IChyZXMgIT09IG51bGwgJiYgcmVzICE9PSBsb2NhbFJlcykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcyA9IGxvY2FsUmVzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG51bWVyYXRvclt1bml0XSkge1xuICAgICAgICAgICAgLy8gbmVlZHMgdG8gZGl2aWRlIGJ5IHNvbWV0aGluZyBidXQgY2FuJ3QhXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGR1ciwgZG9udFJldHVybldlZWtzKSB7XG4gICAgdmFyIG1zID0gZHVyLm1pbGxpc2Vjb25kcztcbiAgICBpZiAobXMpIHtcbiAgICAgICAgaWYgKG1zICUgMTAwMCAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IG1zIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zICUgKDEwMDAgKiA2MCkgIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdzZWNvbmQnLCB2YWx1ZTogbXMgLyAxMDAwIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zICUgKDEwMDAgKiA2MCAqIDYwKSAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbnV0ZScsIHZhbHVlOiBtcyAvICgxMDAwICogNjApIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnaG91cicsIHZhbHVlOiBtcyAvICgxMDAwICogNjAgKiA2MCkgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZHVyLmRheXMpIHtcbiAgICAgICAgaWYgKCFkb250UmV0dXJuV2Vla3MgJiYgZHVyLmRheXMgJSA3ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnd2VlaycsIHZhbHVlOiBkdXIuZGF5cyAvIDcgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB1bml0OiAnZGF5JywgdmFsdWU6IGR1ci5kYXlzIH07XG4gICAgfVxuICAgIGlmIChkdXIubW9udGhzKSB7XG4gICAgICAgIHJldHVybiB7IHVuaXQ6ICdtb250aCcsIHZhbHVlOiBkdXIubW9udGhzIH07XG4gICAgfVxuICAgIGlmIChkdXIueWVhcnMpIHtcbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3llYXInLCB2YWx1ZTogZHVyLnllYXJzIH07XG4gICAgfVxuICAgIHJldHVybiB7IHVuaXQ6ICdtaWxsaXNlY29uZCcsIHZhbHVlOiAwIH07XG59XG5cbi8qIEZ1bGxDYWxlbmRhci1zcGVjaWZpYyBET00gVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbi8vIEdpdmVuIHRoZSBzY3JvbGxiYXIgd2lkdGhzIG9mIHNvbWUgb3RoZXIgY29udGFpbmVyLCBjcmVhdGUgYm9yZGVycy9tYXJnaW5zIG9uIHJvd0VscyBpbiBvcmRlciB0byBtYXRjaCB0aGUgbGVmdFxuLy8gYW5kIHJpZ2h0IHNwYWNlIHRoYXQgd2FzIG9mZnNldCBieSB0aGUgc2Nyb2xsYmFycy4gQSAxLXBpeGVsIGJvcmRlciBmaXJzdCwgdGhlbiBtYXJnaW4gYmV5b25kIHRoYXQuXG5mdW5jdGlvbiBjb21wZW5zYXRlU2Nyb2xsKHJvd0VsLCBzY3JvbGxiYXJXaWR0aHMpIHtcbiAgICBpZiAoc2Nyb2xsYmFyV2lkdGhzLmxlZnQpIHtcbiAgICAgICAgYXBwbHlTdHlsZShyb3dFbCwge1xuICAgICAgICAgICAgYm9yZGVyTGVmdFdpZHRoOiAxLFxuICAgICAgICAgICAgbWFyZ2luTGVmdDogc2Nyb2xsYmFyV2lkdGhzLmxlZnQgLSAxXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoc2Nyb2xsYmFyV2lkdGhzLnJpZ2h0KSB7XG4gICAgICAgIGFwcGx5U3R5bGUocm93RWwsIHtcbiAgICAgICAgICAgIGJvcmRlclJpZ2h0V2lkdGg6IDEsXG4gICAgICAgICAgICBtYXJnaW5SaWdodDogc2Nyb2xsYmFyV2lkdGhzLnJpZ2h0IC0gMVxuICAgICAgICB9KTtcbiAgICB9XG59XG4vLyBVbmRvZXMgY29tcGVuc2F0ZVNjcm9sbCBhbmQgcmVzdG9yZXMgYWxsIGJvcmRlcnMvbWFyZ2luc1xuZnVuY3Rpb24gdW5jb21wZW5zYXRlU2Nyb2xsKHJvd0VsKSB7XG4gICAgYXBwbHlTdHlsZShyb3dFbCwge1xuICAgICAgICBtYXJnaW5MZWZ0OiAnJyxcbiAgICAgICAgbWFyZ2luUmlnaHQ6ICcnLFxuICAgICAgICBib3JkZXJMZWZ0V2lkdGg6ICcnLFxuICAgICAgICBib3JkZXJSaWdodFdpZHRoOiAnJ1xuICAgIH0pO1xufVxuLy8gTWFrZSB0aGUgbW91c2UgY3Vyc29yIGV4cHJlc3MgdGhhdCBhbiBldmVudCBpcyBub3QgYWxsb3dlZCBpbiB0aGUgY3VycmVudCBhcmVhXG5mdW5jdGlvbiBkaXNhYmxlQ3Vyc29yKCkge1xuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgnZmMtbm90LWFsbG93ZWQnKTtcbn1cbi8vIFJldHVybnMgdGhlIG1vdXNlIGN1cnNvciB0byBpdHMgb3JpZ2luYWwgbG9va1xuZnVuY3Rpb24gZW5hYmxlQ3Vyc29yKCkge1xuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnZmMtbm90LWFsbG93ZWQnKTtcbn1cbi8vIEdpdmVuIGEgdG90YWwgYXZhaWxhYmxlIGhlaWdodCB0byBmaWxsLCBoYXZlIGBlbHNgIChlc3NlbnRpYWxseSBjaGlsZCByb3dzKSBleHBhbmQgdG8gYWNjb21vZGF0ZS5cbi8vIEJ5IGRlZmF1bHQsIGFsbCBlbGVtZW50cyB0aGF0IGFyZSBzaG9ydGVyIHRoYW4gdGhlIHJlY29tbWVuZGVkIGhlaWdodCBhcmUgZXhwYW5kZWQgdW5pZm9ybWx5LCBub3QgY29uc2lkZXJpbmdcbi8vIGFueSBvdGhlciBlbHMgdGhhdCBhcmUgYWxyZWFkeSB0b28gdGFsbC4gaWYgYHNob3VsZFJlZGlzdHJpYnV0ZWAgaXMgb24sIGl0IGNvbnNpZGVycyB0aGVzZSB0YWxsIHJvd3MgYW5kXG4vLyByZWR1Y2VzIHRoZSBhdmFpbGFibGUgaGVpZ2h0LlxuZnVuY3Rpb24gZGlzdHJpYnV0ZUhlaWdodChlbHMsIGF2YWlsYWJsZUhlaWdodCwgc2hvdWxkUmVkaXN0cmlidXRlKSB7XG4gICAgLy8gKkZMT09SSU5HIE5PVEUqOiB3ZSBmbG9vciBpbiBjZXJ0YWluIHBsYWNlcyBiZWNhdXNlIHpvb20gY2FuIGdpdmUgaW5hY2N1cmF0ZSBmbG9hdGluZy1wb2ludCBkaW1lbnNpb25zLFxuICAgIC8vIGFuZCBpdCBpcyBiZXR0ZXIgdG8gYmUgc2hvcnRlciB0aGFuIHRhbGxlciwgdG8gYXZvaWQgY3JlYXRpbmcgdW5uZWNlc3Nhcnkgc2Nyb2xsYmFycy5cbiAgICB2YXIgbWluT2Zmc2V0MSA9IE1hdGguZmxvb3IoYXZhaWxhYmxlSGVpZ2h0IC8gZWxzLmxlbmd0aCk7IC8vIGZvciBub24tbGFzdCBlbGVtZW50XG4gICAgdmFyIG1pbk9mZnNldDIgPSBNYXRoLmZsb29yKGF2YWlsYWJsZUhlaWdodCAtIG1pbk9mZnNldDEgKiAoZWxzLmxlbmd0aCAtIDEpKTsgLy8gZm9yIGxhc3QgZWxlbWVudCAqRkxPT1JJTkcgTk9URSpcbiAgICB2YXIgZmxleEVscyA9IFtdOyAvLyBlbGVtZW50cyB0aGF0IGFyZSBhbGxvd2VkIHRvIGV4cGFuZC4gYXJyYXkgb2YgRE9NIG5vZGVzXG4gICAgdmFyIGZsZXhPZmZzZXRzID0gW107IC8vIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpdCB0YWtlcyB1cFxuICAgIHZhciBmbGV4SGVpZ2h0cyA9IFtdOyAvLyBhY3R1YWwgY3NzIGhlaWdodFxuICAgIHZhciB1c2VkSGVpZ2h0ID0gMDtcbiAgICB1bmRpc3RyaWJ1dGVIZWlnaHQoZWxzKTsgLy8gZ2l2ZSBhbGwgZWxlbWVudHMgdGhlaXIgbmF0dXJhbCBoZWlnaHRcbiAgICAvLyBmaW5kIGVsZW1lbnRzIHRoYXQgYXJlIGJlbG93IHRoZSByZWNvbW1lbmRlZCBoZWlnaHQgKGV4cGFuZGFibGUpLlxuICAgIC8vIGltcG9ydGFudCB0byBxdWVyeSBmb3IgaGVpZ2h0cyBpbiBhIHNpbmdsZSBmaXJzdCBwYXNzICh0byBhdm9pZCByZWZsb3cgb3NjaWxsYXRpb24pLlxuICAgIGVscy5mb3JFYWNoKGZ1bmN0aW9uIChlbCwgaSkge1xuICAgICAgICB2YXIgbWluT2Zmc2V0ID0gaSA9PT0gZWxzLmxlbmd0aCAtIDEgPyBtaW5PZmZzZXQyIDogbWluT2Zmc2V0MTtcbiAgICAgICAgdmFyIG5hdHVyYWxIZWlnaHQgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgICAgIHZhciBuYXR1cmFsT2Zmc2V0ID0gbmF0dXJhbEhlaWdodCArIGNvbXB1dGVWTWFyZ2lucyhlbCk7XG4gICAgICAgIGlmIChuYXR1cmFsT2Zmc2V0IDwgbWluT2Zmc2V0KSB7XG4gICAgICAgICAgICBmbGV4RWxzLnB1c2goZWwpO1xuICAgICAgICAgICAgZmxleE9mZnNldHMucHVzaChuYXR1cmFsT2Zmc2V0KTtcbiAgICAgICAgICAgIGZsZXhIZWlnaHRzLnB1c2gobmF0dXJhbEhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyB0aGlzIGVsZW1lbnQgc3RyZXRjaGVzIHBhc3QgcmVjb21tZW5kZWQgaGVpZ2h0IChub24tZXhwYW5kYWJsZSkuIG1hcmsgdGhlIHNwYWNlIGFzIG9jY3VwaWVkLlxuICAgICAgICAgICAgdXNlZEhlaWdodCArPSBuYXR1cmFsT2Zmc2V0O1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgLy8gcmVhZGp1c3QgdGhlIHJlY29tbWVuZGVkIGhlaWdodCB0byBvbmx5IGNvbnNpZGVyIHRoZSBoZWlnaHQgYXZhaWxhYmxlIHRvIG5vbi1tYXhlZC1vdXQgcm93cy5cbiAgICBpZiAoc2hvdWxkUmVkaXN0cmlidXRlKSB7XG4gICAgICAgIGF2YWlsYWJsZUhlaWdodCAtPSB1c2VkSGVpZ2h0O1xuICAgICAgICBtaW5PZmZzZXQxID0gTWF0aC5mbG9vcihhdmFpbGFibGVIZWlnaHQgLyBmbGV4RWxzLmxlbmd0aCk7XG4gICAgICAgIG1pbk9mZnNldDIgPSBNYXRoLmZsb29yKGF2YWlsYWJsZUhlaWdodCAtIG1pbk9mZnNldDEgKiAoZmxleEVscy5sZW5ndGggLSAxKSk7IC8vICpGTE9PUklORyBOT1RFKlxuICAgIH1cbiAgICAvLyBhc3NpZ24gaGVpZ2h0cyB0byBhbGwgZXhwYW5kYWJsZSBlbGVtZW50c1xuICAgIGZsZXhFbHMuZm9yRWFjaChmdW5jdGlvbiAoZWwsIGkpIHtcbiAgICAgICAgdmFyIG1pbk9mZnNldCA9IGkgPT09IGZsZXhFbHMubGVuZ3RoIC0gMSA/IG1pbk9mZnNldDIgOiBtaW5PZmZzZXQxO1xuICAgICAgICB2YXIgbmF0dXJhbE9mZnNldCA9IGZsZXhPZmZzZXRzW2ldO1xuICAgICAgICB2YXIgbmF0dXJhbEhlaWdodCA9IGZsZXhIZWlnaHRzW2ldO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gbWluT2Zmc2V0IC0gKG5hdHVyYWxPZmZzZXQgLSBuYXR1cmFsSGVpZ2h0KTsgLy8gc3VidHJhY3QgdGhlIG1hcmdpbi9wYWRkaW5nXG4gICAgICAgIGlmIChuYXR1cmFsT2Zmc2V0IDwgbWluT2Zmc2V0KSB7IC8vIHdlIGNoZWNrIHRoaXMgYWdhaW4gYmVjYXVzZSByZWRpc3RyaWJ1dGlvbiBtaWdodCBoYXZlIGNoYW5nZWQgdGhpbmdzXG4gICAgICAgICAgICBlbC5zdHlsZS5oZWlnaHQgPSBuZXdIZWlnaHQgKyAncHgnO1xuICAgICAgICB9XG4gICAgfSk7XG59XG4vLyBVbmRvZXMgZGlzdHJ1YnV0ZUhlaWdodCwgcmVzdG9yaW5nIGFsbCBlbHMgdG8gdGhlaXIgbmF0dXJhbCBoZWlnaHRcbmZ1bmN0aW9uIHVuZGlzdHJpYnV0ZUhlaWdodChlbHMpIHtcbiAgICBlbHMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgZWwuc3R5bGUuaGVpZ2h0ID0gJyc7XG4gICAgfSk7XG59XG4vLyBHaXZlbiBgZWxzYCwgYSBzZXQgb2YgPHRkPiBjZWxscywgZmluZCB0aGUgY2VsbCB3aXRoIHRoZSBsYXJnZXN0IG5hdHVyYWwgd2lkdGggYW5kIHNldCB0aGUgd2lkdGhzIG9mIGFsbCB0aGVcbi8vIGNlbGxzIHRvIGJlIHRoYXQgd2lkdGguXG4vLyBQUkVSRVFVSVNJVEU6IGlmIHlvdSB3YW50IGEgY2VsbCB0byB0YWtlIHVwIHdpZHRoLCBpdCBuZWVkcyB0byBoYXZlIGEgc2luZ2xlIGlubmVyIGVsZW1lbnQgdy8gZGlzcGxheTppbmxpbmVcbmZ1bmN0aW9uIG1hdGNoQ2VsbFdpZHRocyhlbHMpIHtcbiAgICB2YXIgbWF4SW5uZXJXaWR0aCA9IDA7XG4gICAgZWxzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBpbm5lckVsID0gZWwuZmlyc3RDaGlsZDsgLy8gaG9wZWZ1bGx5IGFuIGVsZW1lbnRcbiAgICAgICAgaWYgKGlubmVyRWwgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGlubmVyV2lkdGhfMSA9IGlubmVyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG4gICAgICAgICAgICBpZiAoaW5uZXJXaWR0aF8xID4gbWF4SW5uZXJXaWR0aCkge1xuICAgICAgICAgICAgICAgIG1heElubmVyV2lkdGggPSBpbm5lcldpZHRoXzE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBtYXhJbm5lcldpZHRoKys7IC8vIHNvbWV0aW1lcyBub3QgYWNjdXJhdGUgb2Ygd2lkdGggdGhlIHRleHQgbmVlZHMgdG8gc3RheSBvbiBvbmUgbGluZS4gaW5zdXJhbmNlXG4gICAgZWxzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIGVsLnN0eWxlLndpZHRoID0gbWF4SW5uZXJXaWR0aCArICdweCc7XG4gICAgfSk7XG4gICAgcmV0dXJuIG1heElubmVyV2lkdGg7XG59XG4vLyBHaXZlbiBvbmUgZWxlbWVudCB0aGF0IHJlc2lkZXMgaW5zaWRlIGFub3RoZXIsXG4vLyBTdWJ0cmFjdHMgdGhlIGhlaWdodCBvZiB0aGUgaW5uZXIgZWxlbWVudCBmcm9tIHRoZSBvdXRlciBlbGVtZW50LlxuZnVuY3Rpb24gc3VidHJhY3RJbm5lckVsSGVpZ2h0KG91dGVyRWwsIGlubmVyRWwpIHtcbiAgICAvLyBlZmZpbicgSUU4LzkvMTAvMTEgc29tZXRpbWVzIHJldHVybnMgMCBmb3IgZGltZW5zaW9ucy4gdGhpcyB3ZWlyZCBoYWNrIHdhcyB0aGUgb25seSB0aGluZyB0aGF0IHdvcmtlZFxuICAgIHZhciByZWZsb3dTdHlsZVByb3BzID0ge1xuICAgICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICAgbGVmdDogLTEgLy8gZW5zdXJlIHJlZmxvdyBpbiBjYXNlIHRoZSBlbCB3YXMgYWxyZWFkeSByZWxhdGl2ZS4gbmVnYXRpdmUgaXMgbGVzcyBsaWtlbHkgdG8gY2F1c2UgbmV3IHNjcm9sbFxuICAgIH07XG4gICAgYXBwbHlTdHlsZShvdXRlckVsLCByZWZsb3dTdHlsZVByb3BzKTtcbiAgICBhcHBseVN0eWxlKGlubmVyRWwsIHJlZmxvd1N0eWxlUHJvcHMpO1xuICAgIHZhciBkaWZmID0gLy8gZ3JhYiB0aGUgZGltZW5zaW9uc1xuICAgICBvdXRlckVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCAtXG4gICAgICAgIGlubmVyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xuICAgIC8vIHVuZG8gaGFja1xuICAgIHZhciByZXNldFN0eWxlUHJvcHMgPSB7IHBvc2l0aW9uOiAnJywgbGVmdDogJycgfTtcbiAgICBhcHBseVN0eWxlKG91dGVyRWwsIHJlc2V0U3R5bGVQcm9wcyk7XG4gICAgYXBwbHlTdHlsZShpbm5lckVsLCByZXNldFN0eWxlUHJvcHMpO1xuICAgIHJldHVybiBkaWZmO1xufVxuLyogU2VsZWN0aW9uXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIHByZXZlbnRTZWxlY3Rpb24oZWwpIHtcbiAgICBlbC5jbGFzc0xpc3QuYWRkKCdmYy11bnNlbGVjdGFibGUnKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdzZWxlY3RzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcbn1cbmZ1bmN0aW9uIGFsbG93U2VsZWN0aW9uKGVsKSB7XG4gICAgZWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtdW5zZWxlY3RhYmxlJyk7XG4gICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG4vKiBDb250ZXh0IE1lbnVcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gcHJldmVudENvbnRleHRNZW51KGVsKSB7XG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG5mdW5jdGlvbiBhbGxvd0NvbnRleHRNZW51KGVsKSB7XG4gICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG4vKiBPYmplY3QgT3JkZXJpbmcgYnkgRmllbGRcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gcGFyc2VGaWVsZFNwZWNzKGlucHV0KSB7XG4gICAgdmFyIHNwZWNzID0gW107XG4gICAgdmFyIHRva2VucyA9IFtdO1xuICAgIHZhciBpO1xuICAgIHZhciB0b2tlbjtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICB0b2tlbnMgPSBpbnB1dC5zcGxpdCgvXFxzKixcXHMqLyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0b2tlbnMgPSBbaW5wdXRdO1xuICAgIH1cbiAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICB0b2tlbnMgPSBpbnB1dDtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHNwZWNzLnB1c2godG9rZW4uY2hhckF0KDApID09PSAnLScgP1xuICAgICAgICAgICAgICAgIHsgZmllbGQ6IHRva2VuLnN1YnN0cmluZygxKSwgb3JkZXI6IC0xIH0gOlxuICAgICAgICAgICAgICAgIHsgZmllbGQ6IHRva2VuLCBvcmRlcjogMSB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdG9rZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHNwZWNzLnB1c2goeyBmdW5jOiB0b2tlbiB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3BlY3M7XG59XG5mdW5jdGlvbiBjb21wYXJlQnlGaWVsZFNwZWNzKG9iajAsIG9iajEsIGZpZWxkU3BlY3MpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgY21wO1xuICAgIGZvciAoaSA9IDA7IGkgPCBmaWVsZFNwZWNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNtcCA9IGNvbXBhcmVCeUZpZWxkU3BlYyhvYmowLCBvYmoxLCBmaWVsZFNwZWNzW2ldKTtcbiAgICAgICAgaWYgKGNtcCkge1xuICAgICAgICAgICAgcmV0dXJuIGNtcDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIGNvbXBhcmVCeUZpZWxkU3BlYyhvYmowLCBvYmoxLCBmaWVsZFNwZWMpIHtcbiAgICBpZiAoZmllbGRTcGVjLmZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIGZpZWxkU3BlYy5mdW5jKG9iajAsIG9iajEpO1xuICAgIH1cbiAgICByZXR1cm4gZmxleGlibGVDb21wYXJlKG9iajBbZmllbGRTcGVjLmZpZWxkXSwgb2JqMVtmaWVsZFNwZWMuZmllbGRdKVxuICAgICAgICAqIChmaWVsZFNwZWMub3JkZXIgfHwgMSk7XG59XG5mdW5jdGlvbiBmbGV4aWJsZUNvbXBhcmUoYSwgYikge1xuICAgIGlmICghYSAmJiAhYikge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKGIgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmIChhID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoYSkubG9jYWxlQ29tcGFyZShTdHJpbmcoYikpO1xuICAgIH1cbiAgICByZXR1cm4gYSAtIGI7XG59XG4vKiBTdHJpbmcgVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIGNhcGl0YWxpc2VGaXJzdExldHRlcihzdHIpIHtcbiAgICByZXR1cm4gc3RyLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyLnNsaWNlKDEpO1xufVxuZnVuY3Rpb24gcGFkU3RhcnQodmFsLCBsZW4pIHtcbiAgICB2YXIgcyA9IFN0cmluZyh2YWwpO1xuICAgIHJldHVybiAnMDAwJy5zdWJzdHIoMCwgbGVuIC0gcy5sZW5ndGgpICsgcztcbn1cbi8qIE51bWJlciBVdGlsaXRpZXNcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gY29tcGFyZU51bWJlcnMoYSwgYikge1xuICAgIHJldHVybiBhIC0gYjtcbn1cbmZ1bmN0aW9uIGlzSW50KG4pIHtcbiAgICByZXR1cm4gbiAlIDEgPT09IDA7XG59XG4vKiBXZWlyZCBVdGlsaXRpZXNcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gYXBwbHlBbGwoZnVuY3Rpb25zLCB0aGlzT2JqLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiBmdW5jdGlvbnMgPT09ICdmdW5jdGlvbicpIHsgLy8gc3VwcGxpZWQgYSBzaW5nbGUgZnVuY3Rpb25cbiAgICAgICAgZnVuY3Rpb25zID0gW2Z1bmN0aW9uc107XG4gICAgfVxuICAgIGlmIChmdW5jdGlvbnMpIHtcbiAgICAgICAgdmFyIGkgPSB2b2lkIDA7XG4gICAgICAgIHZhciByZXQgPSB2b2lkIDA7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBmdW5jdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJldCA9IGZ1bmN0aW9uc1tpXS5hcHBseSh0aGlzT2JqLCBhcmdzKSB8fCByZXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG59XG5mdW5jdGlvbiBmaXJzdERlZmluZWQoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICBhcmdzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYXJnc1tpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJnc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgYXMgbG9uZyBhcyBpdCBjb250aW51ZXMgdG8gYmUgaW52b2tlZCwgd2lsbCBub3Rcbi8vIGJlIHRyaWdnZXJlZC4gVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIGl0IHN0b3BzIGJlaW5nIGNhbGxlZCBmb3Jcbi8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxuLy8gbGVhZGluZyBlZGdlLCBpbnN0ZWFkIG9mIHRoZSB0cmFpbGluZy5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qYXNoa2VuYXMvdW5kZXJzY29yZS9ibG9iLzEuNi4wL3VuZGVyc2NvcmUuanMjTDcxNFxuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCkge1xuICAgIHZhciB0aW1lb3V0O1xuICAgIHZhciBhcmdzO1xuICAgIHZhciBjb250ZXh0O1xuICAgIHZhciB0aW1lc3RhbXA7XG4gICAgdmFyIHJlc3VsdDtcbiAgICB2YXIgbGF0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBsYXN0ID0gbmV3IERhdGUoKS52YWx1ZU9mKCkgLSB0aW1lc3RhbXA7XG4gICAgICAgIGlmIChsYXN0IDwgd2FpdCkge1xuICAgICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHRpbWVzdGFtcCA9IG5ldyBEYXRlKCkudmFsdWVPZigpO1xuICAgICAgICBpZiAoIXRpbWVvdXQpIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG59XG4vLyBOdW1iZXIgYW5kIEJvb2xlYW4gYXJlIG9ubHkgdHlwZXMgdGhhdCBkZWZhdWx0cyBvciBub3QgY29tcHV0ZWQgZm9yXG4vLyBUT0RPOiB3cml0ZSBtb3JlIGNvbW1lbnRzXG5mdW5jdGlvbiByZWZpbmVQcm9wcyhyYXdQcm9wcywgcHJvY2Vzc29ycywgZGVmYXVsdHMsIGxlZnRvdmVyUHJvcHMpIHtcbiAgICBpZiAoZGVmYXVsdHMgPT09IHZvaWQgMCkgeyBkZWZhdWx0cyA9IHt9OyB9XG4gICAgdmFyIHJlZmluZWQgPSB7fTtcbiAgICBmb3IgKHZhciBrZXkgaW4gcHJvY2Vzc29ycykge1xuICAgICAgICB2YXIgcHJvY2Vzc29yID0gcHJvY2Vzc29yc1trZXldO1xuICAgICAgICBpZiAocmF3UHJvcHNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBmb3VuZFxuICAgICAgICAgICAgaWYgKHByb2Nlc3NvciA9PT0gRnVuY3Rpb24pIHtcbiAgICAgICAgICAgICAgICByZWZpbmVkW2tleV0gPSB0eXBlb2YgcmF3UHJvcHNba2V5XSA9PT0gJ2Z1bmN0aW9uJyA/IHJhd1Byb3BzW2tleV0gOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocHJvY2Vzc29yKSB7IC8vIGEgcmVmaW5pbmcgZnVuY3Rpb24/XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gcHJvY2Vzc29yKHJhd1Byb3BzW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gcmF3UHJvcHNba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkZWZhdWx0c1trZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIHRoZXJlJ3MgYW4gZXhwbGljaXQgZGVmYXVsdFxuICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gZGVmYXVsdHNba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIG11c3QgY29tcHV0ZSBhIGRlZmF1bHRcbiAgICAgICAgICAgIGlmIChwcm9jZXNzb3IgPT09IFN0cmluZykge1xuICAgICAgICAgICAgICAgIHJlZmluZWRba2V5XSA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgaXMgZGVmYXVsdCBmb3IgU3RyaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghcHJvY2Vzc29yIHx8IHByb2Nlc3NvciA9PT0gTnVtYmVyIHx8IHByb2Nlc3NvciA9PT0gQm9vbGVhbiB8fCBwcm9jZXNzb3IgPT09IEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gbnVsbDsgLy8gYXNzaWduIG51bGwgZm9yIG90aGVyIG5vbi1jdXN0b20gcHJvY2Vzc29yIGZ1bmNzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWZpbmVkW2tleV0gPSBwcm9jZXNzb3IobnVsbCk7IC8vIHJ1biB0aGUgY3VzdG9tIHByb2Nlc3NvciBmdW5jXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxlZnRvdmVyUHJvcHMpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHJhd1Byb3BzKSB7XG4gICAgICAgICAgICBpZiAocHJvY2Vzc29yc1trZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBsZWZ0b3ZlclByb3BzW2tleV0gPSByYXdQcm9wc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWZpbmVkO1xufVxuLyogRGF0ZSBzdHVmZiB0aGF0IGRvZXNuJ3QgYmVsb25nIGluIGRhdGVsaWIgY29yZVxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4vLyBnaXZlbiBhIHRpbWVkIHJhbmdlLCBjb21wdXRlcyBhbiBhbGwtZGF5IHJhbmdlIHRoYXQgaGFzIHRoZSBzYW1lIGV4YWN0IGR1cmF0aW9uLFxuLy8gYnV0IHdob3NlIHN0YXJ0IHRpbWUgaXMgYWxpZ25lZCB3aXRoIHRoZSBzdGFydCBvZiB0aGUgZGF5LlxuZnVuY3Rpb24gY29tcHV0ZUFsaWduZWREYXlSYW5nZSh0aW1lZFJhbmdlKSB7XG4gICAgdmFyIGRheUNudCA9IE1hdGguZmxvb3IoZGlmZkRheXModGltZWRSYW5nZS5zdGFydCwgdGltZWRSYW5nZS5lbmQpKSB8fCAxO1xuICAgIHZhciBzdGFydCA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5zdGFydCk7XG4gICAgdmFyIGVuZCA9IGFkZERheXMoc3RhcnQsIGRheUNudCk7XG4gICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xufVxuLy8gZ2l2ZW4gYSB0aW1lZCByYW5nZSwgY29tcHV0ZXMgYW4gYWxsLWRheSByYW5nZSBiYXNlZCBvbiBob3cgZm9yIHRoZSBlbmQgZGF0ZSBibGVlZHMgaW50byB0aGUgbmV4dCBkYXlcbi8vIFRPRE86IGdpdmUgbmV4dERheVRocmVzaG9sZCBhIGRlZmF1bHQgYXJnXG5mdW5jdGlvbiBjb21wdXRlVmlzaWJsZURheVJhbmdlKHRpbWVkUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQpIHtcbiAgICBpZiAobmV4dERheVRocmVzaG9sZCA9PT0gdm9pZCAwKSB7IG5leHREYXlUaHJlc2hvbGQgPSBjcmVhdGVEdXJhdGlvbigwKTsgfVxuICAgIHZhciBzdGFydERheSA9IG51bGw7XG4gICAgdmFyIGVuZERheSA9IG51bGw7XG4gICAgaWYgKHRpbWVkUmFuZ2UuZW5kKSB7XG4gICAgICAgIGVuZERheSA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5lbmQpO1xuICAgICAgICB2YXIgZW5kVGltZU1TID0gdGltZWRSYW5nZS5lbmQudmFsdWVPZigpIC0gZW5kRGF5LnZhbHVlT2YoKTsgLy8gIyBvZiBtaWxsaXNlY29uZHMgaW50byBgZW5kRGF5YFxuICAgICAgICAvLyBJZiB0aGUgZW5kIHRpbWUgaXMgYWN0dWFsbHkgaW5jbHVzaXZlbHkgcGFydCBvZiB0aGUgbmV4dCBkYXkgYW5kIGlzIGVxdWFsIHRvIG9yXG4gICAgICAgIC8vIGJleW9uZCB0aGUgbmV4dCBkYXkgdGhyZXNob2xkLCBhZGp1c3QgdGhlIGVuZCB0byBiZSB0aGUgZXhjbHVzaXZlIGVuZCBvZiBgZW5kRGF5YC5cbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBsZWF2aW5nIGl0IGFzIGluY2x1c2l2ZSB3aWxsIGNhdXNlIGl0IHRvIGV4Y2x1ZGUgYGVuZERheWAuXG4gICAgICAgIGlmIChlbmRUaW1lTVMgJiYgZW5kVGltZU1TID49IGFzUm91Z2hNcyhuZXh0RGF5VGhyZXNob2xkKSkge1xuICAgICAgICAgICAgZW5kRGF5ID0gYWRkRGF5cyhlbmREYXksIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0aW1lZFJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0RGF5ID0gc3RhcnRPZkRheSh0aW1lZFJhbmdlLnN0YXJ0KTsgLy8gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF5IHRoZSByYW5nZSBzdGFydHNcbiAgICAgICAgLy8gSWYgZW5kIGlzIHdpdGhpbiBgc3RhcnREYXlgIGJ1dCBub3QgcGFzdCBuZXh0RGF5VGhyZXNob2xkLCBhc3NpZ24gdGhlIGRlZmF1bHQgZHVyYXRpb24gb2Ygb25lIGRheS5cbiAgICAgICAgaWYgKGVuZERheSAmJiBlbmREYXkgPD0gc3RhcnREYXkpIHtcbiAgICAgICAgICAgIGVuZERheSA9IGFkZERheXMoc3RhcnREYXksIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydERheSwgZW5kOiBlbmREYXkgfTtcbn1cbi8vIHNwYW5zIGZyb20gb25lIGRheSBpbnRvIGFub3RoZXI/XG5mdW5jdGlvbiBpc011bHRpRGF5UmFuZ2UocmFuZ2UpIHtcbiAgICB2YXIgdmlzaWJsZVJhbmdlID0gY29tcHV0ZVZpc2libGVEYXlSYW5nZShyYW5nZSk7XG4gICAgcmV0dXJuIGRpZmZEYXlzKHZpc2libGVSYW5nZS5zdGFydCwgdmlzaWJsZVJhbmdlLmVuZCkgPiAxO1xufVxuZnVuY3Rpb24gZGlmZkRhdGVzKGRhdGUwLCBkYXRlMSwgZGF0ZUVudiwgbGFyZ2VVbml0KSB7XG4gICAgaWYgKGxhcmdlVW5pdCA9PT0gJ3llYXInKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbihkYXRlRW52LmRpZmZXaG9sZVllYXJzKGRhdGUwLCBkYXRlMSksICd5ZWFyJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGxhcmdlVW5pdCA9PT0gJ21vbnRoJykge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oZGF0ZUVudi5kaWZmV2hvbGVNb250aHMoZGF0ZTAsIGRhdGUxKSwgJ21vbnRoJyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gZGlmZkRheUFuZFRpbWUoZGF0ZTAsIGRhdGUxKTsgLy8gcmV0dXJucyBhIGR1cmF0aW9uXG4gICAgfVxufVxuXG4vKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5mdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG52YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfTtcclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59O1xuXG5mdW5jdGlvbiBwYXJzZVJlY3VycmluZyhldmVudElucHV0LCBhbGxEYXlEZWZhdWx0LCBkYXRlRW52LCByZWN1cnJpbmdUeXBlcywgbGVmdG92ZXJzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWN1cnJpbmdUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbG9jYWxMZWZ0b3ZlcnMgPSB7fTtcbiAgICAgICAgdmFyIHBhcnNlZCA9IHJlY3VycmluZ1R5cGVzW2ldLnBhcnNlKGV2ZW50SW5wdXQsIGxvY2FsTGVmdG92ZXJzLCBkYXRlRW52KTtcbiAgICAgICAgaWYgKHBhcnNlZCkge1xuICAgICAgICAgICAgdmFyIGFsbERheSA9IGxvY2FsTGVmdG92ZXJzLmFsbERheTtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2NhbExlZnRvdmVycy5hbGxEYXk7IC8vIHJlbW92ZSBmcm9tIGxlZnRvdmVyc1xuICAgICAgICAgICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYWxsRGF5ID0gYWxsRGF5RGVmYXVsdDtcbiAgICAgICAgICAgICAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWxsRGF5ID0gcGFyc2VkLmFsbERheUd1ZXNzO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbERheSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX19hc3NpZ24obGVmdG92ZXJzLCBsb2NhbExlZnRvdmVycyk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFsbERheTogYWxsRGF5LFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBwYXJzZWQuZHVyYXRpb24sXG4gICAgICAgICAgICAgICAgdHlwZURhdGE6IHBhcnNlZC50eXBlRGF0YSxcbiAgICAgICAgICAgICAgICB0eXBlSWQ6IGlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG4vKlxuRXZlbnQgTVVTVCBoYXZlIGEgcmVjdXJyaW5nRGVmXG4qL1xuZnVuY3Rpb24gZXhwYW5kUmVjdXJyaW5nUmFuZ2VzKGV2ZW50RGVmLCBkdXJhdGlvbiwgZnJhbWluZ1JhbmdlLCBkYXRlRW52LCByZWN1cnJpbmdUeXBlcykge1xuICAgIHZhciB0eXBlRGVmID0gcmVjdXJyaW5nVHlwZXNbZXZlbnREZWYucmVjdXJyaW5nRGVmLnR5cGVJZF07XG4gICAgdmFyIG1hcmtlcnMgPSB0eXBlRGVmLmV4cGFuZChldmVudERlZi5yZWN1cnJpbmdEZWYudHlwZURhdGEsIHtcbiAgICAgICAgc3RhcnQ6IGRhdGVFbnYuc3VidHJhY3QoZnJhbWluZ1JhbmdlLnN0YXJ0LCBkdXJhdGlvbiksXG4gICAgICAgIGVuZDogZnJhbWluZ1JhbmdlLmVuZFxuICAgIH0sIGRhdGVFbnYpO1xuICAgIC8vIHRoZSByZWN1cnJlbmNlIHBsdWdpbnMgZG9uJ3QgZ3VhcmFudGVlIHRoYXQgYWxsLWRheSBldmVudHMgYXJlIHN0YXJ0LW9mLWRheSwgc28gd2UgaGF2ZSB0b1xuICAgIGlmIChldmVudERlZi5hbGxEYXkpIHtcbiAgICAgICAgbWFya2VycyA9IG1hcmtlcnMubWFwKHN0YXJ0T2ZEYXkpO1xuICAgIH1cbiAgICByZXR1cm4gbWFya2Vycztcbn1cblxudmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbi8vIE1lcmdlcyBhbiBhcnJheSBvZiBvYmplY3RzIGludG8gYSBzaW5nbGUgb2JqZWN0LlxuLy8gVGhlIHNlY29uZCBhcmd1bWVudCBhbGxvd3MgZm9yIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIHdobydzIG9iamVjdCB2YWx1ZXMgd2lsbCBiZSBtZXJnZWQgdG9nZXRoZXIuXG5mdW5jdGlvbiBtZXJnZVByb3BzKHByb3BPYmpzLCBjb21wbGV4UHJvcHMpIHtcbiAgICB2YXIgZGVzdCA9IHt9O1xuICAgIHZhciBpO1xuICAgIHZhciBuYW1lO1xuICAgIHZhciBjb21wbGV4T2JqcztcbiAgICB2YXIgajtcbiAgICB2YXIgdmFsO1xuICAgIHZhciBwcm9wcztcbiAgICBpZiAoY29tcGxleFByb3BzKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb21wbGV4UHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5hbWUgPSBjb21wbGV4UHJvcHNbaV07XG4gICAgICAgICAgICBjb21wbGV4T2JqcyA9IFtdO1xuICAgICAgICAgICAgLy8gY29sbGVjdCB0aGUgdHJhaWxpbmcgb2JqZWN0IHZhbHVlcywgc3RvcHBpbmcgd2hlbiBhIG5vbi1vYmplY3QgaXMgZGlzY292ZXJlZFxuICAgICAgICAgICAgZm9yIChqID0gcHJvcE9ianMubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICB2YWwgPSBwcm9wT2Jqc1tqXVtuYW1lXTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsKSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICBjb21wbGV4T2Jqcy51bnNoaWZ0KHZhbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3RbbmFtZV0gPSB2YWw7IC8vIGlmIHRoZXJlIHdlcmUgbm8gb2JqZWN0cywgdGhpcyB2YWx1ZSB3aWxsIGJlIHVzZWRcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgdGhlIHRyYWlsaW5nIHZhbHVlcyB3ZXJlIG9iamVjdHMsIHVzZSB0aGUgbWVyZ2VkIHZhbHVlXG4gICAgICAgICAgICBpZiAoY29tcGxleE9ianMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVzdFtuYW1lXSA9IG1lcmdlUHJvcHMoY29tcGxleE9ianMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGNvcHkgdmFsdWVzIGludG8gdGhlIGRlc3RpbmF0aW9uLCBnb2luZyBmcm9tIGxhc3QgdG8gZmlyc3RcbiAgICBmb3IgKGkgPSBwcm9wT2Jqcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBwcm9wcyA9IHByb3BPYmpzW2ldO1xuICAgICAgICBmb3IgKG5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgIGlmICghKG5hbWUgaW4gZGVzdCkpIHsgLy8gaWYgYWxyZWFkeSBhc3NpZ25lZCBieSBwcmV2aW91cyBwcm9wcyBvciBjb21wbGV4IHByb3BzLCBkb24ndCByZWFzc2lnblxuICAgICAgICAgICAgICAgIGRlc3RbbmFtZV0gPSBwcm9wc1tuYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn1cbmZ1bmN0aW9uIGZpbHRlckhhc2goaGFzaCwgZnVuYykge1xuICAgIHZhciBmaWx0ZXJlZCA9IHt9O1xuICAgIGZvciAodmFyIGtleSBpbiBoYXNoKSB7XG4gICAgICAgIGlmIChmdW5jKGhhc2hba2V5XSwga2V5KSkge1xuICAgICAgICAgICAgZmlsdGVyZWRba2V5XSA9IGhhc2hba2V5XTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmlsdGVyZWQ7XG59XG5mdW5jdGlvbiBtYXBIYXNoKGhhc2gsIGZ1bmMpIHtcbiAgICB2YXIgbmV3SGFzaCA9IHt9O1xuICAgIGZvciAodmFyIGtleSBpbiBoYXNoKSB7XG4gICAgICAgIG5ld0hhc2hba2V5XSA9IGZ1bmMoaGFzaFtrZXldLCBrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3SGFzaDtcbn1cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGEpIHtcbiAgICB2YXIgaGFzaCA9IHt9O1xuICAgIGZvciAodmFyIF9pID0gMCwgYV8xID0gYTsgX2kgPCBhXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gYV8xW19pXTtcbiAgICAgICAgaGFzaFtpdGVtXSA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBoYXNoO1xufVxuZnVuY3Rpb24gaGFzaFZhbHVlc1RvQXJyYXkob2JqKSB7XG4gICAgdmFyIGEgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgIGEucHVzaChvYmpba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufVxuZnVuY3Rpb24gaXNQcm9wc0VxdWFsKG9iajAsIG9iajEpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqMCkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmowLCBrZXkpKSB7XG4gICAgICAgICAgICBpZiAoIShrZXkgaW4gb2JqMSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIga2V5IGluIG9iajEpIHtcbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqMSwga2V5KSkge1xuICAgICAgICAgICAgaWYgKG9iajBba2V5XSAhPT0gb2JqMVtrZXldKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBwYXJzZUV2ZW50cyhyYXdFdmVudHMsIHNvdXJjZUlkLCBjYWxlbmRhciwgYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICB2YXIgZXZlbnRTdG9yZSA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgIGZvciAodmFyIF9pID0gMCwgcmF3RXZlbnRzXzEgPSByYXdFdmVudHM7IF9pIDwgcmF3RXZlbnRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciByYXdFdmVudCA9IHJhd0V2ZW50c18xW19pXTtcbiAgICAgICAgdmFyIHR1cGxlID0gcGFyc2VFdmVudChyYXdFdmVudCwgc291cmNlSWQsIGNhbGVuZGFyLCBhbGxvd09wZW5SYW5nZSk7XG4gICAgICAgIGlmICh0dXBsZSkge1xuICAgICAgICAgICAgZXZlbnRUdXBsZVRvU3RvcmUodHVwbGUsIGV2ZW50U3RvcmUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBldmVudFN0b3JlO1xufVxuZnVuY3Rpb24gZXZlbnRUdXBsZVRvU3RvcmUodHVwbGUsIGV2ZW50U3RvcmUpIHtcbiAgICBpZiAoZXZlbnRTdG9yZSA9PT0gdm9pZCAwKSB7IGV2ZW50U3RvcmUgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTsgfVxuICAgIGV2ZW50U3RvcmUuZGVmc1t0dXBsZS5kZWYuZGVmSWRdID0gdHVwbGUuZGVmO1xuICAgIGlmICh0dXBsZS5pbnN0YW5jZSkge1xuICAgICAgICBldmVudFN0b3JlLmluc3RhbmNlc1t0dXBsZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSA9IHR1cGxlLmluc3RhbmNlO1xuICAgIH1cbiAgICByZXR1cm4gZXZlbnRTdG9yZTtcbn1cbmZ1bmN0aW9uIGV4cGFuZFJlY3VycmluZyhldmVudFN0b3JlLCBmcmFtaW5nUmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRhdGVFbnYgPSBjYWxlbmRhci5kYXRlRW52O1xuICAgIHZhciBkZWZzID0gZXZlbnRTdG9yZS5kZWZzLCBpbnN0YW5jZXMgPSBldmVudFN0b3JlLmluc3RhbmNlcztcbiAgICAvLyByZW1vdmUgZXhpc3RpbmcgcmVjdXJyaW5nIGluc3RhbmNlc1xuICAgIGluc3RhbmNlcyA9IGZpbHRlckhhc2goaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgcmV0dXJuICFkZWZzW2luc3RhbmNlLmRlZklkXS5yZWN1cnJpbmdEZWY7XG4gICAgfSk7XG4gICAgZm9yICh2YXIgZGVmSWQgaW4gZGVmcykge1xuICAgICAgICB2YXIgZGVmID0gZGVmc1tkZWZJZF07XG4gICAgICAgIGlmIChkZWYucmVjdXJyaW5nRGVmKSB7XG4gICAgICAgICAgICB2YXIgZHVyYXRpb24gPSBkZWYucmVjdXJyaW5nRGVmLmR1cmF0aW9uO1xuICAgICAgICAgICAgaWYgKCFkdXJhdGlvbikge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gZGVmLmFsbERheSA/XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdGFydHMgPSBleHBhbmRSZWN1cnJpbmdSYW5nZXMoZGVmLCBkdXJhdGlvbiwgZnJhbWluZ1JhbmdlLCBjYWxlbmRhci5kYXRlRW52LCBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MucmVjdXJyaW5nVHlwZXMpO1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBzdGFydHNfMSA9IHN0YXJ0czsgX2kgPCBzdGFydHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RhcnQgPSBzdGFydHNfMVtfaV07XG4gICAgICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWZJZCwge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogc3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogZGF0ZUVudi5hZGQoc3RhcnQsIGR1cmF0aW9uKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGluc3RhbmNlc1tpbnN0YW5jZS5pbnN0YW5jZUlkXSA9IGluc3RhbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGRlZnM6IGRlZnMsIGluc3RhbmNlczogaW5zdGFuY2VzIH07XG59XG4vLyByZXRyaWV2ZXMgZXZlbnRzIHRoYXQgaGF2ZSB0aGUgc2FtZSBncm91cElkIGFzIHRoZSBpbnN0YW5jZSBzcGVjaWZpZWQgYnkgYGluc3RhbmNlSWRgXG4vLyBvciB0aGV5IGFyZSB0aGUgc2FtZSBhcyB0aGUgaW5zdGFuY2UuXG4vLyB3aHkgbWlnaHQgaW5zdGFuY2VJZCBub3QgYmUgaW4gdGhlIHN0b3JlPyBhbiBldmVudCBmcm9tIGFub3RoZXIgY2FsZW5kYXI/XG5mdW5jdGlvbiBnZXRSZWxldmFudEV2ZW50cyhldmVudFN0b3JlLCBpbnN0YW5jZUlkKSB7XG4gICAgdmFyIGluc3RhbmNlID0gZXZlbnRTdG9yZS5pbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgIHZhciBkZWZfMSA9IGV2ZW50U3RvcmUuZGVmc1tpbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIC8vIGdldCBldmVudHMvaW5zdGFuY2VzIHdpdGggc2FtZSBncm91cFxuICAgICAgICB2YXIgbmV3U3RvcmUgPSBmaWx0ZXJFdmVudFN0b3JlRGVmcyhldmVudFN0b3JlLCBmdW5jdGlvbiAobG9va0RlZikge1xuICAgICAgICAgICAgcmV0dXJuIGlzRXZlbnREZWZzR3JvdXBlZChkZWZfMSwgbG9va0RlZik7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBhZGQgdGhlIG9yaWdpbmFsXG4gICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgdXNlIGV2ZW50VHVwbGVUb1N0b3JlIG9yIHNvbWV0aGluZyBsaWtlIGl0XG4gICAgICAgIG5ld1N0b3JlLmRlZnNbZGVmXzEuZGVmSWRdID0gZGVmXzE7XG4gICAgICAgIG5ld1N0b3JlLmluc3RhbmNlc1tpbnN0YW5jZS5pbnN0YW5jZUlkXSA9IGluc3RhbmNlO1xuICAgICAgICByZXR1cm4gbmV3U3RvcmU7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbn1cbmZ1bmN0aW9uIGlzRXZlbnREZWZzR3JvdXBlZChkZWYwLCBkZWYxKSB7XG4gICAgcmV0dXJuIEJvb2xlYW4oZGVmMC5ncm91cElkICYmIGRlZjAuZ3JvdXBJZCA9PT0gZGVmMS5ncm91cElkKTtcbn1cbmZ1bmN0aW9uIHRyYW5zZm9ybVJhd0V2ZW50cyhyYXdFdmVudHMsIGV2ZW50U291cmNlLCBjYWxlbmRhcikge1xuICAgIHZhciBjYWxFYWNoVHJhbnNmb3JtID0gY2FsZW5kYXIub3B0KCdldmVudERhdGFUcmFuc2Zvcm0nKTtcbiAgICB2YXIgc291cmNlRWFjaFRyYW5zZm9ybSA9IGV2ZW50U291cmNlID8gZXZlbnRTb3VyY2UuZXZlbnREYXRhVHJhbnNmb3JtIDogbnVsbDtcbiAgICBpZiAoc291cmNlRWFjaFRyYW5zZm9ybSkge1xuICAgICAgICByYXdFdmVudHMgPSB0cmFuc2Zvcm1FYWNoUmF3RXZlbnQocmF3RXZlbnRzLCBzb3VyY2VFYWNoVHJhbnNmb3JtKTtcbiAgICB9XG4gICAgaWYgKGNhbEVhY2hUcmFuc2Zvcm0pIHtcbiAgICAgICAgcmF3RXZlbnRzID0gdHJhbnNmb3JtRWFjaFJhd0V2ZW50KHJhd0V2ZW50cywgY2FsRWFjaFRyYW5zZm9ybSk7XG4gICAgfVxuICAgIHJldHVybiByYXdFdmVudHM7XG59XG5mdW5jdGlvbiB0cmFuc2Zvcm1FYWNoUmF3RXZlbnQocmF3RXZlbnRzLCBmdW5jKSB7XG4gICAgdmFyIHJlZmluZWRFdmVudHM7XG4gICAgaWYgKCFmdW5jKSB7XG4gICAgICAgIHJlZmluZWRFdmVudHMgPSByYXdFdmVudHM7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZWZpbmVkRXZlbnRzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgcmF3RXZlbnRzXzIgPSByYXdFdmVudHM7IF9pIDwgcmF3RXZlbnRzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcmF3RXZlbnQgPSByYXdFdmVudHNfMltfaV07XG4gICAgICAgICAgICB2YXIgcmVmaW5lZEV2ZW50ID0gZnVuYyhyYXdFdmVudCk7XG4gICAgICAgICAgICBpZiAocmVmaW5lZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZEV2ZW50cy5wdXNoKHJlZmluZWRFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChyZWZpbmVkRXZlbnQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlZmluZWRFdmVudHMucHVzaChyYXdFdmVudCk7XG4gICAgICAgICAgICB9IC8vIGlmIGEgZGlmZmVyZW50IGZhbHN5IHZhbHVlLCBkbyBub3RoaW5nXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlZmluZWRFdmVudHM7XG59XG5mdW5jdGlvbiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKSB7XG4gICAgcmV0dXJuIHsgZGVmczoge30sIGluc3RhbmNlczoge30gfTtcbn1cbmZ1bmN0aW9uIG1lcmdlRXZlbnRTdG9yZXMoc3RvcmUwLCBzdG9yZTEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkZWZzOiBfX2Fzc2lnbih7fSwgc3RvcmUwLmRlZnMsIHN0b3JlMS5kZWZzKSxcbiAgICAgICAgaW5zdGFuY2VzOiBfX2Fzc2lnbih7fSwgc3RvcmUwLmluc3RhbmNlcywgc3RvcmUxLmluc3RhbmNlcylcbiAgICB9O1xufVxuZnVuY3Rpb24gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZmlsdGVyRnVuYykge1xuICAgIHZhciBkZWZzID0gZmlsdGVySGFzaChldmVudFN0b3JlLmRlZnMsIGZpbHRlckZ1bmMpO1xuICAgIHZhciBpbnN0YW5jZXMgPSBmaWx0ZXJIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgcmV0dXJuIGRlZnNbaW5zdGFuY2UuZGVmSWRdOyAvLyBzdGlsbCBleGlzdHM/XG4gICAgfSk7XG4gICAgcmV0dXJuIHsgZGVmczogZGVmcywgaW5zdGFuY2VzOiBpbnN0YW5jZXMgfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VSYW5nZShpbnB1dCwgZGF0ZUVudikge1xuICAgIHZhciBzdGFydCA9IG51bGw7XG4gICAgdmFyIGVuZCA9IG51bGw7XG4gICAgaWYgKGlucHV0LnN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoaW5wdXQuc3RhcnQpO1xuICAgIH1cbiAgICBpZiAoaW5wdXQuZW5kKSB7XG4gICAgICAgIGVuZCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKGlucHV0LmVuZCk7XG4gICAgfVxuICAgIGlmICghc3RhcnQgJiYgIWVuZCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHN0YXJ0ICYmIGVuZCAmJiBlbmQgPCBzdGFydCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xufVxuLy8gU0lERS1FRkZFQ1Q6IHdpbGwgbXV0YXRlIHJhbmdlcy5cbi8vIFdpbGwgcmV0dXJuIGEgbmV3IGFycmF5IHJlc3VsdC5cbmZ1bmN0aW9uIGludmVydFJhbmdlcyhyYW5nZXMsIGNvbnN0cmFpbnRSYW5nZSkge1xuICAgIHZhciBpbnZlcnRlZFJhbmdlcyA9IFtdO1xuICAgIHZhciBzdGFydCA9IGNvbnN0cmFpbnRSYW5nZS5zdGFydDsgLy8gdGhlIGVuZCBvZiB0aGUgcHJldmlvdXMgcmFuZ2UuIHRoZSBzdGFydCBvZiB0aGUgbmV3IHJhbmdlXG4gICAgdmFyIGk7XG4gICAgdmFyIGRhdGVSYW5nZTtcbiAgICAvLyByYW5nZXMgbmVlZCB0byBiZSBpbiBvcmRlci4gcmVxdWlyZWQgZm9yIG91ciBkYXRlLXdhbGtpbmcgYWxnb3JpdGhtXG4gICAgcmFuZ2VzLnNvcnQoY29tcGFyZVJhbmdlcyk7XG4gICAgZm9yIChpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkYXRlUmFuZ2UgPSByYW5nZXNbaV07XG4gICAgICAgIC8vIGFkZCB0aGUgc3BhbiBvZiB0aW1lIGJlZm9yZSB0aGUgZXZlbnQgKGlmIHRoZXJlIGlzIGFueSlcbiAgICAgICAgaWYgKGRhdGVSYW5nZS5zdGFydCA+IHN0YXJ0KSB7IC8vIGNvbXBhcmUgbWlsbGlzZWNvbmQgdGltZSAoc2tpcCBhbnkgYW1iaWcgbG9naWMpXG4gICAgICAgICAgICBpbnZlcnRlZFJhbmdlcy5wdXNoKHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGRhdGVSYW5nZS5zdGFydCB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZVJhbmdlLmVuZCA+IHN0YXJ0KSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVSYW5nZS5lbmQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gYWRkIHRoZSBzcGFuIG9mIHRpbWUgYWZ0ZXIgdGhlIGxhc3QgZXZlbnQgKGlmIHRoZXJlIGlzIGFueSlcbiAgICBpZiAoc3RhcnQgPCBjb25zdHJhaW50UmFuZ2UuZW5kKSB7IC8vIGNvbXBhcmUgbWlsbGlzZWNvbmQgdGltZSAoc2tpcCBhbnkgYW1iaWcgbG9naWMpXG4gICAgICAgIGludmVydGVkUmFuZ2VzLnB1c2goeyBzdGFydDogc3RhcnQsIGVuZDogY29uc3RyYWludFJhbmdlLmVuZCB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGludmVydGVkUmFuZ2VzO1xufVxuZnVuY3Rpb24gY29tcGFyZVJhbmdlcyhyYW5nZTAsIHJhbmdlMSkge1xuICAgIHJldHVybiByYW5nZTAuc3RhcnQudmFsdWVPZigpIC0gcmFuZ2UxLnN0YXJ0LnZhbHVlT2YoKTsgLy8gZWFybGllciByYW5nZXMgZ28gZmlyc3Rcbn1cbmZ1bmN0aW9uIGludGVyc2VjdFJhbmdlcyhyYW5nZTAsIHJhbmdlMSkge1xuICAgIHZhciBzdGFydCA9IHJhbmdlMC5zdGFydDtcbiAgICB2YXIgZW5kID0gcmFuZ2UwLmVuZDtcbiAgICB2YXIgbmV3UmFuZ2UgPSBudWxsO1xuICAgIGlmIChyYW5nZTEuc3RhcnQgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKHN0YXJ0ID09PSBudWxsKSB7XG4gICAgICAgICAgICBzdGFydCA9IHJhbmdlMS5zdGFydDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gbmV3IERhdGUoTWF0aC5tYXgoc3RhcnQudmFsdWVPZigpLCByYW5nZTEuc3RhcnQudmFsdWVPZigpKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHJhbmdlMS5lbmQgIT0gbnVsbCkge1xuICAgICAgICBpZiAoZW5kID09PSBudWxsKSB7XG4gICAgICAgICAgICBlbmQgPSByYW5nZTEuZW5kO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZW5kID0gbmV3IERhdGUoTWF0aC5taW4oZW5kLnZhbHVlT2YoKSwgcmFuZ2UxLmVuZC52YWx1ZU9mKCkpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoc3RhcnQgPT09IG51bGwgfHwgZW5kID09PSBudWxsIHx8IHN0YXJ0IDwgZW5kKSB7XG4gICAgICAgIG5ld1JhbmdlID0geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfVxuICAgIHJldHVybiBuZXdSYW5nZTtcbn1cbmZ1bmN0aW9uIHJhbmdlc0VxdWFsKHJhbmdlMCwgcmFuZ2UxKSB7XG4gICAgcmV0dXJuIChyYW5nZTAuc3RhcnQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UwLnN0YXJ0LnZhbHVlT2YoKSkgPT09IChyYW5nZTEuc3RhcnQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UxLnN0YXJ0LnZhbHVlT2YoKSkgJiZcbiAgICAgICAgKHJhbmdlMC5lbmQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UwLmVuZC52YWx1ZU9mKCkpID09PSAocmFuZ2UxLmVuZCA9PT0gbnVsbCA/IG51bGwgOiByYW5nZTEuZW5kLnZhbHVlT2YoKSk7XG59XG5mdW5jdGlvbiByYW5nZXNJbnRlcnNlY3QocmFuZ2UwLCByYW5nZTEpIHtcbiAgICByZXR1cm4gKHJhbmdlMC5lbmQgPT09IG51bGwgfHwgcmFuZ2UxLnN0YXJ0ID09PSBudWxsIHx8IHJhbmdlMC5lbmQgPiByYW5nZTEuc3RhcnQpICYmXG4gICAgICAgIChyYW5nZTAuc3RhcnQgPT09IG51bGwgfHwgcmFuZ2UxLmVuZCA9PT0gbnVsbCB8fCByYW5nZTAuc3RhcnQgPCByYW5nZTEuZW5kKTtcbn1cbmZ1bmN0aW9uIHJhbmdlQ29udGFpbnNSYW5nZShvdXRlclJhbmdlLCBpbm5lclJhbmdlKSB7XG4gICAgcmV0dXJuIChvdXRlclJhbmdlLnN0YXJ0ID09PSBudWxsIHx8IChpbm5lclJhbmdlLnN0YXJ0ICE9PSBudWxsICYmIGlubmVyUmFuZ2Uuc3RhcnQgPj0gb3V0ZXJSYW5nZS5zdGFydCkpICYmXG4gICAgICAgIChvdXRlclJhbmdlLmVuZCA9PT0gbnVsbCB8fCAoaW5uZXJSYW5nZS5lbmQgIT09IG51bGwgJiYgaW5uZXJSYW5nZS5lbmQgPD0gb3V0ZXJSYW5nZS5lbmQpKTtcbn1cbmZ1bmN0aW9uIHJhbmdlQ29udGFpbnNNYXJrZXIocmFuZ2UsIGRhdGUpIHtcbiAgICByZXR1cm4gKHJhbmdlLnN0YXJ0ID09PSBudWxsIHx8IGRhdGUgPj0gcmFuZ2Uuc3RhcnQpICYmXG4gICAgICAgIChyYW5nZS5lbmQgPT09IG51bGwgfHwgZGF0ZSA8IHJhbmdlLmVuZCk7XG59XG4vLyBJZiB0aGUgZ2l2ZW4gZGF0ZSBpcyBub3Qgd2l0aGluIHRoZSBnaXZlbiByYW5nZSwgbW92ZSBpdCBpbnNpZGUuXG4vLyAoSWYgaXQncyBwYXN0IHRoZSBlbmQsIG1ha2UgaXQgb25lIG1pbGxpc2Vjb25kIGJlZm9yZSB0aGUgZW5kKS5cbmZ1bmN0aW9uIGNvbnN0cmFpbk1hcmtlclRvUmFuZ2UoZGF0ZSwgcmFuZ2UpIHtcbiAgICBpZiAocmFuZ2Uuc3RhcnQgIT0gbnVsbCAmJiBkYXRlIDwgcmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgcmV0dXJuIHJhbmdlLnN0YXJ0O1xuICAgIH1cbiAgICBpZiAocmFuZ2UuZW5kICE9IG51bGwgJiYgZGF0ZSA+PSByYW5nZS5lbmQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHJhbmdlLmVuZC52YWx1ZU9mKCkgLSAxKTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGU7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUV4YWN0KGFycmF5LCBleGFjdFZhbCkge1xuICAgIHZhciByZW1vdmVDbnQgPSAwO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoaSA8IGFycmF5Lmxlbmd0aCkge1xuICAgICAgICBpZiAoYXJyYXlbaV0gPT09IGV4YWN0VmFsKSB7XG4gICAgICAgICAgICBhcnJheS5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICByZW1vdmVDbnQrKztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVtb3ZlQ250O1xufVxuZnVuY3Rpb24gaXNBcnJheXNFcXVhbChhMCwgYTEpIHtcbiAgICB2YXIgbGVuID0gYTAubGVuZ3RoO1xuICAgIHZhciBpO1xuICAgIGlmIChsZW4gIT09IGExLmxlbmd0aCkgeyAvLyBub3QgYXJyYXk/IG9yIG5vdCBzYW1lIGxlbmd0aD9cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYgKGEwW2ldICE9PSBhMVtpXSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1vaXplKHdvcmtlckZ1bmMpIHtcbiAgICB2YXIgYXJncztcbiAgICB2YXIgcmVzO1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghYXJncyB8fCAhaXNBcnJheXNFcXVhbChhcmdzLCBhcmd1bWVudHMpKSB7XG4gICAgICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgcmVzID0gd29ya2VyRnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbn1cbi8qXG5hbHdheXMgZXhlY3V0ZXMgdGhlIHdvcmtlckZ1bmMsIGJ1dCBpZiB0aGUgcmVzdWx0IGlzIGVxdWFsIHRvIHRoZSBwcmV2aW91cyByZXN1bHQsXG5yZXR1cm4gdGhlIHByZXZpb3VzIHJlc3VsdCBpbnN0ZWFkLlxuKi9cbmZ1bmN0aW9uIG1lbW9pemVPdXRwdXQod29ya2VyRnVuYywgZXF1YWxpdHlGdW5jKSB7XG4gICAgdmFyIGNhY2hlZFJlcyA9IG51bGw7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5ld1JlcyA9IHdvcmtlckZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKGNhY2hlZFJlcyA9PT0gbnVsbCB8fCAhKGNhY2hlZFJlcyA9PT0gbmV3UmVzIHx8IGVxdWFsaXR5RnVuYyhjYWNoZWRSZXMsIG5ld1JlcykpKSB7XG4gICAgICAgICAgICBjYWNoZWRSZXMgPSBuZXdSZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhY2hlZFJlcztcbiAgICB9O1xufVxuXG52YXIgRVhURU5ERURfU0VUVElOR1NfQU5EX1NFVkVSSVRJRVMgPSB7XG4gICAgd2VlazogMyxcbiAgICBzZXBhcmF0b3I6IDAsXG4gICAgb21pdFplcm9NaW51dGU6IDAsXG4gICAgbWVyaWRpZW06IDAsXG4gICAgb21pdENvbW1hczogMFxufTtcbnZhciBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFUyA9IHtcbiAgICB0aW1lWm9uZU5hbWU6IDcsXG4gICAgZXJhOiA2LFxuICAgIHllYXI6IDUsXG4gICAgbW9udGg6IDQsXG4gICAgZGF5OiAyLFxuICAgIHdlZWtkYXk6IDIsXG4gICAgaG91cjogMSxcbiAgICBtaW51dGU6IDEsXG4gICAgc2Vjb25kOiAxXG59O1xudmFyIE1FUklESUVNX1JFID0gL1xccyooW2FwXSlcXC4/bVxcLj8vaTsgLy8gZWF0cyB1cCBsZWFkaW5nIHNwYWNlcyB0b29cbnZhciBDT01NQV9SRSA9IC8sL2c7IC8vIHdlIG5lZWQgcmUgZm9yIGdsb2JhbG5lc3NcbnZhciBNVUxUSV9TUEFDRV9SRSA9IC9cXHMrL2c7XG52YXIgTFRSX1JFID0gL1xcdTIwMGUvZzsgLy8gY29udHJvbCBjaGFyYWN0ZXJcbnZhciBVVENfUkUgPSAvVVRDfEdNVC87XG52YXIgTmF0aXZlRm9ybWF0dGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE5hdGl2ZUZvcm1hdHRlcihmb3JtYXRTZXR0aW5ncykge1xuICAgICAgICB2YXIgc3RhbmRhcmREYXRlUHJvcHMgPSB7fTtcbiAgICAgICAgdmFyIGV4dGVuZGVkU2V0dGluZ3MgPSB7fTtcbiAgICAgICAgdmFyIHNldmVyaXR5ID0gMDtcbiAgICAgICAgZm9yICh2YXIgbmFtZV8xIGluIGZvcm1hdFNldHRpbmdzKSB7XG4gICAgICAgICAgICBpZiAobmFtZV8xIGluIEVYVEVOREVEX1NFVFRJTkdTX0FORF9TRVZFUklUSUVTKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5kZWRTZXR0aW5nc1tuYW1lXzFdID0gZm9ybWF0U2V0dGluZ3NbbmFtZV8xXTtcbiAgICAgICAgICAgICAgICBzZXZlcml0eSA9IE1hdGgubWF4KEVYVEVOREVEX1NFVFRJTkdTX0FORF9TRVZFUklUSUVTW25hbWVfMV0sIHNldmVyaXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkRGF0ZVByb3BzW25hbWVfMV0gPSBmb3JtYXRTZXR0aW5nc1tuYW1lXzFdO1xuICAgICAgICAgICAgICAgIGlmIChuYW1lXzEgaW4gU1RBTkRBUkRfREFURV9QUk9QX1NFVkVSSVRJRVMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V2ZXJpdHkgPSBNYXRoLm1heChTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFU1tuYW1lXzFdLCBzZXZlcml0eSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RhbmRhcmREYXRlUHJvcHMgPSBzdGFuZGFyZERhdGVQcm9wcztcbiAgICAgICAgdGhpcy5leHRlbmRlZFNldHRpbmdzID0gZXh0ZW5kZWRTZXR0aW5ncztcbiAgICAgICAgdGhpcy5zZXZlcml0eSA9IHNldmVyaXR5O1xuICAgICAgICB0aGlzLmJ1aWxkRm9ybWF0dGluZ0Z1bmMgPSBtZW1vaXplKGJ1aWxkRm9ybWF0dGluZ0Z1bmMpO1xuICAgIH1cbiAgICBOYXRpdmVGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdCA9IGZ1bmN0aW9uIChkYXRlLCBjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkRm9ybWF0dGluZ0Z1bmModGhpcy5zdGFuZGFyZERhdGVQcm9wcywgdGhpcy5leHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KShkYXRlKTtcbiAgICB9O1xuICAgIE5hdGl2ZUZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0UmFuZ2UgPSBmdW5jdGlvbiAoc3RhcnQsIGVuZCwgY29udGV4dCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBzdGFuZGFyZERhdGVQcm9wcyA9IF9hLnN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzID0gX2EuZXh0ZW5kZWRTZXR0aW5ncztcbiAgICAgICAgdmFyIGRpZmZTZXZlcml0eSA9IGNvbXB1dGVNYXJrZXJEaWZmU2V2ZXJpdHkoc3RhcnQubWFya2VyLCBlbmQubWFya2VyLCBjb250ZXh0LmNhbGVuZGFyU3lzdGVtKTtcbiAgICAgICAgaWYgKCFkaWZmU2V2ZXJpdHkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvcm1hdChzdGFydCwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJpZ2dlc3RVbml0Rm9yUGFydGlhbCA9IGRpZmZTZXZlcml0eTtcbiAgICAgICAgaWYgKGJpZ2dlc3RVbml0Rm9yUGFydGlhbCA+IDEgJiYgLy8gdGhlIHR3byBkYXRlcyBhcmUgZGlmZmVyZW50IGluIGEgd2F5IHRoYXQncyBsYXJnZXIgc2NhbGUgdGhhbiB0aW1lXG4gICAgICAgICAgICAoc3RhbmRhcmREYXRlUHJvcHMueWVhciA9PT0gJ251bWVyaWMnIHx8IHN0YW5kYXJkRGF0ZVByb3BzLnllYXIgPT09ICcyLWRpZ2l0JykgJiZcbiAgICAgICAgICAgIChzdGFuZGFyZERhdGVQcm9wcy5tb250aCA9PT0gJ251bWVyaWMnIHx8IHN0YW5kYXJkRGF0ZVByb3BzLm1vbnRoID09PSAnMi1kaWdpdCcpICYmXG4gICAgICAgICAgICAoc3RhbmRhcmREYXRlUHJvcHMuZGF5ID09PSAnbnVtZXJpYycgfHwgc3RhbmRhcmREYXRlUHJvcHMuZGF5ID09PSAnMi1kaWdpdCcpKSB7XG4gICAgICAgICAgICBiaWdnZXN0VW5pdEZvclBhcnRpYWwgPSAxOyAvLyBtYWtlIGl0IGxvb2sgbGlrZSB0aGUgZGF0ZXMgYXJlIG9ubHkgZGlmZmVyZW50IGluIHRlcm1zIG9mIHRpbWVcbiAgICAgICAgfVxuICAgICAgICB2YXIgZnVsbDAgPSB0aGlzLmZvcm1hdChzdGFydCwgY29udGV4dCk7XG4gICAgICAgIHZhciBmdWxsMSA9IHRoaXMuZm9ybWF0KGVuZCwgY29udGV4dCk7XG4gICAgICAgIGlmIChmdWxsMCA9PT0gZnVsbDEpIHtcbiAgICAgICAgICAgIHJldHVybiBmdWxsMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFydGlhbERhdGVQcm9wcyA9IGNvbXB1dGVQYXJ0aWFsRm9ybWF0dGluZ09wdGlvbnMoc3RhbmRhcmREYXRlUHJvcHMsIGJpZ2dlc3RVbml0Rm9yUGFydGlhbCk7XG4gICAgICAgIHZhciBwYXJ0aWFsRm9ybWF0dGluZ0Z1bmMgPSBidWlsZEZvcm1hdHRpbmdGdW5jKHBhcnRpYWxEYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpO1xuICAgICAgICB2YXIgcGFydGlhbDAgPSBwYXJ0aWFsRm9ybWF0dGluZ0Z1bmMoc3RhcnQpO1xuICAgICAgICB2YXIgcGFydGlhbDEgPSBwYXJ0aWFsRm9ybWF0dGluZ0Z1bmMoZW5kKTtcbiAgICAgICAgdmFyIGluc2VydGlvbiA9IGZpbmRDb21tb25JbnNlcnRpb24oZnVsbDAsIHBhcnRpYWwwLCBmdWxsMSwgcGFydGlhbDEpO1xuICAgICAgICB2YXIgc2VwYXJhdG9yID0gZXh0ZW5kZWRTZXR0aW5ncy5zZXBhcmF0b3IgfHwgJyc7XG4gICAgICAgIGlmIChpbnNlcnRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBpbnNlcnRpb24uYmVmb3JlICsgcGFydGlhbDAgKyBzZXBhcmF0b3IgKyBwYXJ0aWFsMSArIGluc2VydGlvbi5hZnRlcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVsbDAgKyBzZXBhcmF0b3IgKyBmdWxsMTtcbiAgICB9O1xuICAgIE5hdGl2ZUZvcm1hdHRlci5wcm90b3R5cGUuZ2V0TGFyZ2VzdFVuaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5zZXZlcml0eSkge1xuICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgIHJldHVybiAneWVhcic7XG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuICdtb250aCc7XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgcmV0dXJuICd3ZWVrJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkYXknO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gTmF0aXZlRm9ybWF0dGVyO1xufSgpKTtcbmZ1bmN0aW9uIGJ1aWxkRm9ybWF0dGluZ0Z1bmMoc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpIHtcbiAgICB2YXIgc3RhbmRhcmREYXRlUHJvcENudCA9IE9iamVjdC5rZXlzKHN0YW5kYXJkRGF0ZVByb3BzKS5sZW5ndGg7XG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BDbnQgPT09IDEgJiYgc3RhbmRhcmREYXRlUHJvcHMudGltZVpvbmVOYW1lID09PSAnc2hvcnQnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdFRpbWVab25lT2Zmc2V0KGRhdGUudGltZVpvbmVPZmZzZXQpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoc3RhbmRhcmREYXRlUHJvcENudCA9PT0gMCAmJiBleHRlbmRlZFNldHRpbmdzLndlZWspIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0V2Vla051bWJlcihjb250ZXh0LmNvbXB1dGVXZWVrTnVtYmVyKGRhdGUubWFya2VyKSwgY29udGV4dC53ZWVrTGFiZWwsIGNvbnRleHQubG9jYWxlLCBleHRlbmRlZFNldHRpbmdzLndlZWspO1xuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gYnVpbGROYXRpdmVGb3JtYXR0aW5nRnVuYyhzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG59XG5mdW5jdGlvbiBidWlsZE5hdGl2ZUZvcm1hdHRpbmdGdW5jKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgc3RhbmRhcmREYXRlUHJvcHMgPSBfX2Fzc2lnbih7fSwgc3RhbmRhcmREYXRlUHJvcHMpOyAvLyBjb3B5XG4gICAgZXh0ZW5kZWRTZXR0aW5ncyA9IF9fYXNzaWduKHt9LCBleHRlbmRlZFNldHRpbmdzKTsgLy8gY29weVxuICAgIHNhbml0aXplU2V0dGluZ3Moc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MpO1xuICAgIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lID0gJ1VUQyc7IC8vIHdlIGxldmVyYWdlIHRoZSBvbmx5IGd1YXJhbnRlZWQgdGltZVpvbmUgZm9yIG91ciBVVEMgbWFya2Vyc1xuICAgIHZhciBub3JtYWxGb3JtYXQgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChjb250ZXh0LmxvY2FsZS5jb2Rlcywgc3RhbmRhcmREYXRlUHJvcHMpO1xuICAgIHZhciB6ZXJvRm9ybWF0OyAvLyBuZWVkZWQ/XG4gICAgaWYgKGV4dGVuZGVkU2V0dGluZ3Mub21pdFplcm9NaW51dGUpIHtcbiAgICAgICAgdmFyIHplcm9Qcm9wcyA9IF9fYXNzaWduKHt9LCBzdGFuZGFyZERhdGVQcm9wcyk7XG4gICAgICAgIGRlbGV0ZSB6ZXJvUHJvcHMubWludXRlOyAvLyBzZWNvbmRzIGFuZCBtcyB3ZXJlIGFscmVhZHkgY29uc2lkZXJlZCBpbiBzYW5pdGl6ZVNldHRpbmdzXG4gICAgICAgIHplcm9Gb3JtYXQgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChjb250ZXh0LmxvY2FsZS5jb2RlcywgemVyb1Byb3BzKTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgIHZhciBtYXJrZXIgPSBkYXRlLm1hcmtlcjtcbiAgICAgICAgdmFyIGZvcm1hdDtcbiAgICAgICAgaWYgKHplcm9Gb3JtYXQgJiYgIW1hcmtlci5nZXRVVENNaW51dGVzKCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IHplcm9Gb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBub3JtYWxGb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHMgPSBmb3JtYXQuZm9ybWF0KG1hcmtlcik7XG4gICAgICAgIHJldHVybiBwb3N0UHJvY2VzcyhzLCBkYXRlLCBzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHNhbml0aXplU2V0dGluZ3Moc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MpIHtcbiAgICAvLyBkZWFsIHdpdGggYSBicm93c2VyIGluY29uc2lzdGVuY3kgd2hlcmUgZm9ybWF0dGluZyB0aGUgdGltZXpvbmVcbiAgICAvLyByZXF1aXJlcyB0aGF0IHRoZSBob3VyL21pbnV0ZSBiZSBwcmVzZW50LlxuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZU5hbWUpIHtcbiAgICAgICAgaWYgKCFzdGFuZGFyZERhdGVQcm9wcy5ob3VyKSB7XG4gICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy5ob3VyID0gJzItZGlnaXQnO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3RhbmRhcmREYXRlUHJvcHMubWludXRlKSB7XG4gICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy5taW51dGUgPSAnMi1kaWdpdCc7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gb25seSBzdXBwb3J0IHNob3J0IHRpbWV6b25lIG5hbWVzXG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9PT0gJ2xvbmcnKSB7XG4gICAgICAgIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9ICdzaG9ydCc7XG4gICAgfVxuICAgIC8vIGlmIHJlcXVlc3RpbmcgdG8gZGlzcGxheSBzZWNvbmRzLCBNVVNUIGRpc3BsYXkgbWludXRlc1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlICYmIChzdGFuZGFyZERhdGVQcm9wcy5zZWNvbmQgfHwgc3RhbmRhcmREYXRlUHJvcHMubWlsbGlzZWNvbmQpKSB7XG4gICAgICAgIGRlbGV0ZSBleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHBvc3RQcm9jZXNzKHMsIGRhdGUsIHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgcyA9IHMucmVwbGFjZShMVFJfUkUsICcnKTsgLy8gcmVtb3ZlIGxlZnQtdG8tcmlnaHQgY29udHJvbCBjaGFycy4gZG8gZmlyc3QuIGdvb2QgZm9yIG90aGVyIHJlZ2V4ZXNcbiAgICBpZiAoc3RhbmRhcmREYXRlUHJvcHMudGltZVpvbmVOYW1lID09PSAnc2hvcnQnKSB7XG4gICAgICAgIHMgPSBpbmplY3RUem9TdHIocywgKGNvbnRleHQudGltZVpvbmUgPT09ICdVVEMnIHx8IGRhdGUudGltZVpvbmVPZmZzZXQgPT0gbnVsbCkgP1xuICAgICAgICAgICAgJ1VUQycgOiAvLyBpbXBvcnRhbnQgdG8gbm9ybWFsaXplIGZvciBJRSwgd2hpY2ggZG9lcyBcIkdNVFwiXG4gICAgICAgICAgICBmb3JtYXRUaW1lWm9uZU9mZnNldChkYXRlLnRpbWVab25lT2Zmc2V0KSk7XG4gICAgfVxuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRDb21tYXMpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZShDT01NQV9SRSwgJycpLnRyaW0oKTtcbiAgICB9XG4gICAgaWYgKGV4dGVuZGVkU2V0dGluZ3Mub21pdFplcm9NaW51dGUpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZSgnOjAwJywgJycpOyAvLyB6ZXJvRm9ybWF0IGRvZXNuJ3QgYWx3YXlzIGFjaGlldmUgdGhpc1xuICAgIH1cbiAgICAvLyBeIGRvIGFueXRoaW5nIHRoYXQgbWlnaHQgY3JlYXRlIGFkamFjZW50IHNwYWNlcyBiZWZvcmUgdGhpcyBwb2ludCxcbiAgICAvLyBiZWNhdXNlIE1FUklESUVNX1JFIGxpa2VzIHRvIGVhdCB1cCBsb2FkaW5nIHNwYWNlc1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSBmYWxzZSkge1xuICAgICAgICBzID0gcy5yZXBsYWNlKE1FUklESUVNX1JFLCAnJykudHJpbSgpO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSAnbmFycm93JykgeyAvLyBhL3BcbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgZnVuY3Rpb24gKG0wLCBtMSkge1xuICAgICAgICAgICAgcmV0dXJuIG0xLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSAnc2hvcnQnKSB7IC8vIGFtL3BtXG4gICAgICAgIHMgPSBzLnJlcGxhY2UoTUVSSURJRU1fUkUsIGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgICAgIHJldHVybiBtMS50b0xvY2FsZUxvd2VyQ2FzZSgpICsgJ20nO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5tZXJpZGllbSA9PT0gJ2xvd2VyY2FzZScpIHsgLy8gb3RoZXIgbWVyaWRpZW0gdHJhbnNmb3JtZXJzIGFscmVhZHkgY29udmVydGVkIHRvIGxvd2VyY2FzZVxuICAgICAgICBzID0gcy5yZXBsYWNlKE1FUklESUVNX1JFLCBmdW5jdGlvbiAobTApIHtcbiAgICAgICAgICAgIHJldHVybiBtMC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcyA9IHMucmVwbGFjZShNVUxUSV9TUEFDRV9SRSwgJyAnKTtcbiAgICBzID0gcy50cmltKCk7XG4gICAgcmV0dXJuIHM7XG59XG5mdW5jdGlvbiBpbmplY3RUem9TdHIocywgdHpvU3RyKSB7XG4gICAgdmFyIHJlcGxhY2VkID0gZmFsc2U7XG4gICAgcyA9IHMucmVwbGFjZShVVENfUkUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVwbGFjZWQgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdHpvU3RyO1xuICAgIH0pO1xuICAgIC8vIElFMTEgZG9lc24ndCBpbmNsdWRlIFVUQy9HTVQgaW4gdGhlIG9yaWdpbmFsIHN0cmluZywgc28gYXBwZW5kIHRvIGVuZFxuICAgIGlmICghcmVwbGFjZWQpIHtcbiAgICAgICAgcyArPSAnICcgKyB0em9TdHI7XG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuZnVuY3Rpb24gZm9ybWF0V2Vla051bWJlcihudW0sIHdlZWtMYWJlbCwgbG9jYWxlLCBkaXNwbGF5KSB7XG4gICAgdmFyIHBhcnRzID0gW107XG4gICAgaWYgKGRpc3BsYXkgPT09ICduYXJyb3cnKSB7XG4gICAgICAgIHBhcnRzLnB1c2god2Vla0xhYmVsKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZGlzcGxheSA9PT0gJ3Nob3J0Jykge1xuICAgICAgICBwYXJ0cy5wdXNoKHdlZWtMYWJlbCwgJyAnKTtcbiAgICB9XG4gICAgLy8gb3RoZXJ3aXNlLCBjb25zaWRlcmVkICdudW1lcmljJ1xuICAgIHBhcnRzLnB1c2gobG9jYWxlLnNpbXBsZU51bWJlckZvcm1hdC5mb3JtYXQobnVtKSk7XG4gICAgaWYgKGxvY2FsZS5vcHRpb25zLmlzUnRsKSB7IC8vIFRPRE86IHVzZSBjb250cm9sIGNoYXJhY3RlcnMgaW5zdGVhZD9cbiAgICAgICAgcGFydHMucmV2ZXJzZSgpO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHMuam9pbignJyk7XG59XG4vLyBSYW5nZSBGb3JtYXR0aW5nIFV0aWxzXG4vLyAwID0gZXhhY3RseSB0aGUgc2FtZVxuLy8gMSA9IGRpZmZlcmVudCBieSB0aW1lXG4vLyBhbmQgYmlnZ2VyXG5mdW5jdGlvbiBjb21wdXRlTWFya2VyRGlmZlNldmVyaXR5KGQwLCBkMSwgY2EpIHtcbiAgICBpZiAoY2EuZ2V0TWFya2VyWWVhcihkMCkgIT09IGNhLmdldE1hcmtlclllYXIoZDEpKSB7XG4gICAgICAgIHJldHVybiA1O1xuICAgIH1cbiAgICBpZiAoY2EuZ2V0TWFya2VyTW9udGgoZDApICE9PSBjYS5nZXRNYXJrZXJNb250aChkMSkpIHtcbiAgICAgICAgcmV0dXJuIDQ7XG4gICAgfVxuICAgIGlmIChjYS5nZXRNYXJrZXJEYXkoZDApICE9PSBjYS5nZXRNYXJrZXJEYXkoZDEpKSB7XG4gICAgICAgIHJldHVybiAyO1xuICAgIH1cbiAgICBpZiAodGltZUFzTXMoZDApICE9PSB0aW1lQXNNcyhkMSkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIHJldHVybiAwO1xufVxuZnVuY3Rpb24gY29tcHV0ZVBhcnRpYWxGb3JtYXR0aW5nT3B0aW9ucyhvcHRpb25zLCBiaWdnZXN0VW5pdCkge1xuICAgIHZhciBwYXJ0aWFsT3B0aW9ucyA9IHt9O1xuICAgIGZvciAodmFyIG5hbWVfMiBpbiBvcHRpb25zKSB7XG4gICAgICAgIGlmICghKG5hbWVfMiBpbiBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFUykgfHwgLy8gbm90IGEgZGF0ZSBwYXJ0IHByb3AgKGxpa2UgdGltZVpvbmUpXG4gICAgICAgICAgICBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFU1tuYW1lXzJdIDw9IGJpZ2dlc3RVbml0KSB7XG4gICAgICAgICAgICBwYXJ0aWFsT3B0aW9uc1tuYW1lXzJdID0gb3B0aW9uc1tuYW1lXzJdO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJ0aWFsT3B0aW9ucztcbn1cbmZ1bmN0aW9uIGZpbmRDb21tb25JbnNlcnRpb24oZnVsbDAsIHBhcnRpYWwwLCBmdWxsMSwgcGFydGlhbDEpIHtcbiAgICB2YXIgaTAgPSAwO1xuICAgIHdoaWxlIChpMCA8IGZ1bGwwLmxlbmd0aCkge1xuICAgICAgICB2YXIgZm91bmQwID0gZnVsbDAuaW5kZXhPZihwYXJ0aWFsMCwgaTApO1xuICAgICAgICBpZiAoZm91bmQwID09PSAtMSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJlZm9yZTAgPSBmdWxsMC5zdWJzdHIoMCwgZm91bmQwKTtcbiAgICAgICAgaTAgPSBmb3VuZDAgKyBwYXJ0aWFsMC5sZW5ndGg7XG4gICAgICAgIHZhciBhZnRlcjAgPSBmdWxsMC5zdWJzdHIoaTApO1xuICAgICAgICB2YXIgaTEgPSAwO1xuICAgICAgICB3aGlsZSAoaTEgPCBmdWxsMS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBmb3VuZDEgPSBmdWxsMS5pbmRleE9mKHBhcnRpYWwxLCBpMSk7XG4gICAgICAgICAgICBpZiAoZm91bmQxID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGJlZm9yZTEgPSBmdWxsMS5zdWJzdHIoMCwgZm91bmQxKTtcbiAgICAgICAgICAgIGkxID0gZm91bmQxICsgcGFydGlhbDEubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGFmdGVyMSA9IGZ1bGwxLnN1YnN0cihpMSk7XG4gICAgICAgICAgICBpZiAoYmVmb3JlMCA9PT0gYmVmb3JlMSAmJiBhZnRlcjAgPT09IGFmdGVyMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGJlZm9yZTogYmVmb3JlMCxcbiAgICAgICAgICAgICAgICAgICAgYWZ0ZXI6IGFmdGVyMFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbi8qXG5UT0RPOiBmaXggdGhlIHRlcm1pbm9sb2d5IG9mIFwiZm9ybWF0dGVyXCIgdnMgXCJmb3JtYXR0aW5nIGZ1bmNcIlxuKi9cbi8qXG5BdCB0aGUgdGltZSBvZiBpbnN0YW50aWF0aW9uLCB0aGlzIG9iamVjdCBkb2VzIG5vdCBrbm93IHdoaWNoIGNtZC1mb3JtYXR0aW5nIHN5c3RlbSBpdCB3aWxsIHVzZS5cbkl0IHJlY2VpdmVzIHRoaXMgYXQgdGhlIHRpbWUgb2YgZm9ybWF0dGluZywgYXMgYSBzZXR0aW5nLlxuKi9cbnZhciBDbWRGb3JtYXR0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ21kRm9ybWF0dGVyKGNtZFN0ciwgc2VwYXJhdG9yKSB7XG4gICAgICAgIHRoaXMuY21kU3RyID0gY21kU3RyO1xuICAgICAgICB0aGlzLnNlcGFyYXRvciA9IHNlcGFyYXRvcjtcbiAgICB9XG4gICAgQ21kRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAoZGF0ZSwgY29udGV4dCkge1xuICAgICAgICByZXR1cm4gY29udGV4dC5jbWRGb3JtYXR0ZXIodGhpcy5jbWRTdHIsIGNyZWF0ZVZlcmJvc2VGb3JtYXR0aW5nQXJnKGRhdGUsIG51bGwsIGNvbnRleHQsIHRoaXMuc2VwYXJhdG9yKSk7XG4gICAgfTtcbiAgICBDbWRGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIGNvbnRleHQuY21kRm9ybWF0dGVyKHRoaXMuY21kU3RyLCBjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhzdGFydCwgZW5kLCBjb250ZXh0LCB0aGlzLnNlcGFyYXRvcikpO1xuICAgIH07XG4gICAgcmV0dXJuIENtZEZvcm1hdHRlcjtcbn0oKSk7XG5cbnZhciBGdW5jRm9ybWF0dGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZ1bmNGb3JtYXR0ZXIoZnVuYykge1xuICAgICAgICB0aGlzLmZ1bmMgPSBmdW5jO1xuICAgIH1cbiAgICBGdW5jRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAoZGF0ZSwgY29udGV4dCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mdW5jKGNyZWF0ZVZlcmJvc2VGb3JtYXR0aW5nQXJnKGRhdGUsIG51bGwsIGNvbnRleHQpKTtcbiAgICB9O1xuICAgIEZ1bmNGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuYyhjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhzdGFydCwgZW5kLCBjb250ZXh0KSk7XG4gICAgfTtcbiAgICByZXR1cm4gRnVuY0Zvcm1hdHRlcjtcbn0oKSk7XG5cbi8vIEZvcm1hdHRlciBPYmplY3QgQ3JlYXRpb25cbmZ1bmN0aW9uIGNyZWF0ZUZvcm1hdHRlcihpbnB1dCwgZGVmYXVsdFNlcGFyYXRvcikge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICBpZiAodHlwZW9mIGRlZmF1bHRTZXBhcmF0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpbnB1dCA9IF9fYXNzaWduKHsgc2VwYXJhdG9yOiBkZWZhdWx0U2VwYXJhdG9yIH0sIGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZUZvcm1hdHRlcihpbnB1dCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDbWRGb3JtYXR0ZXIoaW5wdXQsIGRlZmF1bHRTZXBhcmF0b3IpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBGdW5jRm9ybWF0dGVyKGlucHV0KTtcbiAgICB9XG59XG4vLyBTdHJpbmcgVXRpbHNcbi8vIHRpbWVab25lT2Zmc2V0IGlzIGluIG1pbnV0ZXNcbmZ1bmN0aW9uIGJ1aWxkSXNvU3RyaW5nKG1hcmtlciwgdGltZVpvbmVPZmZzZXQsIHN0cmlwWmVyb1RpbWUpIHtcbiAgICBpZiAoc3RyaXBaZXJvVGltZSA9PT0gdm9pZCAwKSB7IHN0cmlwWmVyb1RpbWUgPSBmYWxzZTsgfVxuICAgIHZhciBzID0gbWFya2VyLnRvSVNPU3RyaW5nKCk7XG4gICAgcyA9IHMucmVwbGFjZSgnLjAwMCcsICcnKTtcbiAgICBpZiAoc3RyaXBaZXJvVGltZSkge1xuICAgICAgICBzID0gcy5yZXBsYWNlKCdUMDA6MDA6MDBaJywgJycpO1xuICAgIH1cbiAgICBpZiAocy5sZW5ndGggPiAxMCkgeyAvLyB0aW1lIHBhcnQgd2Fzbid0IHN0cmlwcGVkLCBjYW4gYWRkIHRpbWV6b25lIGluZm9cbiAgICAgICAgaWYgKHRpbWVab25lT2Zmc2V0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJ1onLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGltZVpvbmVPZmZzZXQgIT09IDApIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJ1onLCBmb3JtYXRUaW1lWm9uZU9mZnNldCh0aW1lWm9uZU9mZnNldCwgdHJ1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG90aGVyd2lzZSwgaXRzIFVUQy0wIGFuZCB3ZSB3YW50IHRvIGtlZXAgdGhlIFpcbiAgICB9XG4gICAgcmV0dXJuIHM7XG59XG5mdW5jdGlvbiBmb3JtYXRJc29UaW1lU3RyaW5nKG1hcmtlcikge1xuICAgIHJldHVybiBwYWRTdGFydChtYXJrZXIuZ2V0VVRDSG91cnMoKSwgMikgKyAnOicgK1xuICAgICAgICBwYWRTdGFydChtYXJrZXIuZ2V0VVRDTWludXRlcygpLCAyKSArICc6JyArXG4gICAgICAgIHBhZFN0YXJ0KG1hcmtlci5nZXRVVENTZWNvbmRzKCksIDIpO1xufVxuZnVuY3Rpb24gZm9ybWF0VGltZVpvbmVPZmZzZXQobWludXRlcywgZG9Jc28pIHtcbiAgICBpZiAoZG9Jc28gPT09IHZvaWQgMCkgeyBkb0lzbyA9IGZhbHNlOyB9XG4gICAgdmFyIHNpZ24gPSBtaW51dGVzIDwgMCA/ICctJyA6ICcrJztcbiAgICB2YXIgYWJzID0gTWF0aC5hYnMobWludXRlcyk7XG4gICAgdmFyIGhvdXJzID0gTWF0aC5mbG9vcihhYnMgLyA2MCk7XG4gICAgdmFyIG1pbnMgPSBNYXRoLnJvdW5kKGFicyAlIDYwKTtcbiAgICBpZiAoZG9Jc28pIHtcbiAgICAgICAgcmV0dXJuIHNpZ24gKyBwYWRTdGFydChob3VycywgMikgKyAnOicgKyBwYWRTdGFydChtaW5zLCAyKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiAnR01UJyArIHNpZ24gKyBob3VycyArIChtaW5zID8gJzonICsgcGFkU3RhcnQobWlucywgMikgOiAnJyk7XG4gICAgfVxufVxuLy8gQXJnIFV0aWxzXG5mdW5jdGlvbiBjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhzdGFydCwgZW5kLCBjb250ZXh0LCBzZXBhcmF0b3IpIHtcbiAgICB2YXIgc3RhcnRJbmZvID0gZXhwYW5kWm9uZWRNYXJrZXIoc3RhcnQsIGNvbnRleHQuY2FsZW5kYXJTeXN0ZW0pO1xuICAgIHZhciBlbmRJbmZvID0gZW5kID8gZXhwYW5kWm9uZWRNYXJrZXIoZW5kLCBjb250ZXh0LmNhbGVuZGFyU3lzdGVtKSA6IG51bGw7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGF0ZTogc3RhcnRJbmZvLFxuICAgICAgICBzdGFydDogc3RhcnRJbmZvLFxuICAgICAgICBlbmQ6IGVuZEluZm8sXG4gICAgICAgIHRpbWVab25lOiBjb250ZXh0LnRpbWVab25lLFxuICAgICAgICBsb2NhbGVDb2RlczogY29udGV4dC5sb2NhbGUuY29kZXMsXG4gICAgICAgIHNlcGFyYXRvcjogc2VwYXJhdG9yXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGV4cGFuZFpvbmVkTWFya2VyKGRhdGVJbmZvLCBjYWxlbmRhclN5c3RlbSkge1xuICAgIHZhciBhID0gY2FsZW5kYXJTeXN0ZW0ubWFya2VyVG9BcnJheShkYXRlSW5mby5tYXJrZXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIG1hcmtlcjogZGF0ZUluZm8ubWFya2VyLFxuICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZUluZm8udGltZVpvbmVPZmZzZXQsXG4gICAgICAgIGFycmF5OiBhLFxuICAgICAgICB5ZWFyOiBhWzBdLFxuICAgICAgICBtb250aDogYVsxXSxcbiAgICAgICAgZGF5OiBhWzJdLFxuICAgICAgICBob3VyOiBhWzNdLFxuICAgICAgICBtaW51dGU6IGFbNF0sXG4gICAgICAgIHNlY29uZDogYVs1XSxcbiAgICAgICAgbWlsbGlzZWNvbmQ6IGFbNl1cbiAgICB9O1xufVxuXG52YXIgRXZlbnRTb3VyY2VBcGkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRXZlbnRTb3VyY2VBcGkoY2FsZW5kYXIsIGludGVybmFsRXZlbnRTb3VyY2UpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLmludGVybmFsRXZlbnRTb3VyY2UgPSBpbnRlcm5hbEV2ZW50U291cmNlO1xuICAgIH1cbiAgICBFdmVudFNvdXJjZUFwaS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRfU09VUkNFJyxcbiAgICAgICAgICAgIHNvdXJjZUlkOiB0aGlzLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWRcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBFdmVudFNvdXJjZUFwaS5wcm90b3R5cGUucmVmZXRjaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnRkVUQ0hfRVZFTlRfU09VUkNFUycsXG4gICAgICAgICAgICBzb3VyY2VJZHM6IFt0aGlzLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWRdXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50U291cmNlQXBpLnByb3RvdHlwZSwgXCJpZFwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5wdWJsaWNJZDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50U291cmNlQXBpLnByb3RvdHlwZSwgXCJ1cmxcIiwge1xuICAgICAgICAvLyBvbmx5IHJlbGV2YW50IHRvIGpzb24tZmVlZCBldmVudCBzb3VyY2VzXG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5tZXRhLnVybDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIEV2ZW50U291cmNlQXBpO1xufSgpKTtcblxudmFyIEV2ZW50QXBpID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEV2ZW50QXBpKGNhbGVuZGFyLCBkZWYsIGluc3RhbmNlKSB7XG4gICAgICAgIHRoaXMuX2NhbGVuZGFyID0gY2FsZW5kYXI7XG4gICAgICAgIHRoaXMuX2RlZiA9IGRlZjtcbiAgICAgICAgdGhpcy5faW5zdGFuY2UgPSBpbnN0YW5jZSB8fCBudWxsO1xuICAgIH1cbiAgICAvKlxuICAgIFRPRE86IG1ha2UgZXZlbnQgc3RydWN0IG1vcmUgcmVzcG9uc2libGUgZm9yIHRoaXNcbiAgICAqL1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRQcm9wID0gZnVuY3Rpb24gKG5hbWUsIHZhbCkge1xuICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICBpZiAobmFtZSBpbiBEQVRFX1BST1BTKSA7XG4gICAgICAgIGVsc2UgaWYgKG5hbWUgaW4gTk9OX0RBVEVfUFJPUFMpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgTk9OX0RBVEVfUFJPUFNbbmFtZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB2YWwgPSBOT05fREFURV9QUk9QU1tuYW1lXSh2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tdXRhdGUoe1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHM6IChfYSA9IHt9LCBfYVtuYW1lXSA9IHZhbCwgX2EpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuYW1lIGluIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTKSB7XG4gICAgICAgICAgICB2YXIgdWkgPSB2b2lkIDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTW25hbWVdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gVU5TQ09QRURfRVZFTlRfVUlfUFJPUFNbbmFtZV0odmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuYW1lID09PSAnY29sb3InKSB7XG4gICAgICAgICAgICAgICAgdWkgPSB7IGJhY2tncm91bmRDb2xvcjogdmFsLCBib3JkZXJDb2xvcjogdmFsIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChuYW1lID09PSAnZWRpdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgdWkgPSB7IHN0YXJ0RWRpdGFibGU6IHZhbCwgZHVyYXRpb25FZGl0YWJsZTogdmFsIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB1aSA9IChfYiA9IHt9LCBfYltuYW1lXSA9IHZhbCwgX2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tdXRhdGUoe1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHM6IHsgdWk6IHVpIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0RXh0ZW5kZWRQcm9wID0gZnVuY3Rpb24gKG5hbWUsIHZhbCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHRoaXMubXV0YXRlKHtcbiAgICAgICAgICAgIGV4dGVuZGVkUHJvcHM6IChfYSA9IHt9LCBfYVtuYW1lXSA9IHZhbCwgX2EpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLnNldFN0YXJ0ID0gZnVuY3Rpb24gKHN0YXJ0SW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgc3RhcnQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihzdGFydElucHV0KTtcbiAgICAgICAgaWYgKHN0YXJ0ICYmIHRoaXMuX2luc3RhbmNlKSB7IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICAgICAgdmFyIGluc3RhbmNlUmFuZ2UgPSB0aGlzLl9pbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgICAgIHZhciBzdGFydERlbHRhID0gZGlmZkRhdGVzKGluc3RhbmNlUmFuZ2Uuc3RhcnQsIHN0YXJ0LCBkYXRlRW52LCBvcHRpb25zLmdyYW51bGFyaXR5KTsgLy8gd2hhdCBpZiBwYXJzZWQgYmFkIT9cbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1haW50YWluRHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGRhdGVzRGVsdGE6IHN0YXJ0RGVsdGEgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YXJ0RGVsdGE6IHN0YXJ0RGVsdGEgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRFbmQgPSBmdW5jdGlvbiAoZW5kSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgZW5kO1xuICAgICAgICBpZiAoZW5kSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoZW5kSW5wdXQpO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnN0YW5jZSkge1xuICAgICAgICAgICAgaWYgKGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciBlbmREZWx0YSA9IGRpZmZEYXRlcyh0aGlzLl9pbnN0YW5jZS5yYW5nZS5lbmQsIGVuZCwgZGF0ZUVudiwgb3B0aW9ucy5ncmFudWxhcml0eSk7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBlbmREZWx0YTogZW5kRGVsdGEgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YW5kYXJkUHJvcHM6IHsgaGFzRW5kOiBmYWxzZSB9IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0RGF0ZXMgPSBmdW5jdGlvbiAoc3RhcnRJbnB1dCwgZW5kSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgc3RhbmRhcmRQcm9wcyA9IHsgYWxsRGF5OiBvcHRpb25zLmFsbERheSB9O1xuICAgICAgICB2YXIgc3RhcnQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihzdGFydElucHV0KTtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgaWYgKCFzdGFydCkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5kSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoZW5kSW5wdXQpO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnN0YW5jZSkge1xuICAgICAgICAgICAgdmFyIGluc3RhbmNlUmFuZ2UgPSB0aGlzLl9pbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgICAgIC8vIHdoZW4gY29tcHV0aW5nIHRoZSBkaWZmIGZvciBhbiBldmVudCBiZWluZyBjb252ZXJ0ZWQgdG8gYWxsLWRheSxcbiAgICAgICAgICAgIC8vIGNvbXB1dGUgZGlmZiBvZmYgb2YgdGhlIGFsbC1kYXkgdmFsdWVzIHRoZSB3YXkgZXZlbnQtbXV0YXRpb24gZG9lcy5cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFsbERheSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGluc3RhbmNlUmFuZ2UgPSBjb21wdXRlQWxpZ25lZERheVJhbmdlKGluc3RhbmNlUmFuZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHN0YXJ0RGVsdGEgPSBkaWZmRGF0ZXMoaW5zdGFuY2VSYW5nZS5zdGFydCwgc3RhcnQsIGRhdGVFbnYsIG9wdGlvbnMuZ3JhbnVsYXJpdHkpO1xuICAgICAgICAgICAgaWYgKGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciBlbmREZWx0YSA9IGRpZmZEYXRlcyhpbnN0YW5jZVJhbmdlLmVuZCwgZW5kLCBkYXRlRW52LCBvcHRpb25zLmdyYW51bGFyaXR5KTtcbiAgICAgICAgICAgICAgICBpZiAoZHVyYXRpb25zRXF1YWwoc3RhcnREZWx0YSwgZW5kRGVsdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZGF0ZXNEZWx0YTogc3RhcnREZWx0YSwgc3RhbmRhcmRQcm9wczogc3RhbmRhcmRQcm9wcyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgc3RhcnREZWx0YTogc3RhcnREZWx0YSwgZW5kRGVsdGE6IGVuZERlbHRhLCBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgeyAvLyBtZWFucyBcImNsZWFyIHRoZSBlbmRcIlxuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHMuaGFzRW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBkYXRlc0RlbHRhOiBzdGFydERlbHRhLCBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUubW92ZVN0YXJ0ID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgc3RhcnREZWx0YTogZGVsdGEgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5tb3ZlRW5kID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZW5kRGVsdGE6IGRlbHRhIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUubW92ZURhdGVzID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZGF0ZXNEZWx0YTogZGVsdGEgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRBbGxEYXkgPSBmdW5jdGlvbiAoYWxsRGF5LCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciBzdGFuZGFyZFByb3BzID0geyBhbGxEYXk6IGFsbERheSB9O1xuICAgICAgICB2YXIgbWFpbnRhaW5EdXJhdGlvbiA9IG9wdGlvbnMubWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgaWYgKG1haW50YWluRHVyYXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgbWFpbnRhaW5EdXJhdGlvbiA9IHRoaXMuX2NhbGVuZGFyLm9wdCgnYWxsRGF5TWFpbnRhaW5EdXJhdGlvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9kZWYuYWxsRGF5ICE9PSBhbGxEYXkpIHtcbiAgICAgICAgICAgIHN0YW5kYXJkUHJvcHMuaGFzRW5kID0gbWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YW5kYXJkUHJvcHM6IHN0YW5kYXJkUHJvcHMgfSk7XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuZm9ybWF0UmFuZ2UgPSBmdW5jdGlvbiAoZm9ybWF0SW5wdXQpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgdmFyIGZvcm1hdHRlciA9IGNyZWF0ZUZvcm1hdHRlcihmb3JtYXRJbnB1dCwgdGhpcy5fY2FsZW5kYXIub3B0KCdkZWZhdWx0UmFuZ2VTZXBhcmF0b3InKSk7XG4gICAgICAgIGlmICh0aGlzLl9kZWYuaGFzRW5kKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXRSYW5nZShpbnN0YW5jZS5yYW5nZS5zdGFydCwgaW5zdGFuY2UucmFuZ2UuZW5kLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICBmb3JjZWRTdGFydFR6bzogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICAgICAgZm9yY2VkRW5kVHpvOiBpbnN0YW5jZS5mb3JjZWRFbmRUem9cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0KGluc3RhbmNlLnJhbmdlLnN0YXJ0LCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICBmb3JjZWRUem86IGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLm11dGF0ZSA9IGZ1bmN0aW9uIChtdXRhdGlvbikge1xuICAgICAgICB2YXIgZGVmID0gdGhpcy5fZGVmO1xuICAgICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ01VVEFURV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlSWQ6IGluc3RhbmNlLmluc3RhbmNlSWQsXG4gICAgICAgICAgICAgICAgbXV0YXRpb246IG11dGF0aW9uLFxuICAgICAgICAgICAgICAgIGZyb21BcGk6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGV2ZW50U3RvcmUgPSB0aGlzLl9jYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlO1xuICAgICAgICAgICAgdGhpcy5fZGVmID0gZXZlbnRTdG9yZS5kZWZzW2RlZi5kZWZJZF07XG4gICAgICAgICAgICB0aGlzLl9pbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlLmluc3RhbmNlSWRdO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVNT1ZFX0VWRU5UX0RFRicsXG4gICAgICAgICAgICBkZWZJZDogdGhpcy5fZGVmLmRlZklkXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJzb3VyY2VcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2VJZCA9IHRoaXMuX2RlZi5zb3VyY2VJZDtcbiAgICAgICAgICAgIGlmIChzb3VyY2VJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZlbnRTb3VyY2VBcGkodGhpcy5fY2FsZW5kYXIsIHRoaXMuX2NhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlc1tzb3VyY2VJZF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwic3RhcnRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pbnN0YW5jZSA/XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FsZW5kYXIuZGF0ZUVudi50b0RhdGUodGhpcy5faW5zdGFuY2UucmFuZ2Uuc3RhcnQpIDpcbiAgICAgICAgICAgICAgICBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImVuZFwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLl9pbnN0YW5jZSAmJiB0aGlzLl9kZWYuaGFzRW5kKSA/XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FsZW5kYXIuZGF0ZUVudi50b0RhdGUodGhpcy5faW5zdGFuY2UucmFuZ2UuZW5kKSA6XG4gICAgICAgICAgICAgICAgbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJpZFwiLCB7XG4gICAgICAgIC8vIGNvbXB1dGFibGUgcHJvcHMgdGhhdCBhbGwgYWNjZXNzIHRoZSBkZWZcbiAgICAgICAgLy8gVE9ETzogZmluZCBhIFR5cGVTY3JpcHQtY29tcGF0aWJsZSB3YXkgdG8gZG8gdGhpcyBhdCBzY2FsZVxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi5wdWJsaWNJZDsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJncm91cElkXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYuZ3JvdXBJZDsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJhbGxEYXlcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi5hbGxEYXk7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwidGl0bGVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi50aXRsZTsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJ1cmxcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51cmw7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwicmVuZGVyaW5nXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYucmVuZGVyaW5nOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcInN0YXJ0RWRpdGFibGVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5zdGFydEVkaXRhYmxlOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImR1cmF0aW9uRWRpdGFibGVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5kdXJhdGlvbkVkaXRhYmxlOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImNvbnN0cmFpbnRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5jb25zdHJhaW50c1swXSB8fCBudWxsOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcIm92ZXJsYXBcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5vdmVybGFwOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImFsbG93XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYWxsb3dzWzBdIHx8IG51bGw7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwiYmFja2dyb3VuZENvbG9yXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYmFja2dyb3VuZENvbG9yOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImJvcmRlckNvbG9yXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYm9yZGVyQ29sb3I7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwidGV4dENvbG9yXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkudGV4dENvbG9yOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImNsYXNzTmFtZXNcIiwge1xuICAgICAgICAvLyBOT1RFOiB1c2VyIGNhbid0IG1vZGlmeSB0aGVzZSBiZWNhdXNlIE9iamVjdC5mcmVlemUgd2FzIGNhbGxlZCBpbiBldmVudC1kZWYgcGFyc2luZ1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5jbGFzc05hbWVzOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImV4dGVuZGVkUHJvcHNcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi5leHRlbmRlZFByb3BzOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICByZXR1cm4gRXZlbnRBcGk7XG59KCkpO1xuXG4vKlxuU3BlY2lmeWluZyBuZXh0RGF5VGhyZXNob2xkIHNpZ25hbHMgdGhhdCBhbGwtZGF5IHJhbmdlcyBzaG91bGQgYmUgc2xpY2VkLlxuKi9cbmZ1bmN0aW9uIHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGZyYW1pbmdSYW5nZSwgbmV4dERheVRocmVzaG9sZCkge1xuICAgIHZhciBpbnZlcnNlQmdCeUdyb3VwSWQgPSB7fTtcbiAgICB2YXIgaW52ZXJzZUJnQnlEZWZJZCA9IHt9O1xuICAgIHZhciBkZWZCeUdyb3VwSWQgPSB7fTtcbiAgICB2YXIgYmdSYW5nZXMgPSBbXTtcbiAgICB2YXIgZmdSYW5nZXMgPSBbXTtcbiAgICB2YXIgZXZlbnRVaXMgPSBjb21waWxlRXZlbnRVaXMoZXZlbnRTdG9yZS5kZWZzLCBldmVudFVpQmFzZXMpO1xuICAgIGZvciAodmFyIGRlZklkIGluIGV2ZW50U3RvcmUuZGVmcykge1xuICAgICAgICB2YXIgZGVmID0gZXZlbnRTdG9yZS5kZWZzW2RlZklkXTtcbiAgICAgICAgaWYgKGRlZi5yZW5kZXJpbmcgPT09ICdpbnZlcnNlLWJhY2tncm91bmQnKSB7XG4gICAgICAgICAgICBpZiAoZGVmLmdyb3VwSWQpIHtcbiAgICAgICAgICAgICAgICBpbnZlcnNlQmdCeUdyb3VwSWRbZGVmLmdyb3VwSWRdID0gW107XG4gICAgICAgICAgICAgICAgaWYgKCFkZWZCeUdyb3VwSWRbZGVmLmdyb3VwSWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlZkJ5R3JvdXBJZFtkZWYuZ3JvdXBJZF0gPSBkZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlEZWZJZFtkZWZJZF0gPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBpbnN0YW5jZUlkIGluIGV2ZW50U3RvcmUuaW5zdGFuY2VzKSB7XG4gICAgICAgIHZhciBpbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlSWRdO1xuICAgICAgICB2YXIgZGVmID0gZXZlbnRTdG9yZS5kZWZzW2luc3RhbmNlLmRlZklkXTtcbiAgICAgICAgdmFyIHVpID0gZXZlbnRVaXNbZGVmLmRlZklkXTtcbiAgICAgICAgdmFyIG9yaWdSYW5nZSA9IGluc3RhbmNlLnJhbmdlO1xuICAgICAgICB2YXIgbm9ybWFsUmFuZ2UgPSAoIWRlZi5hbGxEYXkgJiYgbmV4dERheVRocmVzaG9sZCkgP1xuICAgICAgICAgICAgY29tcHV0ZVZpc2libGVEYXlSYW5nZShvcmlnUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQpIDpcbiAgICAgICAgICAgIG9yaWdSYW5nZTtcbiAgICAgICAgdmFyIHNsaWNlZFJhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKG5vcm1hbFJhbmdlLCBmcmFtaW5nUmFuZ2UpO1xuICAgICAgICBpZiAoc2xpY2VkUmFuZ2UpIHtcbiAgICAgICAgICAgIGlmIChkZWYucmVuZGVyaW5nID09PSAnaW52ZXJzZS1iYWNrZ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIGlmIChkZWYuZ3JvdXBJZCkge1xuICAgICAgICAgICAgICAgICAgICBpbnZlcnNlQmdCeUdyb3VwSWRbZGVmLmdyb3VwSWRdLnB1c2goc2xpY2VkUmFuZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlEZWZJZFtpbnN0YW5jZS5kZWZJZF0ucHVzaChzbGljZWRSYW5nZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgKGRlZi5yZW5kZXJpbmcgPT09ICdiYWNrZ3JvdW5kJyA/IGJnUmFuZ2VzIDogZmdSYW5nZXMpLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBkZWY6IGRlZixcbiAgICAgICAgICAgICAgICAgICAgdWk6IHVpLFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2UsXG4gICAgICAgICAgICAgICAgICAgIHJhbmdlOiBzbGljZWRSYW5nZSxcbiAgICAgICAgICAgICAgICAgICAgaXNTdGFydDogbm9ybWFsUmFuZ2Uuc3RhcnQgJiYgbm9ybWFsUmFuZ2Uuc3RhcnQudmFsdWVPZigpID09PSBzbGljZWRSYW5nZS5zdGFydC52YWx1ZU9mKCksXG4gICAgICAgICAgICAgICAgICAgIGlzRW5kOiBub3JtYWxSYW5nZS5lbmQgJiYgbm9ybWFsUmFuZ2UuZW5kLnZhbHVlT2YoKSA9PT0gc2xpY2VkUmFuZ2UuZW5kLnZhbHVlT2YoKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAodmFyIGdyb3VwSWQgaW4gaW52ZXJzZUJnQnlHcm91cElkKSB7IC8vIEJZIEdST1VQXG4gICAgICAgIHZhciByYW5nZXMgPSBpbnZlcnNlQmdCeUdyb3VwSWRbZ3JvdXBJZF07XG4gICAgICAgIHZhciBpbnZlcnRlZFJhbmdlcyA9IGludmVydFJhbmdlcyhyYW5nZXMsIGZyYW1pbmdSYW5nZSk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgaW52ZXJ0ZWRSYW5nZXNfMSA9IGludmVydGVkUmFuZ2VzOyBfaSA8IGludmVydGVkUmFuZ2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgaW52ZXJ0ZWRSYW5nZSA9IGludmVydGVkUmFuZ2VzXzFbX2ldO1xuICAgICAgICAgICAgdmFyIGRlZiA9IGRlZkJ5R3JvdXBJZFtncm91cElkXTtcbiAgICAgICAgICAgIHZhciB1aSA9IGV2ZW50VWlzW2RlZi5kZWZJZF07XG4gICAgICAgICAgICBiZ1Jhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBkZWY6IGRlZixcbiAgICAgICAgICAgICAgICB1aTogdWksXG4gICAgICAgICAgICAgICAgaW5zdGFuY2U6IG51bGwsXG4gICAgICAgICAgICAgICAgcmFuZ2U6IGludmVydGVkUmFuZ2UsXG4gICAgICAgICAgICAgICAgaXNTdGFydDogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNFbmQ6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBkZWZJZCBpbiBpbnZlcnNlQmdCeURlZklkKSB7XG4gICAgICAgIHZhciByYW5nZXMgPSBpbnZlcnNlQmdCeURlZklkW2RlZklkXTtcbiAgICAgICAgdmFyIGludmVydGVkUmFuZ2VzID0gaW52ZXJ0UmFuZ2VzKHJhbmdlcywgZnJhbWluZ1JhbmdlKTtcbiAgICAgICAgZm9yICh2YXIgX2EgPSAwLCBpbnZlcnRlZFJhbmdlc18yID0gaW52ZXJ0ZWRSYW5nZXM7IF9hIDwgaW52ZXJ0ZWRSYW5nZXNfMi5sZW5ndGg7IF9hKyspIHtcbiAgICAgICAgICAgIHZhciBpbnZlcnRlZFJhbmdlID0gaW52ZXJ0ZWRSYW5nZXNfMltfYV07XG4gICAgICAgICAgICBiZ1Jhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBkZWY6IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF0sXG4gICAgICAgICAgICAgICAgdWk6IGV2ZW50VWlzW2RlZklkXSxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZTogbnVsbCxcbiAgICAgICAgICAgICAgICByYW5nZTogaW52ZXJ0ZWRSYW5nZSxcbiAgICAgICAgICAgICAgICBpc1N0YXJ0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc0VuZDogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGJnOiBiZ1JhbmdlcywgZmc6IGZnUmFuZ2VzIH07XG59XG5mdW5jdGlvbiBoYXNCZ1JlbmRlcmluZyhkZWYpIHtcbiAgICByZXR1cm4gZGVmLnJlbmRlcmluZyA9PT0gJ2JhY2tncm91bmQnIHx8IGRlZi5yZW5kZXJpbmcgPT09ICdpbnZlcnNlLWJhY2tncm91bmQnO1xufVxuZnVuY3Rpb24gZmlsdGVyU2Vnc1ZpYUVscyhjb250ZXh0LCBzZWdzLCBpc01pcnJvcikge1xuICAgIHZhciBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXIsIHZpZXcgPSBjb250ZXh0LnZpZXc7XG4gICAgaWYgKGNhbGVuZGFyLmhhc1B1YmxpY0hhbmRsZXJzKCdldmVudFJlbmRlcicpKSB7XG4gICAgICAgIHNlZ3MgPSBzZWdzLmZpbHRlcihmdW5jdGlvbiAoc2VnKSB7XG4gICAgICAgICAgICB2YXIgY3VzdG9tID0gY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlbmRlcicsIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIHNlZy5ldmVudFJhbmdlLmRlZiwgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBpc01pcnJvcjogaXNNaXJyb3IsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IHNlZy5pc1N0YXJ0LFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogc2VnLmlzRW5kLFxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBpbmNsdWRlIHNlZy5yYW5nZSBvbmNlIGFsbCBjb21wb25lbnRzIGNvbnNpc3RlbnRseSBnZW5lcmF0ZSBpdFxuICAgICAgICAgICAgICAgICAgICBlbDogc2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICBpZiAoY3VzdG9tID09PSBmYWxzZSkgeyAvLyBtZWFucyBkb24ndCByZW5kZXIgYXQgYWxsXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY3VzdG9tICYmIGN1c3RvbSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHNlZy5lbCA9IGN1c3RvbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZm9yICh2YXIgX2kgPSAwLCBzZWdzXzEgPSBzZWdzOyBfaSA8IHNlZ3NfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMVtfaV07XG4gICAgICAgIHNldEVsU2VnKHNlZy5lbCwgc2VnKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlZ3M7XG59XG5mdW5jdGlvbiBzZXRFbFNlZyhlbCwgc2VnKSB7XG4gICAgZWwuZmNTZWcgPSBzZWc7XG59XG5mdW5jdGlvbiBnZXRFbFNlZyhlbCkge1xuICAgIHJldHVybiBlbC5mY1NlZyB8fCBudWxsO1xufVxuLy8gZXZlbnQgdWkgY29tcHV0YXRpb25cbmZ1bmN0aW9uIGNvbXBpbGVFdmVudFVpcyhldmVudERlZnMsIGV2ZW50VWlCYXNlcykge1xuICAgIHJldHVybiBtYXBIYXNoKGV2ZW50RGVmcywgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgIHJldHVybiBjb21waWxlRXZlbnRVaShldmVudERlZiwgZXZlbnRVaUJhc2VzKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGNvbXBpbGVFdmVudFVpKGV2ZW50RGVmLCBldmVudFVpQmFzZXMpIHtcbiAgICB2YXIgdWlzID0gW107XG4gICAgaWYgKGV2ZW50VWlCYXNlc1snJ10pIHtcbiAgICAgICAgdWlzLnB1c2goZXZlbnRVaUJhc2VzWycnXSk7XG4gICAgfVxuICAgIGlmIChldmVudFVpQmFzZXNbZXZlbnREZWYuZGVmSWRdKSB7XG4gICAgICAgIHVpcy5wdXNoKGV2ZW50VWlCYXNlc1tldmVudERlZi5kZWZJZF0pO1xuICAgIH1cbiAgICB1aXMucHVzaChldmVudERlZi51aSk7XG4gICAgcmV0dXJuIGNvbWJpbmVFdmVudFVpcyh1aXMpO1xufVxuLy8gdHJpZ2dlcnNcbmZ1bmN0aW9uIHRyaWdnZXJSZW5kZXJlZFNlZ3MoY29udGV4dCwgc2VncywgaXNNaXJyb3JzKSB7XG4gICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhciwgdmlldyA9IGNvbnRleHQudmlldztcbiAgICBpZiAoY2FsZW5kYXIuaGFzUHVibGljSGFuZGxlcnMoJ2V2ZW50UG9zaXRpb25lZCcpKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18yID0gc2VnczsgX2kgPCBzZWdzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18yW19pXTtcbiAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlckFmdGVyU2l6aW5nKCdldmVudFBvc2l0aW9uZWQnLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgaXNNaXJyb3I6IGlzTWlycm9ycyxcbiAgICAgICAgICAgICAgICAgICAgaXNTdGFydDogc2VnLmlzU3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIGlzRW5kOiBzZWcuaXNFbmQsXG4gICAgICAgICAgICAgICAgICAgIGVsOiBzZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWNhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlTG9hZGluZ0xldmVsKSB7IC8vIGF2b2lkIGluaXRpYWwgZW1wdHkgc3RhdGUgd2hpbGUgcGVuZGluZ1xuICAgICAgICBjYWxlbmRhci5hZnRlclNpemluZ1RyaWdnZXJzLl9ldmVudHNQb3NpdGlvbmVkID0gW251bGxdOyAvLyBmaXJlIG9uY2VcbiAgICB9XG59XG5mdW5jdGlvbiB0cmlnZ2VyV2lsbFJlbW92ZVNlZ3MoY29udGV4dCwgc2VncywgaXNNaXJyb3JzKSB7XG4gICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhciwgdmlldyA9IGNvbnRleHQudmlldztcbiAgICBmb3IgKHZhciBfaSA9IDAsIHNlZ3NfMyA9IHNlZ3M7IF9pIDwgc2Vnc18zLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc2VnID0gc2Vnc18zW19pXTtcbiAgICAgICAgY2FsZW5kYXIudHJpZ2dlcignZXZlbnRFbFJlbW92ZScsIHNlZy5lbCk7XG4gICAgfVxuICAgIGlmIChjYWxlbmRhci5oYXNQdWJsaWNIYW5kbGVycygnZXZlbnREZXN0cm95JykpIHtcbiAgICAgICAgZm9yICh2YXIgX2EgPSAwLCBzZWdzXzQgPSBzZWdzOyBfYSA8IHNlZ3NfNC5sZW5ndGg7IF9hKyspIHtcbiAgICAgICAgICAgIHZhciBzZWcgPSBzZWdzXzRbX2FdO1xuICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudERlc3Ryb3knLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgaXNNaXJyb3I6IGlzTWlycm9ycyxcbiAgICAgICAgICAgICAgICAgICAgZWw6IHNlZy5lbCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfVxufVxuLy8gaXMtaW50ZXJhY3RhYmxlXG5mdW5jdGlvbiBjb21wdXRlRXZlbnREcmFnZ2FibGUoY29udGV4dCwgZXZlbnREZWYsIGV2ZW50VWkpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBjb250ZXh0LmNhbGVuZGFyLCB2aWV3ID0gY29udGV4dC52aWV3O1xuICAgIHZhciB0cmFuc2Zvcm1lcnMgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnM7XG4gICAgdmFyIHZhbCA9IGV2ZW50VWkuc3RhcnRFZGl0YWJsZTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHRyYW5zZm9ybWVyc18xID0gdHJhbnNmb3JtZXJzOyBfaSA8IHRyYW5zZm9ybWVyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtZXIgPSB0cmFuc2Zvcm1lcnNfMVtfaV07XG4gICAgICAgIHZhbCA9IHRyYW5zZm9ybWVyKHZhbCwgZXZlbnREZWYsIGV2ZW50VWksIHZpZXcpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsO1xufVxuZnVuY3Rpb24gY29tcHV0ZUV2ZW50U3RhcnRSZXNpemFibGUoY29udGV4dCwgZXZlbnREZWYsIGV2ZW50VWkpIHtcbiAgICByZXR1cm4gZXZlbnRVaS5kdXJhdGlvbkVkaXRhYmxlICYmIGNvbnRleHQub3B0aW9ucy5ldmVudFJlc2l6YWJsZUZyb21TdGFydDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVFdmVudEVuZFJlc2l6YWJsZShjb250ZXh0LCBldmVudERlZiwgZXZlbnRVaSkge1xuICAgIHJldHVybiBldmVudFVpLmR1cmF0aW9uRWRpdGFibGU7XG59XG5cbi8vIGFwcGxpZXMgdGhlIG11dGF0aW9uIHRvIEFMTCBkZWZzL2luc3RhbmNlcyB3aXRoaW4gdGhlIGV2ZW50IHN0b3JlXG5mdW5jdGlvbiBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlKGV2ZW50U3RvcmUsIGV2ZW50Q29uZmlnQmFzZSwgbXV0YXRpb24sIGNhbGVuZGFyKSB7XG4gICAgdmFyIGV2ZW50Q29uZmlncyA9IGNvbXBpbGVFdmVudFVpcyhldmVudFN0b3JlLmRlZnMsIGV2ZW50Q29uZmlnQmFzZSk7XG4gICAgdmFyIGRlc3QgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICBmb3IgKHZhciBkZWZJZCBpbiBldmVudFN0b3JlLmRlZnMpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF07XG4gICAgICAgIGRlc3QuZGVmc1tkZWZJZF0gPSBhcHBseU11dGF0aW9uVG9FdmVudERlZihkZWYsIGV2ZW50Q29uZmlnc1tkZWZJZF0sIG11dGF0aW9uLCBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzLCBjYWxlbmRhcik7XG4gICAgfVxuICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gZXZlbnRTdG9yZS5pbnN0YW5jZXMpIHtcbiAgICAgICAgdmFyIGluc3RhbmNlID0gZXZlbnRTdG9yZS5pbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgIHZhciBkZWYgPSBkZXN0LmRlZnNbaW5zdGFuY2UuZGVmSWRdOyAvLyBpbXBvcnRhbnQgdG8gZ3JhYiB0aGUgbmV3bHkgbW9kaWZpZWQgZGVmXG4gICAgICAgIGRlc3QuaW5zdGFuY2VzW2luc3RhbmNlSWRdID0gYXBwbHlNdXRhdGlvblRvRXZlbnRJbnN0YW5jZShpbnN0YW5jZSwgZGVmLCBldmVudENvbmZpZ3NbaW5zdGFuY2UuZGVmSWRdLCBtdXRhdGlvbiwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn1cbmZ1bmN0aW9uIGFwcGx5TXV0YXRpb25Ub0V2ZW50RGVmKGV2ZW50RGVmLCBldmVudENvbmZpZywgbXV0YXRpb24sIGFwcGxpZXJzLCBjYWxlbmRhcikge1xuICAgIHZhciBzdGFuZGFyZFByb3BzID0gbXV0YXRpb24uc3RhbmRhcmRQcm9wcyB8fCB7fTtcbiAgICAvLyBpZiBoYXNFbmQgaGFzIG5vdCBiZWVuIHNwZWNpZmllZCwgZ3Vlc3MgYSBnb29kIHZhbHVlIGJhc2VkIG9uIGRlbHRhcy5cbiAgICAvLyBpZiBkdXJhdGlvbiB3aWxsIGNoYW5nZSwgdGhlcmUncyBubyB3YXkgdGhlIGRlZmF1bHQgZHVyYXRpb24gd2lsbCBwZXJzaXN0LFxuICAgIC8vIGFuZCB0aHVzLCB3ZSBuZWVkIHRvIG1hcmsgdGhlIGV2ZW50IGFzIGhhdmluZyBhIHJlYWwgZW5kXG4gICAgaWYgKHN0YW5kYXJkUHJvcHMuaGFzRW5kID09IG51bGwgJiZcbiAgICAgICAgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSAmJlxuICAgICAgICAobXV0YXRpb24uc3RhcnREZWx0YSB8fCBtdXRhdGlvbi5lbmREZWx0YSkpIHtcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5oYXNFbmQgPSB0cnVlOyAvLyBUT0RPOiBpcyB0aGlzIG11dGF0aW9uIG9rYXk/XG4gICAgfVxuICAgIHZhciBjb3B5ID0gX19hc3NpZ24oe30sIGV2ZW50RGVmLCBzdGFuZGFyZFByb3BzLCB7IHVpOiBfX2Fzc2lnbih7fSwgZXZlbnREZWYudWksIHN0YW5kYXJkUHJvcHMudWkpIH0pO1xuICAgIGlmIChtdXRhdGlvbi5leHRlbmRlZFByb3BzKSB7XG4gICAgICAgIGNvcHkuZXh0ZW5kZWRQcm9wcyA9IF9fYXNzaWduKHt9LCBjb3B5LmV4dGVuZGVkUHJvcHMsIG11dGF0aW9uLmV4dGVuZGVkUHJvcHMpO1xuICAgIH1cbiAgICBmb3IgKHZhciBfaSA9IDAsIGFwcGxpZXJzXzEgPSBhcHBsaWVyczsgX2kgPCBhcHBsaWVyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgYXBwbGllciA9IGFwcGxpZXJzXzFbX2ldO1xuICAgICAgICBhcHBsaWVyKGNvcHksIG11dGF0aW9uLCBjYWxlbmRhcik7XG4gICAgfVxuICAgIGlmICghY29weS5oYXNFbmQgJiYgY2FsZW5kYXIub3B0KCdmb3JjZUV2ZW50RHVyYXRpb24nKSkge1xuICAgICAgICBjb3B5Lmhhc0VuZCA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xufVxuZnVuY3Rpb24gYXBwbHlNdXRhdGlvblRvRXZlbnRJbnN0YW5jZShldmVudEluc3RhbmNlLCBldmVudERlZiwgLy8gbXVzdCBmaXJzdCBiZSBtb2RpZmllZCBieSBhcHBseU11dGF0aW9uVG9FdmVudERlZlxuZXZlbnRDb25maWcsIG11dGF0aW9uLCBjYWxlbmRhcikge1xuICAgIHZhciBkYXRlRW52ID0gY2FsZW5kYXIuZGF0ZUVudjtcbiAgICB2YXIgZm9yY2VBbGxEYXkgPSBtdXRhdGlvbi5zdGFuZGFyZFByb3BzICYmIG11dGF0aW9uLnN0YW5kYXJkUHJvcHMuYWxsRGF5ID09PSB0cnVlO1xuICAgIHZhciBjbGVhckVuZCA9IG11dGF0aW9uLnN0YW5kYXJkUHJvcHMgJiYgbXV0YXRpb24uc3RhbmRhcmRQcm9wcy5oYXNFbmQgPT09IGZhbHNlO1xuICAgIHZhciBjb3B5ID0gX19hc3NpZ24oe30sIGV2ZW50SW5zdGFuY2UpO1xuICAgIGlmIChmb3JjZUFsbERheSkge1xuICAgICAgICBjb3B5LnJhbmdlID0gY29tcHV0ZUFsaWduZWREYXlSYW5nZShjb3B5LnJhbmdlKTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLmRhdGVzRGVsdGEgJiYgZXZlbnRDb25maWcuc3RhcnRFZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2Uuc3RhcnQsIG11dGF0aW9uLmRhdGVzRGVsdGEpLFxuICAgICAgICAgICAgZW5kOiBkYXRlRW52LmFkZChjb3B5LnJhbmdlLmVuZCwgbXV0YXRpb24uZGF0ZXNEZWx0YSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLnN0YXJ0RGVsdGEgJiYgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2Uuc3RhcnQsIG11dGF0aW9uLnN0YXJ0RGVsdGEpLFxuICAgICAgICAgICAgZW5kOiBjb3B5LnJhbmdlLmVuZFxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24uZW5kRGVsdGEgJiYgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGNvcHkucmFuZ2Uuc3RhcnQsXG4gICAgICAgICAgICBlbmQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2UuZW5kLCBtdXRhdGlvbi5lbmREZWx0YSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKGNsZWFyRW5kKSB7XG4gICAgICAgIGNvcHkucmFuZ2UgPSB7XG4gICAgICAgICAgICBzdGFydDogY29weS5yYW5nZS5zdGFydCxcbiAgICAgICAgICAgIGVuZDogY2FsZW5kYXIuZ2V0RGVmYXVsdEV2ZW50RW5kKGV2ZW50RGVmLmFsbERheSwgY29weS5yYW5nZS5zdGFydClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gaW4gY2FzZSBldmVudCB3YXMgYWxsLWRheSBidXQgdGhlIHN1cHBsaWVkIGRlbHRhcyB3ZXJlIG5vdFxuICAgIC8vIGJldHRlciB1dGlsIGZvciB0aGlzP1xuICAgIGlmIChldmVudERlZi5hbGxEYXkpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBzdGFydE9mRGF5KGNvcHkucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kOiBzdGFydE9mRGF5KGNvcHkucmFuZ2UuZW5kKVxuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBoYW5kbGUgaW52YWxpZCBkdXJhdGlvbnNcbiAgICBpZiAoY29weS5yYW5nZS5lbmQgPCBjb3B5LnJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIGNvcHkucmFuZ2UuZW5kID0gY2FsZW5kYXIuZ2V0RGVmYXVsdEV2ZW50RW5kKGV2ZW50RGVmLmFsbERheSwgY29weS5yYW5nZS5zdGFydCk7XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xufVxuXG5mdW5jdGlvbiByZWR1Y2VFdmVudFN0b3JlIChldmVudFN0b3JlLCBhY3Rpb24sIGV2ZW50U291cmNlcywgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdSRUNFSVZFX0VWRU5UUyc6IC8vIHJhd1xuICAgICAgICAgICAgcmV0dXJuIHJlY2VpdmVSYXdFdmVudHMoZXZlbnRTdG9yZSwgZXZlbnRTb3VyY2VzW2FjdGlvbi5zb3VyY2VJZF0sIGFjdGlvbi5mZXRjaElkLCBhY3Rpb24uZmV0Y2hSYW5nZSwgYWN0aW9uLnJhd0V2ZW50cywgY2FsZW5kYXIpO1xuICAgICAgICBjYXNlICdBRERfRVZFTlRTJzogLy8gYWxyZWFkeSBwYXJzZWQsIGJ1dCBub3QgZXhwYW5kZWRcbiAgICAgICAgICAgIHJldHVybiBhZGRFdmVudChldmVudFN0b3JlLCBhY3Rpb24uZXZlbnRTdG9yZSwgLy8gbmV3IG9uZXNcbiAgICAgICAgICAgIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ01FUkdFX0VWRU5UUyc6IC8vIGFscmVhZHkgcGFyc2VkIGFuZCBleHBhbmRlZFxuICAgICAgICAgICAgcmV0dXJuIG1lcmdlRXZlbnRTdG9yZXMoZXZlbnRTdG9yZSwgYWN0aW9uLmV2ZW50U3RvcmUpO1xuICAgICAgICBjYXNlICdQUkVWJzogLy8gVE9ETzogaG93IGRvIHdlIHRyYWNrIGFsbCBhY3Rpb25zIHRoYXQgYWZmZWN0IGRhdGVQcm9maWxlIDooXG4gICAgICAgIGNhc2UgJ05FWFQnOlxuICAgICAgICBjYXNlICdTRVRfREFURSc6XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgaWYgKGRhdGVQcm9maWxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4cGFuZFJlY3VycmluZyhldmVudFN0b3JlLCBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmU7XG4gICAgICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9USU1FWk9ORSc6XG4gICAgICAgICAgICByZXR1cm4gcmV6b25lRGF0ZXMoZXZlbnRTdG9yZSwgYWN0aW9uLm9sZERhdGVFbnYsIGNhbGVuZGFyLmRhdGVFbnYpO1xuICAgICAgICBjYXNlICdNVVRBVEVfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiBhcHBseU11dGF0aW9uVG9SZWxhdGVkKGV2ZW50U3RvcmUsIGFjdGlvbi5pbnN0YW5jZUlkLCBhY3Rpb24ubXV0YXRpb24sIGFjdGlvbi5mcm9tQXBpLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9JTlNUQU5DRVMnOlxuICAgICAgICAgICAgcmV0dXJuIGV4Y2x1ZGVJbnN0YW5jZXMoZXZlbnRTdG9yZSwgYWN0aW9uLmluc3RhbmNlcyk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9ERUYnOlxuICAgICAgICAgICAgcmV0dXJuIGZpbHRlckV2ZW50U3RvcmVEZWZzKGV2ZW50U3RvcmUsIGZ1bmN0aW9uIChldmVudERlZikge1xuICAgICAgICAgICAgICAgIHJldHVybiBldmVudERlZi5kZWZJZCAhPT0gYWN0aW9uLmRlZklkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9TT1VSQ0UnOlxuICAgICAgICAgICAgcmV0dXJuIGV4Y2x1ZGVFdmVudHNCeVNvdXJjZUlkKGV2ZW50U3RvcmUsIGFjdGlvbi5zb3VyY2VJZCk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9BTExfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICFldmVudERlZi5zb3VyY2VJZDsgLy8gb25seSBrZWVwIGV2ZW50cyB3aXRoIG5vIHNvdXJjZSBpZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9BTExfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgY2FzZSAnUkVTRVRfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZGVmczogZXZlbnRTdG9yZS5kZWZzLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlczogZXZlbnRTdG9yZS5pbnN0YW5jZXNcbiAgICAgICAgICAgIH07XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZXZlbnRTdG9yZTtcbiAgICB9XG59XG5mdW5jdGlvbiByZWNlaXZlUmF3RXZlbnRzKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlLCBmZXRjaElkLCBmZXRjaFJhbmdlLCByYXdFdmVudHMsIGNhbGVuZGFyKSB7XG4gICAgaWYgKGV2ZW50U291cmNlICYmIC8vIG5vdCBhbHJlYWR5IHJlbW92ZWRcbiAgICAgICAgZmV0Y2hJZCA9PT0gZXZlbnRTb3VyY2UubGF0ZXN0RmV0Y2hJZCAvLyBUT0RPOiB3aXNoIHRoaXMgbG9naWMgd2FzIGFsd2F5cyBpbiBldmVudC1zb3VyY2VzXG4gICAgKSB7XG4gICAgICAgIHZhciBzdWJzZXQgPSBwYXJzZUV2ZW50cyh0cmFuc2Zvcm1SYXdFdmVudHMocmF3RXZlbnRzLCBldmVudFNvdXJjZSwgY2FsZW5kYXIpLCBldmVudFNvdXJjZS5zb3VyY2VJZCwgY2FsZW5kYXIpO1xuICAgICAgICBpZiAoZmV0Y2hSYW5nZSkge1xuICAgICAgICAgICAgc3Vic2V0ID0gZXhwYW5kUmVjdXJyaW5nKHN1YnNldCwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXJnZUV2ZW50U3RvcmVzKGV4Y2x1ZGVFdmVudHNCeVNvdXJjZUlkKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlLnNvdXJjZUlkKSwgc3Vic2V0KTtcbiAgICB9XG4gICAgcmV0dXJuIGV2ZW50U3RvcmU7XG59XG5mdW5jdGlvbiBhZGRFdmVudChldmVudFN0b3JlLCBzdWJzZXQsIGV4cGFuZFJhbmdlLCBjYWxlbmRhcikge1xuICAgIGlmIChleHBhbmRSYW5nZSkge1xuICAgICAgICBzdWJzZXQgPSBleHBhbmRSZWN1cnJpbmcoc3Vic2V0LCBleHBhbmRSYW5nZSwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICByZXR1cm4gbWVyZ2VFdmVudFN0b3JlcyhldmVudFN0b3JlLCBzdWJzZXQpO1xufVxuZnVuY3Rpb24gcmV6b25lRGF0ZXMoZXZlbnRTdG9yZSwgb2xkRGF0ZUVudiwgbmV3RGF0ZUVudikge1xuICAgIHZhciBkZWZzID0gZXZlbnRTdG9yZS5kZWZzO1xuICAgIHZhciBpbnN0YW5jZXMgPSBtYXBIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgdmFyIGRlZiA9IGRlZnNbaW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICBpZiAoZGVmLmFsbERheSB8fCBkZWYucmVjdXJyaW5nRGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7IC8vIGlzbid0IGRlcGVuZGVudCBvbiB0aW1lem9uZVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXNzaWduKHt9LCBpbnN0YW5jZSwgeyByYW5nZToge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogbmV3RGF0ZUVudi5jcmVhdGVNYXJrZXIob2xkRGF0ZUVudi50b0RhdGUoaW5zdGFuY2UucmFuZ2Uuc3RhcnQsIGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvKSksXG4gICAgICAgICAgICAgICAgICAgIGVuZDogbmV3RGF0ZUVudi5jcmVhdGVNYXJrZXIob2xkRGF0ZUVudi50b0RhdGUoaW5zdGFuY2UucmFuZ2UuZW5kLCBpbnN0YW5jZS5mb3JjZWRFbmRUem8pKVxuICAgICAgICAgICAgICAgIH0sIGZvcmNlZFN0YXJ0VHpvOiBuZXdEYXRlRW52LmNhbkNvbXB1dGVPZmZzZXQgPyBudWxsIDogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sIGZvcmNlZEVuZFR6bzogbmV3RGF0ZUVudi5jYW5Db21wdXRlT2Zmc2V0ID8gbnVsbCA6IGluc3RhbmNlLmZvcmNlZEVuZFR6byB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7IGRlZnM6IGRlZnMsIGluc3RhbmNlczogaW5zdGFuY2VzIH07XG59XG5mdW5jdGlvbiBhcHBseU11dGF0aW9uVG9SZWxhdGVkKGV2ZW50U3RvcmUsIGluc3RhbmNlSWQsIG11dGF0aW9uLCBmcm9tQXBpLCBjYWxlbmRhcikge1xuICAgIHZhciByZWxldmFudCA9IGdldFJlbGV2YW50RXZlbnRzKGV2ZW50U3RvcmUsIGluc3RhbmNlSWQpO1xuICAgIHZhciBldmVudENvbmZpZ0Jhc2UgPSBmcm9tQXBpID9cbiAgICAgICAgeyAnJzoge1xuICAgICAgICAgICAgICAgIHN0YXJ0RWRpdGFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjb25zdHJhaW50czogW10sXG4gICAgICAgICAgICAgICAgb3ZlcmxhcDogbnVsbCxcbiAgICAgICAgICAgICAgICBhbGxvd3M6IFtdLFxuICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJycsXG4gICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6ICcnLFxuICAgICAgICAgICAgICAgIHRleHRDb2xvcjogJycsXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lczogW11cbiAgICAgICAgICAgIH0gfSA6XG4gICAgICAgIGNhbGVuZGFyLmV2ZW50VWlCYXNlcztcbiAgICByZWxldmFudCA9IGFwcGx5TXV0YXRpb25Ub0V2ZW50U3RvcmUocmVsZXZhbnQsIGV2ZW50Q29uZmlnQmFzZSwgbXV0YXRpb24sIGNhbGVuZGFyKTtcbiAgICByZXR1cm4gbWVyZ2VFdmVudFN0b3JlcyhldmVudFN0b3JlLCByZWxldmFudCk7XG59XG5mdW5jdGlvbiBleGNsdWRlRXZlbnRzQnlTb3VyY2VJZChldmVudFN0b3JlLCBzb3VyY2VJZCkge1xuICAgIHJldHVybiBmaWx0ZXJFdmVudFN0b3JlRGVmcyhldmVudFN0b3JlLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50RGVmLnNvdXJjZUlkICE9PSBzb3VyY2VJZDtcbiAgICB9KTtcbn1cbi8vIFFVRVNUSU9OOiB3aHkgbm90IGp1c3QgcmV0dXJuIGluc3RhbmNlcz8gZG8gYSBnZW5lcmFsIG9iamVjdC1wcm9wZXJ0eS1leGNsdXNpb24gdXRpbFxuZnVuY3Rpb24gZXhjbHVkZUluc3RhbmNlcyhldmVudFN0b3JlLCByZW1vdmFscykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGRlZnM6IGV2ZW50U3RvcmUuZGVmcyxcbiAgICAgICAgaW5zdGFuY2VzOiBmaWx0ZXJIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHJldHVybiAhcmVtb3ZhbHNbaW5zdGFuY2UuaW5zdGFuY2VJZF07XG4gICAgICAgIH0pXG4gICAgfTtcbn1cblxuLy8gaGlnaC1sZXZlbCBzZWdtZW50aW5nLWF3YXJlIHRlc3RlciBmdW5jdGlvbnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gaXNJbnRlcmFjdGlvblZhbGlkKGludGVyYWN0aW9uLCBjYWxlbmRhcikge1xuICAgIHJldHVybiBpc05ld1Byb3BzVmFsaWQoeyBldmVudERyYWc6IGludGVyYWN0aW9uIH0sIGNhbGVuZGFyKTsgLy8gSEFDSzogdGhlIGV2ZW50RHJhZyBwcm9wcyBpcyB1c2VkIGZvciBBTEwgaW50ZXJhY3Rpb25zXG59XG5mdW5jdGlvbiBpc0RhdGVTZWxlY3Rpb25WYWxpZChkYXRlU2VsZWN0aW9uLCBjYWxlbmRhcikge1xuICAgIHJldHVybiBpc05ld1Byb3BzVmFsaWQoeyBkYXRlU2VsZWN0aW9uOiBkYXRlU2VsZWN0aW9uIH0sIGNhbGVuZGFyKTtcbn1cbmZ1bmN0aW9uIGlzTmV3UHJvcHNWYWxpZChuZXdQcm9wcywgY2FsZW5kYXIpIHtcbiAgICB2YXIgdmlldyA9IGNhbGVuZGFyLnZpZXc7XG4gICAgdmFyIHByb3BzID0gX19hc3NpZ24oeyBidXNpbmVzc0hvdXJzOiB2aWV3ID8gdmlldy5wcm9wcy5idXNpbmVzc0hvdXJzIDogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksIGRhdGVTZWxlY3Rpb246ICcnLCBldmVudFN0b3JlOiBjYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlLCBldmVudFVpQmFzZXM6IGNhbGVuZGFyLmV2ZW50VWlCYXNlcywgZXZlbnRTZWxlY3Rpb246ICcnLCBldmVudERyYWc6IG51bGwsIGV2ZW50UmVzaXplOiBudWxsIH0sIG5ld1Byb3BzKTtcbiAgICByZXR1cm4gKGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5pc1Byb3BzVmFsaWQgfHwgaXNQcm9wc1ZhbGlkKShwcm9wcywgY2FsZW5kYXIpO1xufVxuZnVuY3Rpb24gaXNQcm9wc1ZhbGlkKHN0YXRlLCBjYWxlbmRhciwgZGF0ZVNwYW5NZXRhLCBmaWx0ZXJDb25maWcpIHtcbiAgICBpZiAoZGF0ZVNwYW5NZXRhID09PSB2b2lkIDApIHsgZGF0ZVNwYW5NZXRhID0ge307IH1cbiAgICBpZiAoc3RhdGUuZXZlbnREcmFnICYmICFpc0ludGVyYWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChzdGF0ZS5kYXRlU2VsZWN0aW9uICYmICFpc0RhdGVTZWxlY3Rpb25Qcm9wc1ZhbGlkKHN0YXRlLCBjYWxlbmRhciwgZGF0ZVNwYW5NZXRhLCBmaWx0ZXJDb25maWcpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG4vLyBNb3ZpbmcgRXZlbnQgVmFsaWRhdGlvblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBpc0ludGVyYWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgdmFyIGludGVyYWN0aW9uID0gc3RhdGUuZXZlbnREcmFnOyAvLyBIQUNLOiB0aGUgZXZlbnREcmFnIHByb3BzIGlzIHVzZWQgZm9yIEFMTCBpbnRlcmFjdGlvbnNcbiAgICB2YXIgc3ViamVjdEV2ZW50U3RvcmUgPSBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzO1xuICAgIHZhciBzdWJqZWN0RGVmcyA9IHN1YmplY3RFdmVudFN0b3JlLmRlZnM7XG4gICAgdmFyIHN1YmplY3RJbnN0YW5jZXMgPSBzdWJqZWN0RXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIHN1YmplY3RDb25maWdzID0gY29tcGlsZUV2ZW50VWlzKHN1YmplY3REZWZzLCBpbnRlcmFjdGlvbi5pc0V2ZW50ID9cbiAgICAgICAgc3RhdGUuZXZlbnRVaUJhc2VzIDpcbiAgICAgICAgeyAnJzogY2FsZW5kYXIuc2VsZWN0aW9uQ29uZmlnIH0gLy8gaWYgbm90IGEgcmVhbCBldmVudCwgdmFsaWRhdGUgYXMgYSBzZWxlY3Rpb25cbiAgICApO1xuICAgIGlmIChmaWx0ZXJDb25maWcpIHtcbiAgICAgICAgc3ViamVjdENvbmZpZ3MgPSBtYXBIYXNoKHN1YmplY3RDb25maWdzLCBmaWx0ZXJDb25maWcpO1xuICAgIH1cbiAgICB2YXIgb3RoZXJFdmVudFN0b3JlID0gZXhjbHVkZUluc3RhbmNlcyhzdGF0ZS5ldmVudFN0b3JlLCBpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cy5pbnN0YW5jZXMpOyAvLyBleGNsdWRlIHRoZSBzdWJqZWN0IGV2ZW50cy4gVE9ETzogZXhjbHVkZSBkZWZzIHRvbz9cbiAgICB2YXIgb3RoZXJEZWZzID0gb3RoZXJFdmVudFN0b3JlLmRlZnM7XG4gICAgdmFyIG90aGVySW5zdGFuY2VzID0gb3RoZXJFdmVudFN0b3JlLmluc3RhbmNlcztcbiAgICB2YXIgb3RoZXJDb25maWdzID0gY29tcGlsZUV2ZW50VWlzKG90aGVyRGVmcywgc3RhdGUuZXZlbnRVaUJhc2VzKTtcbiAgICBmb3IgKHZhciBzdWJqZWN0SW5zdGFuY2VJZCBpbiBzdWJqZWN0SW5zdGFuY2VzKSB7XG4gICAgICAgIHZhciBzdWJqZWN0SW5zdGFuY2UgPSBzdWJqZWN0SW5zdGFuY2VzW3N1YmplY3RJbnN0YW5jZUlkXTtcbiAgICAgICAgdmFyIHN1YmplY3RSYW5nZSA9IHN1YmplY3RJbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgdmFyIHN1YmplY3RDb25maWcgPSBzdWJqZWN0Q29uZmlnc1tzdWJqZWN0SW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICB2YXIgc3ViamVjdERlZiA9IHN1YmplY3REZWZzW3N1YmplY3RJbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIC8vIGNvbnN0cmFpbnRcbiAgICAgICAgaWYgKCFhbGxDb25zdHJhaW50c1Bhc3Moc3ViamVjdENvbmZpZy5jb25zdHJhaW50cywgc3ViamVjdFJhbmdlLCBvdGhlckV2ZW50U3RvcmUsIHN0YXRlLmJ1c2luZXNzSG91cnMsIGNhbGVuZGFyKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIG92ZXJsYXBcbiAgICAgICAgdmFyIG92ZXJsYXBGdW5jID0gY2FsZW5kYXIub3B0KCdldmVudE92ZXJsYXAnKTtcbiAgICAgICAgaWYgKHR5cGVvZiBvdmVybGFwRnVuYyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgb3ZlcmxhcEZ1bmMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIG90aGVySW5zdGFuY2VJZCBpbiBvdGhlckluc3RhbmNlcykge1xuICAgICAgICAgICAgdmFyIG90aGVySW5zdGFuY2UgPSBvdGhlckluc3RhbmNlc1tvdGhlckluc3RhbmNlSWRdO1xuICAgICAgICAgICAgLy8gaW50ZXJzZWN0ISBldmFsdWF0ZVxuICAgICAgICAgICAgaWYgKHJhbmdlc0ludGVyc2VjdChzdWJqZWN0UmFuZ2UsIG90aGVySW5zdGFuY2UucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgdmFyIG90aGVyT3ZlcmxhcCA9IG90aGVyQ29uZmlnc1tvdGhlckluc3RhbmNlLmRlZklkXS5vdmVybGFwO1xuICAgICAgICAgICAgICAgIC8vIGNvbnNpZGVyIHRoZSBvdGhlciBldmVudCdzIG92ZXJsYXAuIG9ubHkgZG8gdGhpcyBpZiB0aGUgc3ViamVjdCBldmVudCBpcyBhIFwicmVhbFwiIGV2ZW50XG4gICAgICAgICAgICAgICAgaWYgKG90aGVyT3ZlcmxhcCA9PT0gZmFsc2UgJiYgaW50ZXJhY3Rpb24uaXNFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdWJqZWN0Q29uZmlnLm92ZXJsYXAgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG92ZXJsYXBGdW5jICYmICFvdmVybGFwRnVuYyhuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIG90aGVyRGVmc1tvdGhlckluc3RhbmNlLmRlZklkXSwgb3RoZXJJbnN0YW5jZSksIC8vIHN0aWxsIGV2ZW50XG4gICAgICAgICAgICAgICAgbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzdWJqZWN0RGVmLCBzdWJqZWN0SW5zdGFuY2UpIC8vIG1vdmluZyBldmVudFxuICAgICAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBhbGxvdyAoYSBmdW5jdGlvbilcbiAgICAgICAgdmFyIGNhbGVuZGFyRXZlbnRTdG9yZSA9IGNhbGVuZGFyLnN0YXRlLmV2ZW50U3RvcmU7IC8vIG5lZWQgZ2xvYmFsLXRvLWNhbGVuZGFyLCBub3QgbG9jYWwgdG8gY29tcG9uZW50IChzcGxpdHRhYmxlKXN0YXRlXG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBzdWJqZWN0Q29uZmlnLmFsbG93czsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzdWJqZWN0QWxsb3cgPSBfYVtfaV07XG4gICAgICAgICAgICB2YXIgc3ViamVjdERhdGVTcGFuID0gX19hc3NpZ24oe30sIGRhdGVTcGFuTWV0YSwgeyByYW5nZTogc3ViamVjdEluc3RhbmNlLnJhbmdlLCBhbGxEYXk6IHN1YmplY3REZWYuYWxsRGF5IH0pO1xuICAgICAgICAgICAgdmFyIG9yaWdEZWYgPSBjYWxlbmRhckV2ZW50U3RvcmUuZGVmc1tzdWJqZWN0RGVmLmRlZklkXTtcbiAgICAgICAgICAgIHZhciBvcmlnSW5zdGFuY2UgPSBjYWxlbmRhckV2ZW50U3RvcmUuaW5zdGFuY2VzW3N1YmplY3RJbnN0YW5jZUlkXTtcbiAgICAgICAgICAgIHZhciBldmVudEFwaSA9IHZvaWQgMDtcbiAgICAgICAgICAgIGlmIChvcmlnRGVmKSB7IC8vIHdhcyBwcmV2aW91c2x5IGluIHRoZSBjYWxlbmRhclxuICAgICAgICAgICAgICAgIGV2ZW50QXBpID0gbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBvcmlnRGVmLCBvcmlnSW5zdGFuY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7IC8vIHdhcyBhbiBleHRlcm5hbCBldmVudFxuICAgICAgICAgICAgICAgIGV2ZW50QXBpID0gbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzdWJqZWN0RGVmKTsgLy8gbm8gaW5zdGFuY2UsIGJlY2F1c2UgaGFkIG5vIGRhdGVzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXN1YmplY3RBbGxvdyhjYWxlbmRhci5idWlsZERhdGVTcGFuQXBpKHN1YmplY3REYXRlU3BhbiksIGV2ZW50QXBpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8vIERhdGUgU2VsZWN0aW9uIFZhbGlkYXRpb25cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gaXNEYXRlU2VsZWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgdmFyIHJlbGV2YW50RXZlbnRTdG9yZSA9IHN0YXRlLmV2ZW50U3RvcmU7XG4gICAgdmFyIHJlbGV2YW50RGVmcyA9IHJlbGV2YW50RXZlbnRTdG9yZS5kZWZzO1xuICAgIHZhciByZWxldmFudEluc3RhbmNlcyA9IHJlbGV2YW50RXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIHNlbGVjdGlvbiA9IHN0YXRlLmRhdGVTZWxlY3Rpb247XG4gICAgdmFyIHNlbGVjdGlvblJhbmdlID0gc2VsZWN0aW9uLnJhbmdlO1xuICAgIHZhciBzZWxlY3Rpb25Db25maWcgPSBjYWxlbmRhci5zZWxlY3Rpb25Db25maWc7XG4gICAgaWYgKGZpbHRlckNvbmZpZykge1xuICAgICAgICBzZWxlY3Rpb25Db25maWcgPSBmaWx0ZXJDb25maWcoc2VsZWN0aW9uQ29uZmlnKTtcbiAgICB9XG4gICAgLy8gY29uc3RyYWludFxuICAgIGlmICghYWxsQ29uc3RyYWludHNQYXNzKHNlbGVjdGlvbkNvbmZpZy5jb25zdHJhaW50cywgc2VsZWN0aW9uUmFuZ2UsIHJlbGV2YW50RXZlbnRTdG9yZSwgc3RhdGUuYnVzaW5lc3NIb3VycywgY2FsZW5kYXIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gb3ZlcmxhcFxuICAgIHZhciBvdmVybGFwRnVuYyA9IGNhbGVuZGFyLm9wdCgnc2VsZWN0T3ZlcmxhcCcpO1xuICAgIGlmICh0eXBlb2Ygb3ZlcmxhcEZ1bmMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgb3ZlcmxhcEZ1bmMgPSBudWxsO1xuICAgIH1cbiAgICBmb3IgKHZhciByZWxldmFudEluc3RhbmNlSWQgaW4gcmVsZXZhbnRJbnN0YW5jZXMpIHtcbiAgICAgICAgdmFyIHJlbGV2YW50SW5zdGFuY2UgPSByZWxldmFudEluc3RhbmNlc1tyZWxldmFudEluc3RhbmNlSWRdO1xuICAgICAgICAvLyBpbnRlcnNlY3QhIGV2YWx1YXRlXG4gICAgICAgIGlmIChyYW5nZXNJbnRlcnNlY3Qoc2VsZWN0aW9uUmFuZ2UsIHJlbGV2YW50SW5zdGFuY2UucmFuZ2UpKSB7XG4gICAgICAgICAgICBpZiAoc2VsZWN0aW9uQ29uZmlnLm92ZXJsYXAgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG92ZXJsYXBGdW5jICYmICFvdmVybGFwRnVuYyhuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIHJlbGV2YW50RGVmc1tyZWxldmFudEluc3RhbmNlLmRlZklkXSwgcmVsZXZhbnRJbnN0YW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGFsbG93IChhIGZ1bmN0aW9uKVxuICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBzZWxlY3Rpb25Db25maWcuYWxsb3dzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc2VsZWN0aW9uQWxsb3cgPSBfYVtfaV07XG4gICAgICAgIHZhciBmdWxsRGF0ZVNwYW4gPSBfX2Fzc2lnbih7fSwgZGF0ZVNwYW5NZXRhLCBzZWxlY3Rpb24pO1xuICAgICAgICBpZiAoIXNlbGVjdGlvbkFsbG93KGNhbGVuZGFyLmJ1aWxkRGF0ZVNwYW5BcGkoZnVsbERhdGVTcGFuKSwgbnVsbCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8vIENvbnN0cmFpbnQgVXRpbHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYWxsQ29uc3RyYWludHNQYXNzKGNvbnN0cmFpbnRzLCBzdWJqZWN0UmFuZ2UsIG90aGVyRXZlbnRTdG9yZSwgYnVzaW5lc3NIb3Vyc1VuZXhwYW5kZWQsIGNhbGVuZGFyKSB7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBjb25zdHJhaW50c18xID0gY29uc3RyYWludHM7IF9pIDwgY29uc3RyYWludHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSBjb25zdHJhaW50c18xW19pXTtcbiAgICAgICAgaWYgKCFhbnlSYW5nZXNDb250YWluUmFuZ2UoY29uc3RyYWludFRvUmFuZ2VzKGNvbnN0cmFpbnQsIHN1YmplY3RSYW5nZSwgb3RoZXJFdmVudFN0b3JlLCBidXNpbmVzc0hvdXJzVW5leHBhbmRlZCwgY2FsZW5kYXIpLCBzdWJqZWN0UmFuZ2UpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBjb25zdHJhaW50VG9SYW5nZXMoY29uc3RyYWludCwgc3ViamVjdFJhbmdlLCAvLyBmb3IgZXhwYW5kaW5nIGEgcmVjdXJyaW5nIGNvbnN0cmFpbnQsIG9yIGV4cGFuZGluZyBidXNpbmVzcyBob3Vyc1xub3RoZXJFdmVudFN0b3JlLCAvLyBmb3IgaWYgY29uc3RyYWludCBpcyBhbiBldmVuIGdyb3VwIElEXG5idXNpbmVzc0hvdXJzVW5leHBhbmRlZCwgLy8gZm9yIGlmIGNvbnN0cmFpbnQgaXMgJ2J1c2luZXNzSG91cnMnXG5jYWxlbmRhciAvLyBmb3IgZXhwYW5kaW5nIGJ1c2luZXNzaG91cnNcbikge1xuICAgIGlmIChjb25zdHJhaW50ID09PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmVUb1JhbmdlcyhleHBhbmRSZWN1cnJpbmcoYnVzaW5lc3NIb3Vyc1VuZXhwYW5kZWQsIHN1YmplY3RSYW5nZSwgY2FsZW5kYXIpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGNvbnN0cmFpbnQgPT09ICdzdHJpbmcnKSB7IC8vIGFuIGdyb3VwIElEXG4gICAgICAgIHJldHVybiBldmVudFN0b3JlVG9SYW5nZXMoZmlsdGVyRXZlbnRTdG9yZURlZnMob3RoZXJFdmVudFN0b3JlLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBldmVudERlZi5ncm91cElkID09PSBjb25zdHJhaW50O1xuICAgICAgICB9KSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBjb25zdHJhaW50ID09PSAnb2JqZWN0JyAmJiBjb25zdHJhaW50KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gZXZlbnRTdG9yZVRvUmFuZ2VzKGV4cGFuZFJlY3VycmluZyhjb25zdHJhaW50LCBzdWJqZWN0UmFuZ2UsIGNhbGVuZGFyKSk7XG4gICAgfVxuICAgIHJldHVybiBbXTsgLy8gaWYgaXQncyBmYWxzZVxufVxuLy8gVE9ETzogbW92ZSB0byBldmVudC1zdG9yZSBmaWxlP1xuZnVuY3Rpb24gZXZlbnRTdG9yZVRvUmFuZ2VzKGV2ZW50U3RvcmUpIHtcbiAgICB2YXIgaW5zdGFuY2VzID0gZXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIHJhbmdlcyA9IFtdO1xuICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgIHJhbmdlcy5wdXNoKGluc3RhbmNlc1tpbnN0YW5jZUlkXS5yYW5nZSk7XG4gICAgfVxuICAgIHJldHVybiByYW5nZXM7XG59XG4vLyBUT0RPOiBtb3ZlIHRvIGdlb20gZmlsZT9cbmZ1bmN0aW9uIGFueVJhbmdlc0NvbnRhaW5SYW5nZShvdXRlclJhbmdlcywgaW5uZXJSYW5nZSkge1xuICAgIGZvciAodmFyIF9pID0gMCwgb3V0ZXJSYW5nZXNfMSA9IG91dGVyUmFuZ2VzOyBfaSA8IG91dGVyUmFuZ2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBvdXRlclJhbmdlID0gb3V0ZXJSYW5nZXNfMVtfaV07XG4gICAgICAgIGlmIChyYW5nZUNvbnRhaW5zUmFuZ2Uob3V0ZXJSYW5nZSwgaW5uZXJSYW5nZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8vIFBhcnNpbmdcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gbm9ybWFsaXplQ29uc3RyYWludChpbnB1dCwgY2FsZW5kYXIpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlRXZlbnRzKGlucHV0LCAnJywgY2FsZW5kYXIsIHRydWUpOyAvLyBhbGxvd09wZW5SYW5nZT10cnVlXG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgaW5wdXQpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgIHJldHVybiBwYXJzZUV2ZW50cyhbaW5wdXRdLCAnJywgY2FsZW5kYXIsIHRydWUpOyAvLyBhbGxvd09wZW5SYW5nZT10cnVlXG4gICAgfVxuICAgIGVsc2UgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyhpbnB1dCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGh0bWxFc2NhcGUocykge1xuICAgIHJldHVybiAocyArICcnKS5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gICAgICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JylcbiAgICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKVxuICAgICAgICAucmVwbGFjZSgvJy9nLCAnJiMwMzk7JylcbiAgICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxuICAgICAgICAucmVwbGFjZSgvXFxuL2csICc8YnIgLz4nKTtcbn1cbi8vIEdpdmVuIGEgaGFzaCBvZiBDU1MgcHJvcGVydGllcywgcmV0dXJucyBhIHN0cmluZyBvZiBDU1MuXG4vLyBVc2VzIHByb3BlcnR5IG5hbWVzIGFzLWlzIChubyBjYW1lbC1jYXNlIGNvbnZlcnNpb24pLiBXaWxsIG5vdCBtYWtlIHN0YXRlbWVudHMgZm9yIG51bGwvdW5kZWZpbmVkIHZhbHVlcy5cbmZ1bmN0aW9uIGNzc1RvU3RyKGNzc1Byb3BzKSB7XG4gICAgdmFyIHN0YXRlbWVudHMgPSBbXTtcbiAgICBmb3IgKHZhciBuYW1lXzEgaW4gY3NzUHJvcHMpIHtcbiAgICAgICAgdmFyIHZhbCA9IGNzc1Byb3BzW25hbWVfMV07XG4gICAgICAgIGlmICh2YWwgIT0gbnVsbCAmJiB2YWwgIT09ICcnKSB7XG4gICAgICAgICAgICBzdGF0ZW1lbnRzLnB1c2gobmFtZV8xICsgJzonICsgdmFsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3RhdGVtZW50cy5qb2luKCc7Jyk7XG59XG4vLyBHaXZlbiBhbiBvYmplY3QgaGFzaCBvZiBIVE1MIGF0dHJpYnV0ZSBuYW1lcyB0byB2YWx1ZXMsXG4vLyBnZW5lcmF0ZXMgYSBzdHJpbmcgdGhhdCBjYW4gYmUgaW5qZWN0ZWQgYmV0d2VlbiA8ID4gaW4gSFRNTFxuZnVuY3Rpb24gYXR0cnNUb1N0cihhdHRycykge1xuICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgIGZvciAodmFyIG5hbWVfMiBpbiBhdHRycykge1xuICAgICAgICB2YXIgdmFsID0gYXR0cnNbbmFtZV8yXTtcbiAgICAgICAgaWYgKHZhbCAhPSBudWxsKSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKG5hbWVfMiArICc9XCInICsgaHRtbEVzY2FwZSh2YWwpICsgJ1wiJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBhcnRzLmpvaW4oJyAnKTtcbn1cbmZ1bmN0aW9uIHBhcnNlQ2xhc3NOYW1lKHJhdykge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHtcbiAgICAgICAgcmV0dXJuIHJhdztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHJhdyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHJhdy5zcGxpdCgvXFxzKy8pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbn1cblxudmFyIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTID0ge1xuICAgIGVkaXRhYmxlOiBCb29sZWFuLFxuICAgIHN0YXJ0RWRpdGFibGU6IEJvb2xlYW4sXG4gICAgZHVyYXRpb25FZGl0YWJsZTogQm9vbGVhbixcbiAgICBjb25zdHJhaW50OiBudWxsLFxuICAgIG92ZXJsYXA6IG51bGwsXG4gICAgYWxsb3c6IG51bGwsXG4gICAgY2xhc3NOYW1lOiBwYXJzZUNsYXNzTmFtZSxcbiAgICBjbGFzc05hbWVzOiBwYXJzZUNsYXNzTmFtZSxcbiAgICBjb2xvcjogU3RyaW5nLFxuICAgIGJhY2tncm91bmRDb2xvcjogU3RyaW5nLFxuICAgIGJvcmRlckNvbG9yOiBTdHJpbmcsXG4gICAgdGV4dENvbG9yOiBTdHJpbmdcbn07XG5mdW5jdGlvbiBwcm9jZXNzVW5zY29wZWRVaVByb3BzKHJhd1Byb3BzLCBjYWxlbmRhciwgbGVmdG92ZXJzKSB7XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3UHJvcHMsIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTLCB7fSwgbGVmdG92ZXJzKTtcbiAgICB2YXIgY29uc3RyYWludCA9IG5vcm1hbGl6ZUNvbnN0cmFpbnQocHJvcHMuY29uc3RyYWludCwgY2FsZW5kYXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0RWRpdGFibGU6IHByb3BzLnN0YXJ0RWRpdGFibGUgIT0gbnVsbCA/IHByb3BzLnN0YXJ0RWRpdGFibGUgOiBwcm9wcy5lZGl0YWJsZSxcbiAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogcHJvcHMuZHVyYXRpb25FZGl0YWJsZSAhPSBudWxsID8gcHJvcHMuZHVyYXRpb25FZGl0YWJsZSA6IHByb3BzLmVkaXRhYmxlLFxuICAgICAgICBjb25zdHJhaW50czogY29uc3RyYWludCAhPSBudWxsID8gW2NvbnN0cmFpbnRdIDogW10sXG4gICAgICAgIG92ZXJsYXA6IHByb3BzLm92ZXJsYXAsXG4gICAgICAgIGFsbG93czogcHJvcHMuYWxsb3cgIT0gbnVsbCA/IFtwcm9wcy5hbGxvd10gOiBbXSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBwcm9wcy5iYWNrZ3JvdW5kQ29sb3IgfHwgcHJvcHMuY29sb3IsXG4gICAgICAgIGJvcmRlckNvbG9yOiBwcm9wcy5ib3JkZXJDb2xvciB8fCBwcm9wcy5jb2xvcixcbiAgICAgICAgdGV4dENvbG9yOiBwcm9wcy50ZXh0Q29sb3IsXG4gICAgICAgIGNsYXNzTmFtZXM6IHByb3BzLmNsYXNzTmFtZXMuY29uY2F0KHByb3BzLmNsYXNzTmFtZSlcbiAgICB9O1xufVxuZnVuY3Rpb24gcHJvY2Vzc1Njb3BlZFVpUHJvcHMocHJlZml4LCByYXdTY29wZWQsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMpIHtcbiAgICB2YXIgcmF3VW5zY29wZWQgPSB7fTtcbiAgICB2YXIgd2FzRm91bmQgPSB7fTtcbiAgICBmb3IgKHZhciBrZXkgaW4gVU5TQ09QRURfRVZFTlRfVUlfUFJPUFMpIHtcbiAgICAgICAgdmFyIHNjb3BlZEtleSA9IHByZWZpeCArIGNhcGl0YWxpc2VGaXJzdExldHRlcihrZXkpO1xuICAgICAgICByYXdVbnNjb3BlZFtrZXldID0gcmF3U2NvcGVkW3Njb3BlZEtleV07XG4gICAgICAgIHdhc0ZvdW5kW3Njb3BlZEtleV0gPSB0cnVlO1xuICAgIH1cbiAgICBpZiAocHJlZml4ID09PSAnZXZlbnQnKSB7XG4gICAgICAgIHJhd1Vuc2NvcGVkLmVkaXRhYmxlID0gcmF3U2NvcGVkLmVkaXRhYmxlOyAvLyBzcGVjaWFsIGNhc2UuIHRoZXJlIGlzIG5vICdldmVudEVkaXRhYmxlJywganVzdCAnZWRpdGFibGUnXG4gICAgfVxuICAgIGlmIChsZWZ0b3ZlcnMpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHJhd1Njb3BlZCkge1xuICAgICAgICAgICAgaWYgKCF3YXNGb3VuZFtrZXldKSB7XG4gICAgICAgICAgICAgICAgbGVmdG92ZXJzW2tleV0gPSByYXdTY29wZWRba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcHJvY2Vzc1Vuc2NvcGVkVWlQcm9wcyhyYXdVbnNjb3BlZCwgY2FsZW5kYXIpO1xufVxudmFyIEVNUFRZX0VWRU5UX1VJID0ge1xuICAgIHN0YXJ0RWRpdGFibGU6IG51bGwsXG4gICAgZHVyYXRpb25FZGl0YWJsZTogbnVsbCxcbiAgICBjb25zdHJhaW50czogW10sXG4gICAgb3ZlcmxhcDogbnVsbCxcbiAgICBhbGxvd3M6IFtdLFxuICAgIGJhY2tncm91bmRDb2xvcjogJycsXG4gICAgYm9yZGVyQ29sb3I6ICcnLFxuICAgIHRleHRDb2xvcjogJycsXG4gICAgY2xhc3NOYW1lczogW11cbn07XG4vLyBwcmV2ZW50IGFnYWluc3QgcHJvYmxlbXMgd2l0aCA8MiBhcmdzIVxuZnVuY3Rpb24gY29tYmluZUV2ZW50VWlzKHVpcykge1xuICAgIHJldHVybiB1aXMucmVkdWNlKGNvbWJpbmVUd29FdmVudFVpcywgRU1QVFlfRVZFTlRfVUkpO1xufVxuZnVuY3Rpb24gY29tYmluZVR3b0V2ZW50VWlzKGl0ZW0wLCBpdGVtMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0RWRpdGFibGU6IGl0ZW0xLnN0YXJ0RWRpdGFibGUgIT0gbnVsbCA/IGl0ZW0xLnN0YXJ0RWRpdGFibGUgOiBpdGVtMC5zdGFydEVkaXRhYmxlLFxuICAgICAgICBkdXJhdGlvbkVkaXRhYmxlOiBpdGVtMS5kdXJhdGlvbkVkaXRhYmxlICE9IG51bGwgPyBpdGVtMS5kdXJhdGlvbkVkaXRhYmxlIDogaXRlbTAuZHVyYXRpb25FZGl0YWJsZSxcbiAgICAgICAgY29uc3RyYWludHM6IGl0ZW0wLmNvbnN0cmFpbnRzLmNvbmNhdChpdGVtMS5jb25zdHJhaW50cyksXG4gICAgICAgIG92ZXJsYXA6IHR5cGVvZiBpdGVtMS5vdmVybGFwID09PSAnYm9vbGVhbicgPyBpdGVtMS5vdmVybGFwIDogaXRlbTAub3ZlcmxhcCxcbiAgICAgICAgYWxsb3dzOiBpdGVtMC5hbGxvd3MuY29uY2F0KGl0ZW0xLmFsbG93cyksXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogaXRlbTEuYmFja2dyb3VuZENvbG9yIHx8IGl0ZW0wLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgYm9yZGVyQ29sb3I6IGl0ZW0xLmJvcmRlckNvbG9yIHx8IGl0ZW0wLmJvcmRlckNvbG9yLFxuICAgICAgICB0ZXh0Q29sb3I6IGl0ZW0xLnRleHRDb2xvciB8fCBpdGVtMC50ZXh0Q29sb3IsXG4gICAgICAgIGNsYXNzTmFtZXM6IGl0ZW0wLmNsYXNzTmFtZXMuY29uY2F0KGl0ZW0xLmNsYXNzTmFtZXMpXG4gICAgfTtcbn1cblxudmFyIE5PTl9EQVRFX1BST1BTID0ge1xuICAgIGlkOiBTdHJpbmcsXG4gICAgZ3JvdXBJZDogU3RyaW5nLFxuICAgIHRpdGxlOiBTdHJpbmcsXG4gICAgdXJsOiBTdHJpbmcsXG4gICAgcmVuZGVyaW5nOiBTdHJpbmcsXG4gICAgZXh0ZW5kZWRQcm9wczogbnVsbFxufTtcbnZhciBEQVRFX1BST1BTID0ge1xuICAgIHN0YXJ0OiBudWxsLFxuICAgIGRhdGU6IG51bGwsXG4gICAgZW5kOiBudWxsLFxuICAgIGFsbERheTogbnVsbFxufTtcbnZhciB1aWQgPSAwO1xuZnVuY3Rpb24gcGFyc2VFdmVudChyYXcsIHNvdXJjZUlkLCBjYWxlbmRhciwgYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICB2YXIgYWxsRGF5RGVmYXVsdCA9IGNvbXB1dGVJc0FsbERheURlZmF1bHQoc291cmNlSWQsIGNhbGVuZGFyKTtcbiAgICB2YXIgbGVmdG92ZXJzMCA9IHt9O1xuICAgIHZhciByZWN1cnJpbmdSZXMgPSBwYXJzZVJlY3VycmluZyhyYXcsIC8vIHJhdywgYnV0IHdpdGggc2luZ2xlLWV2ZW50IHN0dWZmIHN0cmlwcGVkIG91dFxuICAgIGFsbERheURlZmF1bHQsIGNhbGVuZGFyLmRhdGVFbnYsIGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5yZWN1cnJpbmdUeXBlcywgbGVmdG92ZXJzMCAvLyB3aWxsIHBvcHVsYXRlIHdpdGggbm9uLXJlY3VycmluZyBwcm9wc1xuICAgICk7XG4gICAgaWYgKHJlY3VycmluZ1Jlcykge1xuICAgICAgICB2YXIgZGVmID0gcGFyc2VFdmVudERlZihsZWZ0b3ZlcnMwLCBzb3VyY2VJZCwgcmVjdXJyaW5nUmVzLmFsbERheSwgQm9vbGVhbihyZWN1cnJpbmdSZXMuZHVyYXRpb24pLCBjYWxlbmRhcik7XG4gICAgICAgIGRlZi5yZWN1cnJpbmdEZWYgPSB7XG4gICAgICAgICAgICB0eXBlSWQ6IHJlY3VycmluZ1Jlcy50eXBlSWQsXG4gICAgICAgICAgICB0eXBlRGF0YTogcmVjdXJyaW5nUmVzLnR5cGVEYXRhLFxuICAgICAgICAgICAgZHVyYXRpb246IHJlY3VycmluZ1Jlcy5kdXJhdGlvblxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4geyBkZWY6IGRlZiwgaW5zdGFuY2U6IG51bGwgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBsZWZ0b3ZlcnMxID0ge307XG4gICAgICAgIHZhciBzaW5nbGVSZXMgPSBwYXJzZVNpbmdsZShyYXcsIGFsbERheURlZmF1bHQsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMxLCBhbGxvd09wZW5SYW5nZSk7XG4gICAgICAgIGlmIChzaW5nbGVSZXMpIHtcbiAgICAgICAgICAgIHZhciBkZWYgPSBwYXJzZUV2ZW50RGVmKGxlZnRvdmVyczEsIHNvdXJjZUlkLCBzaW5nbGVSZXMuYWxsRGF5LCBzaW5nbGVSZXMuaGFzRW5kLCBjYWxlbmRhcik7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBjcmVhdGVFdmVudEluc3RhbmNlKGRlZi5kZWZJZCwgc2luZ2xlUmVzLnJhbmdlLCBzaW5nbGVSZXMuZm9yY2VkU3RhcnRUem8sIHNpbmdsZVJlcy5mb3JjZWRFbmRUem8pO1xuICAgICAgICAgICAgcmV0dXJuIHsgZGVmOiBkZWYsIGluc3RhbmNlOiBpbnN0YW5jZSB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuLypcbldpbGwgTk9UIHBvcHVsYXRlIGV4dGVuZGVkUHJvcHMgd2l0aCB0aGUgbGVmdG92ZXIgcHJvcGVydGllcy5cbldpbGwgTk9UIHBvcHVsYXRlIGRhdGUtcmVsYXRlZCBwcm9wcy5cblRoZSBFdmVudE5vbkRhdGVJbnB1dCBoYXMgYmVlbiBub3JtYWxpemVkIChpZCA9PiBwdWJsaWNJZCwgZXRjKS5cbiovXG5mdW5jdGlvbiBwYXJzZUV2ZW50RGVmKHJhdywgc291cmNlSWQsIGFsbERheSwgaGFzRW5kLCBjYWxlbmRhcikge1xuICAgIHZhciBsZWZ0b3ZlcnMgPSB7fTtcbiAgICB2YXIgZGVmID0gcGx1Y2tOb25EYXRlUHJvcHMocmF3LCBjYWxlbmRhciwgbGVmdG92ZXJzKTtcbiAgICBkZWYuZGVmSWQgPSBTdHJpbmcodWlkKyspO1xuICAgIGRlZi5zb3VyY2VJZCA9IHNvdXJjZUlkO1xuICAgIGRlZi5hbGxEYXkgPSBhbGxEYXk7XG4gICAgZGVmLmhhc0VuZCA9IGhhc0VuZDtcbiAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50RGVmUGFyc2VyczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIGV2ZW50RGVmUGFyc2VyID0gX2FbX2ldO1xuICAgICAgICB2YXIgbmV3TGVmdG92ZXJzID0ge307XG4gICAgICAgIGV2ZW50RGVmUGFyc2VyKGRlZiwgbGVmdG92ZXJzLCBuZXdMZWZ0b3ZlcnMpO1xuICAgICAgICBsZWZ0b3ZlcnMgPSBuZXdMZWZ0b3ZlcnM7XG4gICAgfVxuICAgIGRlZi5leHRlbmRlZFByb3BzID0gX19hc3NpZ24obGVmdG92ZXJzLCBkZWYuZXh0ZW5kZWRQcm9wcyB8fCB7fSk7XG4gICAgLy8gaGVscCBvdXQgRXZlbnRBcGkgZnJvbSBoYXZpbmcgdXNlciBtb2RpZnkgcHJvcHNcbiAgICBPYmplY3QuZnJlZXplKGRlZi51aS5jbGFzc05hbWVzKTtcbiAgICBPYmplY3QuZnJlZXplKGRlZi5leHRlbmRlZFByb3BzKTtcbiAgICByZXR1cm4gZGVmO1xufVxuZnVuY3Rpb24gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWZJZCwgcmFuZ2UsIGZvcmNlZFN0YXJ0VHpvLCBmb3JjZWRFbmRUem8pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBpbnN0YW5jZUlkOiBTdHJpbmcodWlkKyspLFxuICAgICAgICBkZWZJZDogZGVmSWQsXG4gICAgICAgIHJhbmdlOiByYW5nZSxcbiAgICAgICAgZm9yY2VkU3RhcnRUem86IGZvcmNlZFN0YXJ0VHpvID09IG51bGwgPyBudWxsIDogZm9yY2VkU3RhcnRUem8sXG4gICAgICAgIGZvcmNlZEVuZFR6bzogZm9yY2VkRW5kVHpvID09IG51bGwgPyBudWxsIDogZm9yY2VkRW5kVHpvXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlU2luZ2xlKHJhdywgYWxsRGF5RGVmYXVsdCwgY2FsZW5kYXIsIGxlZnRvdmVycywgYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICB2YXIgcHJvcHMgPSBwbHVja0RhdGVQcm9wcyhyYXcsIGxlZnRvdmVycyk7XG4gICAgdmFyIGFsbERheSA9IHByb3BzLmFsbERheTtcbiAgICB2YXIgc3RhcnRNZXRhO1xuICAgIHZhciBzdGFydE1hcmtlciA9IG51bGw7XG4gICAgdmFyIGhhc0VuZCA9IGZhbHNlO1xuICAgIHZhciBlbmRNZXRhO1xuICAgIHZhciBlbmRNYXJrZXIgPSBudWxsO1xuICAgIHN0YXJ0TWV0YSA9IGNhbGVuZGFyLmRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShwcm9wcy5zdGFydCk7XG4gICAgaWYgKHN0YXJ0TWV0YSkge1xuICAgICAgICBzdGFydE1hcmtlciA9IHN0YXJ0TWV0YS5tYXJrZXI7XG4gICAgfVxuICAgIGVsc2UgaWYgKCFhbGxvd09wZW5SYW5nZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHByb3BzLmVuZCAhPSBudWxsKSB7XG4gICAgICAgIGVuZE1ldGEgPSBjYWxlbmRhci5kYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEocHJvcHMuZW5kKTtcbiAgICB9XG4gICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgIGlmIChhbGxEYXlEZWZhdWx0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGFsbERheSA9IGFsbERheURlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBmYWxsIGJhY2sgdG8gdGhlIGRhdGUgcHJvcHMgTEFTVFxuICAgICAgICAgICAgYWxsRGF5ID0gKCFzdGFydE1ldGEgfHwgc3RhcnRNZXRhLmlzVGltZVVuc3BlY2lmaWVkKSAmJlxuICAgICAgICAgICAgICAgICghZW5kTWV0YSB8fCBlbmRNZXRhLmlzVGltZVVuc3BlY2lmaWVkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYWxsRGF5ICYmIHN0YXJ0TWFya2VyKSB7XG4gICAgICAgIHN0YXJ0TWFya2VyID0gc3RhcnRPZkRheShzdGFydE1hcmtlcik7XG4gICAgfVxuICAgIGlmIChlbmRNZXRhKSB7XG4gICAgICAgIGVuZE1hcmtlciA9IGVuZE1ldGEubWFya2VyO1xuICAgICAgICBpZiAoYWxsRGF5KSB7XG4gICAgICAgICAgICBlbmRNYXJrZXIgPSBzdGFydE9mRGF5KGVuZE1hcmtlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXJ0TWFya2VyICYmIGVuZE1hcmtlciA8PSBzdGFydE1hcmtlcikge1xuICAgICAgICAgICAgZW5kTWFya2VyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZW5kTWFya2VyKSB7XG4gICAgICAgIGhhc0VuZCA9IHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYgKCFhbGxvd09wZW5SYW5nZSkge1xuICAgICAgICBoYXNFbmQgPSBjYWxlbmRhci5vcHQoJ2ZvcmNlRXZlbnREdXJhdGlvbicpIHx8IGZhbHNlO1xuICAgICAgICBlbmRNYXJrZXIgPSBjYWxlbmRhci5kYXRlRW52LmFkZChzdGFydE1hcmtlciwgYWxsRGF5ID9cbiAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uIDpcbiAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBhbGxEYXk6IGFsbERheSxcbiAgICAgICAgaGFzRW5kOiBoYXNFbmQsXG4gICAgICAgIHJhbmdlOiB7IHN0YXJ0OiBzdGFydE1hcmtlciwgZW5kOiBlbmRNYXJrZXIgfSxcbiAgICAgICAgZm9yY2VkU3RhcnRUem86IHN0YXJ0TWV0YSA/IHN0YXJ0TWV0YS5mb3JjZWRUem8gOiBudWxsLFxuICAgICAgICBmb3JjZWRFbmRUem86IGVuZE1ldGEgPyBlbmRNZXRhLmZvcmNlZFR6byA6IG51bGxcbiAgICB9O1xufVxuZnVuY3Rpb24gcGx1Y2tEYXRlUHJvcHMocmF3LCBsZWZ0b3ZlcnMpIHtcbiAgICB2YXIgcHJvcHMgPSByZWZpbmVQcm9wcyhyYXcsIERBVEVfUFJPUFMsIHt9LCBsZWZ0b3ZlcnMpO1xuICAgIHByb3BzLnN0YXJ0ID0gKHByb3BzLnN0YXJ0ICE9PSBudWxsKSA/IHByb3BzLnN0YXJ0IDogcHJvcHMuZGF0ZTtcbiAgICBkZWxldGUgcHJvcHMuZGF0ZTtcbiAgICByZXR1cm4gcHJvcHM7XG59XG5mdW5jdGlvbiBwbHVja05vbkRhdGVQcm9wcyhyYXcsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMpIHtcbiAgICB2YXIgcHJlTGVmdG92ZXJzID0ge307XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3LCBOT05fREFURV9QUk9QUywge30sIHByZUxlZnRvdmVycyk7XG4gICAgdmFyIHVpID0gcHJvY2Vzc1Vuc2NvcGVkVWlQcm9wcyhwcmVMZWZ0b3ZlcnMsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMpO1xuICAgIHByb3BzLnB1YmxpY0lkID0gcHJvcHMuaWQ7XG4gICAgZGVsZXRlIHByb3BzLmlkO1xuICAgIHByb3BzLnVpID0gdWk7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuZnVuY3Rpb24gY29tcHV0ZUlzQWxsRGF5RGVmYXVsdChzb3VyY2VJZCwgY2FsZW5kYXIpIHtcbiAgICB2YXIgcmVzID0gbnVsbDtcbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGNhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlc1tzb3VyY2VJZF07XG4gICAgICAgIHJlcyA9IHNvdXJjZS5hbGxEYXlEZWZhdWx0O1xuICAgIH1cbiAgICBpZiAocmVzID09IG51bGwpIHtcbiAgICAgICAgcmVzID0gY2FsZW5kYXIub3B0KCdhbGxEYXlEZWZhdWx0Jyk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5cbnZhciBERUZfREVGQVVMVFMgPSB7XG4gICAgc3RhcnRUaW1lOiAnMDk6MDAnLFxuICAgIGVuZFRpbWU6ICcxNzowMCcsXG4gICAgZGF5c09mV2VlazogWzEsIDIsIDMsIDQsIDVdLFxuICAgIHJlbmRlcmluZzogJ2ludmVyc2UtYmFja2dyb3VuZCcsXG4gICAgY2xhc3NOYW1lczogJ2ZjLW5vbmJ1c2luZXNzJyxcbiAgICBncm91cElkOiAnX2J1c2luZXNzSG91cnMnIC8vIHNvIG11bHRpcGxlIGRlZnMgZ2V0IGdyb3VwZWRcbn07XG4vKlxuVE9ETzogcGFzcyBhcm91bmQgYXMgRXZlbnREZWZIYXNoISEhXG4qL1xuZnVuY3Rpb24gcGFyc2VCdXNpbmVzc0hvdXJzKGlucHV0LCBjYWxlbmRhcikge1xuICAgIHJldHVybiBwYXJzZUV2ZW50cyhyZWZpbmVJbnB1dHMoaW5wdXQpLCAnJywgY2FsZW5kYXIpO1xufVxuZnVuY3Rpb24gcmVmaW5lSW5wdXRzKGlucHV0KSB7XG4gICAgdmFyIHJhd0RlZnM7XG4gICAgaWYgKGlucHV0ID09PSB0cnVlKSB7XG4gICAgICAgIHJhd0RlZnMgPSBbe31dOyAvLyB3aWxsIGdldCBERUZfREVGQVVMVFMgdmVyYmF0aW1cbiAgICB9XG4gICAgZWxzZSBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgLy8gaWYgc3BlY2lmeWluZyBhbiBhcnJheSwgZXZlcnkgc3ViLWRlZmluaXRpb24gTkVFRFMgYSBkYXktb2Ytd2Vla1xuICAgICAgICByYXdEZWZzID0gaW5wdXQuZmlsdGVyKGZ1bmN0aW9uIChyYXdEZWYpIHtcbiAgICAgICAgICAgIHJldHVybiByYXdEZWYuZGF5c09mV2VlaztcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgaW5wdXQpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgIHJhd0RlZnMgPSBbaW5wdXRdO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gaXMgcHJvYmFibHkgZmFsc2VcbiAgICAgICAgcmF3RGVmcyA9IFtdO1xuICAgIH1cbiAgICByYXdEZWZzID0gcmF3RGVmcy5tYXAoZnVuY3Rpb24gKHJhd0RlZikge1xuICAgICAgICByZXR1cm4gX19hc3NpZ24oe30sIERFRl9ERUZBVUxUUywgcmF3RGVmKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmF3RGVmcztcbn1cblxuZnVuY3Rpb24gbWVtb2l6ZVJlbmRlcmluZyhyZW5kZXJGdW5jLCB1bnJlbmRlckZ1bmMsIGRlcGVuZGVuY2llcykge1xuICAgIGlmIChkZXBlbmRlbmNpZXMgPT09IHZvaWQgMCkgeyBkZXBlbmRlbmNpZXMgPSBbXTsgfVxuICAgIHZhciBkZXBlbmRlbnRzID0gW107XG4gICAgdmFyIHRoaXNDb250ZXh0O1xuICAgIHZhciBwcmV2QXJncztcbiAgICBmdW5jdGlvbiB1bnJlbmRlcigpIHtcbiAgICAgICAgaWYgKHByZXZBcmdzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIGRlcGVuZGVudHNfMSA9IGRlcGVuZGVudHM7IF9pIDwgZGVwZW5kZW50c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBkZXBlbmRlbnQgPSBkZXBlbmRlbnRzXzFbX2ldO1xuICAgICAgICAgICAgICAgIGRlcGVuZGVudC51bnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVucmVuZGVyRnVuYykge1xuICAgICAgICAgICAgICAgIHVucmVuZGVyRnVuYy5hcHBseSh0aGlzQ29udGV4dCwgcHJldkFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJldkFyZ3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlcygpIHtcbiAgICAgICAgaWYgKCFwcmV2QXJncyB8fCAhaXNBcnJheXNFcXVhbChwcmV2QXJncywgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgdW5yZW5kZXIoKTtcbiAgICAgICAgICAgIHRoaXNDb250ZXh0ID0gdGhpcztcbiAgICAgICAgICAgIHByZXZBcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgcmVuZGVyRnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlcy5kZXBlbmRlbnRzID0gZGVwZW5kZW50cztcbiAgICByZXMudW5yZW5kZXIgPSB1bnJlbmRlcjtcbiAgICBmb3IgKHZhciBfaSA9IDAsIGRlcGVuZGVuY2llc18xID0gZGVwZW5kZW5jaWVzOyBfaSA8IGRlcGVuZGVuY2llc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgZGVwZW5kZW5jeSA9IGRlcGVuZGVuY2llc18xW19pXTtcbiAgICAgICAgZGVwZW5kZW5jeS5kZXBlbmRlbnRzLnB1c2gocmVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxudmFyIEVNUFRZX0VWRU5UX1NUT1JFID0gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7IC8vIGZvciBwdXJlY29tcG9uZW50cy4gVE9ETzoga2VlcCBlbHNld2hlcmVcbnZhciBTcGxpdHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTcGxpdHRlcigpIHtcbiAgICAgICAgdGhpcy5nZXRLZXlzRm9yRXZlbnREZWZzID0gbWVtb2l6ZSh0aGlzLl9nZXRLZXlzRm9yRXZlbnREZWZzKTtcbiAgICAgICAgdGhpcy5zcGxpdERhdGVTZWxlY3Rpb24gPSBtZW1vaXplKHRoaXMuX3NwbGl0RGF0ZVNwYW4pO1xuICAgICAgICB0aGlzLnNwbGl0RXZlbnRTdG9yZSA9IG1lbW9pemUodGhpcy5fc3BsaXRFdmVudFN0b3JlKTtcbiAgICAgICAgdGhpcy5zcGxpdEluZGl2aWR1YWxVaSA9IG1lbW9pemUodGhpcy5fc3BsaXRJbmRpdmlkdWFsVWkpO1xuICAgICAgICB0aGlzLnNwbGl0RXZlbnREcmFnID0gbWVtb2l6ZSh0aGlzLl9zcGxpdEludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50UmVzaXplID0gbWVtb2l6ZSh0aGlzLl9zcGxpdEludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5ldmVudFVpQnVpbGRlcnMgPSB7fTsgLy8gVE9ETzogdHlwZXNjcmlwdCBwcm90ZWN0aW9uXG4gICAgfVxuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5zcGxpdFByb3BzID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBrZXlJbmZvcyA9IHRoaXMuZ2V0S2V5SW5mbyhwcm9wcyk7XG4gICAgICAgIHZhciBkZWZLZXlzID0gdGhpcy5nZXRLZXlzRm9yRXZlbnREZWZzKHByb3BzLmV2ZW50U3RvcmUpO1xuICAgICAgICB2YXIgZGF0ZVNlbGVjdGlvbnMgPSB0aGlzLnNwbGl0RGF0ZVNlbGVjdGlvbihwcm9wcy5kYXRlU2VsZWN0aW9uKTtcbiAgICAgICAgdmFyIGluZGl2aWR1YWxVaSA9IHRoaXMuc3BsaXRJbmRpdmlkdWFsVWkocHJvcHMuZXZlbnRVaUJhc2VzLCBkZWZLZXlzKTsgLy8gdGhlIGluZGl2aWR1YWwgKmJhc2VzKlxuICAgICAgICB2YXIgZXZlbnRTdG9yZXMgPSB0aGlzLnNwbGl0RXZlbnRTdG9yZShwcm9wcy5ldmVudFN0b3JlLCBkZWZLZXlzKTtcbiAgICAgICAgdmFyIGV2ZW50RHJhZ3MgPSB0aGlzLnNwbGl0RXZlbnREcmFnKHByb3BzLmV2ZW50RHJhZyk7XG4gICAgICAgIHZhciBldmVudFJlc2l6ZXMgPSB0aGlzLnNwbGl0RXZlbnRSZXNpemUocHJvcHMuZXZlbnRSZXNpemUpO1xuICAgICAgICB2YXIgc3BsaXRQcm9wcyA9IHt9O1xuICAgICAgICB0aGlzLmV2ZW50VWlCdWlsZGVycyA9IG1hcEhhc2goa2V5SW5mb3MsIGZ1bmN0aW9uIChpbmZvLCBrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5ldmVudFVpQnVpbGRlcnNba2V5XSB8fCBtZW1vaXplKGJ1aWxkRXZlbnRVaUZvcktleSk7XG4gICAgICAgIH0pO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4ga2V5SW5mb3MpIHtcbiAgICAgICAgICAgIHZhciBrZXlJbmZvID0ga2V5SW5mb3Nba2V5XTtcbiAgICAgICAgICAgIHZhciBldmVudFN0b3JlID0gZXZlbnRTdG9yZXNba2V5XSB8fCBFTVBUWV9FVkVOVF9TVE9SRTtcbiAgICAgICAgICAgIHZhciBidWlsZEV2ZW50VWkgPSB0aGlzLmV2ZW50VWlCdWlsZGVyc1trZXldO1xuICAgICAgICAgICAgc3BsaXRQcm9wc1trZXldID0ge1xuICAgICAgICAgICAgICAgIGJ1c2luZXNzSG91cnM6IGtleUluZm8uYnVzaW5lc3NIb3VycyB8fCBwcm9wcy5idXNpbmVzc0hvdXJzLFxuICAgICAgICAgICAgICAgIGRhdGVTZWxlY3Rpb246IGRhdGVTZWxlY3Rpb25zW2tleV0gfHwgbnVsbCxcbiAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFN0b3JlLFxuICAgICAgICAgICAgICAgIGV2ZW50VWlCYXNlczogYnVpbGRFdmVudFVpKHByb3BzLmV2ZW50VWlCYXNlc1snJ10sIGtleUluZm8udWksIGluZGl2aWR1YWxVaVtrZXldKSxcbiAgICAgICAgICAgICAgICBldmVudFNlbGVjdGlvbjogZXZlbnRTdG9yZS5pbnN0YW5jZXNbcHJvcHMuZXZlbnRTZWxlY3Rpb25dID8gcHJvcHMuZXZlbnRTZWxlY3Rpb24gOiAnJyxcbiAgICAgICAgICAgICAgICBldmVudERyYWc6IGV2ZW50RHJhZ3Nba2V5XSB8fCBudWxsLFxuICAgICAgICAgICAgICAgIGV2ZW50UmVzaXplOiBldmVudFJlc2l6ZXNba2V5XSB8fCBudWxsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdFByb3BzO1xuICAgIH07XG4gICAgU3BsaXR0ZXIucHJvdG90eXBlLl9zcGxpdERhdGVTcGFuID0gZnVuY3Rpb24gKGRhdGVTcGFuKSB7XG4gICAgICAgIHZhciBkYXRlU3BhbnMgPSB7fTtcbiAgICAgICAgaWYgKGRhdGVTcGFuKSB7XG4gICAgICAgICAgICB2YXIga2V5cyA9IHRoaXMuZ2V0S2V5c0ZvckRhdGVTcGFuKGRhdGVTcGFuKTtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwga2V5c18xID0ga2V5czsgX2kgPCBrZXlzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGtleXNfMVtfaV07XG4gICAgICAgICAgICAgICAgZGF0ZVNwYW5zW2tleV0gPSBkYXRlU3BhbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZVNwYW5zO1xuICAgIH07XG4gICAgU3BsaXR0ZXIucHJvdG90eXBlLl9nZXRLZXlzRm9yRXZlbnREZWZzID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIG1hcEhhc2goZXZlbnRTdG9yZS5kZWZzLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5nZXRLZXlzRm9yRXZlbnREZWYoZXZlbnREZWYpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fc3BsaXRFdmVudFN0b3JlID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUsIGRlZktleXMpIHtcbiAgICAgICAgdmFyIGRlZnMgPSBldmVudFN0b3JlLmRlZnMsIGluc3RhbmNlcyA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzO1xuICAgICAgICB2YXIgc3BsaXRTdG9yZXMgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgZGVmSWQgaW4gZGVmcykge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGRlZktleXNbZGVmSWRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKCFzcGxpdFN0b3Jlc1trZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwbGl0U3RvcmVzW2tleV0gPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3BsaXRTdG9yZXNba2V5XS5kZWZzW2RlZklkXSA9IGRlZnNbZGVmSWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgICAgICBmb3IgKHZhciBfYiA9IDAsIF9jID0gZGVmS2V5c1tpbnN0YW5jZS5kZWZJZF07IF9iIDwgX2MubGVuZ3RoOyBfYisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IF9jW19iXTtcbiAgICAgICAgICAgICAgICBpZiAoc3BsaXRTdG9yZXNba2V5XSkgeyAvLyBtdXN0IGhhdmUgYWxyZWFkeSBiZWVuIGNyZWF0ZWRcbiAgICAgICAgICAgICAgICAgICAgc3BsaXRTdG9yZXNba2V5XS5pbnN0YW5jZXNbaW5zdGFuY2VJZF0gPSBpbnN0YW5jZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwbGl0U3RvcmVzO1xuICAgIH07XG4gICAgU3BsaXR0ZXIucHJvdG90eXBlLl9zcGxpdEluZGl2aWR1YWxVaSA9IGZ1bmN0aW9uIChldmVudFVpQmFzZXMsIGRlZktleXMpIHtcbiAgICAgICAgdmFyIHNwbGl0SGFzaGVzID0ge307XG4gICAgICAgIGZvciAodmFyIGRlZklkIGluIGV2ZW50VWlCYXNlcykge1xuICAgICAgICAgICAgaWYgKGRlZklkKSB7IC8vIG5vdCB0aGUgJycga2V5XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGRlZktleXNbZGVmSWRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNwbGl0SGFzaGVzW2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwbGl0SGFzaGVzW2tleV0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzcGxpdEhhc2hlc1trZXldW2RlZklkXSA9IGV2ZW50VWlCYXNlc1tkZWZJZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdEhhc2hlcztcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fc3BsaXRJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbikge1xuICAgICAgICB2YXIgc3BsaXRTdGF0ZXMgPSB7fTtcbiAgICAgICAgaWYgKGludGVyYWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgYWZmZWN0ZWRTdG9yZXNfMSA9IHRoaXMuX3NwbGl0RXZlbnRTdG9yZShpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cywgdGhpcy5fZ2V0S2V5c0ZvckV2ZW50RGVmcyhpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cykgLy8gY2FuJ3QgdXNlIGNhY2hlZC4gbWlnaHQgYmUgZXZlbnRzIGZyb20gb3RoZXIgY2FsZW5kYXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICAvLyBjYW4ndCByZWx5IG9uIGRlZktleXMgYmVjYXVzZSBldmVudCBkYXRhIGlzIG11dGF0ZWRcbiAgICAgICAgICAgIHZhciBtdXRhdGVkS2V5c0J5RGVmSWQgPSB0aGlzLl9nZXRLZXlzRm9yRXZlbnREZWZzKGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMpO1xuICAgICAgICAgICAgdmFyIG11dGF0ZWRTdG9yZXNfMSA9IHRoaXMuX3NwbGl0RXZlbnRTdG9yZShpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzLCBtdXRhdGVkS2V5c0J5RGVmSWQpO1xuICAgICAgICAgICAgdmFyIHBvcHVsYXRlID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgIGlmICghc3BsaXRTdGF0ZXNba2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBzcGxpdFN0YXRlc1trZXldID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IGFmZmVjdGVkU3RvcmVzXzFba2V5XSB8fCBFTVBUWV9FVkVOVF9TVE9SRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IG11dGF0ZWRTdG9yZXNfMVtrZXldIHx8IEVNUFRZX0VWRU5UX1NUT1JFLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNFdmVudDogaW50ZXJhY3Rpb24uaXNFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdTZWc6IGludGVyYWN0aW9uLm9yaWdTZWdcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGFmZmVjdGVkU3RvcmVzXzEpIHtcbiAgICAgICAgICAgICAgICBwb3B1bGF0ZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG11dGF0ZWRTdG9yZXNfMSkge1xuICAgICAgICAgICAgICAgIHBvcHVsYXRlKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwbGl0U3RhdGVzO1xuICAgIH07XG4gICAgcmV0dXJuIFNwbGl0dGVyO1xufSgpKTtcbmZ1bmN0aW9uIGJ1aWxkRXZlbnRVaUZvcktleShhbGxVaSwgZXZlbnRVaUZvcktleSwgaW5kaXZpZHVhbFVpKSB7XG4gICAgdmFyIGJhc2VQYXJ0cyA9IFtdO1xuICAgIGlmIChhbGxVaSkge1xuICAgICAgICBiYXNlUGFydHMucHVzaChhbGxVaSk7XG4gICAgfVxuICAgIGlmIChldmVudFVpRm9yS2V5KSB7XG4gICAgICAgIGJhc2VQYXJ0cy5wdXNoKGV2ZW50VWlGb3JLZXkpO1xuICAgIH1cbiAgICB2YXIgc3R1ZmYgPSB7XG4gICAgICAgICcnOiBjb21iaW5lRXZlbnRVaXMoYmFzZVBhcnRzKVxuICAgIH07XG4gICAgaWYgKGluZGl2aWR1YWxVaSkge1xuICAgICAgICBfX2Fzc2lnbihzdHVmZiwgaW5kaXZpZHVhbFVpKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0dWZmO1xufVxuXG4vLyBHZW5lcmF0ZXMgSFRNTCBmb3IgYW4gYW5jaG9yIHRvIGFub3RoZXIgdmlldyBpbnRvIHRoZSBjYWxlbmRhci5cbi8vIFdpbGwgZWl0aGVyIGdlbmVyYXRlIGFuIDxhPiB0YWcgb3IgYSBub24tY2xpY2thYmxlIDxzcGFuPiB0YWcsIGRlcGVuZGluZyBvbiBlbmFibGVkIHNldHRpbmdzLlxuLy8gYGdvdG9PcHRpb25zYCBjYW4gZWl0aGVyIGJlIGEgRGF0ZU1hcmtlciwgb3IgYW4gb2JqZWN0IHdpdGggdGhlIGZvcm06XG4vLyB7IGRhdGUsIHR5cGUsIGZvcmNlT2ZmIH1cbi8vIGB0eXBlYCBpcyBhIHZpZXctdHlwZSBsaWtlIFwiZGF5XCIgb3IgXCJ3ZWVrXCIuIGRlZmF1bHQgdmFsdWUgaXMgXCJkYXlcIi5cbi8vIGBhdHRyc2AgYW5kIGBpbm5lckh0bWxgIGFyZSB1c2UgdG8gZ2VuZXJhdGUgdGhlIHJlc3Qgb2YgdGhlIEhUTUwgdGFnLlxuZnVuY3Rpb24gYnVpbGRHb3RvQW5jaG9ySHRtbChhbGxPcHRpb25zLCBkYXRlRW52LCBnb3RvT3B0aW9ucywgYXR0cnMsIGlubmVySHRtbCkge1xuICAgIHZhciBkYXRlO1xuICAgIHZhciB0eXBlO1xuICAgIHZhciBmb3JjZU9mZjtcbiAgICB2YXIgZmluYWxPcHRpb25zO1xuICAgIGlmIChnb3RvT3B0aW9ucyBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgZGF0ZSA9IGdvdG9PcHRpb25zOyAvLyBhIHNpbmdsZSBkYXRlLWxpa2UgaW5wdXRcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGRhdGUgPSBnb3RvT3B0aW9ucy5kYXRlO1xuICAgICAgICB0eXBlID0gZ290b09wdGlvbnMudHlwZTtcbiAgICAgICAgZm9yY2VPZmYgPSBnb3RvT3B0aW9ucy5mb3JjZU9mZjtcbiAgICB9XG4gICAgZmluYWxPcHRpb25zID0ge1xuICAgICAgICBkYXRlOiBkYXRlRW52LmZvcm1hdElzbyhkYXRlLCB7IG9taXRUaW1lOiB0cnVlIH0pLFxuICAgICAgICB0eXBlOiB0eXBlIHx8ICdkYXknXG4gICAgfTtcbiAgICBpZiAodHlwZW9mIGF0dHJzID09PSAnc3RyaW5nJykge1xuICAgICAgICBpbm5lckh0bWwgPSBhdHRycztcbiAgICAgICAgYXR0cnMgPSBudWxsO1xuICAgIH1cbiAgICBhdHRycyA9IGF0dHJzID8gJyAnICsgYXR0cnNUb1N0cihhdHRycykgOiAnJzsgLy8gd2lsbCBoYXZlIGEgbGVhZGluZyBzcGFjZVxuICAgIGlubmVySHRtbCA9IGlubmVySHRtbCB8fCAnJztcbiAgICBpZiAoIWZvcmNlT2ZmICYmIGFsbE9wdGlvbnMubmF2TGlua3MpIHtcbiAgICAgICAgcmV0dXJuICc8YScgKyBhdHRycyArXG4gICAgICAgICAgICAnIGRhdGEtZ290bz1cIicgKyBodG1sRXNjYXBlKEpTT04uc3RyaW5naWZ5KGZpbmFsT3B0aW9ucykpICsgJ1wiPicgK1xuICAgICAgICAgICAgaW5uZXJIdG1sICtcbiAgICAgICAgICAgICc8L2E+JztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiAnPHNwYW4nICsgYXR0cnMgKyAnPicgK1xuICAgICAgICAgICAgaW5uZXJIdG1sICtcbiAgICAgICAgICAgICc8L3NwYW4+JztcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRBbGxEYXlIdG1sKGFsbE9wdGlvbnMpIHtcbiAgICByZXR1cm4gYWxsT3B0aW9ucy5hbGxEYXlIdG1sIHx8IGh0bWxFc2NhcGUoYWxsT3B0aW9ucy5hbGxEYXlUZXh0KTtcbn1cbi8vIENvbXB1dGVzIEhUTUwgY2xhc3NOYW1lcyBmb3IgYSBzaW5nbGUtZGF5IGVsZW1lbnRcbmZ1bmN0aW9uIGdldERheUNsYXNzZXMoZGF0ZSwgZGF0ZVByb2ZpbGUsIGNvbnRleHQsIG5vVGhlbWVIaWdobGlnaHQpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBjb250ZXh0LmNhbGVuZGFyLCBvcHRpb25zID0gY29udGV4dC5vcHRpb25zLCB0aGVtZSA9IGNvbnRleHQudGhlbWUsIGRhdGVFbnYgPSBjb250ZXh0LmRhdGVFbnY7XG4gICAgdmFyIGNsYXNzZXMgPSBbXTtcbiAgICB2YXIgdG9kYXlTdGFydDtcbiAgICB2YXIgdG9kYXlFbmQ7XG4gICAgaWYgKCFyYW5nZUNvbnRhaW5zTWFya2VyKGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBkYXRlKSkge1xuICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLWRpc2FibGVkLWRheScpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy0nICsgREFZX0lEU1tkYXRlLmdldFVUQ0RheSgpXSk7XG4gICAgICAgIGlmIChvcHRpb25zLm1vbnRoTW9kZSAmJlxuICAgICAgICAgICAgZGF0ZUVudi5nZXRNb250aChkYXRlKSAhPT0gZGF0ZUVudi5nZXRNb250aChkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2Uuc3RhcnQpKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLW90aGVyLW1vbnRoJyk7XG4gICAgICAgIH1cbiAgICAgICAgdG9kYXlTdGFydCA9IHN0YXJ0T2ZEYXkoY2FsZW5kYXIuZ2V0Tm93KCkpO1xuICAgICAgICB0b2RheUVuZCA9IGFkZERheXModG9kYXlTdGFydCwgMSk7XG4gICAgICAgIGlmIChkYXRlIDwgdG9kYXlTdGFydCkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1wYXN0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZGF0ZSA+PSB0b2RheUVuZCkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1mdXR1cmUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtdG9kYXknKTtcbiAgICAgICAgICAgIGlmIChub1RoZW1lSGlnaGxpZ2h0ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHRoZW1lLmdldENsYXNzKCd0b2RheScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xhc3Nlcztcbn1cblxuLy8gZ2l2ZW4gYSBmdW5jdGlvbiB0aGF0IHJlc29sdmVzIGEgcmVzdWx0IGFzeW5jaHJvbm91c2x5LlxuLy8gdGhlIGZ1bmN0aW9uIGNhbiBlaXRoZXIgY2FsbCBwYXNzZWQtaW4gc3VjY2VzcyBhbmQgZmFpbHVyZSBjYWxsYmFja3MsXG4vLyBvciBpdCBjYW4gcmV0dXJuIGEgcHJvbWlzZS5cbi8vIGlmIHlvdSBuZWVkIHRvIHBhc3MgYWRkaXRpb25hbCBwYXJhbXMgdG8gZnVuYywgYmluZCB0aGVtIGZpcnN0LlxuZnVuY3Rpb24gdW5wcm9taXNpZnkoZnVuYywgc3VjY2VzcywgZmFpbHVyZSkge1xuICAgIC8vIGd1YXJkIGFnYWluc3Qgc3VjY2Vzcy9mYWlsdXJlIGNhbGxiYWNrcyBiZWluZyBjYWxsZWQgbW9yZSB0aGFuIG9uY2VcbiAgICAvLyBhbmQgZ3VhcmQgYWdhaW5zdCBhIHByb21pc2UgQU5EIGNhbGxiYWNrIGJlaW5nIHVzZWQgdG9nZXRoZXIuXG4gICAgdmFyIGlzUmVzb2x2ZWQgPSBmYWxzZTtcbiAgICB2YXIgd3JhcHBlZFN1Y2Nlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghaXNSZXNvbHZlZCkge1xuICAgICAgICAgICAgaXNSZXNvbHZlZCA9IHRydWU7XG4gICAgICAgICAgICBzdWNjZXNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHZhciB3cmFwcGVkRmFpbHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFpc1Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpc1Jlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChmYWlsdXJlKSB7XG4gICAgICAgICAgICAgICAgZmFpbHVyZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICB2YXIgcmVzID0gZnVuYyh3cmFwcGVkU3VjY2Vzcywgd3JhcHBlZEZhaWx1cmUpO1xuICAgIGlmIChyZXMgJiYgdHlwZW9mIHJlcy50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJlcy50aGVuKHdyYXBwZWRTdWNjZXNzLCB3cmFwcGVkRmFpbHVyZSk7XG4gICAgfVxufVxuXG52YXIgTWl4aW4gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTWl4aW4oKSB7XG4gICAgfVxuICAgIC8vIG1peCBpbnRvIGEgQ0xBU1NcbiAgICBNaXhpbi5taXhJbnRvID0gZnVuY3Rpb24gKGRlc3RDbGFzcykge1xuICAgICAgICB0aGlzLm1peEludG9PYmooZGVzdENsYXNzLnByb3RvdHlwZSk7XG4gICAgfTtcbiAgICAvLyBtaXggaW50byBBTlkgb2JqZWN0XG4gICAgTWl4aW4ubWl4SW50b09iaiA9IGZ1bmN0aW9uIChkZXN0T2JqKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICBpZiAoIWRlc3RPYmpbbmFtZV0pIHsgLy8gaWYgZGVzdGluYXRpb24gZG9lc24ndCBhbHJlYWR5IGRlZmluZSBpdFxuICAgICAgICAgICAgICAgIGRlc3RPYmpbbmFtZV0gPSBfdGhpcy5wcm90b3R5cGVbbmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLypcbiAgICB3aWxsIG92ZXJyaWRlIGV4aXN0aW5nIG1ldGhvZHNcbiAgICBUT0RPOiByZW1vdmUhIG5vdCB1c2VkIGFueW1vcmVcbiAgICAqL1xuICAgIE1peGluLm1peE92ZXIgPSBmdW5jdGlvbiAoZGVzdENsYXNzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICBkZXN0Q2xhc3MucHJvdG90eXBlW25hbWVdID0gX3RoaXMucHJvdG90eXBlW25hbWVdO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBNaXhpbjtcbn0oKSk7XG5cbi8qXG5VU0FHRTpcbiAgaW1wb3J0IHsgZGVmYXVsdCBhcyBFbWl0dGVyTWl4aW4sIEVtaXR0ZXJJbnRlcmZhY2UgfSBmcm9tICcuL0VtaXR0ZXJNaXhpbidcbmluIGNsYXNzOlxuICBvbjogRW1pdHRlckludGVyZmFjZVsnb24nXVxuICBvbmU6IEVtaXR0ZXJJbnRlcmZhY2VbJ29uZSddXG4gIG9mZjogRW1pdHRlckludGVyZmFjZVsnb2ZmJ11cbiAgdHJpZ2dlcjogRW1pdHRlckludGVyZmFjZVsndHJpZ2dlciddXG4gIHRyaWdnZXJXaXRoOiBFbWl0dGVySW50ZXJmYWNlWyd0cmlnZ2VyV2l0aCddXG4gIGhhc0hhbmRsZXJzOiBFbWl0dGVySW50ZXJmYWNlWydoYXNIYW5kbGVycyddXG5hZnRlciBjbGFzczpcbiAgRW1pdHRlck1peGluLm1peEludG8oVGhlQ2xhc3MpXG4qL1xudmFyIEVtaXR0ZXJNaXhpbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRW1pdHRlck1peGluLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEVtaXR0ZXJNaXhpbigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBFbWl0dGVyTWl4aW4ucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgYWRkVG9IYXNoKHRoaXMuX2hhbmRsZXJzIHx8ICh0aGlzLl9oYW5kbGVycyA9IHt9KSwgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIHJldHVybiB0aGlzOyAvLyBmb3IgY2hhaW5pbmdcbiAgICB9O1xuICAgIC8vIHRvZG86IGFkZCBjb21tZW50c1xuICAgIEVtaXR0ZXJNaXhpbi5wcm90b3R5cGUub25lID0gZnVuY3Rpb24gKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgYWRkVG9IYXNoKHRoaXMuX29uZUhhbmRsZXJzIHx8ICh0aGlzLl9vbmVIYW5kbGVycyA9IHt9KSwgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIHJldHVybiB0aGlzOyAvLyBmb3IgY2hhaW5pbmdcbiAgICB9O1xuICAgIEVtaXR0ZXJNaXhpbi5wcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuX2hhbmRsZXJzKSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tSGFzaCh0aGlzLl9oYW5kbGVycywgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX29uZUhhbmRsZXJzKSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tSGFzaCh0aGlzLl9vbmVIYW5kbGVycywgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGZvciBjaGFpbmluZ1xuICAgIH07XG4gICAgRW1pdHRlck1peGluLnByb3RvdHlwZS50cmlnZ2VyID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAxOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGFyZ3NbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50cmlnZ2VyV2l0aCh0eXBlLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGZvciBjaGFpbmluZ1xuICAgIH07XG4gICAgRW1pdHRlck1peGluLnByb3RvdHlwZS50cmlnZ2VyV2l0aCA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0LCBhcmdzKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYW5kbGVycykge1xuICAgICAgICAgICAgYXBwbHlBbGwodGhpcy5faGFuZGxlcnNbdHlwZV0sIGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9vbmVIYW5kbGVycykge1xuICAgICAgICAgICAgYXBwbHlBbGwodGhpcy5fb25lSGFuZGxlcnNbdHlwZV0sIGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX29uZUhhbmRsZXJzW3R5cGVdOyAvLyB3aWxsIG5ldmVyIGZpcmUgYWdhaW5cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpczsgLy8gZm9yIGNoYWluaW5nXG4gICAgfTtcbiAgICBFbWl0dGVyTWl4aW4ucHJvdG90eXBlLmhhc0hhbmRsZXJzID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9oYW5kbGVycyAmJiB0aGlzLl9oYW5kbGVyc1t0eXBlXSAmJiB0aGlzLl9oYW5kbGVyc1t0eXBlXS5sZW5ndGgpIHx8XG4gICAgICAgICAgICAodGhpcy5fb25lSGFuZGxlcnMgJiYgdGhpcy5fb25lSGFuZGxlcnNbdHlwZV0gJiYgdGhpcy5fb25lSGFuZGxlcnNbdHlwZV0ubGVuZ3RoKTtcbiAgICB9O1xuICAgIHJldHVybiBFbWl0dGVyTWl4aW47XG59KE1peGluKSk7XG5mdW5jdGlvbiBhZGRUb0hhc2goaGFzaCwgdHlwZSwgaGFuZGxlcikge1xuICAgIChoYXNoW3R5cGVdIHx8IChoYXNoW3R5cGVdID0gW10pKVxuICAgICAgICAucHVzaChoYW5kbGVyKTtcbn1cbmZ1bmN0aW9uIHJlbW92ZUZyb21IYXNoKGhhc2gsIHR5cGUsIGhhbmRsZXIpIHtcbiAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICBpZiAoaGFzaFt0eXBlXSkge1xuICAgICAgICAgICAgaGFzaFt0eXBlXSA9IGhhc2hbdHlwZV0uZmlsdGVyKGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmMgIT09IGhhbmRsZXI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZGVsZXRlIGhhc2hbdHlwZV07IC8vIHJlbW92ZSBhbGwgaGFuZGxlciBmdW5jcyBmb3IgdGhpcyB0eXBlXG4gICAgfVxufVxuXG4vKlxuUmVjb3JkcyBvZmZzZXQgaW5mb3JtYXRpb24gZm9yIGEgc2V0IG9mIGVsZW1lbnRzLCByZWxhdGl2ZSB0byBhbiBvcmlnaW4gZWxlbWVudC5cbkNhbiByZWNvcmQgdGhlIGxlZnQvcmlnaHQgT1IgdGhlIHRvcC9ib3R0b20gT1IgYm90aC5cblByb3ZpZGVzIG1ldGhvZHMgZm9yIHF1ZXJ5aW5nIHRoZSBjYWNoZSBieSBwb3NpdGlvbi5cbiovXG52YXIgUG9zaXRpb25DYWNoZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQb3NpdGlvbkNhY2hlKG9yaWdpbkVsLCBlbHMsIGlzSG9yaXpvbnRhbCwgaXNWZXJ0aWNhbCkge1xuICAgICAgICB0aGlzLm9yaWdpbkVsID0gb3JpZ2luRWw7XG4gICAgICAgIHRoaXMuZWxzID0gZWxzO1xuICAgICAgICB0aGlzLmlzSG9yaXpvbnRhbCA9IGlzSG9yaXpvbnRhbDtcbiAgICAgICAgdGhpcy5pc1ZlcnRpY2FsID0gaXNWZXJ0aWNhbDtcbiAgICB9XG4gICAgLy8gUXVlcmllcyB0aGUgZWxzIGZvciBjb29yZGluYXRlcyBhbmQgc3RvcmVzIHRoZW0uXG4gICAgLy8gQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgdXNpbmcgYW5kIG9mIHRoZSBnZXQqIG1ldGhvZHMgYmVsb3cuXG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuYnVpbGQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvcmlnaW5FbCA9IHRoaXMub3JpZ2luRWw7XG4gICAgICAgIHZhciBvcmlnaW5DbGllbnRSZWN0ID0gdGhpcy5vcmlnaW5DbGllbnRSZWN0ID1cbiAgICAgICAgICAgIG9yaWdpbkVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyByZWxhdGl2ZSB0byB2aWV3cG9ydCB0b3AtbGVmdFxuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgIHRoaXMuYnVpbGRFbEhvcml6b250YWxzKG9yaWdpbkNsaWVudFJlY3QubGVmdCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNWZXJ0aWNhbCkge1xuICAgICAgICAgICAgdGhpcy5idWlsZEVsVmVydGljYWxzKG9yaWdpbkNsaWVudFJlY3QudG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gUG9wdWxhdGVzIHRoZSBsZWZ0L3JpZ2h0IGludGVybmFsIGNvb3JkaW5hdGUgYXJyYXlzXG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuYnVpbGRFbEhvcml6b250YWxzID0gZnVuY3Rpb24gKG9yaWdpbkNsaWVudExlZnQpIHtcbiAgICAgICAgdmFyIGxlZnRzID0gW107XG4gICAgICAgIHZhciByaWdodHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZWxzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGVsID0gX2FbX2ldO1xuICAgICAgICAgICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGxlZnRzLnB1c2gocmVjdC5sZWZ0IC0gb3JpZ2luQ2xpZW50TGVmdCk7XG4gICAgICAgICAgICByaWdodHMucHVzaChyZWN0LnJpZ2h0IC0gb3JpZ2luQ2xpZW50TGVmdCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sZWZ0cyA9IGxlZnRzO1xuICAgICAgICB0aGlzLnJpZ2h0cyA9IHJpZ2h0cztcbiAgICB9O1xuICAgIC8vIFBvcHVsYXRlcyB0aGUgdG9wL2JvdHRvbSBpbnRlcm5hbCBjb29yZGluYXRlIGFycmF5c1xuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmJ1aWxkRWxWZXJ0aWNhbHMgPSBmdW5jdGlvbiAob3JpZ2luQ2xpZW50VG9wKSB7XG4gICAgICAgIHZhciB0b3BzID0gW107XG4gICAgICAgIHZhciBib3R0b21zID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmVsczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBlbCA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB0b3BzLnB1c2gocmVjdC50b3AgLSBvcmlnaW5DbGllbnRUb3ApO1xuICAgICAgICAgICAgYm90dG9tcy5wdXNoKHJlY3QuYm90dG9tIC0gb3JpZ2luQ2xpZW50VG9wKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRvcHMgPSB0b3BzO1xuICAgICAgICB0aGlzLmJvdHRvbXMgPSBib3R0b21zO1xuICAgIH07XG4gICAgLy8gR2l2ZW4gYSBsZWZ0IG9mZnNldCAoZnJvbSBkb2N1bWVudCBsZWZ0KSwgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGVsIHRoYXQgaXQgaG9yaXpvbnRhbGx5IGludGVyc2VjdHMuXG4gICAgLy8gSWYgbm8gaW50ZXJzZWN0aW9uIGlzIG1hZGUsIHJldHVybnMgdW5kZWZpbmVkLlxuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmxlZnRUb0luZGV4ID0gZnVuY3Rpb24gKGxlZnRQb3NpdGlvbikge1xuICAgICAgICB2YXIgbGVmdHMgPSB0aGlzLmxlZnRzO1xuICAgICAgICB2YXIgcmlnaHRzID0gdGhpcy5yaWdodHM7XG4gICAgICAgIHZhciBsZW4gPSBsZWZ0cy5sZW5ndGg7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChsZWZ0UG9zaXRpb24gPj0gbGVmdHNbaV0gJiYgbGVmdFBvc2l0aW9uIDwgcmlnaHRzW2ldKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgdG9wIG9mZnNldCAoZnJvbSBkb2N1bWVudCB0b3ApLCByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZWwgdGhhdCBpdCB2ZXJ0aWNhbGx5IGludGVyc2VjdHMuXG4gICAgLy8gSWYgbm8gaW50ZXJzZWN0aW9uIGlzIG1hZGUsIHJldHVybnMgdW5kZWZpbmVkLlxuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLnRvcFRvSW5kZXggPSBmdW5jdGlvbiAodG9wUG9zaXRpb24pIHtcbiAgICAgICAgdmFyIHRvcHMgPSB0aGlzLnRvcHM7XG4gICAgICAgIHZhciBib3R0b21zID0gdGhpcy5ib3R0b21zO1xuICAgICAgICB2YXIgbGVuID0gdG9wcy5sZW5ndGg7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0b3BQb3NpdGlvbiA+PSB0b3BzW2ldICYmIHRvcFBvc2l0aW9uIDwgYm90dG9tc1tpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgZWxlbWVudCBhdCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICBQb3NpdGlvbkNhY2hlLnByb3RvdHlwZS5nZXRXaWR0aCA9IGZ1bmN0aW9uIChsZWZ0SW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmlnaHRzW2xlZnRJbmRleF0gLSB0aGlzLmxlZnRzW2xlZnRJbmRleF07XG4gICAgfTtcbiAgICAvLyBHZXRzIHRoZSBoZWlnaHQgb2YgdGhlIGVsZW1lbnQgYXQgdGhlIGdpdmVuIGluZGV4XG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuZ2V0SGVpZ2h0ID0gZnVuY3Rpb24gKHRvcEluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvdHRvbXNbdG9wSW5kZXhdIC0gdGhpcy50b3BzW3RvcEluZGV4XTtcbiAgICB9O1xuICAgIHJldHVybiBQb3NpdGlvbkNhY2hlO1xufSgpKTtcblxuLypcbkFuIG9iamVjdCBmb3IgZ2V0dGluZy9zZXR0aW5nIHNjcm9sbC1yZWxhdGVkIGluZm9ybWF0aW9uIGZvciBhbiBlbGVtZW50LlxuSW50ZXJuYWxseSwgdGhpcyBpcyBkb25lIHZlcnkgZGlmZmVyZW50bHkgZm9yIHdpbmRvdyB2ZXJzdXMgRE9NIGVsZW1lbnQsXG5zbyB0aGlzIG9iamVjdCBzZXJ2ZXMgYXMgYSBjb21tb24gaW50ZXJmYWNlLlxuKi9cbnZhciBTY3JvbGxDb250cm9sbGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNjcm9sbENvbnRyb2xsZXIoKSB7XG4gICAgfVxuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldE1heFNjcm9sbFRvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KCkgLSB0aGlzLmdldENsaWVudEhlaWdodCgpO1xuICAgIH07XG4gICAgU2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0TWF4U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsV2lkdGgoKSAtIHRoaXMuZ2V0Q2xpZW50V2lkdGgoKTtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbFZlcnRpY2FsbHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE1heFNjcm9sbFRvcCgpID4gMDtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbEhvcml6b250YWxseSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWF4U2Nyb2xsTGVmdCgpID4gMDtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbFVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxUb3AoKSA+IDA7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxUb3AoKSA8IHRoaXMuZ2V0TWF4U2Nyb2xsVG9wKCk7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxMZWZ0KCkgPiAwO1xuICAgIH07XG4gICAgU2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuY2FuU2Nyb2xsUmlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFNjcm9sbExlZnQoKSA8IHRoaXMuZ2V0TWF4U2Nyb2xsTGVmdCgpO1xuICAgIH07XG4gICAgcmV0dXJuIFNjcm9sbENvbnRyb2xsZXI7XG59KCkpO1xudmFyIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhFbGVtZW50U2Nyb2xsQ29udHJvbGxlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbGVtZW50U2Nyb2xsQ29udHJvbGxlcihlbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbCA9IGVsO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbFRvcDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5zY3JvbGxMZWZ0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLnNldFNjcm9sbFRvcCA9IGZ1bmN0aW9uICh0b3ApIHtcbiAgICAgICAgdGhpcy5lbC5zY3JvbGxUb3AgPSB0b3A7XG4gICAgfTtcbiAgICBFbGVtZW50U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uIChsZWZ0KSB7XG4gICAgICAgIHRoaXMuZWwuc2Nyb2xsTGVmdCA9IGxlZnQ7XG4gICAgfTtcbiAgICBFbGVtZW50U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbFdpZHRoO1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuc2Nyb2xsSGVpZ2h0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldENsaWVudEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuY2xpZW50SGVpZ2h0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldENsaWVudFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5jbGllbnRXaWR0aDtcbiAgICB9O1xuICAgIHJldHVybiBFbGVtZW50U2Nyb2xsQ29udHJvbGxlcjtcbn0oU2Nyb2xsQ29udHJvbGxlcikpO1xudmFyIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFdpbmRvd1Njcm9sbENvbnRyb2xsZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gV2luZG93U2Nyb2xsQ29udHJvbGxlcigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cucGFnZVlPZmZzZXQ7XG4gICAgfTtcbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnBhZ2VYT2Zmc2V0O1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuc2V0U2Nyb2xsVG9wID0gZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgd2luZG93LnNjcm9sbCh3aW5kb3cucGFnZVhPZmZzZXQsIG4pO1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uIChuKSB7XG4gICAgICAgIHdpbmRvdy5zY3JvbGwobiwgd2luZG93LnBhZ2VZT2Zmc2V0KTtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNjcm9sbFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFdpZHRoO1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldENsaWVudEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgfTtcbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDbGllbnRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aDtcbiAgICB9O1xuICAgIHJldHVybiBXaW5kb3dTY3JvbGxDb250cm9sbGVyO1xufShTY3JvbGxDb250cm9sbGVyKSk7XG5cbi8qXG5FbWJvZGllcyBhIGRpdiB0aGF0IGhhcyBwb3RlbnRpYWwgc2Nyb2xsYmFyc1xuKi9cbnZhciBTY3JvbGxDb21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNjcm9sbENvbXBvbmVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTY3JvbGxDb21wb25lbnQob3ZlcmZsb3dYLCBvdmVyZmxvd1kpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY3JlYXRlRWxlbWVudCgnZGl2Jywge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnZmMtc2Nyb2xsZXInXG4gICAgICAgIH0pKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5vdmVyZmxvd1ggPSBvdmVyZmxvd1g7XG4gICAgICAgIF90aGlzLm92ZXJmbG93WSA9IG92ZXJmbG93WTtcbiAgICAgICAgX3RoaXMuYXBwbHlPdmVyZmxvdygpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIC8vIHNldHMgdG8gbmF0dXJhbCBoZWlnaHQsIHVubG9ja3Mgb3ZlcmZsb3dcbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldEhlaWdodCgnYXV0bycpO1xuICAgICAgICB0aGlzLmFwcGx5T3ZlcmZsb3coKTtcbiAgICB9O1xuICAgIFNjcm9sbENvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmVsKTtcbiAgICB9O1xuICAgIC8vIE92ZXJmbG93XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmFwcGx5T3ZlcmZsb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFwcGx5U3R5bGUodGhpcy5lbCwge1xuICAgICAgICAgICAgb3ZlcmZsb3dYOiB0aGlzLm92ZXJmbG93WCxcbiAgICAgICAgICAgIG92ZXJmbG93WTogdGhpcy5vdmVyZmxvd1lcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBDYXVzZXMgYW55ICdhdXRvJyBvdmVyZmxvdyB2YWx1ZXMgdG8gcmVzb2x2ZXMgdG8gJ3Njcm9sbCcgb3IgJ2hpZGRlbicuXG4gICAgLy8gVXNlZnVsIGZvciBwcmVzZXJ2aW5nIHNjcm9sbGJhciB3aWR0aHMgcmVnYXJkbGVzcyBvZiBmdXR1cmUgcmVzaXplcy5cbiAgICAvLyBDYW4gcGFzcyBpbiBzY3JvbGxiYXJXaWR0aHMgZm9yIG9wdGltaXphdGlvbi5cbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmxvY2tPdmVyZmxvdyA9IGZ1bmN0aW9uIChzY3JvbGxiYXJXaWR0aHMpIHtcbiAgICAgICAgdmFyIG92ZXJmbG93WCA9IHRoaXMub3ZlcmZsb3dYO1xuICAgICAgICB2YXIgb3ZlcmZsb3dZID0gdGhpcy5vdmVyZmxvd1k7XG4gICAgICAgIHNjcm9sbGJhcldpZHRocyA9IHNjcm9sbGJhcldpZHRocyB8fCB0aGlzLmdldFNjcm9sbGJhcldpZHRocygpO1xuICAgICAgICBpZiAob3ZlcmZsb3dYID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIG92ZXJmbG93WCA9IChzY3JvbGxiYXJXaWR0aHMuYm90dG9tIHx8IC8vIGhvcml6b250YWwgc2Nyb2xsYmFycz9cbiAgICAgICAgICAgICAgICB0aGlzLmNhblNjcm9sbEhvcml6b250YWxseSgpIC8vIE9SIHNjcm9sbGluZyBwYW5lIHdpdGggbWFzc2xlc3Mgc2Nyb2xsYmFycz9cbiAgICAgICAgICAgICkgPyAnc2Nyb2xsJyA6ICdoaWRkZW4nO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvdmVyZmxvd1kgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgb3ZlcmZsb3dZID0gKHNjcm9sbGJhcldpZHRocy5sZWZ0IHx8IHNjcm9sbGJhcldpZHRocy5yaWdodCB8fCAvLyBob3Jpem9udGFsIHNjcm9sbGJhcnM/XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5TY3JvbGxWZXJ0aWNhbGx5KCkgLy8gT1Igc2Nyb2xsaW5nIHBhbmUgd2l0aCBtYXNzbGVzcyBzY3JvbGxiYXJzP1xuICAgICAgICAgICAgKSA/ICdzY3JvbGwnIDogJ2hpZGRlbic7XG4gICAgICAgIH1cbiAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmVsLCB7IG92ZXJmbG93WDogb3ZlcmZsb3dYLCBvdmVyZmxvd1k6IG92ZXJmbG93WSB9KTtcbiAgICB9O1xuICAgIFNjcm9sbENvbXBvbmVudC5wcm90b3R5cGUuc2V0SGVpZ2h0ID0gZnVuY3Rpb24gKGhlaWdodCkge1xuICAgICAgICBhcHBseVN0eWxlUHJvcCh0aGlzLmVsLCAnaGVpZ2h0JywgaGVpZ2h0KTtcbiAgICB9O1xuICAgIFNjcm9sbENvbXBvbmVudC5wcm90b3R5cGUuZ2V0U2Nyb2xsYmFyV2lkdGhzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZWRnZXMgPSBjb21wdXRlRWRnZXModGhpcy5lbCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsZWZ0OiBlZGdlcy5zY3JvbGxiYXJMZWZ0LFxuICAgICAgICAgICAgcmlnaHQ6IGVkZ2VzLnNjcm9sbGJhclJpZ2h0LFxuICAgICAgICAgICAgYm90dG9tOiBlZGdlcy5zY3JvbGxiYXJCb3R0b21cbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBTY3JvbGxDb21wb25lbnQ7XG59KEVsZW1lbnRTY3JvbGxDb250cm9sbGVyKSk7XG5cbnZhciBUaGVtZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUaGVtZShjYWxlbmRhck9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhck9wdGlvbnMgPSBjYWxlbmRhck9wdGlvbnM7XG4gICAgICAgIHRoaXMucHJvY2Vzc0ljb25PdmVycmlkZSgpO1xuICAgIH1cbiAgICBUaGVtZS5wcm90b3R5cGUucHJvY2Vzc0ljb25PdmVycmlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWNvbk92ZXJyaWRlT3B0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnNldEljb25PdmVycmlkZSh0aGlzLmNhbGVuZGFyT3B0aW9uc1t0aGlzLmljb25PdmVycmlkZU9wdGlvbl0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUaGVtZS5wcm90b3R5cGUuc2V0SWNvbk92ZXJyaWRlID0gZnVuY3Rpb24gKGljb25PdmVycmlkZUhhc2gpIHtcbiAgICAgICAgdmFyIGljb25DbGFzc2VzQ29weTtcbiAgICAgICAgdmFyIGJ1dHRvbk5hbWU7XG4gICAgICAgIGlmICh0eXBlb2YgaWNvbk92ZXJyaWRlSGFzaCA9PT0gJ29iamVjdCcgJiYgaWNvbk92ZXJyaWRlSGFzaCkgeyAvLyBub24tbnVsbCBvYmplY3RcbiAgICAgICAgICAgIGljb25DbGFzc2VzQ29weSA9IF9fYXNzaWduKHt9LCB0aGlzLmljb25DbGFzc2VzKTtcbiAgICAgICAgICAgIGZvciAoYnV0dG9uTmFtZSBpbiBpY29uT3ZlcnJpZGVIYXNoKSB7XG4gICAgICAgICAgICAgICAgaWNvbkNsYXNzZXNDb3B5W2J1dHRvbk5hbWVdID0gdGhpcy5hcHBseUljb25PdmVycmlkZVByZWZpeChpY29uT3ZlcnJpZGVIYXNoW2J1dHRvbk5hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaWNvbkNsYXNzZXMgPSBpY29uQ2xhc3Nlc0NvcHk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaWNvbk92ZXJyaWRlSGFzaCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMuaWNvbkNsYXNzZXMgPSB7fTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVGhlbWUucHJvdG90eXBlLmFwcGx5SWNvbk92ZXJyaWRlUHJlZml4ID0gZnVuY3Rpb24gKGNsYXNzTmFtZSkge1xuICAgICAgICB2YXIgcHJlZml4ID0gdGhpcy5pY29uT3ZlcnJpZGVQcmVmaXg7XG4gICAgICAgIGlmIChwcmVmaXggJiYgY2xhc3NOYW1lLmluZGV4T2YocHJlZml4KSAhPT0gMCkgeyAvLyBpZiBub3QgYWxyZWFkeSBwcmVzZW50XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBwcmVmaXggKyBjbGFzc05hbWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNsYXNzTmFtZTtcbiAgICB9O1xuICAgIFRoZW1lLnByb3RvdHlwZS5nZXRDbGFzcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xhc3Nlc1trZXldIHx8ICcnO1xuICAgIH07XG4gICAgVGhlbWUucHJvdG90eXBlLmdldEljb25DbGFzcyA9IGZ1bmN0aW9uIChidXR0b25OYW1lKSB7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSB0aGlzLmljb25DbGFzc2VzW2J1dHRvbk5hbWVdO1xuICAgICAgICBpZiAoY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iYXNlSWNvbkNsYXNzICsgJyAnICsgY2xhc3NOYW1lO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuICAgIFRoZW1lLnByb3RvdHlwZS5nZXRDdXN0b21CdXR0b25JY29uQ2xhc3MgPSBmdW5jdGlvbiAoY3VzdG9tQnV0dG9uUHJvcHMpIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZTtcbiAgICAgICAgaWYgKHRoaXMuaWNvbk92ZXJyaWRlQ3VzdG9tQnV0dG9uT3B0aW9uKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBjdXN0b21CdXR0b25Qcm9wc1t0aGlzLmljb25PdmVycmlkZUN1c3RvbUJ1dHRvbk9wdGlvbl07XG4gICAgICAgICAgICBpZiAoY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmFzZUljb25DbGFzcyArICcgJyArIHRoaXMuYXBwbHlJY29uT3ZlcnJpZGVQcmVmaXgoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfTtcbiAgICByZXR1cm4gVGhlbWU7XG59KCkpO1xuVGhlbWUucHJvdG90eXBlLmNsYXNzZXMgPSB7fTtcblRoZW1lLnByb3RvdHlwZS5pY29uQ2xhc3NlcyA9IHt9O1xuVGhlbWUucHJvdG90eXBlLmJhc2VJY29uQ2xhc3MgPSAnJztcblRoZW1lLnByb3RvdHlwZS5pY29uT3ZlcnJpZGVQcmVmaXggPSAnJztcblxudmFyIGd1aWQgPSAwO1xudmFyIENvbXBvbmVudENvbnRleHQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29tcG9uZW50Q29udGV4dChjYWxlbmRhciwgdGhlbWUsIGRhdGVFbnYsIG9wdGlvbnMsIHZpZXcpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLnRoZW1lID0gdGhlbWU7XG4gICAgICAgIHRoaXMuZGF0ZUVudiA9IGRhdGVFbnY7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIHRoaXMudmlldyA9IHZpZXc7XG4gICAgICAgIHRoaXMuaXNSdGwgPSBvcHRpb25zLmRpciA9PT0gJ3J0bCc7XG4gICAgICAgIHRoaXMuZXZlbnRPcmRlclNwZWNzID0gcGFyc2VGaWVsZFNwZWNzKG9wdGlvbnMuZXZlbnRPcmRlcik7XG4gICAgICAgIHRoaXMubmV4dERheVRocmVzaG9sZCA9IGNyZWF0ZUR1cmF0aW9uKG9wdGlvbnMubmV4dERheVRocmVzaG9sZCk7XG4gICAgfVxuICAgIENvbXBvbmVudENvbnRleHQucHJvdG90eXBlLmV4dGVuZCA9IGZ1bmN0aW9uIChvcHRpb25zLCB2aWV3KSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29tcG9uZW50Q29udGV4dCh0aGlzLmNhbGVuZGFyLCB0aGlzLnRoZW1lLCB0aGlzLmRhdGVFbnYsIG9wdGlvbnMgfHwgdGhpcy5vcHRpb25zLCB2aWV3IHx8IHRoaXMudmlldyk7XG4gICAgfTtcbiAgICByZXR1cm4gQ29tcG9uZW50Q29udGV4dDtcbn0oKSk7XG52YXIgQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgICAgICAgdGhpcy5ldmVyUmVuZGVyZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy51aWQgPSBTdHJpbmcoZ3VpZCsrKTtcbiAgICB9XG4gICAgQ29tcG9uZW50LmFkZEVxdWFsaXR5RnVuY3MgPSBmdW5jdGlvbiAobmV3RnVuY3MpIHtcbiAgICAgICAgdGhpcy5wcm90b3R5cGUuZXF1YWxpdHlGdW5jcyA9IF9fYXNzaWduKHt9LCB0aGlzLnByb3RvdHlwZS5lcXVhbGl0eUZ1bmNzLCBuZXdGdW5jcyk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnJlY2VpdmVQcm9wcyA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgICAgICB0aGlzLnJlY2VpdmVDb250ZXh0KGNvbnRleHQpO1xuICAgICAgICB2YXIgX2EgPSByZWN5Y2xlUHJvcHModGhpcy5wcm9wcyB8fCB7fSwgcHJvcHMsIHRoaXMuZXF1YWxpdHlGdW5jcyksIGFueUNoYW5nZXMgPSBfYS5hbnlDaGFuZ2VzLCBjb21ib1Byb3BzID0gX2EuY29tYm9Qcm9wcztcbiAgICAgICAgdGhpcy5wcm9wcyA9IGNvbWJvUHJvcHM7XG4gICAgICAgIGlmIChhbnlDaGFuZ2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVyUmVuZGVyZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJlZm9yZVVwZGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZW5kZXIoY29tYm9Qcm9wcywgY29udGV4dCk7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVyUmVuZGVyZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFmdGVyVXBkYXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmVyUmVuZGVyZWQgPSB0cnVlO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5yZWNlaXZlQ29udGV4dCA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgIHZhciBvbGRDb250ZXh0ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICBpZiAoIW9sZENvbnRleHQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyc3RDb250ZXh0KGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5maXJzdENvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5iZWZvcmVVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmFmdGVyVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgLy8gYWZ0ZXIgZGVzdHJveSBpcyBjYWxsZWQsIHRoaXMgY29tcG9uZW50IHdvbid0IGV2ZXIgYmUgdXNlZCBhZ2FpblxuICAgIENvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIHJldHVybiBDb21wb25lbnQ7XG59KCkpO1xuQ29tcG9uZW50LnByb3RvdHlwZS5lcXVhbGl0eUZ1bmNzID0ge307XG4vKlxuUmV1c2VzIG9sZCB2YWx1ZXMgd2hlbiBlcXVhbC4gSWYgYW55dGhpbmcgaXMgdW5lcXVhbCwgcmV0dXJucyBuZXdQcm9wcyBhcy1pcy5cbkdyZWF0IGZvciBQdXJlQ29tcG9uZW50LCBidXQgd29uJ3QgYmUgZmVhc2libGUgd2l0aCBSZWFjdCwgc28ganVzdCBlbGltaW5hdGUgYW5kIHVzZSBSZWFjdCdzIERPTSBkaWZmaW5nLlxuKi9cbmZ1bmN0aW9uIHJlY3ljbGVQcm9wcyhvbGRQcm9wcywgbmV3UHJvcHMsIGVxdWFsaXR5RnVuY3MpIHtcbiAgICB2YXIgY29tYm9Qcm9wcyA9IHt9OyAvLyBzb21lIG9sZCwgc29tZSBuZXdcbiAgICB2YXIgYW55Q2hhbmdlcyA9IGZhbHNlO1xuICAgIGZvciAodmFyIGtleSBpbiBuZXdQcm9wcykge1xuICAgICAgICBpZiAoa2V5IGluIG9sZFByb3BzICYmIChvbGRQcm9wc1trZXldID09PSBuZXdQcm9wc1trZXldIHx8XG4gICAgICAgICAgICAoZXF1YWxpdHlGdW5jc1trZXldICYmIGVxdWFsaXR5RnVuY3Nba2V5XShvbGRQcm9wc1trZXldLCBuZXdQcm9wc1trZXldKSkpKSB7XG4gICAgICAgICAgICAvLyBlcXVhbCB0byBvbGQ/IHVzZSBvbGQgcHJvcFxuICAgICAgICAgICAgY29tYm9Qcm9wc1trZXldID0gb2xkUHJvcHNba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbWJvUHJvcHNba2V5XSA9IG5ld1Byb3BzW2tleV07XG4gICAgICAgICAgICBhbnlDaGFuZ2VzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBrZXkgaW4gb2xkUHJvcHMpIHtcbiAgICAgICAgaWYgKCEoa2V5IGluIG5ld1Byb3BzKSkge1xuICAgICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBhbnlDaGFuZ2VzOiBhbnlDaGFuZ2VzLCBjb21ib1Byb3BzOiBjb21ib1Byb3BzIH07XG59XG5cbi8qXG5QVVJQT1NFUzpcbi0gaG9vayB1cCB0byBmZywgZmlsbCwgYW5kIG1pcnJvciByZW5kZXJlcnNcbi0gaW50ZXJmYWNlIGZvciBkcmFnZ2luZyBhbmQgaGl0c1xuKi9cbnZhciBEYXRlQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXRlQ29tcG9uZW50LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERhdGVDb21wb25lbnQoZWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZWwgPSBlbDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmVsKTtcbiAgICB9O1xuICAgIC8vIEhpdCBTeXN0ZW1cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmJ1aWxkUG9zaXRpb25DYWNoZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5xdWVyeUhpdCA9IGZ1bmN0aW9uIChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wLCBlbFdpZHRoLCBlbEhlaWdodCkge1xuICAgICAgICByZXR1cm4gbnVsbDsgLy8gdGhpcyBzaG91bGQgYmUgYWJzdHJhY3RcbiAgICB9O1xuICAgIC8vIFZhbGlkYXRpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzSW50ZXJhY3Rpb25WYWxpZCA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbikge1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzLmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBkYXRlUHJvZmlsZSA9IHRoaXMucHJvcHMuZGF0ZVByb2ZpbGU7IC8vIEhBQ0tcbiAgICAgICAgdmFyIGluc3RhbmNlcyA9IGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMuaW5zdGFuY2VzO1xuICAgICAgICBpZiAoZGF0ZVByb2ZpbGUpIHsgLy8gSEFDSyBmb3IgRGF5VGlsZVxuICAgICAgICAgICAgZm9yICh2YXIgaW5zdGFuY2VJZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXJhbmdlQ29udGFpbnNSYW5nZShkYXRlUHJvZmlsZS52YWxpZFJhbmdlLCBpbnN0YW5jZXNbaW5zdGFuY2VJZF0ucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbiwgY2FsZW5kYXIpO1xuICAgIH07XG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuaXNEYXRlU2VsZWN0aW9uVmFsaWQgPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXMuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgdmFyIGRhdGVQcm9maWxlID0gdGhpcy5wcm9wcy5kYXRlUHJvZmlsZTsgLy8gSEFDS1xuICAgICAgICBpZiAoZGF0ZVByb2ZpbGUgJiYgLy8gSEFDSyBmb3IgRGF5VGlsZVxuICAgICAgICAgICAgIXJhbmdlQ29udGFpbnNSYW5nZShkYXRlUHJvZmlsZS52YWxpZFJhbmdlLCBzZWxlY3Rpb24ucmFuZ2UpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzRGF0ZVNlbGVjdGlvblZhbGlkKHNlbGVjdGlvbiwgY2FsZW5kYXIpO1xuICAgIH07XG4gICAgLy8gUG9pbnRlciBJbnRlcmFjdGlvbiBVdGlsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuaXNWYWxpZFNlZ0Rvd25FbCA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gIXRoaXMucHJvcHMuZXZlbnREcmFnICYmIC8vIEhBQ0tcbiAgICAgICAgICAgICF0aGlzLnByb3BzLmV2ZW50UmVzaXplICYmIC8vIEhBQ0tcbiAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1taXJyb3InKSAmJlxuICAgICAgICAgICAgKHRoaXMuaXNQb3BvdmVyKCkgfHwgIXRoaXMuaXNJblBvcG92ZXIoZWwpKTtcbiAgICAgICAgLy8gXmFib3ZlIGxpbmUgZW5zdXJlcyB3ZSBkb24ndCBkZXRlY3QgYSBzZWcgaW50ZXJhY3Rpb24gd2l0aGluIGEgbmVzdGVkIGNvbXBvbmVudC5cbiAgICAgICAgLy8gaXQncyBhIEhBQ0sgYmVjYXVzZSBpdCBvbmx5IHN1cHBvcnRzIGEgcG9wb3ZlciBhcyB0aGUgbmVzdGVkIGNvbXBvbmVudC5cbiAgICB9O1xuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzVmFsaWREYXRlRG93bkVsID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBzZWdFbCA9IGVsZW1lbnRDbG9zZXN0KGVsLCB0aGlzLmZnU2VnU2VsZWN0b3IpO1xuICAgICAgICByZXR1cm4gKCFzZWdFbCB8fCBzZWdFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLW1pcnJvcicpKSAmJlxuICAgICAgICAgICAgIWVsZW1lbnRDbG9zZXN0KGVsLCAnLmZjLW1vcmUnKSAmJiAvLyBhIFwibW9yZS4uXCIgbGlua1xuICAgICAgICAgICAgIWVsZW1lbnRDbG9zZXN0KGVsLCAnYVtkYXRhLWdvdG9dJykgJiYgLy8gYSBjbGlja2FibGUgbmF2IGxpbmtcbiAgICAgICAgICAgICF0aGlzLmlzSW5Qb3BvdmVyKGVsKTtcbiAgICB9O1xuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzUG9wb3ZlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYy1wb3BvdmVyJyk7XG4gICAgfTtcbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5pc0luUG9wb3ZlciA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gQm9vbGVhbihlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1wb3BvdmVyJykpO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVDb21wb25lbnQ7XG59KENvbXBvbmVudCkpO1xuRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuZmdTZWdTZWxlY3RvciA9ICcuZmMtZXZlbnQtY29udGFpbmVyID4gKic7XG5EYXRlQ29tcG9uZW50LnByb3RvdHlwZS5iZ1NlZ1NlbGVjdG9yID0gJy5mYy1iZ2V2ZW50Om5vdCguZmMtbm9uYnVzaW5lc3MpJztcblxudmFyIHVpZCQxID0gMDtcbmZ1bmN0aW9uIGNyZWF0ZVBsdWdpbihpbnB1dCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGlkOiBTdHJpbmcodWlkJDErKyksXG4gICAgICAgIGRlcHM6IGlucHV0LmRlcHMgfHwgW10sXG4gICAgICAgIHJlZHVjZXJzOiBpbnB1dC5yZWR1Y2VycyB8fCBbXSxcbiAgICAgICAgZXZlbnREZWZQYXJzZXJzOiBpbnB1dC5ldmVudERlZlBhcnNlcnMgfHwgW10sXG4gICAgICAgIGlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzOiBpbnB1dC5pc0RyYWdnYWJsZVRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnM6IGlucHV0LmV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzIHx8IFtdLFxuICAgICAgICBldmVudERlZk11dGF0aW9uQXBwbGllcnM6IGlucHV0LmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycyB8fCBbXSxcbiAgICAgICAgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyczogaW5wdXQuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgZGF0ZVBvaW50VHJhbnNmb3JtczogaW5wdXQuZGF0ZVBvaW50VHJhbnNmb3JtcyB8fCBbXSxcbiAgICAgICAgZGF0ZVNwYW5UcmFuc2Zvcm1zOiBpbnB1dC5kYXRlU3BhblRyYW5zZm9ybXMgfHwgW10sXG4gICAgICAgIHZpZXdzOiBpbnB1dC52aWV3cyB8fCB7fSxcbiAgICAgICAgdmlld1Byb3BzVHJhbnNmb3JtZXJzOiBpbnB1dC52aWV3UHJvcHNUcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGlzUHJvcHNWYWxpZDogaW5wdXQuaXNQcm9wc1ZhbGlkIHx8IG51bGwsXG4gICAgICAgIGV4dGVybmFsRGVmVHJhbnNmb3JtczogaW5wdXQuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zIHx8IFtdLFxuICAgICAgICBldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zOiBpbnB1dC5ldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zIHx8IFtdLFxuICAgICAgICB2aWV3Q29udGFpbmVyTW9kaWZpZXJzOiBpbnB1dC52aWV3Q29udGFpbmVyTW9kaWZpZXJzIHx8IFtdLFxuICAgICAgICBldmVudERyb3BUcmFuc2Zvcm1lcnM6IGlucHV0LmV2ZW50RHJvcFRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgY29tcG9uZW50SW50ZXJhY3Rpb25zOiBpbnB1dC5jb21wb25lbnRJbnRlcmFjdGlvbnMgfHwgW10sXG4gICAgICAgIGNhbGVuZGFySW50ZXJhY3Rpb25zOiBpbnB1dC5jYWxlbmRhckludGVyYWN0aW9ucyB8fCBbXSxcbiAgICAgICAgdGhlbWVDbGFzc2VzOiBpbnB1dC50aGVtZUNsYXNzZXMgfHwge30sXG4gICAgICAgIGV2ZW50U291cmNlRGVmczogaW5wdXQuZXZlbnRTb3VyY2VEZWZzIHx8IFtdLFxuICAgICAgICBjbWRGb3JtYXR0ZXI6IGlucHV0LmNtZEZvcm1hdHRlcixcbiAgICAgICAgcmVjdXJyaW5nVHlwZXM6IGlucHV0LnJlY3VycmluZ1R5cGVzIHx8IFtdLFxuICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IGlucHV0Lm5hbWVkVGltZVpvbmVkSW1wbCxcbiAgICAgICAgZGVmYXVsdFZpZXc6IGlucHV0LmRlZmF1bHRWaWV3IHx8ICcnLFxuICAgICAgICBlbGVtZW50RHJhZ2dpbmdJbXBsOiBpbnB1dC5lbGVtZW50RHJhZ2dpbmdJbXBsLFxuICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczogaW5wdXQub3B0aW9uQ2hhbmdlSGFuZGxlcnMgfHwge31cbiAgICB9O1xufVxudmFyIFBsdWdpblN5c3RlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQbHVnaW5TeXN0ZW0oKSB7XG4gICAgICAgIHRoaXMuaG9va3MgPSB7XG4gICAgICAgICAgICByZWR1Y2VyczogW10sXG4gICAgICAgICAgICBldmVudERlZlBhcnNlcnM6IFtdLFxuICAgICAgICAgICAgaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzOiBbXSxcbiAgICAgICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IFtdLFxuICAgICAgICAgICAgZGF0ZVBvaW50VHJhbnNmb3JtczogW10sXG4gICAgICAgICAgICBkYXRlU3BhblRyYW5zZm9ybXM6IFtdLFxuICAgICAgICAgICAgdmlld3M6IHt9LFxuICAgICAgICAgICAgdmlld1Byb3BzVHJhbnNmb3JtZXJzOiBbXSxcbiAgICAgICAgICAgIGlzUHJvcHNWYWxpZDogbnVsbCxcbiAgICAgICAgICAgIGV4dGVybmFsRGVmVHJhbnNmb3JtczogW10sXG4gICAgICAgICAgICBldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zOiBbXSxcbiAgICAgICAgICAgIHZpZXdDb250YWluZXJNb2RpZmllcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREcm9wVHJhbnNmb3JtZXJzOiBbXSxcbiAgICAgICAgICAgIGNvbXBvbmVudEludGVyYWN0aW9uczogW10sXG4gICAgICAgICAgICBjYWxlbmRhckludGVyYWN0aW9uczogW10sXG4gICAgICAgICAgICB0aGVtZUNsYXNzZXM6IHt9LFxuICAgICAgICAgICAgZXZlbnRTb3VyY2VEZWZzOiBbXSxcbiAgICAgICAgICAgIGNtZEZvcm1hdHRlcjogbnVsbCxcbiAgICAgICAgICAgIHJlY3VycmluZ1R5cGVzOiBbXSxcbiAgICAgICAgICAgIG5hbWVkVGltZVpvbmVkSW1wbDogbnVsbCxcbiAgICAgICAgICAgIGRlZmF1bHRWaWV3OiAnJyxcbiAgICAgICAgICAgIGVsZW1lbnREcmFnZ2luZ0ltcGw6IG51bGwsXG4gICAgICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczoge31cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRlZEhhc2ggPSB7fTtcbiAgICB9XG4gICAgUGx1Z2luU3lzdGVtLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAocGx1Z2luKSB7XG4gICAgICAgIGlmICghdGhpcy5hZGRlZEhhc2hbcGx1Z2luLmlkXSkge1xuICAgICAgICAgICAgdGhpcy5hZGRlZEhhc2hbcGx1Z2luLmlkXSA9IHRydWU7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gcGx1Z2luLmRlcHM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRlcCA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZChkZXApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5ob29rcyA9IGNvbWJpbmVIb29rcyh0aGlzLmhvb2tzLCBwbHVnaW4pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gUGx1Z2luU3lzdGVtO1xufSgpKTtcbmZ1bmN0aW9uIGNvbWJpbmVIb29rcyhob29rczAsIGhvb2tzMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHJlZHVjZXJzOiBob29rczAucmVkdWNlcnMuY29uY2F0KGhvb2tzMS5yZWR1Y2VycyksXG4gICAgICAgIGV2ZW50RGVmUGFyc2VyczogaG9va3MwLmV2ZW50RGVmUGFyc2Vycy5jb25jYXQoaG9va3MxLmV2ZW50RGVmUGFyc2VycyksXG4gICAgICAgIGlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzOiBob29rczAuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnMuY29uY2F0KGhvb2tzMS5pc0RyYWdnYWJsZVRyYW5zZm9ybWVycyksXG4gICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBob29rczAuZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnMuY29uY2F0KGhvb2tzMS5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2VycyksXG4gICAgICAgIGV2ZW50RGVmTXV0YXRpb25BcHBsaWVyczogaG9va3MwLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycy5jb25jYXQoaG9va3MxLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycyksXG4gICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IGhvb2tzMC5kYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyksXG4gICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IGhvb2tzMC5kYXRlUG9pbnRUcmFuc2Zvcm1zLmNvbmNhdChob29rczEuZGF0ZVBvaW50VHJhbnNmb3JtcyksXG4gICAgICAgIGRhdGVTcGFuVHJhbnNmb3JtczogaG9va3MwLmRhdGVTcGFuVHJhbnNmb3Jtcy5jb25jYXQoaG9va3MxLmRhdGVTcGFuVHJhbnNmb3JtcyksXG4gICAgICAgIHZpZXdzOiBfX2Fzc2lnbih7fSwgaG9va3MwLnZpZXdzLCBob29rczEudmlld3MpLFxuICAgICAgICB2aWV3UHJvcHNUcmFuc2Zvcm1lcnM6IGhvb2tzMC52aWV3UHJvcHNUcmFuc2Zvcm1lcnMuY29uY2F0KGhvb2tzMS52aWV3UHJvcHNUcmFuc2Zvcm1lcnMpLFxuICAgICAgICBpc1Byb3BzVmFsaWQ6IGhvb2tzMS5pc1Byb3BzVmFsaWQgfHwgaG9va3MwLmlzUHJvcHNWYWxpZCxcbiAgICAgICAgZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zOiBob29rczAuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zLmNvbmNhdChob29rczEuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zKSxcbiAgICAgICAgZXZlbnRSZXNpemVKb2luVHJhbnNmb3JtczogaG9va3MwLmV2ZW50UmVzaXplSm9pblRyYW5zZm9ybXMuY29uY2F0KGhvb2tzMS5ldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zKSxcbiAgICAgICAgdmlld0NvbnRhaW5lck1vZGlmaWVyczogaG9va3MwLnZpZXdDb250YWluZXJNb2RpZmllcnMuY29uY2F0KGhvb2tzMS52aWV3Q29udGFpbmVyTW9kaWZpZXJzKSxcbiAgICAgICAgZXZlbnREcm9wVHJhbnNmb3JtZXJzOiBob29rczAuZXZlbnREcm9wVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEuZXZlbnREcm9wVHJhbnNmb3JtZXJzKSxcbiAgICAgICAgY2FsZW5kYXJJbnRlcmFjdGlvbnM6IGhvb2tzMC5jYWxlbmRhckludGVyYWN0aW9ucy5jb25jYXQoaG9va3MxLmNhbGVuZGFySW50ZXJhY3Rpb25zKSxcbiAgICAgICAgY29tcG9uZW50SW50ZXJhY3Rpb25zOiBob29rczAuY29tcG9uZW50SW50ZXJhY3Rpb25zLmNvbmNhdChob29rczEuY29tcG9uZW50SW50ZXJhY3Rpb25zKSxcbiAgICAgICAgdGhlbWVDbGFzc2VzOiBfX2Fzc2lnbih7fSwgaG9va3MwLnRoZW1lQ2xhc3NlcywgaG9va3MxLnRoZW1lQ2xhc3NlcyksXG4gICAgICAgIGV2ZW50U291cmNlRGVmczogaG9va3MwLmV2ZW50U291cmNlRGVmcy5jb25jYXQoaG9va3MxLmV2ZW50U291cmNlRGVmcyksXG4gICAgICAgIGNtZEZvcm1hdHRlcjogaG9va3MxLmNtZEZvcm1hdHRlciB8fCBob29rczAuY21kRm9ybWF0dGVyLFxuICAgICAgICByZWN1cnJpbmdUeXBlczogaG9va3MwLnJlY3VycmluZ1R5cGVzLmNvbmNhdChob29rczEucmVjdXJyaW5nVHlwZXMpLFxuICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IGhvb2tzMS5uYW1lZFRpbWVab25lZEltcGwgfHwgaG9va3MwLm5hbWVkVGltZVpvbmVkSW1wbCxcbiAgICAgICAgZGVmYXVsdFZpZXc6IGhvb2tzMC5kZWZhdWx0VmlldyB8fCBob29rczEuZGVmYXVsdFZpZXcsXG4gICAgICAgIGVsZW1lbnREcmFnZ2luZ0ltcGw6IGhvb2tzMC5lbGVtZW50RHJhZ2dpbmdJbXBsIHx8IGhvb2tzMS5lbGVtZW50RHJhZ2dpbmdJbXBsLFxuICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczogX19hc3NpZ24oe30sIGhvb2tzMC5vcHRpb25DaGFuZ2VIYW5kbGVycywgaG9va3MxLm9wdGlvbkNoYW5nZUhhbmRsZXJzKVxuICAgIH07XG59XG5cbnZhciBldmVudFNvdXJjZURlZiA9IHtcbiAgICBpZ25vcmVSYW5nZTogdHJ1ZSxcbiAgICBwYXJzZU1ldGE6IGZ1bmN0aW9uIChyYXcpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmF3KSkgeyAvLyBzaG9ydCBmb3JtXG4gICAgICAgICAgICByZXR1cm4gcmF3O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocmF3LmV2ZW50cykpIHtcbiAgICAgICAgICAgIHJldHVybiByYXcuZXZlbnRzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgZmV0Y2g6IGZ1bmN0aW9uIChhcmcsIHN1Y2Nlc3MpIHtcbiAgICAgICAgc3VjY2Vzcyh7XG4gICAgICAgICAgICByYXdFdmVudHM6IGFyZy5ldmVudFNvdXJjZS5tZXRhXG4gICAgICAgIH0pO1xuICAgIH1cbn07XG52YXIgQXJyYXlFdmVudFNvdXJjZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgZXZlbnRTb3VyY2VEZWZzOiBbZXZlbnRTb3VyY2VEZWZdXG59KTtcblxudmFyIGV2ZW50U291cmNlRGVmJDEgPSB7XG4gICAgcGFyc2VNZXRhOiBmdW5jdGlvbiAocmF3KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmF3ID09PSAnZnVuY3Rpb24nKSB7IC8vIHNob3J0IGZvcm1cbiAgICAgICAgICAgIHJldHVybiByYXc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHJhdy5ldmVudHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiByYXcuZXZlbnRzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgZmV0Y2g6IGZ1bmN0aW9uIChhcmcsIHN1Y2Nlc3MsIGZhaWx1cmUpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSBhcmcuY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdmFyIGZ1bmMgPSBhcmcuZXZlbnRTb3VyY2UubWV0YTtcbiAgICAgICAgdW5wcm9taXNpZnkoZnVuYy5iaW5kKG51bGwsIHtcbiAgICAgICAgICAgIHN0YXJ0OiBkYXRlRW52LnRvRGF0ZShhcmcucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kOiBkYXRlRW52LnRvRGF0ZShhcmcucmFuZ2UuZW5kKSxcbiAgICAgICAgICAgIHN0YXJ0U3RyOiBkYXRlRW52LmZvcm1hdElzbyhhcmcucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kU3RyOiBkYXRlRW52LmZvcm1hdElzbyhhcmcucmFuZ2UuZW5kKSxcbiAgICAgICAgICAgIHRpbWVab25lOiBkYXRlRW52LnRpbWVab25lXG4gICAgICAgIH0pLCBmdW5jdGlvbiAocmF3RXZlbnRzKSB7XG4gICAgICAgICAgICBzdWNjZXNzKHsgcmF3RXZlbnRzOiByYXdFdmVudHMgfSk7IC8vIG5lZWRzIGFuIG9iamVjdCByZXNwb25zZVxuICAgICAgICB9LCBmYWlsdXJlIC8vIHNlbmQgZXJyb3JPYmogZGlyZWN0bHkgdG8gZmFpbHVyZSBjYWxsYmFja1xuICAgICAgICApO1xuICAgIH1cbn07XG52YXIgRnVuY0V2ZW50U291cmNlUGx1Z2luID0gY3JlYXRlUGx1Z2luKHtcbiAgICBldmVudFNvdXJjZURlZnM6IFtldmVudFNvdXJjZURlZiQxXVxufSk7XG5cbmZ1bmN0aW9uIHJlcXVlc3RKc29uKG1ldGhvZCwgdXJsLCBwYXJhbXMsIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgbWV0aG9kID0gbWV0aG9kLnRvVXBwZXJDYXNlKCk7XG4gICAgdmFyIGJvZHkgPSBudWxsO1xuICAgIGlmIChtZXRob2QgPT09ICdHRVQnKSB7XG4gICAgICAgIHVybCA9IGluamVjdFF1ZXJ5U3RyaW5nUGFyYW1zKHVybCwgcGFyYW1zKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGJvZHkgPSBlbmNvZGVQYXJhbXMocGFyYW1zKTtcbiAgICB9XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKG1ldGhvZCwgdXJsLCB0cnVlKTtcbiAgICBpZiAobWV0aG9kICE9PSAnR0VUJykge1xuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpO1xuICAgIH1cbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDQwMCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gSlNPTi5wYXJzZSh4aHIucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2socmVzLCB4aHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjaygnRmFpbHVyZSBwYXJzaW5nIEpTT04nLCB4aHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZmFpbHVyZUNhbGxiYWNrKCdSZXF1ZXN0IGZhaWxlZCcsIHhocik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmYWlsdXJlQ2FsbGJhY2soJ1JlcXVlc3QgZmFpbGVkJywgeGhyKTtcbiAgICB9O1xuICAgIHhoci5zZW5kKGJvZHkpO1xufVxuZnVuY3Rpb24gaW5qZWN0UXVlcnlTdHJpbmdQYXJhbXModXJsLCBwYXJhbXMpIHtcbiAgICByZXR1cm4gdXJsICtcbiAgICAgICAgKHVybC5pbmRleE9mKCc/JykgPT09IC0xID8gJz8nIDogJyYnKSArXG4gICAgICAgIGVuY29kZVBhcmFtcyhwYXJhbXMpO1xufVxuZnVuY3Rpb24gZW5jb2RlUGFyYW1zKHBhcmFtcykge1xuICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBwYXJhbXMpIHtcbiAgICAgICAgcGFydHMucHVzaChlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChwYXJhbXNba2V5XSkpO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHMuam9pbignJicpO1xufVxuXG52YXIgZXZlbnRTb3VyY2VEZWYkMiA9IHtcbiAgICBwYXJzZU1ldGE6IGZ1bmN0aW9uIChyYXcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7IC8vIHNob3J0IGZvcm1cbiAgICAgICAgICAgIHJhdyA9IHsgdXJsOiByYXcgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghcmF3IHx8IHR5cGVvZiByYXcgIT09ICdvYmplY3QnIHx8ICFyYXcudXJsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdXJsOiByYXcudXJsLFxuICAgICAgICAgICAgbWV0aG9kOiAocmF3Lm1ldGhvZCB8fCAnR0VUJykudG9VcHBlckNhc2UoKSxcbiAgICAgICAgICAgIGV4dHJhUGFyYW1zOiByYXcuZXh0cmFQYXJhbXMsXG4gICAgICAgICAgICBzdGFydFBhcmFtOiByYXcuc3RhcnRQYXJhbSxcbiAgICAgICAgICAgIGVuZFBhcmFtOiByYXcuZW5kUGFyYW0sXG4gICAgICAgICAgICB0aW1lWm9uZVBhcmFtOiByYXcudGltZVpvbmVQYXJhbVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgZmV0Y2g6IGZ1bmN0aW9uIChhcmcsIHN1Y2Nlc3MsIGZhaWx1cmUpIHtcbiAgICAgICAgdmFyIG1ldGEgPSBhcmcuZXZlbnRTb3VyY2UubWV0YTtcbiAgICAgICAgdmFyIHJlcXVlc3RQYXJhbXMgPSBidWlsZFJlcXVlc3RQYXJhbXMobWV0YSwgYXJnLnJhbmdlLCBhcmcuY2FsZW5kYXIpO1xuICAgICAgICByZXF1ZXN0SnNvbihtZXRhLm1ldGhvZCwgbWV0YS51cmwsIHJlcXVlc3RQYXJhbXMsIGZ1bmN0aW9uIChyYXdFdmVudHMsIHhocikge1xuICAgICAgICAgICAgc3VjY2Vzcyh7IHJhd0V2ZW50czogcmF3RXZlbnRzLCB4aHI6IHhociB9KTtcbiAgICAgICAgfSwgZnVuY3Rpb24gKGVycm9yTWVzc2FnZSwgeGhyKSB7XG4gICAgICAgICAgICBmYWlsdXJlKHsgbWVzc2FnZTogZXJyb3JNZXNzYWdlLCB4aHI6IHhociB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxufTtcbnZhciBKc29uRmVlZEV2ZW50U291cmNlUGx1Z2luID0gY3JlYXRlUGx1Z2luKHtcbiAgICBldmVudFNvdXJjZURlZnM6IFtldmVudFNvdXJjZURlZiQyXVxufSk7XG5mdW5jdGlvbiBidWlsZFJlcXVlc3RQYXJhbXMobWV0YSwgcmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRhdGVFbnYgPSBjYWxlbmRhci5kYXRlRW52O1xuICAgIHZhciBzdGFydFBhcmFtO1xuICAgIHZhciBlbmRQYXJhbTtcbiAgICB2YXIgdGltZVpvbmVQYXJhbTtcbiAgICB2YXIgY3VzdG9tUmVxdWVzdFBhcmFtcztcbiAgICB2YXIgcGFyYW1zID0ge307XG4gICAgc3RhcnRQYXJhbSA9IG1ldGEuc3RhcnRQYXJhbTtcbiAgICBpZiAoc3RhcnRQYXJhbSA9PSBudWxsKSB7XG4gICAgICAgIHN0YXJ0UGFyYW0gPSBjYWxlbmRhci5vcHQoJ3N0YXJ0UGFyYW0nKTtcbiAgICB9XG4gICAgZW5kUGFyYW0gPSBtZXRhLmVuZFBhcmFtO1xuICAgIGlmIChlbmRQYXJhbSA9PSBudWxsKSB7XG4gICAgICAgIGVuZFBhcmFtID0gY2FsZW5kYXIub3B0KCdlbmRQYXJhbScpO1xuICAgIH1cbiAgICB0aW1lWm9uZVBhcmFtID0gbWV0YS50aW1lWm9uZVBhcmFtO1xuICAgIGlmICh0aW1lWm9uZVBhcmFtID09IG51bGwpIHtcbiAgICAgICAgdGltZVpvbmVQYXJhbSA9IGNhbGVuZGFyLm9wdCgndGltZVpvbmVQYXJhbScpO1xuICAgIH1cbiAgICAvLyByZXRyaWV2ZSBhbnkgb3V0Ym91bmQgR0VUL1BPU1QgZGF0YSBmcm9tIHRoZSBvcHRpb25zXG4gICAgaWYgKHR5cGVvZiBtZXRhLmV4dHJhUGFyYW1zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIHN1cHBsaWVkIGFzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEga2V5L3ZhbHVlIG9iamVjdFxuICAgICAgICBjdXN0b21SZXF1ZXN0UGFyYW1zID0gbWV0YS5leHRyYVBhcmFtcygpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gcHJvYmFibHkgc3VwcGxpZWQgYXMgYSBzdHJhaWdodCBrZXkvdmFsdWUgb2JqZWN0XG4gICAgICAgIGN1c3RvbVJlcXVlc3RQYXJhbXMgPSBtZXRhLmV4dHJhUGFyYW1zIHx8IHt9O1xuICAgIH1cbiAgICBfX2Fzc2lnbihwYXJhbXMsIGN1c3RvbVJlcXVlc3RQYXJhbXMpO1xuICAgIHBhcmFtc1tzdGFydFBhcmFtXSA9IGRhdGVFbnYuZm9ybWF0SXNvKHJhbmdlLnN0YXJ0KTtcbiAgICBwYXJhbXNbZW5kUGFyYW1dID0gZGF0ZUVudi5mb3JtYXRJc28ocmFuZ2UuZW5kKTtcbiAgICBpZiAoZGF0ZUVudi50aW1lWm9uZSAhPT0gJ2xvY2FsJykge1xuICAgICAgICBwYXJhbXNbdGltZVpvbmVQYXJhbV0gPSBkYXRlRW52LnRpbWVab25lO1xuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xufVxuXG52YXIgcmVjdXJyaW5nID0ge1xuICAgIHBhcnNlOiBmdW5jdGlvbiAocmF3RXZlbnQsIGxlZnRvdmVyUHJvcHMsIGRhdGVFbnYpIHtcbiAgICAgICAgdmFyIGNyZWF0ZU1hcmtlciA9IGRhdGVFbnYuY3JlYXRlTWFya2VyLmJpbmQoZGF0ZUVudik7XG4gICAgICAgIHZhciBwcm9jZXNzb3JzID0ge1xuICAgICAgICAgICAgZGF5c09mV2VlazogbnVsbCxcbiAgICAgICAgICAgIHN0YXJ0VGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgICAgICAgICBlbmRUaW1lOiBjcmVhdGVEdXJhdGlvbixcbiAgICAgICAgICAgIHN0YXJ0UmVjdXI6IGNyZWF0ZU1hcmtlcixcbiAgICAgICAgICAgIGVuZFJlY3VyOiBjcmVhdGVNYXJrZXJcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3RXZlbnQsIHByb2Nlc3NvcnMsIHt9LCBsZWZ0b3ZlclByb3BzKTtcbiAgICAgICAgdmFyIGFueVZhbGlkID0gZmFsc2U7XG4gICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICBpZiAocHJvcHNbcHJvcE5hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhbnlWYWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFueVZhbGlkKSB7XG4gICAgICAgICAgICB2YXIgZHVyYXRpb24gPSBudWxsO1xuICAgICAgICAgICAgaWYgKCdkdXJhdGlvbicgaW4gbGVmdG92ZXJQcm9wcykge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24obGVmdG92ZXJQcm9wcy5kdXJhdGlvbik7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGxlZnRvdmVyUHJvcHMuZHVyYXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWR1cmF0aW9uICYmIHByb3BzLnN0YXJ0VGltZSAmJiBwcm9wcy5lbmRUaW1lKSB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb24gPSBzdWJ0cmFjdER1cmF0aW9ucyhwcm9wcy5lbmRUaW1lLCBwcm9wcy5zdGFydFRpbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhbGxEYXlHdWVzczogQm9vbGVhbighcHJvcHMuc3RhcnRUaW1lICYmICFwcm9wcy5lbmRUaW1lKSxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24sXG4gICAgICAgICAgICAgICAgdHlwZURhdGE6IHByb3BzIC8vIGRvZXNuJ3QgbmVlZCBlbmRUaW1lIGFueW1vcmUgYnV0IG9oIHdlbGxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSxcbiAgICBleHBhbmQ6IGZ1bmN0aW9uICh0eXBlRGF0YSwgZnJhbWluZ1JhbmdlLCBkYXRlRW52KSB7XG4gICAgICAgIHZhciBjbGlwcGVkRnJhbWluZ1JhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKGZyYW1pbmdSYW5nZSwgeyBzdGFydDogdHlwZURhdGEuc3RhcnRSZWN1ciwgZW5kOiB0eXBlRGF0YS5lbmRSZWN1ciB9KTtcbiAgICAgICAgaWYgKGNsaXBwZWRGcmFtaW5nUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBleHBhbmRSYW5nZXModHlwZURhdGEuZGF5c09mV2VlaywgdHlwZURhdGEuc3RhcnRUaW1lLCBjbGlwcGVkRnJhbWluZ1JhbmdlLCBkYXRlRW52KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgIH1cbn07XG52YXIgU2ltcGxlUmVjdXJyZW5jZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgcmVjdXJyaW5nVHlwZXM6IFtyZWN1cnJpbmddXG59KTtcbmZ1bmN0aW9uIGV4cGFuZFJhbmdlcyhkYXlzT2ZXZWVrLCBzdGFydFRpbWUsIGZyYW1pbmdSYW5nZSwgZGF0ZUVudikge1xuICAgIHZhciBkb3dIYXNoID0gZGF5c09mV2VlayA/IGFycmF5VG9IYXNoKGRheXNPZldlZWspIDogbnVsbDtcbiAgICB2YXIgZGF5TWFya2VyID0gc3RhcnRPZkRheShmcmFtaW5nUmFuZ2Uuc3RhcnQpO1xuICAgIHZhciBlbmRNYXJrZXIgPSBmcmFtaW5nUmFuZ2UuZW5kO1xuICAgIHZhciBpbnN0YW5jZVN0YXJ0cyA9IFtdO1xuICAgIHdoaWxlIChkYXlNYXJrZXIgPCBlbmRNYXJrZXIpIHtcbiAgICAgICAgdmFyIGluc3RhbmNlU3RhcnQgXG4gICAgICAgIC8vIGlmIGV2ZXJ5ZGF5LCBvciB0aGlzIHBhcnRpY3VsYXIgZGF5LW9mLXdlZWtcbiAgICAgICAgPSB2b2lkIDA7XG4gICAgICAgIC8vIGlmIGV2ZXJ5ZGF5LCBvciB0aGlzIHBhcnRpY3VsYXIgZGF5LW9mLXdlZWtcbiAgICAgICAgaWYgKCFkb3dIYXNoIHx8IGRvd0hhc2hbZGF5TWFya2VyLmdldFVUQ0RheSgpXSkge1xuICAgICAgICAgICAgaWYgKHN0YXJ0VGltZSkge1xuICAgICAgICAgICAgICAgIGluc3RhbmNlU3RhcnQgPSBkYXRlRW52LmFkZChkYXlNYXJrZXIsIHN0YXJ0VGltZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnN0YW5jZVN0YXJ0ID0gZGF5TWFya2VyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5zdGFuY2VTdGFydHMucHVzaChpbnN0YW5jZVN0YXJ0KTtcbiAgICAgICAgfVxuICAgICAgICBkYXlNYXJrZXIgPSBhZGREYXlzKGRheU1hcmtlciwgMSk7XG4gICAgfVxuICAgIHJldHVybiBpbnN0YW5jZVN0YXJ0cztcbn1cblxudmFyIERlZmF1bHRPcHRpb25DaGFuZ2VIYW5kbGVycyA9IGNyZWF0ZVBsdWdpbih7XG4gICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IHtcbiAgICAgICAgZXZlbnRzOiBmdW5jdGlvbiAoZXZlbnRzLCBjYWxlbmRhciwgZGVlcEVxdWFsKSB7XG4gICAgICAgICAgICBoYW5kbGVFdmVudFNvdXJjZXMoW2V2ZW50c10sIGNhbGVuZGFyLCBkZWVwRXF1YWwpO1xuICAgICAgICB9LFxuICAgICAgICBldmVudFNvdXJjZXM6IGhhbmRsZUV2ZW50U291cmNlcyxcbiAgICAgICAgcGx1Z2luczogaGFuZGxlUGx1Z2luc1xuICAgIH1cbn0pO1xuZnVuY3Rpb24gaGFuZGxlRXZlbnRTb3VyY2VzKGlucHV0cywgY2FsZW5kYXIsIGRlZXBFcXVhbCkge1xuICAgIHZhciB1bmZvdW5kU291cmNlcyA9IGhhc2hWYWx1ZXNUb0FycmF5KGNhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlcyk7XG4gICAgdmFyIG5ld0lucHV0cyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMCwgaW5wdXRzXzEgPSBpbnB1dHM7IF9pIDwgaW5wdXRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBpbnB1dCA9IGlucHV0c18xW19pXTtcbiAgICAgICAgdmFyIGlucHV0Rm91bmQgPSBmYWxzZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1bmZvdW5kU291cmNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGRlZXBFcXVhbCh1bmZvdW5kU291cmNlc1tpXS5fcmF3LCBpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICB1bmZvdW5kU291cmNlcy5zcGxpY2UoaSwgMSk7IC8vIGRlbGV0ZVxuICAgICAgICAgICAgICAgIGlucHV0Rm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghaW5wdXRGb3VuZCkge1xuICAgICAgICAgICAgbmV3SW5wdXRzLnB1c2goaW5wdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAodmFyIF9hID0gMCwgdW5mb3VuZFNvdXJjZXNfMSA9IHVuZm91bmRTb3VyY2VzOyBfYSA8IHVuZm91bmRTb3VyY2VzXzEubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgIHZhciB1bmZvdW5kU291cmNlID0gdW5mb3VuZFNvdXJjZXNfMVtfYV07XG4gICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRfU09VUkNFJyxcbiAgICAgICAgICAgIHNvdXJjZUlkOiB1bmZvdW5kU291cmNlLnNvdXJjZUlkXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBmb3IgKHZhciBfYiA9IDAsIG5ld0lucHV0c18xID0gbmV3SW5wdXRzOyBfYiA8IG5ld0lucHV0c18xLmxlbmd0aDsgX2IrKykge1xuICAgICAgICB2YXIgbmV3SW5wdXQgPSBuZXdJbnB1dHNfMVtfYl07XG4gICAgICAgIGNhbGVuZGFyLmFkZEV2ZW50U291cmNlKG5ld0lucHV0KTtcbiAgICB9XG59XG4vLyBzaG9ydGNvbWluZzogd29uJ3QgcmVtb3ZlIHBsdWdpbnNcbmZ1bmN0aW9uIGhhbmRsZVBsdWdpbnMoaW5wdXRzLCBjYWxlbmRhcikge1xuICAgIGNhbGVuZGFyLmFkZFBsdWdpbklucHV0cyhpbnB1dHMpOyAvLyB3aWxsIGdyYWNlZnVsbHkgaGFuZGxlIGR1cGxpY2F0ZXNcbn1cblxudmFyIGNvbmZpZyA9IHt9OyAvLyBUT0RPOiBtYWtlIHRoZXNlIG9wdGlvbnNcbnZhciBnbG9iYWxEZWZhdWx0cyA9IHtcbiAgICBkZWZhdWx0UmFuZ2VTZXBhcmF0b3I6ICcgLSAnLFxuICAgIHRpdGxlUmFuZ2VTZXBhcmF0b3I6ICcgXFx1MjAxMyAnLFxuICAgIGRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb246ICcwMTowMDowMCcsXG4gICAgZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb246IHsgZGF5OiAxIH0sXG4gICAgZm9yY2VFdmVudER1cmF0aW9uOiBmYWxzZSxcbiAgICBuZXh0RGF5VGhyZXNob2xkOiAnMDA6MDA6MDAnLFxuICAgIC8vIGRpc3BsYXlcbiAgICBjb2x1bW5IZWFkZXI6IHRydWUsXG4gICAgZGVmYXVsdFZpZXc6ICcnLFxuICAgIGFzcGVjdFJhdGlvOiAxLjM1LFxuICAgIGhlYWRlcjoge1xuICAgICAgICBsZWZ0OiAndGl0bGUnLFxuICAgICAgICBjZW50ZXI6ICcnLFxuICAgICAgICByaWdodDogJ3RvZGF5IHByZXYsbmV4dCdcbiAgICB9LFxuICAgIHdlZWtlbmRzOiB0cnVlLFxuICAgIHdlZWtOdW1iZXJzOiBmYWxzZSxcbiAgICB3ZWVrTnVtYmVyQ2FsY3VsYXRpb246ICdsb2NhbCcsXG4gICAgZWRpdGFibGU6IGZhbHNlLFxuICAgIC8vIG5vd0luZGljYXRvcjogZmFsc2UsXG4gICAgc2Nyb2xsVGltZTogJzA2OjAwOjAwJyxcbiAgICBtaW5UaW1lOiAnMDA6MDA6MDAnLFxuICAgIG1heFRpbWU6ICcyNDowMDowMCcsXG4gICAgc2hvd05vbkN1cnJlbnREYXRlczogdHJ1ZSxcbiAgICAvLyBldmVudCBhamF4XG4gICAgbGF6eUZldGNoaW5nOiB0cnVlLFxuICAgIHN0YXJ0UGFyYW06ICdzdGFydCcsXG4gICAgZW5kUGFyYW06ICdlbmQnLFxuICAgIHRpbWVab25lUGFyYW06ICd0aW1lWm9uZScsXG4gICAgdGltZVpvbmU6ICdsb2NhbCcsXG4gICAgLy8gYWxsRGF5RGVmYXVsdDogdW5kZWZpbmVkLFxuICAgIC8vIGxvY2FsZVxuICAgIGxvY2FsZXM6IFtdLFxuICAgIGxvY2FsZTogJycsXG4gICAgLy8gZGlyOiB3aWxsIGdldCB0aGlzIGZyb20gdGhlIGRlZmF1bHQgbG9jYWxlXG4gICAgLy8gYnV0dG9uSWNvbnM6IG51bGwsXG4gICAgLy8gYWxsb3dzIHNldHRpbmcgYSBtaW4taGVpZ2h0IHRvIHRoZSBldmVudCBzZWdtZW50IHRvIHByZXZlbnQgc2hvcnQgZXZlbnRzIG92ZXJsYXBwaW5nIGVhY2ggb3RoZXJcbiAgICB0aW1lR3JpZEV2ZW50TWluSGVpZ2h0OiAwLFxuICAgIHRoZW1lU3lzdGVtOiAnc3RhbmRhcmQnLFxuICAgIC8vIGV2ZW50UmVzaXphYmxlRnJvbVN0YXJ0OiBmYWxzZSxcbiAgICBkcmFnUmV2ZXJ0RHVyYXRpb246IDUwMCxcbiAgICBkcmFnU2Nyb2xsOiB0cnVlLFxuICAgIGFsbERheU1haW50YWluRHVyYXRpb246IGZhbHNlLFxuICAgIC8vIHNlbGVjdGFibGU6IGZhbHNlLFxuICAgIHVuc2VsZWN0QXV0bzogdHJ1ZSxcbiAgICAvLyBzZWxlY3RNaW5EaXN0YW5jZTogMCxcbiAgICBkcm9wQWNjZXB0OiAnKicsXG4gICAgZXZlbnRPcmRlcjogJ3N0YXJ0LC1kdXJhdGlvbixhbGxEYXksdGl0bGUnLFxuICAgIC8vIF4gaWYgc3RhcnQgdGllLCBsb25nZXIgZXZlbnRzIGdvIGJlZm9yZSBzaG9ydGVyLiBmaW5hbCB0aWUtYnJlYWtlciBpcyB0aXRsZSB0ZXh0XG4gICAgLy8gcmVyZW5kZXJEZWxheTogbnVsbCxcbiAgICBldmVudExpbWl0OiBmYWxzZSxcbiAgICBldmVudExpbWl0Q2xpY2s6ICdwb3BvdmVyJyxcbiAgICBkYXlQb3BvdmVyRm9ybWF0OiB7IG1vbnRoOiAnbG9uZycsIGRheTogJ251bWVyaWMnLCB5ZWFyOiAnbnVtZXJpYycgfSxcbiAgICBoYW5kbGVXaW5kb3dSZXNpemU6IHRydWUsXG4gICAgd2luZG93UmVzaXplRGVsYXk6IDEwMCxcbiAgICBsb25nUHJlc3NEZWxheTogMTAwMCxcbiAgICBldmVudERyYWdNaW5EaXN0YW5jZTogNSAvLyBvbmx5IGFwcGxpZXMgdG8gbW91c2Vcbn07XG52YXIgcnRsRGVmYXVsdHMgPSB7XG4gICAgaGVhZGVyOiB7XG4gICAgICAgIGxlZnQ6ICduZXh0LHByZXYgdG9kYXknLFxuICAgICAgICBjZW50ZXI6ICcnLFxuICAgICAgICByaWdodDogJ3RpdGxlJ1xuICAgIH0sXG4gICAgYnV0dG9uSWNvbnM6IHtcbiAgICAgICAgLy8gVE9ETzogbWFrZSBSVEwgc3VwcG9ydCB0aGUgcmVzcG9uaWJpbGl0eSBvZiB0aGUgdGhlbWVcbiAgICAgICAgcHJldjogJ2ZjLWljb24tY2hldnJvbi1yaWdodCcsXG4gICAgICAgIG5leHQ6ICdmYy1pY29uLWNoZXZyb24tbGVmdCcsXG4gICAgICAgIHByZXZZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1yaWdodCcsXG4gICAgICAgIG5leHRZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1sZWZ0J1xuICAgIH1cbn07XG52YXIgY29tcGxleE9wdGlvbnMgPSBbXG4gICAgJ2hlYWRlcicsXG4gICAgJ2Zvb3RlcicsXG4gICAgJ2J1dHRvblRleHQnLFxuICAgICdidXR0b25JY29ucydcbl07XG4vLyBNZXJnZXMgYW4gYXJyYXkgb2Ygb3B0aW9uIG9iamVjdHMgaW50byBhIHNpbmdsZSBvYmplY3RcbmZ1bmN0aW9uIG1lcmdlT3B0aW9ucyhvcHRpb25PYmpzKSB7XG4gICAgcmV0dXJuIG1lcmdlUHJvcHMob3B0aW9uT2JqcywgY29tcGxleE9wdGlvbnMpO1xufVxuLy8gVE9ETzogbW92ZSB0aGlzIHN0dWZmIHRvIGEgXCJwbHVnaW5cIi1yZWxhdGVkIGZpbGUuLi5cbnZhciBJTlRFUk5BTF9QTFVHSU5TID0gW1xuICAgIEFycmF5RXZlbnRTb3VyY2VQbHVnaW4sXG4gICAgRnVuY0V2ZW50U291cmNlUGx1Z2luLFxuICAgIEpzb25GZWVkRXZlbnRTb3VyY2VQbHVnaW4sXG4gICAgU2ltcGxlUmVjdXJyZW5jZVBsdWdpbixcbiAgICBEZWZhdWx0T3B0aW9uQ2hhbmdlSGFuZGxlcnNcbl07XG5mdW5jdGlvbiByZWZpbmVQbHVnaW5EZWZzKHBsdWdpbklucHV0cykge1xuICAgIHZhciBwbHVnaW5zID0gW107XG4gICAgZm9yICh2YXIgX2kgPSAwLCBwbHVnaW5JbnB1dHNfMSA9IHBsdWdpbklucHV0czsgX2kgPCBwbHVnaW5JbnB1dHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHBsdWdpbklucHV0ID0gcGx1Z2luSW5wdXRzXzFbX2ldO1xuICAgICAgICBpZiAodHlwZW9mIHBsdWdpbklucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdmFyIGdsb2JhbE5hbWUgPSAnRnVsbENhbGVuZGFyJyArIGNhcGl0YWxpc2VGaXJzdExldHRlcihwbHVnaW5JbnB1dCk7XG4gICAgICAgICAgICBpZiAoIXdpbmRvd1tnbG9iYWxOYW1lXSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUGx1Z2luIGZpbGUgbm90IGxvYWRlZCBmb3IgJyArIHBsdWdpbklucHV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHBsdWdpbnMucHVzaCh3aW5kb3dbZ2xvYmFsTmFtZV0uZGVmYXVsdCk7IC8vIGlzIGFuIEVTNiBtb2R1bGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBsdWdpbnMucHVzaChwbHVnaW5JbnB1dCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIElOVEVSTkFMX1BMVUdJTlMuY29uY2F0KHBsdWdpbnMpO1xufVxuXG52YXIgUkFXX0VOX0xPQ0FMRSA9IHtcbiAgICBjb2RlOiAnZW4nLFxuICAgIHdlZWs6IHtcbiAgICAgICAgZG93OiAwLFxuICAgICAgICBkb3k6IDQgLy8gNCBkYXlzIG5lZWQgdG8gYmUgd2l0aGluIHRoZSB5ZWFyIHRvIGJlIGNvbnNpZGVyZWQgdGhlIGZpcnN0IHdlZWtcbiAgICB9LFxuICAgIGRpcjogJ2x0cicsXG4gICAgYnV0dG9uVGV4dDoge1xuICAgICAgICBwcmV2OiAncHJldicsXG4gICAgICAgIG5leHQ6ICduZXh0JyxcbiAgICAgICAgcHJldlllYXI6ICdwcmV2IHllYXInLFxuICAgICAgICBuZXh0WWVhcjogJ25leHQgeWVhcicsXG4gICAgICAgIHllYXI6ICd5ZWFyJyxcbiAgICAgICAgdG9kYXk6ICd0b2RheScsXG4gICAgICAgIG1vbnRoOiAnbW9udGgnLFxuICAgICAgICB3ZWVrOiAnd2VlaycsXG4gICAgICAgIGRheTogJ2RheScsXG4gICAgICAgIGxpc3Q6ICdsaXN0J1xuICAgIH0sXG4gICAgd2Vla0xhYmVsOiAnVycsXG4gICAgYWxsRGF5VGV4dDogJ2FsbC1kYXknLFxuICAgIGV2ZW50TGltaXRUZXh0OiAnbW9yZScsXG4gICAgbm9FdmVudHNNZXNzYWdlOiAnTm8gZXZlbnRzIHRvIGRpc3BsYXknXG59O1xuZnVuY3Rpb24gcGFyc2VSYXdMb2NhbGVzKGV4cGxpY2l0UmF3TG9jYWxlcykge1xuICAgIHZhciBkZWZhdWx0Q29kZSA9IGV4cGxpY2l0UmF3TG9jYWxlcy5sZW5ndGggPiAwID8gZXhwbGljaXRSYXdMb2NhbGVzWzBdLmNvZGUgOiAnZW4nO1xuICAgIHZhciBnbG9iYWxBcnJheSA9IHdpbmRvd1snRnVsbENhbGVuZGFyTG9jYWxlc0FsbCddIHx8IFtdOyAvLyBmcm9tIGxvY2FsZXMtYWxsLmpzXG4gICAgdmFyIGdsb2JhbE9iamVjdCA9IHdpbmRvd1snRnVsbENhbGVuZGFyTG9jYWxlcyddIHx8IHt9OyAvLyBmcm9tIGxvY2FsZXMvKi5qcy4ga2V5cyBhcmUgbWVhbmluZ2xlc3NcbiAgICB2YXIgYWxsUmF3TG9jYWxlcyA9IGdsb2JhbEFycmF5LmNvbmNhdCgvLyBnbG9iYWxBcnJheSBpcyBsb3cgcHJpb1xuICAgIGhhc2hWYWx1ZXNUb0FycmF5KGdsb2JhbE9iamVjdCksIC8vIG1lZGl1bSBwcmlvXG4gICAgZXhwbGljaXRSYXdMb2NhbGVzIC8vIGhpZ2hlc3QgcHJpb1xuICAgICk7XG4gICAgdmFyIHJhd0xvY2FsZU1hcCA9IHtcbiAgICAgICAgZW46IFJBV19FTl9MT0NBTEUgLy8gbmVjZXNzYXJ5P1xuICAgIH07XG4gICAgZm9yICh2YXIgX2kgPSAwLCBhbGxSYXdMb2NhbGVzXzEgPSBhbGxSYXdMb2NhbGVzOyBfaSA8IGFsbFJhd0xvY2FsZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHJhd0xvY2FsZSA9IGFsbFJhd0xvY2FsZXNfMVtfaV07XG4gICAgICAgIHJhd0xvY2FsZU1hcFtyYXdMb2NhbGUuY29kZV0gPSByYXdMb2NhbGU7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIG1hcDogcmF3TG9jYWxlTWFwLFxuICAgICAgICBkZWZhdWx0Q29kZTogZGVmYXVsdENvZGVcbiAgICB9O1xufVxuZnVuY3Rpb24gYnVpbGRMb2NhbGUoaW5wdXRTaW5ndWxhciwgYXZhaWxhYmxlKSB7XG4gICAgaWYgKHR5cGVvZiBpbnB1dFNpbmd1bGFyID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShpbnB1dFNpbmd1bGFyKSkge1xuICAgICAgICByZXR1cm4gcGFyc2VMb2NhbGUoaW5wdXRTaW5ndWxhci5jb2RlLCBbaW5wdXRTaW5ndWxhci5jb2RlXSwgaW5wdXRTaW5ndWxhcik7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcXVlcnlMb2NhbGUoaW5wdXRTaW5ndWxhciwgYXZhaWxhYmxlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBxdWVyeUxvY2FsZShjb2RlQXJnLCBhdmFpbGFibGUpIHtcbiAgICB2YXIgY29kZXMgPSBbXS5jb25jYXQoY29kZUFyZyB8fCBbXSk7IC8vIHdpbGwgY29udmVydCB0byBhcnJheVxuICAgIHZhciByYXcgPSBxdWVyeVJhd0xvY2FsZShjb2RlcywgYXZhaWxhYmxlKSB8fCBSQVdfRU5fTE9DQUxFO1xuICAgIHJldHVybiBwYXJzZUxvY2FsZShjb2RlQXJnLCBjb2RlcywgcmF3KTtcbn1cbmZ1bmN0aW9uIHF1ZXJ5UmF3TG9jYWxlKGNvZGVzLCBhdmFpbGFibGUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGNvZGVzW2ldLnRvTG9jYWxlTG93ZXJDYXNlKCkuc3BsaXQoJy0nKTtcbiAgICAgICAgZm9yICh2YXIgaiA9IHBhcnRzLmxlbmd0aDsgaiA+IDA7IGotLSkge1xuICAgICAgICAgICAgdmFyIHNpbXBsZUlkID0gcGFydHMuc2xpY2UoMCwgaikuam9pbignLScpO1xuICAgICAgICAgICAgaWYgKGF2YWlsYWJsZVtzaW1wbGVJZF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXZhaWxhYmxlW3NpbXBsZUlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIHBhcnNlTG9jYWxlKGNvZGVBcmcsIGNvZGVzLCByYXcpIHtcbiAgICB2YXIgbWVyZ2VkID0gbWVyZ2VQcm9wcyhbUkFXX0VOX0xPQ0FMRSwgcmF3XSwgWydidXR0b25UZXh0J10pO1xuICAgIGRlbGV0ZSBtZXJnZWQuY29kZTsgLy8gZG9uJ3Qgd2FudCB0aGlzIHBhcnQgb2YgdGhlIG9wdGlvbnNcbiAgICB2YXIgd2VlayA9IG1lcmdlZC53ZWVrO1xuICAgIGRlbGV0ZSBtZXJnZWQud2VlaztcbiAgICByZXR1cm4ge1xuICAgICAgICBjb2RlQXJnOiBjb2RlQXJnLFxuICAgICAgICBjb2RlczogY29kZXMsXG4gICAgICAgIHdlZWs6IHdlZWssXG4gICAgICAgIHNpbXBsZU51bWJlckZvcm1hdDogbmV3IEludGwuTnVtYmVyRm9ybWF0KGNvZGVBcmcpLFxuICAgICAgICBvcHRpb25zOiBtZXJnZWRcbiAgICB9O1xufVxuXG52YXIgT3B0aW9uc01hbmFnZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT3B0aW9uc01hbmFnZXIob3ZlcnJpZGVzKSB7XG4gICAgICAgIHRoaXMub3ZlcnJpZGVzID0gX19hc3NpZ24oe30sIG92ZXJyaWRlcyk7IC8vIG1ha2UgYSBjb3B5XG4gICAgICAgIHRoaXMuZHluYW1pY092ZXJyaWRlcyA9IHt9O1xuICAgICAgICB0aGlzLmNvbXB1dGUoKTtcbiAgICB9XG4gICAgT3B0aW9uc01hbmFnZXIucHJvdG90eXBlLm11dGF0ZSA9IGZ1bmN0aW9uICh1cGRhdGVzLCByZW1vdmFscywgaXNEeW5hbWljKSB7XG4gICAgICAgIGlmICghT2JqZWN0LmtleXModXBkYXRlcykubGVuZ3RoICYmICFyZW1vdmFscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3ZlcnJpZGVIYXNoID0gaXNEeW5hbWljID8gdGhpcy5keW5hbWljT3ZlcnJpZGVzIDogdGhpcy5vdmVycmlkZXM7XG4gICAgICAgIF9fYXNzaWduKG92ZXJyaWRlSGFzaCwgdXBkYXRlcyk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgcmVtb3ZhbHNfMSA9IHJlbW92YWxzOyBfaSA8IHJlbW92YWxzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSByZW1vdmFsc18xW19pXTtcbiAgICAgICAgICAgIGRlbGV0ZSBvdmVycmlkZUhhc2hbcHJvcE5hbWVdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29tcHV0ZSgpO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgdGhlIGZsYXR0ZW5lZCBvcHRpb25zIGhhc2ggZm9yIHRoZSBjYWxlbmRhciBhbmQgYXNzaWducyB0byBgdGhpcy5vcHRpb25zYC5cbiAgICAvLyBBc3N1bWVzIHRoaXMub3ZlcnJpZGVzIGFuZCB0aGlzLmR5bmFtaWNPdmVycmlkZXMgaGF2ZSBhbHJlYWR5IGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAgT3B0aW9uc01hbmFnZXIucHJvdG90eXBlLmNvbXB1dGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFRPRE86IG5vdCBhIHZlcnkgZWZmaWNpZW50IHN5c3RlbVxuICAgICAgICB2YXIgbG9jYWxlcyA9IGZpcnN0RGVmaW5lZCgvLyBleHBsaWNpdCBsb2NhbGUgb3B0aW9uIGdpdmVuP1xuICAgICAgICB0aGlzLmR5bmFtaWNPdmVycmlkZXMubG9jYWxlcywgdGhpcy5vdmVycmlkZXMubG9jYWxlcywgZ2xvYmFsRGVmYXVsdHMubG9jYWxlcyk7XG4gICAgICAgIHZhciBsb2NhbGUgPSBmaXJzdERlZmluZWQoLy8gZXhwbGljaXQgbG9jYWxlcyBvcHRpb24gZ2l2ZW4/XG4gICAgICAgIHRoaXMuZHluYW1pY092ZXJyaWRlcy5sb2NhbGUsIHRoaXMub3ZlcnJpZGVzLmxvY2FsZSwgZ2xvYmFsRGVmYXVsdHMubG9jYWxlKTtcbiAgICAgICAgdmFyIGF2YWlsYWJsZSA9IHBhcnNlUmF3TG9jYWxlcyhsb2NhbGVzKTtcbiAgICAgICAgdmFyIGxvY2FsZURlZmF1bHRzID0gYnVpbGRMb2NhbGUobG9jYWxlIHx8IGF2YWlsYWJsZS5kZWZhdWx0Q29kZSwgYXZhaWxhYmxlLm1hcCkub3B0aW9ucztcbiAgICAgICAgdmFyIGRpciA9IGZpcnN0RGVmaW5lZCgvLyBiYXNlZCBvbiBvcHRpb25zIGNvbXB1dGVkIHNvIGZhciwgaXMgZGlyZWN0aW9uIFJUTD9cbiAgICAgICAgdGhpcy5keW5hbWljT3ZlcnJpZGVzLmRpciwgdGhpcy5vdmVycmlkZXMuZGlyLCBsb2NhbGVEZWZhdWx0cy5kaXIpO1xuICAgICAgICB2YXIgZGlyRGVmYXVsdHMgPSBkaXIgPT09ICdydGwnID8gcnRsRGVmYXVsdHMgOiB7fTtcbiAgICAgICAgdGhpcy5kaXJEZWZhdWx0cyA9IGRpckRlZmF1bHRzO1xuICAgICAgICB0aGlzLmxvY2FsZURlZmF1bHRzID0gbG9jYWxlRGVmYXVsdHM7XG4gICAgICAgIHRoaXMuY29tcHV0ZWQgPSBtZXJnZU9wdGlvbnMoW1xuICAgICAgICAgICAgZ2xvYmFsRGVmYXVsdHMsXG4gICAgICAgICAgICBkaXJEZWZhdWx0cyxcbiAgICAgICAgICAgIGxvY2FsZURlZmF1bHRzLFxuICAgICAgICAgICAgdGhpcy5vdmVycmlkZXMsXG4gICAgICAgICAgICB0aGlzLmR5bmFtaWNPdmVycmlkZXNcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICByZXR1cm4gT3B0aW9uc01hbmFnZXI7XG59KCkpO1xuXG52YXIgY2FsZW5kYXJTeXN0ZW1DbGFzc01hcCA9IHt9O1xuZnVuY3Rpb24gcmVnaXN0ZXJDYWxlbmRhclN5c3RlbShuYW1lLCB0aGVDbGFzcykge1xuICAgIGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXBbbmFtZV0gPSB0aGVDbGFzcztcbn1cbmZ1bmN0aW9uIGNyZWF0ZUNhbGVuZGFyU3lzdGVtKG5hbWUpIHtcbiAgICByZXR1cm4gbmV3IGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXBbbmFtZV0oKTtcbn1cbnZhciBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbSgpIHtcbiAgICB9XG4gICAgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0ucHJvdG90eXBlLmdldE1hcmtlclllYXIgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICByZXR1cm4gZC5nZXRVVENGdWxsWWVhcigpO1xuICAgIH07XG4gICAgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0ucHJvdG90eXBlLmdldE1hcmtlck1vbnRoID0gZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZ2V0VVRDTW9udGgoKTtcbiAgICB9O1xuICAgIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtLnByb3RvdHlwZS5nZXRNYXJrZXJEYXkgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICByZXR1cm4gZC5nZXRVVENEYXRlKCk7XG4gICAgfTtcbiAgICBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbS5wcm90b3R5cGUuYXJyYXlUb01hcmtlciA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGFycik7XG4gICAgfTtcbiAgICBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbS5wcm90b3R5cGUubWFya2VyVG9BcnJheSA9IGZ1bmN0aW9uIChtYXJrZXIpIHtcbiAgICAgICAgcmV0dXJuIGRhdGVUb1V0Y0FycmF5KG1hcmtlcik7XG4gICAgfTtcbiAgICByZXR1cm4gR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW07XG59KCkpO1xucmVnaXN0ZXJDYWxlbmRhclN5c3RlbSgnZ3JlZ29yeScsIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtKTtcblxudmFyIElTT19SRSA9IC9eXFxzKihcXGR7NH0pKC0oXFxkezJ9KSgtKFxcZHsyfSkoW1QgXShcXGR7Mn0pOihcXGR7Mn0pKDooXFxkezJ9KShcXC4oXFxkKykpPyk/KFp8KChbLStdKShcXGR7Mn0pKDo/KFxcZHsyfSkpPykpPyk/KT8pPyQvO1xuZnVuY3Rpb24gcGFyc2Uoc3RyKSB7XG4gICAgdmFyIG0gPSBJU09fUkUuZXhlYyhzdHIpO1xuICAgIGlmIChtKSB7XG4gICAgICAgIHZhciBtYXJrZXIgPSBuZXcgRGF0ZShEYXRlLlVUQyhOdW1iZXIobVsxXSksIG1bM10gPyBOdW1iZXIobVszXSkgLSAxIDogMCwgTnVtYmVyKG1bNV0gfHwgMSksIE51bWJlcihtWzddIHx8IDApLCBOdW1iZXIobVs4XSB8fCAwKSwgTnVtYmVyKG1bMTBdIHx8IDApLCBtWzEyXSA/IE51bWJlcignMC4nICsgbVsxMl0pICogMTAwMCA6IDApKTtcbiAgICAgICAgaWYgKGlzVmFsaWREYXRlKG1hcmtlcikpIHtcbiAgICAgICAgICAgIHZhciB0aW1lWm9uZU9mZnNldCA9IG51bGw7XG4gICAgICAgICAgICBpZiAobVsxM10pIHtcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCA9IChtWzE1XSA9PT0gJy0nID8gLTEgOiAxKSAqIChOdW1iZXIobVsxNl0gfHwgMCkgKiA2MCArXG4gICAgICAgICAgICAgICAgICAgIE51bWJlcihtWzE4XSB8fCAwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1hcmtlcjogbWFya2VyLFxuICAgICAgICAgICAgICAgIGlzVGltZVVuc3BlY2lmaWVkOiAhbVs2XSxcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogdGltZVpvbmVPZmZzZXRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbnZhciBEYXRlRW52ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIERhdGVFbnYoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIHRpbWVab25lID0gdGhpcy50aW1lWm9uZSA9IHNldHRpbmdzLnRpbWVab25lO1xuICAgICAgICB2YXIgaXNOYW1lZFRpbWVab25lID0gdGltZVpvbmUgIT09ICdsb2NhbCcgJiYgdGltZVpvbmUgIT09ICdVVEMnO1xuICAgICAgICBpZiAoc2V0dGluZ3MubmFtZWRUaW1lWm9uZUltcGwgJiYgaXNOYW1lZFRpbWVab25lKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWVkVGltZVpvbmVJbXBsID0gbmV3IHNldHRpbmdzLm5hbWVkVGltZVpvbmVJbXBsKHRpbWVab25lKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbkNvbXB1dGVPZmZzZXQgPSBCb29sZWFuKCFpc05hbWVkVGltZVpvbmUgfHwgdGhpcy5uYW1lZFRpbWVab25lSW1wbCk7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0gPSBjcmVhdGVDYWxlbmRhclN5c3RlbShzZXR0aW5ncy5jYWxlbmRhclN5c3RlbSk7XG4gICAgICAgIHRoaXMubG9jYWxlID0gc2V0dGluZ3MubG9jYWxlO1xuICAgICAgICB0aGlzLndlZWtEb3cgPSBzZXR0aW5ncy5sb2NhbGUud2Vlay5kb3c7XG4gICAgICAgIHRoaXMud2Vla0RveSA9IHNldHRpbmdzLmxvY2FsZS53ZWVrLmRveTtcbiAgICAgICAgaWYgKHNldHRpbmdzLndlZWtOdW1iZXJDYWxjdWxhdGlvbiA9PT0gJ0lTTycpIHtcbiAgICAgICAgICAgIHRoaXMud2Vla0RvdyA9IDE7XG4gICAgICAgICAgICB0aGlzLndlZWtEb3kgPSA0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0dGluZ3MuZmlyc3REYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLndlZWtEb3cgPSBzZXR0aW5ncy5maXJzdERheTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzLndlZWtOdW1iZXJDYWxjdWxhdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy53ZWVrTnVtYmVyRnVuYyA9IHNldHRpbmdzLndlZWtOdW1iZXJDYWxjdWxhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLndlZWtMYWJlbCA9IHNldHRpbmdzLndlZWtMYWJlbCAhPSBudWxsID8gc2V0dGluZ3Mud2Vla0xhYmVsIDogc2V0dGluZ3MubG9jYWxlLm9wdGlvbnMud2Vla0xhYmVsO1xuICAgICAgICB0aGlzLmNtZEZvcm1hdHRlciA9IHNldHRpbmdzLmNtZEZvcm1hdHRlcjtcbiAgICB9XG4gICAgLy8gQ3JlYXRpbmcgLyBQYXJzaW5nXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY3JlYXRlTWFya2VyID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHZhciBtZXRhID0gdGhpcy5jcmVhdGVNYXJrZXJNZXRhKGlucHV0KTtcbiAgICAgICAgaWYgKG1ldGEgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhLm1hcmtlcjtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmNyZWF0ZU5vd01hcmtlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2FuQ29tcHV0ZU9mZnNldCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGltZXN0YW1wVG9NYXJrZXIobmV3IERhdGUoKS52YWx1ZU9mKCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgd2UgY2FuJ3QgY29tcHV0ZSB0aGUgY3VycmVudCBkYXRlIHZhbCBmb3IgYSB0aW1lem9uZSxcbiAgICAgICAgICAgIC8vIGJldHRlciB0byBnaXZlIHRoZSBjdXJyZW50IGxvY2FsIGRhdGUgdmFscyB0aGFuIFVUQ1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGRhdGVUb0xvY2FsQXJyYXkobmV3IERhdGUoKSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5jcmVhdGVNYXJrZXJNZXRhID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShpbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hcmtlciA9IG51bGw7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBtYXJrZXIgPSB0aGlzLnRpbWVzdGFtcFRvTWFya2VyKGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpbnB1dCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICAgIGlucHV0ID0gaW5wdXQudmFsdWVPZigpO1xuICAgICAgICAgICAgaWYgKCFpc05hTihpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICBtYXJrZXIgPSB0aGlzLnRpbWVzdGFtcFRvTWFya2VyKGlucHV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICAgICAgbWFya2VyID0gYXJyYXlUb1V0Y0RhdGUoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXJrZXIgPT09IG51bGwgfHwgIWlzVmFsaWREYXRlKG1hcmtlcikpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IG1hcmtlcjogbWFya2VyLCBpc1RpbWVVbnNwZWNpZmllZDogZmFsc2UsIGZvcmNlZFR6bzogbnVsbCB9O1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbiAocykge1xuICAgICAgICB2YXIgcGFydHMgPSBwYXJzZShzKTtcbiAgICAgICAgaWYgKHBhcnRzID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWFya2VyID0gcGFydHMubWFya2VyO1xuICAgICAgICB2YXIgZm9yY2VkVHpvID0gbnVsbDtcbiAgICAgICAgaWYgKHBhcnRzLnRpbWVab25lT2Zmc2V0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jYW5Db21wdXRlT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgbWFya2VyID0gdGhpcy50aW1lc3RhbXBUb01hcmtlcihtYXJrZXIudmFsdWVPZigpIC0gcGFydHMudGltZVpvbmVPZmZzZXQgKiA2MCAqIDEwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yY2VkVHpvID0gcGFydHMudGltZVpvbmVPZmZzZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgbWFya2VyOiBtYXJrZXIsIGlzVGltZVVuc3BlY2lmaWVkOiBwYXJ0cy5pc1RpbWVVbnNwZWNpZmllZCwgZm9yY2VkVHpvOiBmb3JjZWRUem8gfTtcbiAgICB9O1xuICAgIC8vIEFjY2Vzc29yc1xuICAgIERhdGVFbnYucHJvdG90eXBlLmdldFllYXIgPSBmdW5jdGlvbiAobWFya2VyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobWFya2VyKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmdldE1vbnRoID0gZnVuY3Rpb24gKG1hcmtlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtYXJrZXIpO1xuICAgIH07XG4gICAgLy8gQWRkaW5nIC8gU3VidHJhY3RpbmdcbiAgICBEYXRlRW52LnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAobWFya2VyLCBkdXIpIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVswXSArPSBkdXIueWVhcnM7XG4gICAgICAgIGFbMV0gKz0gZHVyLm1vbnRocztcbiAgICAgICAgYVsyXSArPSBkdXIuZGF5cztcbiAgICAgICAgYVs2XSArPSBkdXIubWlsbGlzZWNvbmRzO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuc3VidHJhY3QgPSBmdW5jdGlvbiAobWFya2VyLCBkdXIpIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVswXSAtPSBkdXIueWVhcnM7XG4gICAgICAgIGFbMV0gLT0gZHVyLm1vbnRocztcbiAgICAgICAgYVsyXSAtPSBkdXIuZGF5cztcbiAgICAgICAgYVs2XSAtPSBkdXIubWlsbGlzZWNvbmRzO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuYWRkWWVhcnMgPSBmdW5jdGlvbiAobWFya2VyLCBuKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMF0gKz0gbjtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmFkZE1vbnRocyA9IGZ1bmN0aW9uIChtYXJrZXIsIG4pIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVsxXSArPSBuO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH07XG4gICAgLy8gRGlmZmluZyBXaG9sZSBVbml0c1xuICAgIERhdGVFbnYucHJvdG90eXBlLmRpZmZXaG9sZVllYXJzID0gZnVuY3Rpb24gKG0wLCBtMSkge1xuICAgICAgICB2YXIgY2FsZW5kYXJTeXN0ZW0gPSB0aGlzLmNhbGVuZGFyU3lzdGVtO1xuICAgICAgICBpZiAodGltZUFzTXMobTApID09PSB0aW1lQXNNcyhtMSkgJiZcbiAgICAgICAgICAgIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlckRheShtMCkgPT09IGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlckRheShtMSkgJiZcbiAgICAgICAgICAgIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0wKSA9PT0gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyTW9udGgobTEpKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtMSkgLSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0wKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmRpZmZXaG9sZU1vbnRocyA9IGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyU3lzdGVtID0gdGhpcy5jYWxlbmRhclN5c3RlbTtcbiAgICAgICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpICYmXG4gICAgICAgICAgICBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTApID09PSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTEpKSB7XG4gICAgICAgICAgICByZXR1cm4gKGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0xKSAtIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0wKSkgK1xuICAgICAgICAgICAgICAgIChjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0xKSAtIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobTApKSAqIDEyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLy8gUmFuZ2UgLyBEdXJhdGlvblxuICAgIERhdGVFbnYucHJvdG90eXBlLmdyZWF0ZXN0V2hvbGVVbml0ID0gZnVuY3Rpb24gKG0wLCBtMSkge1xuICAgICAgICB2YXIgbiA9IHRoaXMuZGlmZldob2xlWWVhcnMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICd5ZWFyJywgdmFsdWU6IG4gfTtcbiAgICAgICAgfVxuICAgICAgICBuID0gdGhpcy5kaWZmV2hvbGVNb250aHMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdtb250aCcsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZXaG9sZVdlZWtzKG0wLCBtMSk7XG4gICAgICAgIGlmIChuICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnd2VlaycsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZXaG9sZURheXMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdkYXknLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmSG91cnMobTAsIG0xKTtcbiAgICAgICAgaWYgKGlzSW50KG4pKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnaG91cicsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZNaW51dGVzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbnV0ZScsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZTZWNvbmRzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3NlY29uZCcsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSB9O1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY291bnREdXJhdGlvbnNCZXR3ZWVuID0gZnVuY3Rpb24gKG0wLCBtMSwgZCkge1xuICAgICAgICAvLyBUT0RPOiBjYW4gdXNlIGdyZWF0ZXN0V2hvbGVVbml0XG4gICAgICAgIHZhciBkaWZmO1xuICAgICAgICBpZiAoZC55ZWFycykge1xuICAgICAgICAgICAgZGlmZiA9IHRoaXMuZGlmZldob2xlWWVhcnMobTAsIG0xKTtcbiAgICAgICAgICAgIGlmIChkaWZmICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmYgLyBhc1JvdWdoWWVhcnMoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGQubW9udGhzKSB7XG4gICAgICAgICAgICBkaWZmID0gdGhpcy5kaWZmV2hvbGVNb250aHMobTAsIG0xKTtcbiAgICAgICAgICAgIGlmIChkaWZmICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmYgLyBhc1JvdWdoTW9udGhzKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChkLmRheXMpIHtcbiAgICAgICAgICAgIGRpZmYgPSBkaWZmV2hvbGVEYXlzKG0wLCBtMSk7XG4gICAgICAgICAgICBpZiAoZGlmZiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmIC8gYXNSb3VnaERheXMoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gYXNSb3VnaE1zKGQpO1xuICAgIH07XG4gICAgLy8gU3RhcnQtT2ZcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mID0gZnVuY3Rpb24gKG0sIHVuaXQpIHtcbiAgICAgICAgaWYgKHVuaXQgPT09ICd5ZWFyJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZlllYXIobSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodW5pdCA9PT0gJ21vbnRoJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZk1vbnRoKG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICd3ZWVrJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZldlZWsobSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodW5pdCA9PT0gJ2RheScpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGFydE9mRGF5KG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICdob3VyJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZIb3VyKG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICdtaW51dGUnKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RhcnRPZk1pbnV0ZShtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1bml0ID09PSAnc2Vjb25kJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZTZWNvbmQobSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLnN0YXJ0T2ZZZWFyID0gZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihbXG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobSlcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mTW9udGggPSBmdW5jdGlvbiAobSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKFtcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtKSxcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyTW9udGgobSlcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mV2VlayA9IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmFycmF5VG9NYXJrZXIoW1xuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0pLFxuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtKSxcbiAgICAgICAgICAgIG0uZ2V0VVRDRGF0ZSgpIC0gKChtLmdldFVUQ0RheSgpIC0gdGhpcy53ZWVrRG93ICsgNykgJSA3KVxuICAgICAgICBdKTtcbiAgICB9O1xuICAgIC8vIFdlZWsgTnVtYmVyXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY29tcHV0ZVdlZWtOdW1iZXIgPSBmdW5jdGlvbiAobWFya2VyKSB7XG4gICAgICAgIGlmICh0aGlzLndlZWtOdW1iZXJGdW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53ZWVrTnVtYmVyRnVuYyh0aGlzLnRvRGF0ZShtYXJrZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWVrT2ZZZWFyKG1hcmtlciwgdGhpcy53ZWVrRG93LCB0aGlzLndlZWtEb3kpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBUT0RPOiBjaG9rZSBvbiB0aW1lWm9uZU5hbWU6IGxvbmdcbiAgICBEYXRlRW52LnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAobWFya2VyLCBmb3JtYXR0ZXIsIGRhdGVPcHRpb25zKSB7XG4gICAgICAgIGlmIChkYXRlT3B0aW9ucyA9PT0gdm9pZCAwKSB7IGRhdGVPcHRpb25zID0ge307IH1cbiAgICAgICAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXQoe1xuICAgICAgICAgICAgbWFya2VyOiBtYXJrZXIsXG4gICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZU9wdGlvbnMuZm9yY2VkVHpvICE9IG51bGwgP1xuICAgICAgICAgICAgICAgIGRhdGVPcHRpb25zLmZvcmNlZFR6byA6XG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXRGb3JNYXJrZXIobWFya2VyKVxuICAgICAgICB9LCB0aGlzKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGZvcm1hdHRlciwgZGF0ZU9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGRhdGVPcHRpb25zID09PSB2b2lkIDApIHsgZGF0ZU9wdGlvbnMgPSB7fTsgfVxuICAgICAgICBpZiAoZGF0ZU9wdGlvbnMuaXNFbmRFeGNsdXNpdmUpIHtcbiAgICAgICAgICAgIGVuZCA9IGFkZE1zKGVuZCwgLTEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0UmFuZ2Uoe1xuICAgICAgICAgICAgbWFya2VyOiBzdGFydCxcbiAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0OiBkYXRlT3B0aW9ucy5mb3JjZWRTdGFydFR6byAhPSBudWxsID9cbiAgICAgICAgICAgICAgICBkYXRlT3B0aW9ucy5mb3JjZWRTdGFydFR6byA6XG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXRGb3JNYXJrZXIoc3RhcnQpXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIG1hcmtlcjogZW5kLFxuICAgICAgICAgICAgdGltZVpvbmVPZmZzZXQ6IGRhdGVPcHRpb25zLmZvcmNlZEVuZFR6byAhPSBudWxsID9cbiAgICAgICAgICAgICAgICBkYXRlT3B0aW9ucy5mb3JjZWRFbmRUem8gOlxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0Rm9yTWFya2VyKGVuZClcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5mb3JtYXRJc28gPSBmdW5jdGlvbiAobWFya2VyLCBleHRyYU9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGV4dHJhT3B0aW9ucyA9PT0gdm9pZCAwKSB7IGV4dHJhT3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciB0aW1lWm9uZU9mZnNldCA9IG51bGw7XG4gICAgICAgIGlmICghZXh0cmFPcHRpb25zLm9taXRUaW1lWm9uZU9mZnNldCkge1xuICAgICAgICAgICAgaWYgKGV4dHJhT3B0aW9ucy5mb3JjZWRUem8gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0ID0gZXh0cmFPcHRpb25zLmZvcmNlZFR6bztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0ID0gdGhpcy5vZmZzZXRGb3JNYXJrZXIobWFya2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYnVpbGRJc29TdHJpbmcobWFya2VyLCB0aW1lWm9uZU9mZnNldCwgZXh0cmFPcHRpb25zLm9taXRUaW1lKTtcbiAgICB9O1xuICAgIC8vIFRpbWVab25lXG4gICAgRGF0ZUVudi5wcm90b3R5cGUudGltZXN0YW1wVG9NYXJrZXIgPSBmdW5jdGlvbiAobXMpIHtcbiAgICAgICAgaWYgKHRoaXMudGltZVpvbmUgPT09ICdsb2NhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShkYXRlVG9Mb2NhbEFycmF5KG5ldyBEYXRlKG1zKSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnIHx8ICF0aGlzLm5hbWVkVGltZVpvbmVJbXBsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKHRoaXMubmFtZWRUaW1lWm9uZUltcGwudGltZXN0YW1wVG9BcnJheShtcykpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5vZmZzZXRGb3JNYXJrZXIgPSBmdW5jdGlvbiAobSkge1xuICAgICAgICBpZiAodGhpcy50aW1lWm9uZSA9PT0gJ2xvY2FsJykge1xuICAgICAgICAgICAgcmV0dXJuIC1hcnJheVRvTG9jYWxEYXRlKGRhdGVUb1V0Y0FycmF5KG0pKS5nZXRUaW1lem9uZU9mZnNldCgpOyAvLyBjb252ZXJ0IFwiaW52ZXJzZVwiIG9mZnNldCB0byBcIm5vcm1hbFwiIG9mZnNldFxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLm5hbWVkVGltZVpvbmVJbXBsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uYW1lZFRpbWVab25lSW1wbC5vZmZzZXRGb3JBcnJheShkYXRlVG9VdGNBcnJheShtKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvLyBDb252ZXJzaW9uXG4gICAgRGF0ZUVudi5wcm90b3R5cGUudG9EYXRlID0gZnVuY3Rpb24gKG0sIGZvcmNlZFR6bykge1xuICAgICAgICBpZiAodGhpcy50aW1lWm9uZSA9PT0gJ2xvY2FsJykge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9Mb2NhbERhdGUoZGF0ZVRvVXRjQXJyYXkobSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobS52YWx1ZU9mKCkpOyAvLyBtYWtlIHN1cmUgaXQncyBhIGNvcHlcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghdGhpcy5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG0udmFsdWVPZigpIC0gKGZvcmNlZFR6byB8fCAwKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobS52YWx1ZU9mKCkgLVxuICAgICAgICAgICAgICAgIHRoaXMubmFtZWRUaW1lWm9uZUltcGwub2Zmc2V0Rm9yQXJyYXkoZGF0ZVRvVXRjQXJyYXkobSkpICogMTAwMCAqIDYwIC8vIGNvbnZlcnQgbWludXRlcyAtPiBtc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERhdGVFbnY7XG59KCkpO1xuXG52YXIgU0lNUExFX1NPVVJDRV9QUk9QUyA9IHtcbiAgICBpZDogU3RyaW5nLFxuICAgIGFsbERheURlZmF1bHQ6IEJvb2xlYW4sXG4gICAgZXZlbnREYXRhVHJhbnNmb3JtOiBGdW5jdGlvbixcbiAgICBzdWNjZXNzOiBGdW5jdGlvbixcbiAgICBmYWlsdXJlOiBGdW5jdGlvblxufTtcbnZhciB1aWQkMiA9IDA7XG5mdW5jdGlvbiBkb2VzU291cmNlTmVlZFJhbmdlKGV2ZW50U291cmNlLCBjYWxlbmRhcikge1xuICAgIHZhciBkZWZzID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50U291cmNlRGVmcztcbiAgICByZXR1cm4gIWRlZnNbZXZlbnRTb3VyY2Uuc291cmNlRGVmSWRdLmlnbm9yZVJhbmdlO1xufVxuZnVuY3Rpb24gcGFyc2VFdmVudFNvdXJjZShyYXcsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRlZnMgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZXZlbnRTb3VyY2VEZWZzO1xuICAgIGZvciAodmFyIGkgPSBkZWZzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7IC8vIGxhdGVyLWFkZGVkIHBsdWdpbnMgdGFrZSBwcmVjZWRlbmNlXG4gICAgICAgIHZhciBkZWYgPSBkZWZzW2ldO1xuICAgICAgICB2YXIgbWV0YSA9IGRlZi5wYXJzZU1ldGEocmF3KTtcbiAgICAgICAgaWYgKG1ldGEpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSBwYXJzZUV2ZW50U291cmNlUHJvcHModHlwZW9mIHJhdyA9PT0gJ29iamVjdCcgPyByYXcgOiB7fSwgbWV0YSwgaSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgcmVzLl9yYXcgPSByYXc7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gcGFyc2VFdmVudFNvdXJjZVByb3BzKHJhdywgbWV0YSwgc291cmNlRGVmSWQsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGxlZnRvdmVyczAgPSB7fTtcbiAgICB2YXIgcHJvcHMgPSByZWZpbmVQcm9wcyhyYXcsIFNJTVBMRV9TT1VSQ0VfUFJPUFMsIHt9LCBsZWZ0b3ZlcnMwKTtcbiAgICB2YXIgbGVmdG92ZXJzMSA9IHt9O1xuICAgIHZhciB1aSA9IHByb2Nlc3NVbnNjb3BlZFVpUHJvcHMobGVmdG92ZXJzMCwgY2FsZW5kYXIsIGxlZnRvdmVyczEpO1xuICAgIHByb3BzLmlzRmV0Y2hpbmcgPSBmYWxzZTtcbiAgICBwcm9wcy5sYXRlc3RGZXRjaElkID0gJyc7XG4gICAgcHJvcHMuZmV0Y2hSYW5nZSA9IG51bGw7XG4gICAgcHJvcHMucHVibGljSWQgPSBTdHJpbmcocmF3LmlkIHx8ICcnKTtcbiAgICBwcm9wcy5zb3VyY2VJZCA9IFN0cmluZyh1aWQkMisrKTtcbiAgICBwcm9wcy5zb3VyY2VEZWZJZCA9IHNvdXJjZURlZklkO1xuICAgIHByb3BzLm1ldGEgPSBtZXRhO1xuICAgIHByb3BzLnVpID0gdWk7XG4gICAgcHJvcHMuZXh0ZW5kZWRQcm9wcyA9IGxlZnRvdmVyczE7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuXG5mdW5jdGlvbiByZWR1Y2VFdmVudFNvdXJjZXMgKGV2ZW50U291cmNlcywgYWN0aW9uLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXIpIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ0FERF9FVkVOVF9TT1VSQ0VTJzogLy8gYWxyZWFkeSBwYXJzZWRcbiAgICAgICAgICAgIHJldHVybiBhZGRTb3VyY2VzKGV2ZW50U291cmNlcywgYWN0aW9uLnNvdXJjZXMsIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9TT1VSQ0UnOlxuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZVNvdXJjZShldmVudFNvdXJjZXMsIGFjdGlvbi5zb3VyY2VJZCk7XG4gICAgICAgIGNhc2UgJ1BSRVYnOiAvLyBUT0RPOiBob3cgZG8gd2UgdHJhY2sgYWxsIGFjdGlvbnMgdGhhdCBhZmZlY3QgZGF0ZVByb2ZpbGUgOihcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgIGNhc2UgJ1NFVF9EQVRFJzpcbiAgICAgICAgY2FzZSAnU0VUX1ZJRVdfVFlQRSc6XG4gICAgICAgICAgICBpZiAoZGF0ZVByb2ZpbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmV0Y2hEaXJ0eVNvdXJjZXMoZXZlbnRTb3VyY2VzLCBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV2ZW50U291cmNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAnRkVUQ0hfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9USU1FWk9ORSc6XG4gICAgICAgICAgICByZXR1cm4gZmV0Y2hTb3VyY2VzQnlJZHMoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlSWRzID9cbiAgICAgICAgICAgICAgICBhcnJheVRvSGFzaChhY3Rpb24uc291cmNlSWRzKSA6XG4gICAgICAgICAgICAgICAgZXhjbHVkZVN0YXRpY1NvdXJjZXMoZXZlbnRTb3VyY2VzLCBjYWxlbmRhciksIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ1JFQ0VJVkVfRVZFTlRTJzpcbiAgICAgICAgY2FzZSAnUkVDRUlWRV9FVkVOVF9FUlJPUic6XG4gICAgICAgICAgICByZXR1cm4gcmVjZWl2ZVJlc3BvbnNlKGV2ZW50U291cmNlcywgYWN0aW9uLnNvdXJjZUlkLCBhY3Rpb24uZmV0Y2hJZCwgYWN0aW9uLmZldGNoUmFuZ2UpO1xuICAgICAgICBjYXNlICdSRU1PVkVfQUxMX0VWRU5UX1NPVVJDRVMnOlxuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50U291cmNlcztcbiAgICB9XG59XG52YXIgdWlkJDMgPSAwO1xuZnVuY3Rpb24gYWRkU291cmNlcyhldmVudFNvdXJjZUhhc2gsIHNvdXJjZXMsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHNvdXJjZXNfMSA9IHNvdXJjZXM7IF9pIDwgc291cmNlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc291cmNlID0gc291cmNlc18xW19pXTtcbiAgICAgICAgaGFzaFtzb3VyY2Uuc291cmNlSWRdID0gc291cmNlO1xuICAgIH1cbiAgICBpZiAoZmV0Y2hSYW5nZSkge1xuICAgICAgICBoYXNoID0gZmV0Y2hEaXJ0eVNvdXJjZXMoaGFzaCwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICByZXR1cm4gX19hc3NpZ24oe30sIGV2ZW50U291cmNlSGFzaCwgaGFzaCk7XG59XG5mdW5jdGlvbiByZW1vdmVTb3VyY2UoZXZlbnRTb3VyY2VIYXNoLCBzb3VyY2VJZCkge1xuICAgIHJldHVybiBmaWx0ZXJIYXNoKGV2ZW50U291cmNlSGFzaCwgZnVuY3Rpb24gKGV2ZW50U291cmNlKSB7XG4gICAgICAgIHJldHVybiBldmVudFNvdXJjZS5zb3VyY2VJZCAhPT0gc291cmNlSWQ7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBmZXRjaERpcnR5U291cmNlcyhzb3VyY2VIYXNoLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIHJldHVybiBmZXRjaFNvdXJjZXNCeUlkcyhzb3VyY2VIYXNoLCBmaWx0ZXJIYXNoKHNvdXJjZUhhc2gsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gaXNTb3VyY2VEaXJ0eShldmVudFNvdXJjZSwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xuICAgIH0pLCBmZXRjaFJhbmdlLCBjYWxlbmRhcik7XG59XG5mdW5jdGlvbiBpc1NvdXJjZURpcnR5KGV2ZW50U291cmNlLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIGlmICghZG9lc1NvdXJjZU5lZWRSYW5nZShldmVudFNvdXJjZSwgY2FsZW5kYXIpKSB7XG4gICAgICAgIHJldHVybiAhZXZlbnRTb3VyY2UubGF0ZXN0RmV0Y2hJZDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiAhY2FsZW5kYXIub3B0KCdsYXp5RmV0Y2hpbmcnKSB8fFxuICAgICAgICAgICAgIWV2ZW50U291cmNlLmZldGNoUmFuZ2UgfHxcbiAgICAgICAgICAgIGV2ZW50U291cmNlLmlzRmV0Y2hpbmcgfHwgLy8gYWx3YXlzIGNhbmNlbCBvdXRkYXRlZCBpbi1wcm9ncmVzcyBmZXRjaGVzXG4gICAgICAgICAgICBmZXRjaFJhbmdlLnN0YXJ0IDwgZXZlbnRTb3VyY2UuZmV0Y2hSYW5nZS5zdGFydCB8fFxuICAgICAgICAgICAgZmV0Y2hSYW5nZS5lbmQgPiBldmVudFNvdXJjZS5mZXRjaFJhbmdlLmVuZDtcbiAgICB9XG59XG5mdW5jdGlvbiBmZXRjaFNvdXJjZXNCeUlkcyhwcmV2U291cmNlcywgc291cmNlSWRIYXNoLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIHZhciBuZXh0U291cmNlcyA9IHt9O1xuICAgIGZvciAodmFyIHNvdXJjZUlkIGluIHByZXZTb3VyY2VzKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwcmV2U291cmNlc1tzb3VyY2VJZF07XG4gICAgICAgIGlmIChzb3VyY2VJZEhhc2hbc291cmNlSWRdKSB7XG4gICAgICAgICAgICBuZXh0U291cmNlc1tzb3VyY2VJZF0gPSBmZXRjaFNvdXJjZShzb3VyY2UsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5leHRTb3VyY2VzW3NvdXJjZUlkXSA9IHNvdXJjZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV4dFNvdXJjZXM7XG59XG5mdW5jdGlvbiBmZXRjaFNvdXJjZShldmVudFNvdXJjZSwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgc291cmNlRGVmID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50U291cmNlRGVmc1tldmVudFNvdXJjZS5zb3VyY2VEZWZJZF07XG4gICAgdmFyIGZldGNoSWQgPSBTdHJpbmcodWlkJDMrKyk7XG4gICAgc291cmNlRGVmLmZldGNoKHtcbiAgICAgICAgZXZlbnRTb3VyY2U6IGV2ZW50U291cmNlLFxuICAgICAgICBjYWxlbmRhcjogY2FsZW5kYXIsXG4gICAgICAgIHJhbmdlOiBmZXRjaFJhbmdlXG4gICAgfSwgZnVuY3Rpb24gKHJlcykge1xuICAgICAgICB2YXIgcmF3RXZlbnRzID0gcmVzLnJhd0V2ZW50cztcbiAgICAgICAgdmFyIGNhbFN1Y2Nlc3MgPSBjYWxlbmRhci5vcHQoJ2V2ZW50U291cmNlU3VjY2VzcycpO1xuICAgICAgICB2YXIgY2FsU3VjY2Vzc1JlcztcbiAgICAgICAgdmFyIHNvdXJjZVN1Y2Nlc3NSZXM7XG4gICAgICAgIGlmIChldmVudFNvdXJjZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICBzb3VyY2VTdWNjZXNzUmVzID0gZXZlbnRTb3VyY2Uuc3VjY2VzcyhyYXdFdmVudHMsIHJlcy54aHIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjYWxTdWNjZXNzKSB7XG4gICAgICAgICAgICBjYWxTdWNjZXNzUmVzID0gY2FsU3VjY2VzcyhyYXdFdmVudHMsIHJlcy54aHIpO1xuICAgICAgICB9XG4gICAgICAgIHJhd0V2ZW50cyA9IHNvdXJjZVN1Y2Nlc3NSZXMgfHwgY2FsU3VjY2Vzc1JlcyB8fCByYXdFdmVudHM7XG4gICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRUNFSVZFX0VWRU5UUycsXG4gICAgICAgICAgICBzb3VyY2VJZDogZXZlbnRTb3VyY2Uuc291cmNlSWQsXG4gICAgICAgICAgICBmZXRjaElkOiBmZXRjaElkLFxuICAgICAgICAgICAgZmV0Y2hSYW5nZTogZmV0Y2hSYW5nZSxcbiAgICAgICAgICAgIHJhd0V2ZW50czogcmF3RXZlbnRzXG4gICAgICAgIH0pO1xuICAgIH0sIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICB2YXIgY2FsbEZhaWx1cmUgPSBjYWxlbmRhci5vcHQoJ2V2ZW50U291cmNlRmFpbHVyZScpO1xuICAgICAgICBjb25zb2xlLndhcm4oZXJyb3IubWVzc2FnZSwgZXJyb3IpO1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2UuZmFpbHVyZSkge1xuICAgICAgICAgICAgZXZlbnRTb3VyY2UuZmFpbHVyZShlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNhbGxGYWlsdXJlKSB7XG4gICAgICAgICAgICBjYWxsRmFpbHVyZShlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1JFQ0VJVkVfRVZFTlRfRVJST1InLFxuICAgICAgICAgICAgc291cmNlSWQ6IGV2ZW50U291cmNlLnNvdXJjZUlkLFxuICAgICAgICAgICAgZmV0Y2hJZDogZmV0Y2hJZCxcbiAgICAgICAgICAgIGZldGNoUmFuZ2U6IGZldGNoUmFuZ2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3JcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIF9fYXNzaWduKHt9LCBldmVudFNvdXJjZSwgeyBpc0ZldGNoaW5nOiB0cnVlLCBsYXRlc3RGZXRjaElkOiBmZXRjaElkIH0pO1xufVxuZnVuY3Rpb24gcmVjZWl2ZVJlc3BvbnNlKHNvdXJjZUhhc2gsIHNvdXJjZUlkLCBmZXRjaElkLCBmZXRjaFJhbmdlKSB7XG4gICAgdmFyIF9hO1xuICAgIHZhciBldmVudFNvdXJjZSA9IHNvdXJjZUhhc2hbc291cmNlSWRdO1xuICAgIGlmIChldmVudFNvdXJjZSAmJiAvLyBub3QgYWxyZWFkeSByZW1vdmVkXG4gICAgICAgIGZldGNoSWQgPT09IGV2ZW50U291cmNlLmxhdGVzdEZldGNoSWQpIHtcbiAgICAgICAgcmV0dXJuIF9fYXNzaWduKHt9LCBzb3VyY2VIYXNoLCAoX2EgPSB7fSwgX2Fbc291cmNlSWRdID0gX19hc3NpZ24oe30sIGV2ZW50U291cmNlLCB7IGlzRmV0Y2hpbmc6IGZhbHNlLCBmZXRjaFJhbmdlOiBmZXRjaFJhbmdlIC8vIGFsc28gc2VydmVzIGFzIGEgbWFya2VyIHRoYXQgYXQgbGVhc3Qgb25lIGZldGNoIGhhcyBjb21wbGV0ZWRcbiAgICAgICAgIH0pLCBfYSkpO1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlSGFzaDtcbn1cbmZ1bmN0aW9uIGV4Y2x1ZGVTdGF0aWNTb3VyY2VzKGV2ZW50U291cmNlcywgY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gZmlsdGVySGFzaChldmVudFNvdXJjZXMsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gZG9lc1NvdXJjZU5lZWRSYW5nZShldmVudFNvdXJjZSwgY2FsZW5kYXIpO1xuICAgIH0pO1xufVxuXG52YXIgRGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRGF0ZVByb2ZpbGVHZW5lcmF0b3Iodmlld1NwZWMsIGNhbGVuZGFyKSB7XG4gICAgICAgIHRoaXMudmlld1NwZWMgPSB2aWV3U3BlYztcbiAgICAgICAgdGhpcy5vcHRpb25zID0gdmlld1NwZWMub3B0aW9ucztcbiAgICAgICAgdGhpcy5kYXRlRW52ID0gY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdGhpcy5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLmluaXRIaWRkZW5EYXlzKCk7XG4gICAgfVxuICAgIC8qIERhdGUgUmFuZ2UgQ29tcHV0YXRpb25cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSB3aXRoIGluZm8gYWJvdXQgd2hhdCB0aGUgZGF0ZXMvcmFuZ2VzIHdpbGwgYmUgZm9yIHRoZSBcInByZXZcIiB2aWV3LlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFByZXYgPSBmdW5jdGlvbiAoY3VycmVudERhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIHByZXZEYXRlID0gZGF0ZUVudi5zdWJ0cmFjdChkYXRlRW52LnN0YXJ0T2YoY3VycmVudERhdGUsIGN1cnJlbnREYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2VVbml0KSwgLy8gaW1wb3J0YW50IGZvciBzdGFydC1vZi1tb250aFxuICAgICAgICBjdXJyZW50RGF0ZVByb2ZpbGUuZGF0ZUluY3JlbWVudCk7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkKHByZXZEYXRlLCAtMSk7XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYSBzdHJ1Y3R1cmUgd2l0aCBpbmZvIGFib3V0IHdoYXQgdGhlIGRhdGVzL3JhbmdlcyB3aWxsIGJlIGZvciB0aGUgXCJuZXh0XCIgdmlldy5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGROZXh0ID0gZnVuY3Rpb24gKGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHZhciBuZXh0RGF0ZSA9IGRhdGVFbnYuYWRkKGRhdGVFbnYuc3RhcnRPZihjdXJyZW50RGF0ZSwgY3VycmVudERhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpLCAvLyBpbXBvcnRhbnQgZm9yIHN0YXJ0LW9mLW1vbnRoXG4gICAgICAgIGN1cnJlbnREYXRlUHJvZmlsZS5kYXRlSW5jcmVtZW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGQobmV4dERhdGUsIDEpO1xuICAgIH07XG4gICAgLy8gQnVpbGRzIGEgc3RydWN0dXJlIGhvbGRpbmcgZGF0ZXMvcmFuZ2VzIGZvciByZW5kZXJpbmcgYXJvdW5kIHRoZSBnaXZlbiBkYXRlLlxuICAgIC8vIE9wdGlvbmFsIGRpcmVjdGlvbiBwYXJhbSBpbmRpY2F0ZXMgd2hldGhlciB0aGUgZGF0ZSBpcyBiZWluZyBpbmNyZW1lbnRlZC9kZWNyZW1lbnRlZFxuICAgIC8vIGZyb20gaXRzIHByZXZpb3VzIHZhbHVlLiBkZWNyZW1lbnRlZCA9IC0xLCBpbmNyZW1lbnRlZCA9IDEgKGRlZmF1bHQpLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZCA9IGZ1bmN0aW9uIChjdXJyZW50RGF0ZSwgZGlyZWN0aW9uLCBmb3JjZVRvVmFsaWQpIHtcbiAgICAgICAgaWYgKGZvcmNlVG9WYWxpZCA9PT0gdm9pZCAwKSB7IGZvcmNlVG9WYWxpZCA9IGZhbHNlOyB9XG4gICAgICAgIHZhciB2YWxpZFJhbmdlO1xuICAgICAgICB2YXIgbWluVGltZSA9IG51bGw7XG4gICAgICAgIHZhciBtYXhUaW1lID0gbnVsbDtcbiAgICAgICAgdmFyIGN1cnJlbnRJbmZvO1xuICAgICAgICB2YXIgaXNSYW5nZUFsbERheTtcbiAgICAgICAgdmFyIHJlbmRlclJhbmdlO1xuICAgICAgICB2YXIgYWN0aXZlUmFuZ2U7XG4gICAgICAgIHZhciBpc1ZhbGlkO1xuICAgICAgICB2YWxpZFJhbmdlID0gdGhpcy5idWlsZFZhbGlkUmFuZ2UoKTtcbiAgICAgICAgdmFsaWRSYW5nZSA9IHRoaXMudHJpbUhpZGRlbkRheXModmFsaWRSYW5nZSk7XG4gICAgICAgIGlmIChmb3JjZVRvVmFsaWQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gY29uc3RyYWluTWFya2VyVG9SYW5nZShjdXJyZW50RGF0ZSwgdmFsaWRSYW5nZSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudEluZm8gPSB0aGlzLmJ1aWxkQ3VycmVudFJhbmdlSW5mbyhjdXJyZW50RGF0ZSwgZGlyZWN0aW9uKTtcbiAgICAgICAgaXNSYW5nZUFsbERheSA9IC9eKHllYXJ8bW9udGh8d2Vla3xkYXkpJC8udGVzdChjdXJyZW50SW5mby51bml0KTtcbiAgICAgICAgcmVuZGVyUmFuZ2UgPSB0aGlzLmJ1aWxkUmVuZGVyUmFuZ2UodGhpcy50cmltSGlkZGVuRGF5cyhjdXJyZW50SW5mby5yYW5nZSksIGN1cnJlbnRJbmZvLnVuaXQsIGlzUmFuZ2VBbGxEYXkpO1xuICAgICAgICByZW5kZXJSYW5nZSA9IHRoaXMudHJpbUhpZGRlbkRheXMocmVuZGVyUmFuZ2UpO1xuICAgICAgICBhY3RpdmVSYW5nZSA9IHJlbmRlclJhbmdlO1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93Tm9uQ3VycmVudERhdGVzKSB7XG4gICAgICAgICAgICBhY3RpdmVSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhhY3RpdmVSYW5nZSwgY3VycmVudEluZm8ucmFuZ2UpO1xuICAgICAgICB9XG4gICAgICAgIG1pblRpbWUgPSBjcmVhdGVEdXJhdGlvbih0aGlzLm9wdGlvbnMubWluVGltZSk7XG4gICAgICAgIG1heFRpbWUgPSBjcmVhdGVEdXJhdGlvbih0aGlzLm9wdGlvbnMubWF4VGltZSk7XG4gICAgICAgIGFjdGl2ZVJhbmdlID0gdGhpcy5hZGp1c3RBY3RpdmVSYW5nZShhY3RpdmVSYW5nZSwgbWluVGltZSwgbWF4VGltZSk7XG4gICAgICAgIGFjdGl2ZVJhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKGFjdGl2ZVJhbmdlLCB2YWxpZFJhbmdlKTsgLy8gbWlnaHQgcmV0dXJuIG51bGxcbiAgICAgICAgLy8gaXQncyBpbnZhbGlkIGlmIHRoZSBvcmlnaW5hbGx5IHJlcXVlc3RlZCBkYXRlIGlzIG5vdCBjb250YWluZWQsXG4gICAgICAgIC8vIG9yIGlmIHRoZSByYW5nZSBpcyBjb21wbGV0ZWx5IG91dHNpZGUgb2YgdGhlIHZhbGlkIHJhbmdlLlxuICAgICAgICBpc1ZhbGlkID0gcmFuZ2VzSW50ZXJzZWN0KGN1cnJlbnRJbmZvLnJhbmdlLCB2YWxpZFJhbmdlKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC8vIGNvbnN0cmFpbnQgZm9yIHdoZXJlIHByZXYvbmV4dCBvcGVyYXRpb25zIGNhbiBnbyBhbmQgd2hlcmUgZXZlbnRzIGNhbiBiZSBkcmFnZ2VkL3Jlc2l6ZWQgdG8uXG4gICAgICAgICAgICAvLyBhbiBvYmplY3Qgd2l0aCBvcHRpb25hbCBzdGFydCBhbmQgZW5kIHByb3BlcnRpZXMuXG4gICAgICAgICAgICB2YWxpZFJhbmdlOiB2YWxpZFJhbmdlLFxuICAgICAgICAgICAgLy8gcmFuZ2UgdGhlIHZpZXcgaXMgZm9ybWFsbHkgcmVzcG9uc2libGUgZm9yLlxuICAgICAgICAgICAgLy8gZm9yIGV4YW1wbGUsIGEgbW9udGggdmlldyBtaWdodCBoYXZlIDFzdC0zMXN0LCBleGNsdWRpbmcgcGFkZGVkIGRhdGVzXG4gICAgICAgICAgICBjdXJyZW50UmFuZ2U6IGN1cnJlbnRJbmZvLnJhbmdlLFxuICAgICAgICAgICAgLy8gbmFtZSBvZiBsYXJnZXN0IHVuaXQgYmVpbmcgZGlzcGxheWVkLCBsaWtlIFwibW9udGhcIiBvciBcIndlZWtcIlxuICAgICAgICAgICAgY3VycmVudFJhbmdlVW5pdDogY3VycmVudEluZm8udW5pdCxcbiAgICAgICAgICAgIGlzUmFuZ2VBbGxEYXk6IGlzUmFuZ2VBbGxEYXksXG4gICAgICAgICAgICAvLyBkYXRlcyB0aGF0IGRpc3BsYXkgZXZlbnRzIGFuZCBhY2NlcHQgZHJhZy1uLWRyb3BcbiAgICAgICAgICAgIC8vIHdpbGwgYmUgYG51bGxgIGlmIG5vIGRhdGVzIGFjY2VwdCBldmVudHNcbiAgICAgICAgICAgIGFjdGl2ZVJhbmdlOiBhY3RpdmVSYW5nZSxcbiAgICAgICAgICAgIC8vIGRhdGUgcmFuZ2Ugd2l0aCBhIHJlbmRlcmVkIHNrZWxldG9uXG4gICAgICAgICAgICAvLyBpbmNsdWRlcyBub3QtYWN0aXZlIGRheXMgdGhhdCBuZWVkIHNvbWUgc29ydCBvZiBET01cbiAgICAgICAgICAgIHJlbmRlclJhbmdlOiByZW5kZXJSYW5nZSxcbiAgICAgICAgICAgIC8vIER1cmF0aW9uIG9iamVjdCB0aGF0IGRlbm90ZXMgdGhlIGZpcnN0IHZpc2libGUgdGltZSBvZiBhbnkgZ2l2ZW4gZGF5XG4gICAgICAgICAgICBtaW5UaW1lOiBtaW5UaW1lLFxuICAgICAgICAgICAgLy8gRHVyYXRpb24gb2JqZWN0IHRoYXQgZGVub3RlcyB0aGUgZXhjbHVzaXZlIHZpc2libGUgZW5kIHRpbWUgb2YgYW55IGdpdmVuIGRheVxuICAgICAgICAgICAgbWF4VGltZTogbWF4VGltZSxcbiAgICAgICAgICAgIGlzVmFsaWQ6IGlzVmFsaWQsXG4gICAgICAgICAgICAvLyBob3cgZmFyIHRoZSBjdXJyZW50IGRhdGUgd2lsbCBtb3ZlIGZvciBhIHByZXYvbmV4dCBvcGVyYXRpb25cbiAgICAgICAgICAgIGRhdGVJbmNyZW1lbnQ6IHRoaXMuYnVpbGREYXRlSW5jcmVtZW50KGN1cnJlbnRJbmZvLmR1cmF0aW9uKVxuICAgICAgICAgICAgLy8gcGFzcyBhIGZhbGxiYWNrIChtaWdodCBiZSBudWxsKSBeXG4gICAgICAgIH07XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYW4gb2JqZWN0IHdpdGggb3B0aW9uYWwgc3RhcnQvZW5kIHByb3BlcnRpZXMuXG4gICAgLy8gSW5kaWNhdGVzIHRoZSBtaW5pbXVtL21heGltdW0gZGF0ZXMgdG8gZGlzcGxheS5cbiAgICAvLyBub3QgcmVzcG9uc2libGUgZm9yIHRyaW1taW5nIGhpZGRlbiBkYXlzLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFZhbGlkUmFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJhbmdlT3B0aW9uKCd2YWxpZFJhbmdlJywgdGhpcy5jYWxlbmRhci5nZXROb3coKSkgfHxcbiAgICAgICAgICAgIHsgc3RhcnQ6IG51bGwsIGVuZDogbnVsbCB9OyAvLyBjb21wbGV0ZWx5IG9wZW4tZW5kZWRcbiAgICB9O1xuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSB3aXRoIGluZm8gYWJvdXQgdGhlIFwiY3VycmVudFwiIHJhbmdlLCB0aGUgcmFuZ2UgdGhhdCBpc1xuICAgIC8vIGhpZ2hsaWdodGVkIGFzIGJlaW5nIHRoZSBjdXJyZW50IG1vbnRoIGZvciBleGFtcGxlLlxuICAgIC8vIFNlZSBidWlsZCgpIGZvciBhIGRlc2NyaXB0aW9uIG9mIGBkaXJlY3Rpb25gLlxuICAgIC8vIEd1YXJhbnRlZWQgdG8gaGF2ZSBgcmFuZ2VgIGFuZCBgdW5pdGAgcHJvcGVydGllcy4gYGR1cmF0aW9uYCBpcyBvcHRpb25hbC5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRDdXJyZW50UmFuZ2VJbmZvID0gZnVuY3Rpb24gKGRhdGUsIGRpcmVjdGlvbikge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCB2aWV3U3BlYyA9IF9hLnZpZXdTcGVjLCBkYXRlRW52ID0gX2EuZGF0ZUVudjtcbiAgICAgICAgdmFyIGR1cmF0aW9uID0gbnVsbDtcbiAgICAgICAgdmFyIHVuaXQgPSBudWxsO1xuICAgICAgICB2YXIgcmFuZ2UgPSBudWxsO1xuICAgICAgICB2YXIgZGF5Q291bnQ7XG4gICAgICAgIGlmICh2aWV3U3BlYy5kdXJhdGlvbikge1xuICAgICAgICAgICAgZHVyYXRpb24gPSB2aWV3U3BlYy5kdXJhdGlvbjtcbiAgICAgICAgICAgIHVuaXQgPSB2aWV3U3BlYy5kdXJhdGlvblVuaXQ7XG4gICAgICAgICAgICByYW5nZSA9IHRoaXMuYnVpbGRSYW5nZUZyb21EdXJhdGlvbihkYXRlLCBkaXJlY3Rpb24sIGR1cmF0aW9uLCB1bml0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgoZGF5Q291bnQgPSB0aGlzLm9wdGlvbnMuZGF5Q291bnQpKSB7XG4gICAgICAgICAgICB1bml0ID0gJ2RheSc7XG4gICAgICAgICAgICByYW5nZSA9IHRoaXMuYnVpbGRSYW5nZUZyb21EYXlDb3VudChkYXRlLCBkaXJlY3Rpb24sIGRheUNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgocmFuZ2UgPSB0aGlzLmJ1aWxkQ3VzdG9tVmlzaWJsZVJhbmdlKGRhdGUpKSkge1xuICAgICAgICAgICAgdW5pdCA9IGRhdGVFbnYuZ3JlYXRlc3RXaG9sZVVuaXQocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCkudW5pdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGR1cmF0aW9uID0gdGhpcy5nZXRGYWxsYmFja0R1cmF0aW9uKCk7XG4gICAgICAgICAgICB1bml0ID0gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGR1cmF0aW9uKS51bml0O1xuICAgICAgICAgICAgcmFuZ2UgPSB0aGlzLmJ1aWxkUmFuZ2VGcm9tRHVyYXRpb24oZGF0ZSwgZGlyZWN0aW9uLCBkdXJhdGlvbiwgdW5pdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZHVyYXRpb246IGR1cmF0aW9uLCB1bml0OiB1bml0LCByYW5nZTogcmFuZ2UgfTtcbiAgICB9O1xuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5nZXRGYWxsYmFja0R1cmF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oeyBkYXk6IDEgfSk7XG4gICAgfTtcbiAgICAvLyBSZXR1cm5zIGEgbmV3IGFjdGl2ZVJhbmdlIHRvIGhhdmUgdGltZSB2YWx1ZXMgKHVuLWFtYmlndWF0ZSlcbiAgICAvLyBtaW5UaW1lIG9yIG1heFRpbWUgY2F1c2VzIHRoZSByYW5nZSB0byBleHBhbmQuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmFkanVzdEFjdGl2ZVJhbmdlID0gZnVuY3Rpb24gKHJhbmdlLCBtaW5UaW1lLCBtYXhUaW1lKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgc3RhcnQgPSByYW5nZS5zdGFydDtcbiAgICAgICAgdmFyIGVuZCA9IHJhbmdlLmVuZDtcbiAgICAgICAgaWYgKHRoaXMudmlld1NwZWMuY2xhc3MucHJvdG90eXBlLnVzZXNNaW5NYXhUaW1lKSB7XG4gICAgICAgICAgICAvLyBleHBhbmQgYWN0aXZlIHJhbmdlIGlmIG1pblRpbWUgaXMgbmVnYXRpdmUgKHdoeSBub3Qgd2hlbiBwb3NpdGl2ZT8pXG4gICAgICAgICAgICBpZiAoYXNSb3VnaERheXMobWluVGltZSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5hZGQoc3RhcnQsIG1pblRpbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZXhwYW5kIGFjdGl2ZSByYW5nZSBpZiBtYXhUaW1lIGlzIGJleW9uZCBvbmUgZGF5ICh3aHkgbm90IHdoZW4gcG9zaXRpdmU/KVxuICAgICAgICAgICAgaWYgKGFzUm91Z2hEYXlzKG1heFRpbWUpID4gMSkge1xuICAgICAgICAgICAgICAgIGVuZCA9IHN0YXJ0T2ZEYXkoZW5kKTsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgIGVuZCA9IGFkZERheXMoZW5kLCAtMSk7XG4gICAgICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoZW5kLCBtYXhUaW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgdGhlIFwiY3VycmVudFwiIHJhbmdlIHdoZW4gaXQgaXMgc3BlY2lmaWVkIGFzIGFuIGV4cGxpY2l0IGR1cmF0aW9uLlxuICAgIC8vIGB1bml0YCBpcyB0aGUgYWxyZWFkeS1jb21wdXRlZCBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IgdW5pdCBvZiBkdXJhdGlvbi5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRSYW5nZUZyb21EdXJhdGlvbiA9IGZ1bmN0aW9uIChkYXRlLCBkaXJlY3Rpb24sIGR1cmF0aW9uLCB1bml0KSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgYWxpZ25tZW50ID0gdGhpcy5vcHRpb25zLmRhdGVBbGlnbm1lbnQ7XG4gICAgICAgIHZhciBkYXRlSW5jcmVtZW50SW5wdXQ7XG4gICAgICAgIHZhciBkYXRlSW5jcmVtZW50RHVyYXRpb247XG4gICAgICAgIHZhciBzdGFydDtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgdmFyIHJlcztcbiAgICAgICAgLy8gY29tcHV0ZSB3aGF0IHRoZSBhbGlnbm1lbnQgc2hvdWxkIGJlXG4gICAgICAgIGlmICghYWxpZ25tZW50KSB7XG4gICAgICAgICAgICBkYXRlSW5jcmVtZW50SW5wdXQgPSB0aGlzLm9wdGlvbnMuZGF0ZUluY3JlbWVudDtcbiAgICAgICAgICAgIGlmIChkYXRlSW5jcmVtZW50SW5wdXQpIHtcbiAgICAgICAgICAgICAgICBkYXRlSW5jcmVtZW50RHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbihkYXRlSW5jcmVtZW50SW5wdXQpO1xuICAgICAgICAgICAgICAgIC8vIHVzZSB0aGUgc21hbGxlciBvZiB0aGUgdHdvIHVuaXRzXG4gICAgICAgICAgICAgICAgaWYgKGFzUm91Z2hNcyhkYXRlSW5jcmVtZW50RHVyYXRpb24pIDwgYXNSb3VnaE1zKGR1cmF0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnQgPSBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZGF0ZUluY3JlbWVudER1cmF0aW9uLCAhZ2V0V2Vla3NGcm9tSW5wdXQoZGF0ZUluY3JlbWVudElucHV0KSkudW5pdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFsaWdubWVudCA9IHVuaXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYWxpZ25tZW50ID0gdW5pdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0aGUgdmlldyBkaXNwbGF5cyBhIHNpbmdsZSBkYXkgb3Igc21hbGxlclxuICAgICAgICBpZiAoYXNSb3VnaERheXMoZHVyYXRpb24pIDw9IDEpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzSGlkZGVuRGF5KHN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5za2lwSGlkZGVuRGF5cyhzdGFydCwgZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICBzdGFydCA9IHN0YXJ0T2ZEYXkoc3RhcnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGNvbXB1dGVSZXMoKSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVFbnYuc3RhcnRPZihkYXRlLCBhbGlnbm1lbnQpO1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoc3RhcnQsIGR1cmF0aW9uKTtcbiAgICAgICAgICAgIHJlcyA9IHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbXB1dGVSZXMoKTtcbiAgICAgICAgLy8gaWYgcmFuZ2UgaXMgY29tcGxldGVseSBlbnZlbG9wZWQgYnkgaGlkZGVuIGRheXMsIGdvIHBhc3QgdGhlIGhpZGRlbiBkYXlzXG4gICAgICAgIGlmICghdGhpcy50cmltSGlkZGVuRGF5cyhyZXMpKSB7XG4gICAgICAgICAgICBkYXRlID0gdGhpcy5za2lwSGlkZGVuRGF5cyhkYXRlLCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgY29tcHV0ZVJlcygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgdGhlIFwiY3VycmVudFwiIHJhbmdlIHdoZW4gYSBkYXlDb3VudCBpcyBzcGVjaWZpZWQuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkUmFuZ2VGcm9tRGF5Q291bnQgPSBmdW5jdGlvbiAoZGF0ZSwgZGlyZWN0aW9uLCBkYXlDb3VudCkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIGN1c3RvbUFsaWdubWVudCA9IHRoaXMub3B0aW9ucy5kYXRlQWxpZ25tZW50O1xuICAgICAgICB2YXIgcnVubmluZ0NvdW50ID0gMDtcbiAgICAgICAgdmFyIHN0YXJ0ID0gZGF0ZTtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgaWYgKGN1c3RvbUFsaWdubWVudCkge1xuICAgICAgICAgICAgc3RhcnQgPSBkYXRlRW52LnN0YXJ0T2Yoc3RhcnQsIGN1c3RvbUFsaWdubWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTtcbiAgICAgICAgc3RhcnQgPSB0aGlzLnNraXBIaWRkZW5EYXlzKHN0YXJ0LCBkaXJlY3Rpb24pO1xuICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgZW5kID0gYWRkRGF5cyhlbmQsIDEpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzSGlkZGVuRGF5KGVuZCkpIHtcbiAgICAgICAgICAgICAgICBydW5uaW5nQ291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSB3aGlsZSAocnVubmluZ0NvdW50IDwgZGF5Q291bnQpO1xuICAgICAgICByZXR1cm4geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYSBub3JtYWxpemVkIHJhbmdlIG9iamVjdCBmb3IgdGhlIFwidmlzaWJsZVwiIHJhbmdlLFxuICAgIC8vIHdoaWNoIGlzIGEgd2F5IHRvIGRlZmluZSB0aGUgY3VycmVudFJhbmdlIGFuZCBhY3RpdmVSYW5nZSBhdCB0aGUgc2FtZSB0aW1lLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZEN1c3RvbVZpc2libGVSYW5nZSA9IGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgdmlzaWJsZVJhbmdlID0gdGhpcy5nZXRSYW5nZU9wdGlvbigndmlzaWJsZVJhbmdlJywgZGF0ZUVudi50b0RhdGUoZGF0ZSkpO1xuICAgICAgICBpZiAodmlzaWJsZVJhbmdlICYmICh2aXNpYmxlUmFuZ2Uuc3RhcnQgPT0gbnVsbCB8fCB2aXNpYmxlUmFuZ2UuZW5kID09IG51bGwpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmlzaWJsZVJhbmdlO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgdGhlIHJhbmdlIHRoYXQgd2lsbCByZXByZXNlbnQgdGhlIGVsZW1lbnQvY2VsbHMgZm9yICpyZW5kZXJpbmcqLFxuICAgIC8vIGJ1dCB3aGljaCBtYXkgaGF2ZSB2b2lkZWQgZGF5cy90aW1lcy5cbiAgICAvLyBub3QgcmVzcG9uc2libGUgZm9yIHRyaW1taW5nIGhpZGRlbiBkYXlzLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFJlbmRlclJhbmdlID0gZnVuY3Rpb24gKGN1cnJlbnRSYW5nZSwgY3VycmVudFJhbmdlVW5pdCwgaXNSYW5nZUFsbERheSkge1xuICAgICAgICByZXR1cm4gY3VycmVudFJhbmdlO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZSB0aGUgZHVyYXRpb24gdmFsdWUgdGhhdCBzaG91bGQgYmUgYWRkZWQvc3Vic3RyYWN0ZWQgdG8gdGhlIGN1cnJlbnQgZGF0ZVxuICAgIC8vIHdoZW4gYSBwcmV2L25leHQgb3BlcmF0aW9uIGhhcHBlbnMuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkRGF0ZUluY3JlbWVudCA9IGZ1bmN0aW9uIChmYWxsYmFjaykge1xuICAgICAgICB2YXIgZGF0ZUluY3JlbWVudElucHV0ID0gdGhpcy5vcHRpb25zLmRhdGVJbmNyZW1lbnQ7XG4gICAgICAgIHZhciBjdXN0b21BbGlnbm1lbnQ7XG4gICAgICAgIGlmIChkYXRlSW5jcmVtZW50SW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbihkYXRlSW5jcmVtZW50SW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKChjdXN0b21BbGlnbm1lbnQgPSB0aGlzLm9wdGlvbnMuZGF0ZUFsaWdubWVudCkpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbigxLCBjdXN0b21BbGlnbm1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGZhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsbGJhY2s7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oeyBkYXlzOiAxIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBBcmd1bWVudHMgYWZ0ZXIgbmFtZSB3aWxsIGJlIGZvcndhcmRlZCB0byBhIGh5cG90aGV0aWNhbCBmdW5jdGlvbiB2YWx1ZVxuICAgIC8vIFdBUk5JTkc6IHBhc3NlZC1pbiBhcmd1bWVudHMgd2lsbCBiZSBnaXZlbiB0byBnZW5lcmF0b3IgZnVuY3Rpb25zIGFzLWlzIGFuZCBjYW4gY2F1c2Ugc2lkZS1lZmZlY3RzLlxuICAgIC8vIEFsd2F5cyBjbG9uZSB5b3VyIG9iamVjdHMgaWYgeW91IGZlYXIgbXV0YXRpb24uXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmdldFJhbmdlT3B0aW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIG90aGVyQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDE7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgb3RoZXJBcmdzW19pIC0gMV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLm9wdGlvbnNbbmFtZV07XG4gICAgICAgIGlmICh0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB2YWwgPSB2YWwuYXBwbHkobnVsbCwgb3RoZXJBcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsKSB7XG4gICAgICAgICAgICB2YWwgPSBwYXJzZVJhbmdlKHZhbCwgdGhpcy5kYXRlRW52KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsKSB7XG4gICAgICAgICAgICB2YWwgPSBjb21wdXRlVmlzaWJsZURheVJhbmdlKHZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9O1xuICAgIC8qIEhpZGRlbiBEYXlzXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAvLyBJbml0aWFsaXplcyBpbnRlcm5hbCB2YXJpYWJsZXMgcmVsYXRlZCB0byBjYWxjdWxhdGluZyBoaWRkZW4gZGF5cy1vZi13ZWVrXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmluaXRIaWRkZW5EYXlzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGlkZGVuRGF5cyA9IHRoaXMub3B0aW9ucy5oaWRkZW5EYXlzIHx8IFtdOyAvLyBhcnJheSBvZiBkYXktb2Ytd2VlayBpbmRpY2VzIHRoYXQgYXJlIGhpZGRlblxuICAgICAgICB2YXIgaXNIaWRkZW5EYXlIYXNoID0gW107IC8vIGlzIHRoZSBkYXktb2Ytd2VlayBoaWRkZW4/IChoYXNoIHdpdGggZGF5LW9mLXdlZWstaW5kZXggLT4gYm9vbClcbiAgICAgICAgdmFyIGRheUNudCA9IDA7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLndlZWtlbmRzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgaGlkZGVuRGF5cy5wdXNoKDAsIDYpOyAvLyAwPXN1bmRheSwgNj1zYXR1cmRheVxuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIGlmICghKGlzSGlkZGVuRGF5SGFzaFtpXSA9IGhpZGRlbkRheXMuaW5kZXhPZihpKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAgICAgZGF5Q250Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXlDbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBoaWRkZW5EYXlzJyk7IC8vIGFsbCBkYXlzIHdlcmUgaGlkZGVuPyBiYWQuXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc0hpZGRlbkRheUhhc2ggPSBpc0hpZGRlbkRheUhhc2g7XG4gICAgfTtcbiAgICAvLyBSZW1vdmUgZGF5cyBmcm9tIHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGUgcmFuZ2UgdGhhdCBhcmUgY29tcHV0ZWQgYXMgaGlkZGVuLlxuICAgIC8vIElmIHRoZSB3aG9sZSByYW5nZSBpcyB0cmltbWVkIG9mZiwgcmV0dXJucyBudWxsXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLnRyaW1IaWRkZW5EYXlzID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gICAgICAgIHZhciBzdGFydCA9IHJhbmdlLnN0YXJ0O1xuICAgICAgICB2YXIgZW5kID0gcmFuZ2UuZW5kO1xuICAgICAgICBpZiAoc3RhcnQpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5za2lwSGlkZGVuRGF5cyhzdGFydCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVuZCkge1xuICAgICAgICAgICAgZW5kID0gdGhpcy5za2lwSGlkZGVuRGF5cyhlbmQsIC0xLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RhcnQgPT0gbnVsbCB8fCBlbmQgPT0gbnVsbCB8fCBzdGFydCA8IGVuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLy8gSXMgdGhlIGN1cnJlbnQgZGF5IGhpZGRlbj9cbiAgICAvLyBgZGF5YCBpcyBhIGRheS1vZi13ZWVrIGluZGV4ICgwLTYpLCBvciBhIERhdGUgKHVzZWQgZm9yIFVUQylcbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuaXNIaWRkZW5EYXkgPSBmdW5jdGlvbiAoZGF5KSB7XG4gICAgICAgIGlmIChkYXkgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgICBkYXkgPSBkYXkuZ2V0VVRDRGF5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaXNIaWRkZW5EYXlIYXNoW2RheV07XG4gICAgfTtcbiAgICAvLyBJbmNyZW1lbnRpbmcgdGhlIGN1cnJlbnQgZGF5IHVudGlsIGl0IGlzIG5vIGxvbmdlciBhIGhpZGRlbiBkYXksIHJldHVybmluZyBhIGNvcHkuXG4gICAgLy8gRE9FUyBOT1QgQ09OU0lERVIgdmFsaWRSYW5nZSFcbiAgICAvLyBJZiB0aGUgaW5pdGlhbCB2YWx1ZSBvZiBgZGF0ZWAgaXMgbm90IGEgaGlkZGVuIGRheSwgZG9uJ3QgZG8gYW55dGhpbmcuXG4gICAgLy8gUGFzcyBgaXNFeGNsdXNpdmVgIGFzIGB0cnVlYCBpZiB5b3UgYXJlIGRlYWxpbmcgd2l0aCBhbiBlbmQgZGF0ZS5cbiAgICAvLyBgaW5jYCBkZWZhdWx0cyB0byBgMWAgKGluY3JlbWVudCBvbmUgZGF5IGZvcndhcmQgZWFjaCB0aW1lKVxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5za2lwSGlkZGVuRGF5cyA9IGZ1bmN0aW9uIChkYXRlLCBpbmMsIGlzRXhjbHVzaXZlKSB7XG4gICAgICAgIGlmIChpbmMgPT09IHZvaWQgMCkgeyBpbmMgPSAxOyB9XG4gICAgICAgIGlmIChpc0V4Y2x1c2l2ZSA9PT0gdm9pZCAwKSB7IGlzRXhjbHVzaXZlID0gZmFsc2U7IH1cbiAgICAgICAgd2hpbGUgKHRoaXMuaXNIaWRkZW5EYXlIYXNoWyhkYXRlLmdldFVUQ0RheSgpICsgKGlzRXhjbHVzaXZlID8gaW5jIDogMCkgKyA3KSAlIDddKSB7XG4gICAgICAgICAgICBkYXRlID0gYWRkRGF5cyhkYXRlLCBpbmMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVQcm9maWxlR2VuZXJhdG9yO1xufSgpKTtcbi8vIFRPRE86IGZpbmQgYSB3YXkgdG8gYXZvaWQgY29tcGFyaW5nIERhdGVQcm9maWxlcy4gaXQncyB0ZWRpb3VzXG5mdW5jdGlvbiBpc0RhdGVQcm9maWxlc0VxdWFsKHAwLCBwMSkge1xuICAgIHJldHVybiByYW5nZXNFcXVhbChwMC52YWxpZFJhbmdlLCBwMS52YWxpZFJhbmdlKSAmJlxuICAgICAgICByYW5nZXNFcXVhbChwMC5hY3RpdmVSYW5nZSwgcDEuYWN0aXZlUmFuZ2UpICYmXG4gICAgICAgIHJhbmdlc0VxdWFsKHAwLnJlbmRlclJhbmdlLCBwMS5yZW5kZXJSYW5nZSkgJiZcbiAgICAgICAgZHVyYXRpb25zRXF1YWwocDAubWluVGltZSwgcDEubWluVGltZSkgJiZcbiAgICAgICAgZHVyYXRpb25zRXF1YWwocDAubWF4VGltZSwgcDEubWF4VGltZSk7XG4gICAgLypcbiAgICBUT0RPOiBjb21wYXJlIG1vcmU/XG4gICAgICBjdXJyZW50UmFuZ2U6IERhdGVSYW5nZVxuICAgICAgY3VycmVudFJhbmdlVW5pdDogc3RyaW5nXG4gICAgICBpc1JhbmdlQWxsRGF5OiBib29sZWFuXG4gICAgICBpc1ZhbGlkOiBib29sZWFuXG4gICAgICBkYXRlSW5jcmVtZW50OiBEdXJhdGlvblxuICAgICovXG59XG5cbmZ1bmN0aW9uIHJlZHVjZSAoc3RhdGUsIGFjdGlvbiwgY2FsZW5kYXIpIHtcbiAgICB2YXIgdmlld1R5cGUgPSByZWR1Y2VWaWV3VHlwZShzdGF0ZS52aWV3VHlwZSwgYWN0aW9uKTtcbiAgICB2YXIgZGF0ZVByb2ZpbGUgPSByZWR1Y2VEYXRlUHJvZmlsZShzdGF0ZS5kYXRlUHJvZmlsZSwgYWN0aW9uLCBzdGF0ZS5jdXJyZW50RGF0ZSwgdmlld1R5cGUsIGNhbGVuZGFyKTtcbiAgICB2YXIgZXZlbnRTb3VyY2VzID0gcmVkdWNlRXZlbnRTb3VyY2VzKHN0YXRlLmV2ZW50U291cmNlcywgYWN0aW9uLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXIpO1xuICAgIHZhciBuZXh0U3RhdGUgPSBfX2Fzc2lnbih7fSwgc3RhdGUsIHsgdmlld1R5cGU6IHZpZXdUeXBlLFxuICAgICAgICBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlOiByZWR1Y2VDdXJyZW50RGF0ZShzdGF0ZS5jdXJyZW50RGF0ZSwgYWN0aW9uLCBkYXRlUHJvZmlsZSksIGV2ZW50U291cmNlczogZXZlbnRTb3VyY2VzLCBldmVudFN0b3JlOiByZWR1Y2VFdmVudFN0b3JlKHN0YXRlLmV2ZW50U3RvcmUsIGFjdGlvbiwgZXZlbnRTb3VyY2VzLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXIpLCBkYXRlU2VsZWN0aW9uOiByZWR1Y2VEYXRlU2VsZWN0aW9uKHN0YXRlLmRhdGVTZWxlY3Rpb24sIGFjdGlvbiwgY2FsZW5kYXIpLCBldmVudFNlbGVjdGlvbjogcmVkdWNlU2VsZWN0ZWRFdmVudChzdGF0ZS5ldmVudFNlbGVjdGlvbiwgYWN0aW9uKSwgZXZlbnREcmFnOiByZWR1Y2VFdmVudERyYWcoc3RhdGUuZXZlbnREcmFnLCBhY3Rpb24sIGV2ZW50U291cmNlcywgY2FsZW5kYXIpLCBldmVudFJlc2l6ZTogcmVkdWNlRXZlbnRSZXNpemUoc3RhdGUuZXZlbnRSZXNpemUsIGFjdGlvbiwgZXZlbnRTb3VyY2VzLCBjYWxlbmRhciksIGV2ZW50U291cmNlTG9hZGluZ0xldmVsOiBjb21wdXRlTG9hZGluZ0xldmVsKGV2ZW50U291cmNlcyksIGxvYWRpbmdMZXZlbDogY29tcHV0ZUxvYWRpbmdMZXZlbChldmVudFNvdXJjZXMpIH0pO1xuICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MucmVkdWNlcnM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciByZWR1Y2VyRnVuYyA9IF9hW19pXTtcbiAgICAgICAgbmV4dFN0YXRlID0gcmVkdWNlckZ1bmMobmV4dFN0YXRlLCBhY3Rpb24sIGNhbGVuZGFyKTtcbiAgICB9XG4gICAgLy8gY29uc29sZS5sb2coYWN0aW9uLnR5cGUsIG5leHRTdGF0ZSlcbiAgICByZXR1cm4gbmV4dFN0YXRlO1xufVxuZnVuY3Rpb24gcmVkdWNlVmlld1R5cGUoY3VycmVudFZpZXdUeXBlLCBhY3Rpb24pIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbi52aWV3VHlwZTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50Vmlld1R5cGU7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlRGF0ZVByb2ZpbGUoY3VycmVudERhdGVQcm9maWxlLCBhY3Rpb24sIGN1cnJlbnREYXRlLCB2aWV3VHlwZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgbmV3RGF0ZVByb2ZpbGU7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdQUkVWJzpcbiAgICAgICAgICAgIG5ld0RhdGVQcm9maWxlID0gY2FsZW5kYXIuZGF0ZVByb2ZpbGVHZW5lcmF0b3JzW3ZpZXdUeXBlXS5idWlsZFByZXYoY3VycmVudERhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgICAgICBuZXdEYXRlUHJvZmlsZSA9IGNhbGVuZGFyLmRhdGVQcm9maWxlR2VuZXJhdG9yc1t2aWV3VHlwZV0uYnVpbGROZXh0KGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ1NFVF9EQVRFJzpcbiAgICAgICAgICAgIGlmICghY3VycmVudERhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIHx8XG4gICAgICAgICAgICAgICAgIXJhbmdlQ29udGFpbnNNYXJrZXIoY3VycmVudERhdGVQcm9maWxlLmN1cnJlbnRSYW5nZSwgYWN0aW9uLmRhdGVNYXJrZXIpKSB7XG4gICAgICAgICAgICAgICAgbmV3RGF0ZVByb2ZpbGUgPSBjYWxlbmRhci5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdLmJ1aWxkKGFjdGlvbi5kYXRlTWFya2VyLCB1bmRlZmluZWQsIHRydWUgLy8gZm9yY2VUb1ZhbGlkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdTRVRfVklFV19UWVBFJzpcbiAgICAgICAgICAgIHZhciBnZW5lcmF0b3IgPSBjYWxlbmRhci5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdO1xuICAgICAgICAgICAgaWYgKCFnZW5lcmF0b3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3Iodmlld1R5cGUgP1xuICAgICAgICAgICAgICAgICAgICAnVGhlIEZ1bGxDYWxlbmRhciB2aWV3IFwiJyArIHZpZXdUeXBlICsgJ1wiIGRvZXMgbm90IGV4aXN0LiBNYWtlIHN1cmUgeW91ciBwbHVnaW5zIGFyZSBsb2FkZWQgY29ycmVjdGx5LicgOlxuICAgICAgICAgICAgICAgICAgICAnTm8gYXZhaWxhYmxlIEZ1bGxDYWxlbmRhciB2aWV3IHBsdWdpbnMuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXdEYXRlUHJvZmlsZSA9IGdlbmVyYXRvci5idWlsZChhY3Rpb24uZGF0ZU1hcmtlciB8fCBjdXJyZW50RGF0ZSwgdW5kZWZpbmVkLCB0cnVlIC8vIGZvcmNlVG9WYWxpZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpZiAobmV3RGF0ZVByb2ZpbGUgJiZcbiAgICAgICAgbmV3RGF0ZVByb2ZpbGUuaXNWYWxpZCAmJlxuICAgICAgICAhKGN1cnJlbnREYXRlUHJvZmlsZSAmJiBpc0RhdGVQcm9maWxlc0VxdWFsKGN1cnJlbnREYXRlUHJvZmlsZSwgbmV3RGF0ZVByb2ZpbGUpKSkge1xuICAgICAgICByZXR1cm4gbmV3RGF0ZVByb2ZpbGU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gY3VycmVudERhdGVQcm9maWxlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZHVjZUN1cnJlbnREYXRlKGN1cnJlbnREYXRlLCBhY3Rpb24sIGRhdGVQcm9maWxlKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdQUkVWJzpcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgICAgICBpZiAoIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLCBjdXJyZW50RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnREYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICBjYXNlICdTRVRfREFURSc6XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgdmFyIG5ld0RhdGUgPSBhY3Rpb24uZGF0ZU1hcmtlciB8fCBjdXJyZW50RGF0ZTtcbiAgICAgICAgICAgIGlmIChkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSAmJiAhcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgbmV3RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld0RhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudERhdGU7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlRGF0ZVNlbGVjdGlvbihjdXJyZW50U2VsZWN0aW9uLCBhY3Rpb24sIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRUxFQ1RfREFURVMnOlxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbi5zZWxlY3Rpb247XG4gICAgICAgIGNhc2UgJ1VOU0VMRUNUX0RBVEVTJzpcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRTZWxlY3Rpb247XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlU2VsZWN0ZWRFdmVudChjdXJyZW50SW5zdGFuY2VJZCwgYWN0aW9uKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRUxFQ1RfRVZFTlQnOlxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbi5ldmVudEluc3RhbmNlSWQ7XG4gICAgICAgIGNhc2UgJ1VOU0VMRUNUX0VWRU5UJzpcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50SW5zdGFuY2VJZDtcbiAgICB9XG59XG5mdW5jdGlvbiByZWR1Y2VFdmVudERyYWcoY3VycmVudERyYWcsIGFjdGlvbiwgc291cmNlcywgY2FsZW5kYXIpIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ1NFVF9FVkVOVF9EUkFHJzpcbiAgICAgICAgICAgIHZhciBuZXdEcmFnID0gYWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogbmV3RHJhZy5hZmZlY3RlZEV2ZW50cyxcbiAgICAgICAgICAgICAgICBtdXRhdGVkRXZlbnRzOiBuZXdEcmFnLm11dGF0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgaXNFdmVudDogbmV3RHJhZy5pc0V2ZW50LFxuICAgICAgICAgICAgICAgIG9yaWdTZWc6IG5ld0RyYWcub3JpZ1NlZ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAnVU5TRVRfRVZFTlRfRFJBRyc6XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50RHJhZztcbiAgICB9XG59XG5mdW5jdGlvbiByZWR1Y2VFdmVudFJlc2l6ZShjdXJyZW50UmVzaXplLCBhY3Rpb24sIHNvdXJjZXMsIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRVRfRVZFTlRfUkVTSVpFJzpcbiAgICAgICAgICAgIHZhciBuZXdSZXNpemUgPSBhY3Rpb24uc3RhdGU7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFmZmVjdGVkRXZlbnRzOiBuZXdSZXNpemUuYWZmZWN0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogbmV3UmVzaXplLm11dGF0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgaXNFdmVudDogbmV3UmVzaXplLmlzRXZlbnQsXG4gICAgICAgICAgICAgICAgb3JpZ1NlZzogbmV3UmVzaXplLm9yaWdTZWdcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgJ1VOU0VUX0VWRU5UX1JFU0laRSc6XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50UmVzaXplO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNvbXB1dGVMb2FkaW5nTGV2ZWwoZXZlbnRTb3VyY2VzKSB7XG4gICAgdmFyIGNudCA9IDA7XG4gICAgZm9yICh2YXIgc291cmNlSWQgaW4gZXZlbnRTb3VyY2VzKSB7XG4gICAgICAgIGlmIChldmVudFNvdXJjZXNbc291cmNlSWRdLmlzRmV0Y2hpbmcpIHtcbiAgICAgICAgICAgIGNudCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjbnQ7XG59XG5cbnZhciBTVEFOREFSRF9QUk9QUyA9IHtcbiAgICBzdGFydDogbnVsbCxcbiAgICBlbmQ6IG51bGwsXG4gICAgYWxsRGF5OiBCb29sZWFuXG59O1xuZnVuY3Rpb24gcGFyc2VEYXRlU3BhbihyYXcsIGRhdGVFbnYsIGRlZmF1bHREdXJhdGlvbikge1xuICAgIHZhciBzcGFuID0gcGFyc2VPcGVuRGF0ZVNwYW4ocmF3LCBkYXRlRW52KTtcbiAgICB2YXIgcmFuZ2UgPSBzcGFuLnJhbmdlO1xuICAgIGlmICghcmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICghcmFuZ2UuZW5kKSB7XG4gICAgICAgIGlmIChkZWZhdWx0RHVyYXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByYW5nZS5lbmQgPSBkYXRlRW52LmFkZChyYW5nZS5zdGFydCwgZGVmYXVsdER1cmF0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3Bhbjtcbn1cbi8qXG5UT0RPOiBzb21laG93IGNvbWJpbmUgd2l0aCBwYXJzZVJhbmdlP1xuV2lsbCByZXR1cm4gbnVsbCBpZiB0aGUgc3RhcnQvZW5kIHByb3BzIHdlcmUgcHJlc2VudCBidXQgcGFyc2VkIGludmFsaWRseS5cbiovXG5mdW5jdGlvbiBwYXJzZU9wZW5EYXRlU3BhbihyYXcsIGRhdGVFbnYpIHtcbiAgICB2YXIgbGVmdG92ZXJzID0ge307XG4gICAgdmFyIHN0YW5kYXJkUHJvcHMgPSByZWZpbmVQcm9wcyhyYXcsIFNUQU5EQVJEX1BST1BTLCB7fSwgbGVmdG92ZXJzKTtcbiAgICB2YXIgc3RhcnRNZXRhID0gc3RhbmRhcmRQcm9wcy5zdGFydCA/IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShzdGFuZGFyZFByb3BzLnN0YXJ0KSA6IG51bGw7XG4gICAgdmFyIGVuZE1ldGEgPSBzdGFuZGFyZFByb3BzLmVuZCA/IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShzdGFuZGFyZFByb3BzLmVuZCkgOiBudWxsO1xuICAgIHZhciBhbGxEYXkgPSBzdGFuZGFyZFByb3BzLmFsbERheTtcbiAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgYWxsRGF5ID0gKHN0YXJ0TWV0YSAmJiBzdGFydE1ldGEuaXNUaW1lVW5zcGVjaWZpZWQpICYmXG4gICAgICAgICAgICAoIWVuZE1ldGEgfHwgZW5kTWV0YS5pc1RpbWVVbnNwZWNpZmllZCk7XG4gICAgfVxuICAgIC8vIHVzZSB0aGlzIGxlZnRvdmVyIG9iamVjdCBhcyB0aGUgc2VsZWN0aW9uIG9iamVjdFxuICAgIGxlZnRvdmVycy5yYW5nZSA9IHtcbiAgICAgICAgc3RhcnQ6IHN0YXJ0TWV0YSA/IHN0YXJ0TWV0YS5tYXJrZXIgOiBudWxsLFxuICAgICAgICBlbmQ6IGVuZE1ldGEgPyBlbmRNZXRhLm1hcmtlciA6IG51bGxcbiAgICB9O1xuICAgIGxlZnRvdmVycy5hbGxEYXkgPSBhbGxEYXk7XG4gICAgcmV0dXJuIGxlZnRvdmVycztcbn1cbmZ1bmN0aW9uIGlzRGF0ZVNwYW5zRXF1YWwoc3BhbjAsIHNwYW4xKSB7XG4gICAgcmV0dXJuIHJhbmdlc0VxdWFsKHNwYW4wLnJhbmdlLCBzcGFuMS5yYW5nZSkgJiZcbiAgICAgICAgc3BhbjAuYWxsRGF5ID09PSBzcGFuMS5hbGxEYXkgJiZcbiAgICAgICAgaXNTcGFuUHJvcHNFcXVhbChzcGFuMCwgc3BhbjEpO1xufVxuLy8gdGhlIE5PTi1EQVRFLVJFTEFURUQgcHJvcHNcbmZ1bmN0aW9uIGlzU3BhblByb3BzRXF1YWwoc3BhbjAsIHNwYW4xKSB7XG4gICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gc3BhbjEpIHtcbiAgICAgICAgaWYgKHByb3BOYW1lICE9PSAncmFuZ2UnICYmIHByb3BOYW1lICE9PSAnYWxsRGF5Jykge1xuICAgICAgICAgICAgaWYgKHNwYW4wW3Byb3BOYW1lXSAhPT0gc3BhbjFbcHJvcE5hbWVdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGFyZSB0aGVyZSBhbnkgcHJvcHMgdGhhdCBzcGFuMCBoYXMgdGhhdCBzcGFuMSBET0VTTidUIGhhdmU/XG4gICAgLy8gYm90aCBoYXZlIHJhbmdlL2FsbERheSwgc28gbm8gbmVlZCB0byBzcGVjaWFsLWNhc2UuXG4gICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gc3BhbjApIHtcbiAgICAgICAgaWYgKCEocHJvcE5hbWUgaW4gc3BhbjEpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBidWlsZERhdGVTcGFuQXBpKHNwYW4sIGRhdGVFbnYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogZGF0ZUVudi50b0RhdGUoc3Bhbi5yYW5nZS5zdGFydCksXG4gICAgICAgIGVuZDogZGF0ZUVudi50b0RhdGUoc3Bhbi5yYW5nZS5lbmQpLFxuICAgICAgICBzdGFydFN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5zdGFydCwgeyBvbWl0VGltZTogc3Bhbi5hbGxEYXkgfSksXG4gICAgICAgIGVuZFN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5lbmQsIHsgb21pdFRpbWU6IHNwYW4uYWxsRGF5IH0pLFxuICAgICAgICBhbGxEYXk6IHNwYW4uYWxsRGF5XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRGF0ZVBvaW50QXBpKHNwYW4sIGRhdGVFbnYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkYXRlOiBkYXRlRW52LnRvRGF0ZShzcGFuLnJhbmdlLnN0YXJ0KSxcbiAgICAgICAgZGF0ZVN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5zdGFydCwgeyBvbWl0VGltZTogc3Bhbi5hbGxEYXkgfSksXG4gICAgICAgIGFsbERheTogc3Bhbi5hbGxEYXlcbiAgICB9O1xufVxuZnVuY3Rpb24gZmFicmljYXRlRXZlbnRSYW5nZShkYXRlU3BhbiwgZXZlbnRVaUJhc2VzLCBjYWxlbmRhcikge1xuICAgIHZhciBkZWYgPSBwYXJzZUV2ZW50RGVmKHsgZWRpdGFibGU6IGZhbHNlIH0sICcnLCAvLyBzb3VyY2VJZFxuICAgIGRhdGVTcGFuLmFsbERheSwgdHJ1ZSwgLy8gaGFzRW5kXG4gICAgY2FsZW5kYXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGRlZjogZGVmLFxuICAgICAgICB1aTogY29tcGlsZUV2ZW50VWkoZGVmLCBldmVudFVpQmFzZXMpLFxuICAgICAgICBpbnN0YW5jZTogY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIGRhdGVTcGFuLnJhbmdlKSxcbiAgICAgICAgcmFuZ2U6IGRhdGVTcGFuLnJhbmdlLFxuICAgICAgICBpc1N0YXJ0OiB0cnVlLFxuICAgICAgICBpc0VuZDogdHJ1ZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVWaWV3RGVmcyhkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKSB7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICB2YXIgdmlld1R5cGU7XG4gICAgZm9yICh2aWV3VHlwZSBpbiBkZWZhdWx0Q29uZmlncykge1xuICAgICAgICBlbnN1cmVWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICB9XG4gICAgZm9yICh2aWV3VHlwZSBpbiBvdmVycmlkZUNvbmZpZ3MpIHtcbiAgICAgICAgZW5zdXJlVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgfVxuICAgIHJldHVybiBoYXNoO1xufVxuZnVuY3Rpb24gZW5zdXJlVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncykge1xuICAgIGlmIChoYXNoW3ZpZXdUeXBlXSkge1xuICAgICAgICByZXR1cm4gaGFzaFt2aWV3VHlwZV07XG4gICAgfVxuICAgIHZhciB2aWV3RGVmID0gYnVpbGRWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICBpZiAodmlld0RlZikge1xuICAgICAgICBoYXNoW3ZpZXdUeXBlXSA9IHZpZXdEZWY7XG4gICAgfVxuICAgIHJldHVybiB2aWV3RGVmO1xufVxuZnVuY3Rpb24gYnVpbGRWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKSB7XG4gICAgdmFyIGRlZmF1bHRDb25maWcgPSBkZWZhdWx0Q29uZmlnc1t2aWV3VHlwZV07XG4gICAgdmFyIG92ZXJyaWRlQ29uZmlnID0gb3ZlcnJpZGVDb25maWdzW3ZpZXdUeXBlXTtcbiAgICB2YXIgcXVlcnlQcm9wID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIChkZWZhdWx0Q29uZmlnICYmIGRlZmF1bHRDb25maWdbbmFtZV0gIT09IG51bGwpID8gZGVmYXVsdENvbmZpZ1tuYW1lXSA6XG4gICAgICAgICAgICAoKG92ZXJyaWRlQ29uZmlnICYmIG92ZXJyaWRlQ29uZmlnW25hbWVdICE9PSBudWxsKSA/IG92ZXJyaWRlQ29uZmlnW25hbWVdIDogbnVsbCk7XG4gICAgfTtcbiAgICB2YXIgdGhlQ2xhc3MgPSBxdWVyeVByb3AoJ2NsYXNzJyk7XG4gICAgdmFyIHN1cGVyVHlwZSA9IHF1ZXJ5UHJvcCgnc3VwZXJUeXBlJyk7XG4gICAgaWYgKCFzdXBlclR5cGUgJiYgdGhlQ2xhc3MpIHtcbiAgICAgICAgc3VwZXJUeXBlID1cbiAgICAgICAgICAgIGZpbmRWaWV3TmFtZUJ5U3ViY2xhc3ModGhlQ2xhc3MsIG92ZXJyaWRlQ29uZmlncykgfHxcbiAgICAgICAgICAgICAgICBmaW5kVmlld05hbWVCeVN1YmNsYXNzKHRoZUNsYXNzLCBkZWZhdWx0Q29uZmlncyk7XG4gICAgfVxuICAgIHZhciBzdXBlckRlZiA9IG51bGw7XG4gICAgaWYgKHN1cGVyVHlwZSkge1xuICAgICAgICBpZiAoc3VwZXJUeXBlID09PSB2aWV3VHlwZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IGhhdmUgYSBjdXN0b20gdmlldyB0eXBlIHRoYXQgcmVmZXJlbmNlcyBpdHNlbGYnKTtcbiAgICAgICAgfVxuICAgICAgICBzdXBlckRlZiA9IGVuc3VyZVZpZXdEZWYoc3VwZXJUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICB9XG4gICAgaWYgKCF0aGVDbGFzcyAmJiBzdXBlckRlZikge1xuICAgICAgICB0aGVDbGFzcyA9IHN1cGVyRGVmLmNsYXNzO1xuICAgIH1cbiAgICBpZiAoIXRoZUNsYXNzKSB7XG4gICAgICAgIHJldHVybiBudWxsOyAvLyBkb24ndCB0aHJvdyBhIHdhcm5pbmcsIG1pZ2h0IGJlIHNldHRpbmdzIGZvciBhIHNpbmdsZS11bml0IHZpZXdcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogdmlld1R5cGUsXG4gICAgICAgIGNsYXNzOiB0aGVDbGFzcyxcbiAgICAgICAgZGVmYXVsdHM6IF9fYXNzaWduKHt9LCAoc3VwZXJEZWYgPyBzdXBlckRlZi5kZWZhdWx0cyA6IHt9KSwgKGRlZmF1bHRDb25maWcgPyBkZWZhdWx0Q29uZmlnLm9wdGlvbnMgOiB7fSkpLFxuICAgICAgICBvdmVycmlkZXM6IF9fYXNzaWduKHt9LCAoc3VwZXJEZWYgPyBzdXBlckRlZi5vdmVycmlkZXMgOiB7fSksIChvdmVycmlkZUNvbmZpZyA/IG92ZXJyaWRlQ29uZmlnLm9wdGlvbnMgOiB7fSkpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGZpbmRWaWV3TmFtZUJ5U3ViY2xhc3Modmlld1N1YmNsYXNzLCBjb25maWdzKSB7XG4gICAgdmFyIHN1cGVyUHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yodmlld1N1YmNsYXNzLnByb3RvdHlwZSk7XG4gICAgZm9yICh2YXIgdmlld1R5cGUgaW4gY29uZmlncykge1xuICAgICAgICB2YXIgcGFyc2VkID0gY29uZmlnc1t2aWV3VHlwZV07XG4gICAgICAgIC8vIG5lZWQgRElSRUNUIHN1YmNsYXNzLCBzbyBpbnN0YW5jZW9mIHdvbid0IGRvIGl0XG4gICAgICAgIGlmIChwYXJzZWQuY2xhc3MgJiYgcGFyc2VkLmNsYXNzLnByb3RvdHlwZSA9PT0gc3VwZXJQcm90bykge1xuICAgICAgICAgICAgcmV0dXJuIHZpZXdUeXBlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiAnJztcbn1cblxuZnVuY3Rpb24gcGFyc2VWaWV3Q29uZmlncyhpbnB1dHMpIHtcbiAgICByZXR1cm4gbWFwSGFzaChpbnB1dHMsIHBhcnNlVmlld0NvbmZpZyk7XG59XG52YXIgVklFV19ERUZfUFJPUFMgPSB7XG4gICAgdHlwZTogU3RyaW5nLFxuICAgIGNsYXNzOiBudWxsXG59O1xuZnVuY3Rpb24gcGFyc2VWaWV3Q29uZmlnKGlucHV0KSB7XG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBpbnB1dCA9IHsgY2xhc3M6IGlucHV0IH07XG4gICAgfVxuICAgIHZhciBvcHRpb25zID0ge307XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMoaW5wdXQsIFZJRVdfREVGX1BST1BTLCB7fSwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3VwZXJUeXBlOiBwcm9wcy50eXBlLFxuICAgICAgICBjbGFzczogcHJvcHMuY2xhc3MsXG4gICAgICAgIG9wdGlvbnM6IG9wdGlvbnNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZFZpZXdTcGVjcyhkZWZhdWx0SW5wdXRzLCBvcHRpb25zTWFuYWdlcikge1xuICAgIHZhciBkZWZhdWx0Q29uZmlncyA9IHBhcnNlVmlld0NvbmZpZ3MoZGVmYXVsdElucHV0cyk7XG4gICAgdmFyIG92ZXJyaWRlQ29uZmlncyA9IHBhcnNlVmlld0NvbmZpZ3Mob3B0aW9uc01hbmFnZXIub3ZlcnJpZGVzLnZpZXdzKTtcbiAgICB2YXIgdmlld0RlZnMgPSBjb21waWxlVmlld0RlZnMoZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgcmV0dXJuIG1hcEhhc2godmlld0RlZnMsIGZ1bmN0aW9uICh2aWV3RGVmKSB7XG4gICAgICAgIHJldHVybiBidWlsZFZpZXdTcGVjKHZpZXdEZWYsIG92ZXJyaWRlQ29uZmlncywgb3B0aW9uc01hbmFnZXIpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gYnVpbGRWaWV3U3BlYyh2aWV3RGVmLCBvdmVycmlkZUNvbmZpZ3MsIG9wdGlvbnNNYW5hZ2VyKSB7XG4gICAgdmFyIGR1cmF0aW9uSW5wdXQgPSB2aWV3RGVmLm92ZXJyaWRlcy5kdXJhdGlvbiB8fFxuICAgICAgICB2aWV3RGVmLmRlZmF1bHRzLmR1cmF0aW9uIHx8XG4gICAgICAgIG9wdGlvbnNNYW5hZ2VyLmR5bmFtaWNPdmVycmlkZXMuZHVyYXRpb24gfHxcbiAgICAgICAgb3B0aW9uc01hbmFnZXIub3ZlcnJpZGVzLmR1cmF0aW9uO1xuICAgIHZhciBkdXJhdGlvbiA9IG51bGw7XG4gICAgdmFyIGR1cmF0aW9uVW5pdCA9ICcnO1xuICAgIHZhciBzaW5nbGVVbml0ID0gJyc7XG4gICAgdmFyIHNpbmdsZVVuaXRPdmVycmlkZXMgPSB7fTtcbiAgICBpZiAoZHVyYXRpb25JbnB1dCkge1xuICAgICAgICBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKGR1cmF0aW9uSW5wdXQpO1xuICAgICAgICBpZiAoZHVyYXRpb24pIHsgLy8gdmFsaWQ/XG4gICAgICAgICAgICB2YXIgZGVub20gPSBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZHVyYXRpb24sICFnZXRXZWVrc0Zyb21JbnB1dChkdXJhdGlvbklucHV0KSk7XG4gICAgICAgICAgICBkdXJhdGlvblVuaXQgPSBkZW5vbS51bml0O1xuICAgICAgICAgICAgaWYgKGRlbm9tLnZhbHVlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlVW5pdCA9IGR1cmF0aW9uVW5pdDtcbiAgICAgICAgICAgICAgICBzaW5nbGVVbml0T3ZlcnJpZGVzID0gb3ZlcnJpZGVDb25maWdzW2R1cmF0aW9uVW5pdF0gPyBvdmVycmlkZUNvbmZpZ3NbZHVyYXRpb25Vbml0XS5vcHRpb25zIDoge307XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIHF1ZXJ5QnV0dG9uVGV4dCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciBidXR0b25UZXh0TWFwID0gb3B0aW9ucy5idXR0b25UZXh0IHx8IHt9O1xuICAgICAgICB2YXIgYnV0dG9uVGV4dEtleSA9IHZpZXdEZWYuZGVmYXVsdHMuYnV0dG9uVGV4dEtleTtcbiAgICAgICAgaWYgKGJ1dHRvblRleHRLZXkgIT0gbnVsbCAmJiBidXR0b25UZXh0TWFwW2J1dHRvblRleHRLZXldICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBidXR0b25UZXh0TWFwW2J1dHRvblRleHRLZXldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChidXR0b25UZXh0TWFwW3ZpZXdEZWYudHlwZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGJ1dHRvblRleHRNYXBbdmlld0RlZi50eXBlXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9uVGV4dE1hcFtzaW5nbGVVbml0XSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYnV0dG9uVGV4dE1hcFtzaW5nbGVVbml0XTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogdmlld0RlZi50eXBlLFxuICAgICAgICBjbGFzczogdmlld0RlZi5jbGFzcyxcbiAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uLFxuICAgICAgICBkdXJhdGlvblVuaXQ6IGR1cmF0aW9uVW5pdCxcbiAgICAgICAgc2luZ2xlVW5pdDogc2luZ2xlVW5pdCxcbiAgICAgICAgb3B0aW9uczogX19hc3NpZ24oe30sIGdsb2JhbERlZmF1bHRzLCB2aWV3RGVmLmRlZmF1bHRzLCBvcHRpb25zTWFuYWdlci5kaXJEZWZhdWx0cywgb3B0aW9uc01hbmFnZXIubG9jYWxlRGVmYXVsdHMsIG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcywgc2luZ2xlVW5pdE92ZXJyaWRlcywgdmlld0RlZi5vdmVycmlkZXMsIG9wdGlvbnNNYW5hZ2VyLmR5bmFtaWNPdmVycmlkZXMpLFxuICAgICAgICBidXR0b25UZXh0T3ZlcnJpZGU6IHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5keW5hbWljT3ZlcnJpZGVzKSB8fFxuICAgICAgICAgICAgcXVlcnlCdXR0b25UZXh0KG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcykgfHwgLy8gY29uc3RydWN0b3Itc3BlY2lmaWVkIGJ1dHRvblRleHQgbG9va3VwIGhhc2ggdGFrZXMgcHJlY2VkZW5jZVxuICAgICAgICAgICAgdmlld0RlZi5vdmVycmlkZXMuYnV0dG9uVGV4dCxcbiAgICAgICAgYnV0dG9uVGV4dERlZmF1bHQ6IHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5sb2NhbGVEZWZhdWx0cykgfHxcbiAgICAgICAgICAgIHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5kaXJEZWZhdWx0cykgfHxcbiAgICAgICAgICAgIHZpZXdEZWYuZGVmYXVsdHMuYnV0dG9uVGV4dCB8fFxuICAgICAgICAgICAgcXVlcnlCdXR0b25UZXh0KGdsb2JhbERlZmF1bHRzKSB8fFxuICAgICAgICAgICAgdmlld0RlZi50eXBlIC8vIGZhbGwgYmFjayB0byBnaXZlbiB2aWV3IG5hbWVcbiAgICB9O1xufVxuXG52YXIgVG9vbGJhciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoVG9vbGJhciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBUb29sYmFyKGV4dHJhQ2xhc3NOYW1lKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLl9yZW5kZXJMYXlvdXQgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckxheW91dCwgX3RoaXMudW5yZW5kZXJMYXlvdXQpO1xuICAgICAgICBfdGhpcy5fdXBkYXRlVGl0bGUgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnVwZGF0ZVRpdGxlLCBudWxsLCBbX3RoaXMuX3JlbmRlckxheW91dF0pO1xuICAgICAgICBfdGhpcy5fdXBkYXRlQWN0aXZlQnV0dG9uID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy51cGRhdGVBY3RpdmVCdXR0b24sIG51bGwsIFtfdGhpcy5fcmVuZGVyTGF5b3V0XSk7XG4gICAgICAgIF90aGlzLl91cGRhdGVUb2RheSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMudXBkYXRlVG9kYXksIG51bGwsIFtfdGhpcy5fcmVuZGVyTGF5b3V0XSk7XG4gICAgICAgIF90aGlzLl91cGRhdGVQcmV2ID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy51cGRhdGVQcmV2LCBudWxsLCBbX3RoaXMuX3JlbmRlckxheW91dF0pO1xuICAgICAgICBfdGhpcy5fdXBkYXRlTmV4dCA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMudXBkYXRlTmV4dCwgbnVsbCwgW190aGlzLl9yZW5kZXJMYXlvdXRdKTtcbiAgICAgICAgX3RoaXMuZWwgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLXRvb2xiYXIgJyArIGV4dHJhQ2xhc3NOYW1lIH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFRvb2xiYXIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLl9yZW5kZXJMYXlvdXQudW5yZW5kZXIoKTsgLy8gc2hvdWxkIHVucmVuZGVyIGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICByZW1vdmVFbGVtZW50KHRoaXMuZWwpO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlckxheW91dChwcm9wcy5sYXlvdXQpO1xuICAgICAgICB0aGlzLl91cGRhdGVUaXRsZShwcm9wcy50aXRsZSk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUFjdGl2ZUJ1dHRvbihwcm9wcy5hY3RpdmVCdXR0b24pO1xuICAgICAgICB0aGlzLl91cGRhdGVUb2RheShwcm9wcy5pc1RvZGF5RW5hYmxlZCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZXYocHJvcHMuaXNQcmV2RW5hYmxlZCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZU5leHQocHJvcHMuaXNOZXh0RW5hYmxlZCk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS5yZW5kZXJMYXlvdXQgPSBmdW5jdGlvbiAobGF5b3V0KSB7XG4gICAgICAgIHZhciBlbCA9IHRoaXMuZWw7XG4gICAgICAgIHRoaXMudmlld3NXaXRoQnV0dG9ucyA9IFtdO1xuICAgICAgICBhcHBlbmRUb0VsZW1lbnQoZWwsIHRoaXMucmVuZGVyU2VjdGlvbignbGVmdCcsIGxheW91dC5sZWZ0KSk7XG4gICAgICAgIGFwcGVuZFRvRWxlbWVudChlbCwgdGhpcy5yZW5kZXJTZWN0aW9uKCdjZW50ZXInLCBsYXlvdXQuY2VudGVyKSk7XG4gICAgICAgIGFwcGVuZFRvRWxlbWVudChlbCwgdGhpcy5yZW5kZXJTZWN0aW9uKCdyaWdodCcsIGxheW91dC5yaWdodCkpO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUudW5yZW5kZXJMYXlvdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gJyc7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS5yZW5kZXJTZWN0aW9uID0gZnVuY3Rpb24gKHBvc2l0aW9uLCBidXR0b25TdHIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCB0aGVtZSA9IF9hLnRoZW1lLCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyO1xuICAgICAgICB2YXIgb3B0aW9uc01hbmFnZXIgPSBjYWxlbmRhci5vcHRpb25zTWFuYWdlcjtcbiAgICAgICAgdmFyIHZpZXdTcGVjcyA9IGNhbGVuZGFyLnZpZXdTcGVjcztcbiAgICAgICAgdmFyIHNlY3Rpb25FbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHsgY2xhc3NOYW1lOiAnZmMtJyArIHBvc2l0aW9uIH0pO1xuICAgICAgICB2YXIgY2FsZW5kYXJDdXN0b21CdXR0b25zID0gb3B0aW9uc01hbmFnZXIuY29tcHV0ZWQuY3VzdG9tQnV0dG9ucyB8fCB7fTtcbiAgICAgICAgdmFyIGNhbGVuZGFyQnV0dG9uVGV4dE92ZXJyaWRlcyA9IG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcy5idXR0b25UZXh0IHx8IHt9O1xuICAgICAgICB2YXIgY2FsZW5kYXJCdXR0b25UZXh0ID0gb3B0aW9uc01hbmFnZXIuY29tcHV0ZWQuYnV0dG9uVGV4dCB8fCB7fTtcbiAgICAgICAgaWYgKGJ1dHRvblN0cikge1xuICAgICAgICAgICAgYnV0dG9uU3RyLnNwbGl0KCcgJykuZm9yRWFjaChmdW5jdGlvbiAoYnV0dG9uR3JvdXBTdHIsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBDaGlsZHJlbiA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpc09ubHlCdXR0b25zID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBFbDtcbiAgICAgICAgICAgICAgICBidXR0b25Hcm91cFN0ci5zcGxpdCgnLCcpLmZvckVhY2goZnVuY3Rpb24gKGJ1dHRvbk5hbWUsIGopIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN1c3RvbUJ1dHRvblByb3BzO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmlld1NwZWM7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25DbGljaztcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbkljb247IC8vIG9ubHkgb25lIG9mIHRoZXNlIHdpbGwgYmUgc2V0XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25UZXh0OyAvLyBcIlxuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uSW5uZXJIdG1sO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uQ2xhc3NlcztcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbkVsO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uQXJpYUF0dHI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChidXR0b25OYW1lID09PSAndGl0bGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cENoaWxkcmVuLnB1c2goaHRtbFRvRWxlbWVudCgnPGgyPiZuYnNwOzwvaDI+JykpOyAvLyB3ZSBhbHdheXMgd2FudCBpdCB0byB0YWtlIHVwIGhlaWdodFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNPbmx5QnV0dG9ucyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChjdXN0b21CdXR0b25Qcm9wcyA9IGNhbGVuZGFyQ3VzdG9tQnV0dG9uc1tidXR0b25OYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25DbGljayA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VzdG9tQnV0dG9uUHJvcHMuY2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbUJ1dHRvblByb3BzLmNsaWNrLmNhbGwoYnV0dG9uRWwsIGV2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvbkljb24gPSB0aGVtZS5nZXRDdXN0b21CdXR0b25JY29uQ2xhc3MoY3VzdG9tQnV0dG9uUHJvcHMpKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uSWNvbiA9IHRoZW1lLmdldEljb25DbGFzcyhidXR0b25OYW1lKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSBjdXN0b21CdXR0b25Qcm9wcy50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCh2aWV3U3BlYyA9IHZpZXdTcGVjc1tidXR0b25OYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy52aWV3c1dpdGhCdXR0b25zLnB1c2goYnV0dG9uTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQ2xpY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmNoYW5nZVZpZXcoYnV0dG9uTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uVGV4dCA9IHZpZXdTcGVjLmJ1dHRvblRleHRPdmVycmlkZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvbkljb24gPSB0aGVtZS5nZXRJY29uQ2xhc3MoYnV0dG9uTmFtZSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25UZXh0ID0gdmlld1NwZWMuYnV0dG9uVGV4dERlZmF1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY2FsZW5kYXJbYnV0dG9uTmFtZV0pIHsgLy8gYSBjYWxlbmRhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25DbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXJbYnV0dG9uTmFtZV0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25UZXh0ID0gY2FsZW5kYXJCdXR0b25UZXh0T3ZlcnJpZGVzW2J1dHRvbk5hbWVdKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uSWNvbiA9IHRoZW1lLmdldEljb25DbGFzcyhidXR0b25OYW1lKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSBjYWxlbmRhckJ1dHRvblRleHRbYnV0dG9uTmFtZV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgXiBldmVyeXRoaW5nIGVsc2UgaXMgY29uc2lkZXJlZCBkZWZhdWx0XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYnV0dG9uQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25DbGFzc2VzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZmMtJyArIGJ1dHRvbk5hbWUgKyAnLWJ1dHRvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lLmdldENsYXNzKCdidXR0b24nKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJ1dHRvblRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uSW5uZXJIdG1sID0gaHRtbEVzY2FwZShidXR0b25UZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQXJpYUF0dHIgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYnV0dG9uSWNvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25Jbm5lckh0bWwgPSBcIjxzcGFuIGNsYXNzPSdcIiArIGJ1dHRvbkljb24gKyBcIic+PC9zcGFuPlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25BcmlhQXR0ciA9ICcgYXJpYS1sYWJlbD1cIicgKyBidXR0b25OYW1lICsgJ1wiJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uRWwgPSBodG1sVG9FbGVtZW50KC8vIHR5cGU9XCJidXR0b25cIiBzbyB0aGF0IGl0IGRvZXNuJ3Qgc3VibWl0IGEgZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIicgKyBidXR0b25DbGFzc2VzLmpvaW4oJyAnKSArICdcIicgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25BcmlhQXR0ciArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc+JyArIGJ1dHRvbklubmVySHRtbCArICc8L2J1dHRvbj4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25FbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGJ1dHRvbkNsaWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cENoaWxkcmVuLnB1c2goYnV0dG9uRWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGdyb3VwQ2hpbGRyZW4ubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBncm91cEVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25Hcm91cENsYXNzTmFtZSA9IHRoZW1lLmdldENsYXNzKCdidXR0b25Hcm91cCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNPbmx5QnV0dG9ucyAmJiBidXR0b25Hcm91cENsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBFbC5jbGFzc0xpc3QuYWRkKGJ1dHRvbkdyb3VwQ2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQoZ3JvdXBFbCwgZ3JvdXBDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25FbC5hcHBlbmRDaGlsZChncm91cEVsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudChzZWN0aW9uRWwsIGdyb3VwQ2hpbGRyZW4pOyAvLyAxIG9yIDAgY2hpbGRyZW5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VjdGlvbkVsO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUudXBkYXRlVG9kYXkgPSBmdW5jdGlvbiAoaXNUb2RheUVuYWJsZWQpIHtcbiAgICAgICAgdGhpcy50b2dnbGVCdXR0b25FbmFibGVkKCd0b2RheScsIGlzVG9kYXlFbmFibGVkKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZVByZXYgPSBmdW5jdGlvbiAoaXNQcmV2RW5hYmxlZCkge1xuICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbkVuYWJsZWQoJ3ByZXYnLCBpc1ByZXZFbmFibGVkKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZU5leHQgPSBmdW5jdGlvbiAoaXNOZXh0RW5hYmxlZCkge1xuICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbkVuYWJsZWQoJ25leHQnLCBpc05leHRFbmFibGVkKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZVRpdGxlID0gZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgZmluZEVsZW1lbnRzKHRoaXMuZWwsICdoMicpLmZvckVhY2goZnVuY3Rpb24gKHRpdGxlRWwpIHtcbiAgICAgICAgICAgIHRpdGxlRWwuaW5uZXJUZXh0ID0gdGV4dDtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS51cGRhdGVBY3RpdmVCdXR0b24gPSBmdW5jdGlvbiAoYnV0dG9uTmFtZSkge1xuICAgICAgICB2YXIgdGhlbWUgPSB0aGlzLmNvbnRleHQudGhlbWU7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSB0aGVtZS5nZXRDbGFzcygnYnV0dG9uQWN0aXZlJyk7XG4gICAgICAgIGZpbmRFbGVtZW50cyh0aGlzLmVsLCAnYnV0dG9uJykuZm9yRWFjaChmdW5jdGlvbiAoYnV0dG9uRWwpIHtcbiAgICAgICAgICAgIGlmIChidXR0b25OYW1lICYmIGJ1dHRvbkVsLmNsYXNzTGlzdC5jb250YWlucygnZmMtJyArIGJ1dHRvbk5hbWUgKyAnLWJ1dHRvbicpKSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uRWwuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uRWwuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnRvZ2dsZUJ1dHRvbkVuYWJsZWQgPSBmdW5jdGlvbiAoYnV0dG9uTmFtZSwgYm9vbCkge1xuICAgICAgICBmaW5kRWxlbWVudHModGhpcy5lbCwgJy5mYy0nICsgYnV0dG9uTmFtZSArICctYnV0dG9uJykuZm9yRWFjaChmdW5jdGlvbiAoYnV0dG9uRWwpIHtcbiAgICAgICAgICAgIGJ1dHRvbkVsLmRpc2FibGVkID0gIWJvb2w7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIFRvb2xiYXI7XG59KENvbXBvbmVudCkpO1xuXG52YXIgQ2FsZW5kYXJDb21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKENhbGVuZGFyQ29tcG9uZW50LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENhbGVuZGFyQ29tcG9uZW50KGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmVsQ2xhc3NOYW1lcyA9IFtdO1xuICAgICAgICBfdGhpcy5yZW5kZXJTa2VsZXRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclNrZWxldG9uLCBfdGhpcy5fdW5yZW5kZXJTa2VsZXRvbik7XG4gICAgICAgIF90aGlzLnJlbmRlclRvb2xiYXJzID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyVG9vbGJhcnMsIF90aGlzLl91bnJlbmRlclRvb2xiYXJzLCBbX3RoaXMucmVuZGVyU2tlbGV0b25dKTtcbiAgICAgICAgX3RoaXMuYnVpbGRDb21wb25lbnRDb250ZXh0ID0gbWVtb2l6ZShidWlsZENvbXBvbmVudENvbnRleHQpO1xuICAgICAgICBfdGhpcy5idWlsZFZpZXdQcm9wVHJhbnNmb3JtZXJzID0gbWVtb2l6ZShidWlsZFZpZXdQcm9wVHJhbnNmb3JtZXJzKTtcbiAgICAgICAgX3RoaXMuZWwgPSBlbDtcbiAgICAgICAgX3RoaXMuY29tcHV0ZVRpdGxlID0gbWVtb2l6ZShjb21wdXRlVGl0bGUpO1xuICAgICAgICBfdGhpcy5wYXJzZUJ1c2luZXNzSG91cnMgPSBtZW1vaXplKGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIHBhcnNlQnVzaW5lc3NIb3VycyhpbnB1dCwgX3RoaXMuY29udGV4dC5jYWxlbmRhcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5mcmVlemVIZWlnaHQoKTtcbiAgICAgICAgdmFyIHRpdGxlID0gdGhpcy5jb21wdXRlVGl0bGUocHJvcHMuZGF0ZVByb2ZpbGUsIHByb3BzLnZpZXdTcGVjLm9wdGlvbnMpO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uKGNvbnRleHQpO1xuICAgICAgICB0aGlzLnJlbmRlclRvb2xiYXJzKHByb3BzLnZpZXdTcGVjLCBwcm9wcy5kYXRlUHJvZmlsZSwgcHJvcHMuY3VycmVudERhdGUsIHRpdGxlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJWaWV3KHByb3BzLCB0aXRsZSk7XG4gICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICB0aGlzLnRoYXdIZWlnaHQoKTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5mb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uLnVucmVuZGVyKCk7IC8vIHdpbGwgY2FsbCBkZXN0cm95Vmlld1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5fcmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUVsQ2xhc3NOYW1lcyhjb250ZXh0KTtcbiAgICAgICAgcHJlcGVuZFRvRWxlbWVudCh0aGlzLmVsLCB0aGlzLmNvbnRlbnRFbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHsgY2xhc3NOYW1lOiAnZmMtdmlldy1jb250YWluZXInIH0pKTtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy52aWV3Q29udGFpbmVyTW9kaWZpZXJzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIG1vZGlmeVZpZXdDb250YWluZXIgPSBfYVtfaV07XG4gICAgICAgICAgICBtb2RpZnlWaWV3Q29udGFpbmVyKHRoaXMuY29udGVudEVsLCBjYWxlbmRhcik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5fdW5yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2VpcmQgdG8gaGF2ZSB0aGlzIGhlcmVcbiAgICAgICAgaWYgKHRoaXMudmlldykge1xuICAgICAgICAgICAgdGhpcy5zYXZlZFNjcm9sbCA9IHRoaXMudmlldy5xdWVyeVNjcm9sbCgpO1xuICAgICAgICAgICAgdGhpcy52aWV3LmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHRoaXMudmlldyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmNvbnRlbnRFbCk7XG4gICAgICAgIHRoaXMucmVtb3ZlRWxDbGFzc05hbWVzKCk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUucmVtb3ZlRWxDbGFzc05hbWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2xhc3NMaXN0ID0gdGhpcy5lbC5jbGFzc0xpc3Q7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmVsQ2xhc3NOYW1lczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBjbGFzc05hbWUgPSBfYVtfaV07XG4gICAgICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbENsYXNzTmFtZXMgPSBbXTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS51cGRhdGVFbENsYXNzTmFtZXMgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB0aGlzLnJlbW92ZUVsQ2xhc3NOYW1lcygpO1xuICAgICAgICB2YXIgdGhlbWUgPSBjb250ZXh0LnRoZW1lLCBvcHRpb25zID0gY29udGV4dC5vcHRpb25zO1xuICAgICAgICB0aGlzLmVsQ2xhc3NOYW1lcyA9IFtcbiAgICAgICAgICAgICdmYycsXG4gICAgICAgICAgICAnZmMtJyArIG9wdGlvbnMuZGlyLFxuICAgICAgICAgICAgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldCcpXG4gICAgICAgIF07XG4gICAgICAgIHZhciBjbGFzc0xpc3QgPSB0aGlzLmVsLmNsYXNzTGlzdDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZWxDbGFzc05hbWVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGNsYXNzTmFtZSA9IF9hW19pXTtcbiAgICAgICAgICAgIGNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLl9yZW5kZXJUb29sYmFycyA9IGZ1bmN0aW9uICh2aWV3U3BlYywgZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlLCB0aXRsZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBjb250ZXh0ID0gX2EuY29udGV4dCwgaGVhZGVyID0gX2EuaGVhZGVyLCBmb290ZXIgPSBfYS5mb290ZXI7XG4gICAgICAgIHZhciBvcHRpb25zID0gY29udGV4dC5vcHRpb25zLCBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBoZWFkZXJMYXlvdXQgPSBvcHRpb25zLmhlYWRlcjtcbiAgICAgICAgdmFyIGZvb3RlckxheW91dCA9IG9wdGlvbnMuZm9vdGVyO1xuICAgICAgICB2YXIgZGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSB0aGlzLnByb3BzLmRhdGVQcm9maWxlR2VuZXJhdG9yO1xuICAgICAgICB2YXIgbm93ID0gY2FsZW5kYXIuZ2V0Tm93KCk7XG4gICAgICAgIHZhciB0b2RheUluZm8gPSBkYXRlUHJvZmlsZUdlbmVyYXRvci5idWlsZChub3cpO1xuICAgICAgICB2YXIgcHJldkluZm8gPSBkYXRlUHJvZmlsZUdlbmVyYXRvci5idWlsZFByZXYoZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlKTtcbiAgICAgICAgdmFyIG5leHRJbmZvID0gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGROZXh0KGRhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSk7XG4gICAgICAgIHZhciB0b29sYmFyUHJvcHMgPSB7XG4gICAgICAgICAgICB0aXRsZTogdGl0bGUsXG4gICAgICAgICAgICBhY3RpdmVCdXR0b246IHZpZXdTcGVjLnR5cGUsXG4gICAgICAgICAgICBpc1RvZGF5RW5hYmxlZDogdG9kYXlJbmZvLmlzVmFsaWQgJiYgIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLCBub3cpLFxuICAgICAgICAgICAgaXNQcmV2RW5hYmxlZDogcHJldkluZm8uaXNWYWxpZCxcbiAgICAgICAgICAgIGlzTmV4dEVuYWJsZWQ6IG5leHRJbmZvLmlzVmFsaWRcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGhlYWRlckxheW91dCkge1xuICAgICAgICAgICAgaWYgKCFoZWFkZXIpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXIgPSB0aGlzLmhlYWRlciA9IG5ldyBUb29sYmFyKCdmYy1oZWFkZXItdG9vbGJhcicpO1xuICAgICAgICAgICAgICAgIHByZXBlbmRUb0VsZW1lbnQodGhpcy5lbCwgaGVhZGVyLmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhlYWRlci5yZWNlaXZlUHJvcHMoX19hc3NpZ24oeyBsYXlvdXQ6IGhlYWRlckxheW91dCB9LCB0b29sYmFyUHJvcHMpLCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChoZWFkZXIpIHtcbiAgICAgICAgICAgIGhlYWRlci5kZXN0cm95KCk7XG4gICAgICAgICAgICBoZWFkZXIgPSB0aGlzLmhlYWRlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvb3RlckxheW91dCkge1xuICAgICAgICAgICAgaWYgKCFmb290ZXIpIHtcbiAgICAgICAgICAgICAgICBmb290ZXIgPSB0aGlzLmZvb3RlciA9IG5ldyBUb29sYmFyKCdmYy1mb290ZXItdG9vbGJhcicpO1xuICAgICAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudCh0aGlzLmVsLCBmb290ZXIuZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9vdGVyLnJlY2VpdmVQcm9wcyhfX2Fzc2lnbih7IGxheW91dDogZm9vdGVyTGF5b3V0IH0sIHRvb2xiYXJQcm9wcyksIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGZvb3Rlcikge1xuICAgICAgICAgICAgZm9vdGVyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIGZvb3RlciA9IHRoaXMuZm9vdGVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLl91bnJlbmRlclRvb2xiYXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5mb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnJlbmRlclZpZXcgPSBmdW5jdGlvbiAocHJvcHMsIHRpdGxlKSB7XG4gICAgICAgIHZhciB2aWV3ID0gdGhpcy52aWV3O1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIG9wdGlvbnMgPSBfYS5vcHRpb25zO1xuICAgICAgICB2YXIgdmlld1NwZWMgPSBwcm9wcy52aWV3U3BlYywgZGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSBwcm9wcy5kYXRlUHJvZmlsZUdlbmVyYXRvcjtcbiAgICAgICAgaWYgKCF2aWV3IHx8IHZpZXcudmlld1NwZWMgIT09IHZpZXdTcGVjKSB7XG4gICAgICAgICAgICBpZiAodmlldykge1xuICAgICAgICAgICAgICAgIHZpZXcuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmlldyA9IHRoaXMudmlldyA9IG5ldyB2aWV3U3BlY1snY2xhc3MnXSh2aWV3U3BlYywgdGhpcy5jb250ZW50RWwpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc2F2ZWRTY3JvbGwpIHtcbiAgICAgICAgICAgICAgICB2aWV3LmFkZFNjcm9sbCh0aGlzLnNhdmVkU2Nyb2xsLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNhdmVkU2Nyb2xsID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2aWV3LnRpdGxlID0gdGl0bGU7IC8vIGZvciB0aGUgQVBJXG4gICAgICAgIHZhciB2aWV3UHJvcHMgPSB7XG4gICAgICAgICAgICBkYXRlUHJvZmlsZUdlbmVyYXRvcjogZGF0ZVByb2ZpbGVHZW5lcmF0b3IsXG4gICAgICAgICAgICBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICBidXNpbmVzc0hvdXJzOiB0aGlzLnBhcnNlQnVzaW5lc3NIb3Vycyh2aWV3U3BlYy5vcHRpb25zLmJ1c2luZXNzSG91cnMpLFxuICAgICAgICAgICAgZXZlbnRTdG9yZTogcHJvcHMuZXZlbnRTdG9yZSxcbiAgICAgICAgICAgIGV2ZW50VWlCYXNlczogcHJvcHMuZXZlbnRVaUJhc2VzLFxuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvbjogcHJvcHMuZGF0ZVNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IHByb3BzLmV2ZW50UmVzaXplXG4gICAgICAgIH07XG4gICAgICAgIHZhciB0cmFuc2Zvcm1lcnMgPSB0aGlzLmJ1aWxkVmlld1Byb3BUcmFuc2Zvcm1lcnMoY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLnZpZXdQcm9wc1RyYW5zZm9ybWVycyk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgdHJhbnNmb3JtZXJzXzEgPSB0cmFuc2Zvcm1lcnM7IF9pIDwgdHJhbnNmb3JtZXJzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNmb3JtZXIgPSB0cmFuc2Zvcm1lcnNfMVtfaV07XG4gICAgICAgICAgICBfX2Fzc2lnbih2aWV3UHJvcHMsIHRyYW5zZm9ybWVyLnRyYW5zZm9ybSh2aWV3UHJvcHMsIHZpZXdTcGVjLCBwcm9wcywgb3B0aW9ucykpO1xuICAgICAgICB9XG4gICAgICAgIHZpZXcucmVjZWl2ZVByb3BzKHZpZXdQcm9wcywgdGhpcy5idWlsZENvbXBvbmVudENvbnRleHQodGhpcy5jb250ZXh0LCB2aWV3U3BlYywgdmlldykpO1xuICAgIH07XG4gICAgLy8gU2l6aW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUudXBkYXRlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSkge1xuICAgICAgICBpZiAoaXNSZXNpemUgPT09IHZvaWQgMCkgeyBpc1Jlc2l6ZSA9IGZhbHNlOyB9XG4gICAgICAgIHZhciB2aWV3ID0gdGhpcy52aWV3O1xuICAgICAgICBpZiAoIXZpZXcpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gd2h5P1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Jlc2l6ZSB8fCB0aGlzLmlzSGVpZ2h0QXV0byA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXB1dGVIZWlnaHRWYXJzKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlldy51cGRhdGVTaXplKGlzUmVzaXplLCB0aGlzLnZpZXdIZWlnaHQsIHRoaXMuaXNIZWlnaHRBdXRvKTtcbiAgICAgICAgdmlldy51cGRhdGVOb3dJbmRpY2F0b3IoKTsgLy8gd2UgbmVlZCB0byBndWFyYW50ZWUgdGhpcyB3aWxsIHJ1biBhZnRlciB1cGRhdGVTaXplXG4gICAgICAgIHZpZXcucG9wU2Nyb2xsKGlzUmVzaXplKTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5jb21wdXRlSGVpZ2h0VmFycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdGhpcy5jb250ZXh0LmNhbGVuZGFyOyAvLyB5dWNrLiBuZWVkIHRvIGhhbmRsZSBkeW5hbWljIG9wdGlvbnNcbiAgICAgICAgdmFyIGhlaWdodElucHV0ID0gY2FsZW5kYXIub3B0KCdoZWlnaHQnKTtcbiAgICAgICAgdmFyIGNvbnRlbnRIZWlnaHRJbnB1dCA9IGNhbGVuZGFyLm9wdCgnY29udGVudEhlaWdodCcpO1xuICAgICAgICB0aGlzLmlzSGVpZ2h0QXV0byA9IGhlaWdodElucHV0ID09PSAnYXV0bycgfHwgY29udGVudEhlaWdodElucHV0ID09PSAnYXV0byc7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGVudEhlaWdodElucHV0ID09PSAnbnVtYmVyJykgeyAvLyBleGlzdHMgYW5kIG5vdCAnYXV0bydcbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IGNvbnRlbnRIZWlnaHRJbnB1dDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgY29udGVudEhlaWdodElucHV0ID09PSAnZnVuY3Rpb24nKSB7IC8vIGV4aXN0cyBhbmQgaXMgYSBmdW5jdGlvblxuICAgICAgICAgICAgdGhpcy52aWV3SGVpZ2h0ID0gY29udGVudEhlaWdodElucHV0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGhlaWdodElucHV0ID09PSAnbnVtYmVyJykgeyAvLyBleGlzdHMgYW5kIG5vdCAnYXV0bydcbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IGhlaWdodElucHV0IC0gdGhpcy5xdWVyeVRvb2xiYXJzSGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGhlaWdodElucHV0ID09PSAnZnVuY3Rpb24nKSB7IC8vIGV4aXN0cyBhbmQgaXMgYSBmdW5jdGlvblxuICAgICAgICAgICAgdGhpcy52aWV3SGVpZ2h0ID0gaGVpZ2h0SW5wdXQoKSAtIHRoaXMucXVlcnlUb29sYmFyc0hlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGhlaWdodElucHV0ID09PSAncGFyZW50JykgeyAvLyBzZXQgdG8gaGVpZ2h0IG9mIHBhcmVudCBlbGVtZW50XG4gICAgICAgICAgICB2YXIgcGFyZW50RWwgPSB0aGlzLmVsLnBhcmVudE5vZGU7XG4gICAgICAgICAgICB0aGlzLnZpZXdIZWlnaHQgPSBwYXJlbnRFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgLSB0aGlzLnF1ZXJ5VG9vbGJhcnNIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IE1hdGgucm91bmQodGhpcy5jb250ZW50RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggL1xuICAgICAgICAgICAgICAgIE1hdGgubWF4KGNhbGVuZGFyLm9wdCgnYXNwZWN0UmF0aW8nKSwgLjUpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnF1ZXJ5VG9vbGJhcnNIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBoZWlnaHQgPSAwO1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIGhlaWdodCArPSBjb21wdXRlSGVpZ2h0QW5kTWFyZ2lucyh0aGlzLmhlYWRlci5lbCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZm9vdGVyKSB7XG4gICAgICAgICAgICBoZWlnaHQgKz0gY29tcHV0ZUhlaWdodEFuZE1hcmdpbnModGhpcy5mb290ZXIuZWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoZWlnaHQ7XG4gICAgfTtcbiAgICAvLyBIZWlnaHQgXCJGcmVlemluZ1wiXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUuZnJlZXplSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBhcHBseVN0eWxlKHRoaXMuZWwsIHtcbiAgICAgICAgICAgIGhlaWdodDogdGhpcy5lbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQsXG4gICAgICAgICAgICBvdmVyZmxvdzogJ2hpZGRlbidcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUudGhhd0hlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmVsLCB7XG4gICAgICAgICAgICBoZWlnaHQ6ICcnLFxuICAgICAgICAgICAgb3ZlcmZsb3c6ICcnXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIENhbGVuZGFyQ29tcG9uZW50O1xufShDb21wb25lbnQpKTtcbi8vIFRpdGxlIGFuZCBEYXRlIEZvcm1hdHRpbmdcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDb21wdXRlcyB3aGF0IHRoZSB0aXRsZSBhdCB0aGUgdG9wIG9mIHRoZSBjYWxlbmRhciBzaG91bGQgYmUgZm9yIHRoaXMgdmlld1xuZnVuY3Rpb24gY29tcHV0ZVRpdGxlKGRhdGVQcm9maWxlLCB2aWV3T3B0aW9ucykge1xuICAgIHZhciByYW5nZTtcbiAgICAvLyBmb3Igdmlld3MgdGhhdCBzcGFuIGEgbGFyZ2UgdW5pdCBvZiB0aW1lLCBzaG93IHRoZSBwcm9wZXIgaW50ZXJ2YWwsIGlnbm9yaW5nIHN0cmF5IGRheXMgYmVmb3JlIGFuZCBhZnRlclxuICAgIGlmICgvXih5ZWFyfG1vbnRoKSQvLnRlc3QoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdCkpIHtcbiAgICAgICAgcmFuZ2UgPSBkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2U7XG4gICAgfVxuICAgIGVsc2UgeyAvLyBmb3IgZGF5IHVuaXRzIG9yIHNtYWxsZXIsIHVzZSB0aGUgYWN0dWFsIGRheSByYW5nZVxuICAgICAgICByYW5nZSA9IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYuZm9ybWF0UmFuZ2UocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCwgY3JlYXRlRm9ybWF0dGVyKHZpZXdPcHRpb25zLnRpdGxlRm9ybWF0IHx8IGNvbXB1dGVUaXRsZUZvcm1hdChkYXRlUHJvZmlsZSksIHZpZXdPcHRpb25zLnRpdGxlUmFuZ2VTZXBhcmF0b3IpLCB7IGlzRW5kRXhjbHVzaXZlOiBkYXRlUHJvZmlsZS5pc1JhbmdlQWxsRGF5IH0pO1xufVxuLy8gR2VuZXJhdGVzIHRoZSBmb3JtYXQgc3RyaW5nIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIHRpdGxlIGZvciB0aGUgY3VycmVudCBkYXRlIHJhbmdlLlxuLy8gQXR0ZW1wdHMgdG8gY29tcHV0ZSB0aGUgbW9zdCBhcHByb3ByaWF0ZSBmb3JtYXQgaWYgbm90IGV4cGxpY2l0bHkgc3BlY2lmaWVkIHdpdGggYHRpdGxlRm9ybWF0YC5cbmZ1bmN0aW9uIGNvbXB1dGVUaXRsZUZvcm1hdChkYXRlUHJvZmlsZSkge1xuICAgIHZhciBjdXJyZW50UmFuZ2VVbml0ID0gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdDtcbiAgICBpZiAoY3VycmVudFJhbmdlVW5pdCA9PT0gJ3llYXInKSB7XG4gICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJyB9O1xuICAgIH1cbiAgICBlbHNlIGlmIChjdXJyZW50UmFuZ2VVbml0ID09PSAnbW9udGgnKSB7XG4gICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdsb25nJyB9OyAvLyBsaWtlIFwiU2VwdGVtYmVyIDIwMTRcIlxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGRheXMgPSBkaWZmV2hvbGVEYXlzKGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5zdGFydCwgZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLmVuZCk7XG4gICAgICAgIGlmIChkYXlzICE9PSBudWxsICYmIGRheXMgPiAxKSB7XG4gICAgICAgICAgICAvLyBtdWx0aS1kYXkgcmFuZ2UuIHNob3J0ZXIsIGxpa2UgXCJTZXAgOSAtIDEwIDIwMTRcIlxuICAgICAgICAgICAgcmV0dXJuIHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ3Nob3J0JywgZGF5OiAnbnVtZXJpYycgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIG9uZSBkYXkuIGxvbmdlciwgbGlrZSBcIlNlcHRlbWJlciA5IDIwMTRcIlxuICAgICAgICAgICAgcmV0dXJuIHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJyB9O1xuICAgICAgICB9XG4gICAgfVxufVxuLy8gYnVpbGQgYSBjb250ZXh0IHNjb3BlZCB0byB0aGUgdmlld1xuZnVuY3Rpb24gYnVpbGRDb21wb25lbnRDb250ZXh0KGNvbnRleHQsIHZpZXdTcGVjLCB2aWV3KSB7XG4gICAgcmV0dXJuIGNvbnRleHQuZXh0ZW5kKHZpZXdTcGVjLm9wdGlvbnMsIHZpZXcpO1xufVxuLy8gUGx1Z2luXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyh0aGVDbGFzc2VzKSB7XG4gICAgcmV0dXJuIHRoZUNsYXNzZXMubWFwKGZ1bmN0aW9uICh0aGVDbGFzcykge1xuICAgICAgICByZXR1cm4gbmV3IHRoZUNsYXNzKCk7XG4gICAgfSk7XG59XG5cbnZhciBJbnRlcmFjdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBJbnRlcmFjdGlvbihzZXR0aW5ncykge1xuICAgICAgICB0aGlzLmNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICB9XG4gICAgSW50ZXJhY3Rpb24ucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICByZXR1cm4gSW50ZXJhY3Rpb247XG59KCkpO1xuZnVuY3Rpb24gcGFyc2VJbnRlcmFjdGlvblNldHRpbmdzKGNvbXBvbmVudCwgaW5wdXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCxcbiAgICAgICAgZWw6IGlucHV0LmVsLFxuICAgICAgICB1c2VFdmVudENlbnRlcjogaW5wdXQudXNlRXZlbnRDZW50ZXIgIT0gbnVsbCA/IGlucHV0LnVzZUV2ZW50Q2VudGVyIDogdHJ1ZVxuICAgIH07XG59XG5mdW5jdGlvbiBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykge1xuICAgIHZhciBfYTtcbiAgICByZXR1cm4gX2EgPSB7fSxcbiAgICAgICAgX2Fbc2V0dGluZ3MuY29tcG9uZW50LnVpZF0gPSBzZXR0aW5ncyxcbiAgICAgICAgX2E7XG59XG4vLyBnbG9iYWwgc3RhdGVcbnZhciBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUgPSB7fTtcblxuLypcbkRldGVjdHMgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYW4gZXZlbnQgd2l0aGluIGEgRGF0ZUNvbXBvbmVudFxuKi9cbnZhciBFdmVudENsaWNraW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhFdmVudENsaWNraW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEV2ZW50Q2xpY2tpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmhhbmRsZVNlZ0NsaWNrID0gZnVuY3Rpb24gKGV2LCBzZWdFbCkge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIHZhciBfYSA9IGNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgICAgIHZhciBzZWcgPSBnZXRFbFNlZyhzZWdFbCk7XG4gICAgICAgICAgICBpZiAoc2VnICYmIC8vIG1pZ2h0IGJlIHRoZSA8ZGl2PiBzdXJyb3VuZGluZyB0aGUgbW9yZSBsaW5rXG4gICAgICAgICAgICAgICAgY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwoZXYudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgIC8vIG91ciB3YXkgdG8gc2ltdWxhdGUgYSBsaW5rIGNsaWNrIGZvciBlbGVtZW50cyB0aGF0IGNhbid0IGJlIDxhPiB0YWdzXG4gICAgICAgICAgICAgICAgLy8gZ3JhYiBiZWZvcmUgdHJpZ2dlciBmaXJlZCBpbiBjYXNlIHRyaWdnZXIgdHJhc2hlcyBET00gdGhydSByZXJlbmRlcmluZ1xuICAgICAgICAgICAgICAgIHZhciBoYXNVcmxDb250YWluZXIgPSBlbGVtZW50Q2xvc2VzdChldi50YXJnZXQsICcuZmMtaGFzLXVybCcpO1xuICAgICAgICAgICAgICAgIHZhciB1cmwgPSBoYXNVcmxDb250YWluZXIgPyBoYXNVcmxDb250YWluZXIucXVlcnlTZWxlY3RvcignYVtocmVmXScpLmhyZWYgOiAnJztcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50Q2xpY2snLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiBzZWdFbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIsIHNlZy5ldmVudFJhbmdlLmRlZiwgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICBpZiAodXJsICYmICFldi5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgX3RoaXMuZGVzdHJveSA9IGxpc3RlbkJ5U2VsZWN0b3IoY29tcG9uZW50LmVsLCAnY2xpY2snLCBjb21wb25lbnQuZmdTZWdTZWxlY3RvciArICcsJyArIGNvbXBvbmVudC5iZ1NlZ1NlbGVjdG9yLCBfdGhpcy5oYW5kbGVTZWdDbGljayk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIEV2ZW50Q2xpY2tpbmc7XG59KEludGVyYWN0aW9uKSk7XG5cbi8qXG5UcmlnZ2VycyBldmVudHMgYW5kIGFkZHMvcmVtb3ZlcyBjb3JlIGNsYXNzTmFtZXMgd2hlbiB0aGUgdXNlcidzIHBvaW50ZXJcbmVudGVycy9sZWF2ZXMgZXZlbnQtZWxlbWVudHMgb2YgYSBjb21wb25lbnQuXG4qL1xudmFyIEV2ZW50SG92ZXJpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEV2ZW50SG92ZXJpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRXZlbnRIb3ZlcmluZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgLy8gZm9yIHNpbXVsYXRpbmcgYW4gZXZlbnRNb3VzZUxlYXZlIHdoZW4gdGhlIGV2ZW50IGVsIGlzIGRlc3Ryb3llZCB3aGlsZSBtb3VzZSBpcyBvdmVyIGl0XG4gICAgICAgIF90aGlzLmhhbmRsZUV2ZW50RWxSZW1vdmUgPSBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbCA9PT0gX3RoaXMuY3VycmVudFNlZ0VsKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGFuZGxlU2VnTGVhdmUobnVsbCwgX3RoaXMuY3VycmVudFNlZ0VsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlU2VnRW50ZXIgPSBmdW5jdGlvbiAoZXYsIHNlZ0VsKSB7XG4gICAgICAgICAgICBpZiAoZ2V0RWxTZWcoc2VnRWwpKSB7IC8vIFRPRE86IGJldHRlciB3YXkgdG8gbWFrZSBzdXJlIG5vdCBob3ZlcmluZyBvdmVyIG1vcmUrIGxpbmsgb3IgaXRzIHdyYXBwZXJcbiAgICAgICAgICAgICAgICBzZWdFbC5jbGFzc0xpc3QuYWRkKCdmYy1hbGxvdy1tb3VzZS1yZXNpemUnKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jdXJyZW50U2VnRWwgPSBzZWdFbDtcbiAgICAgICAgICAgICAgICBfdGhpcy50cmlnZ2VyRXZlbnQoJ2V2ZW50TW91c2VFbnRlcicsIGV2LCBzZWdFbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVNlZ0xlYXZlID0gZnVuY3Rpb24gKGV2LCBzZWdFbCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmN1cnJlbnRTZWdFbCkge1xuICAgICAgICAgICAgICAgIHNlZ0VsLmNsYXNzTGlzdC5yZW1vdmUoJ2ZjLWFsbG93LW1vdXNlLXJlc2l6ZScpO1xuICAgICAgICAgICAgICAgIF90aGlzLmN1cnJlbnRTZWdFbCA9IG51bGw7XG4gICAgICAgICAgICAgICAgX3RoaXMudHJpZ2dlckV2ZW50KCdldmVudE1vdXNlTGVhdmUnLCBldiwgc2VnRWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gc2V0dGluZ3MuY29tcG9uZW50O1xuICAgICAgICBfdGhpcy5yZW1vdmVIb3Zlckxpc3RlbmVycyA9IGxpc3RlblRvSG92ZXJCeVNlbGVjdG9yKGNvbXBvbmVudC5lbCwgY29tcG9uZW50LmZnU2VnU2VsZWN0b3IgKyAnLCcgKyBjb21wb25lbnQuYmdTZWdTZWxlY3RvciwgX3RoaXMuaGFuZGxlU2VnRW50ZXIsIF90aGlzLmhhbmRsZVNlZ0xlYXZlKTtcbiAgICAgICAgLy8gaG93IHRvIG1ha2Ugc3VyZSBjb21wb25lbnQgYWxyZWFkeSBoYXMgY29udGV4dD9cbiAgICAgICAgY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIub24oJ2V2ZW50RWxSZW1vdmUnLCBfdGhpcy5oYW5kbGVFdmVudEVsUmVtb3ZlKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBFdmVudEhvdmVyaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlbW92ZUhvdmVyTGlzdGVuZXJzKCk7XG4gICAgICAgIHRoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIub2ZmKCdldmVudEVsUmVtb3ZlJywgdGhpcy5oYW5kbGVFdmVudEVsUmVtb3ZlKTtcbiAgICB9O1xuICAgIEV2ZW50SG92ZXJpbmcucHJvdG90eXBlLnRyaWdnZXJFdmVudCA9IGZ1bmN0aW9uIChwdWJsaWNFdk5hbWUsIGV2LCBzZWdFbCkge1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnQ7XG4gICAgICAgIHZhciBfYSA9IGNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgdmFyIHNlZyA9IGdldEVsU2VnKHNlZ0VsKTtcbiAgICAgICAgaWYgKCFldiB8fCBjb21wb25lbnQuaXNWYWxpZFNlZ0Rvd25FbChldi50YXJnZXQpKSB7XG4gICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIocHVibGljRXZOYW1lLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBlbDogc2VnRWwsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIHNlZy5ldmVudFJhbmdlLmRlZiwgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gRXZlbnRIb3ZlcmluZztcbn0oSW50ZXJhY3Rpb24pKTtcblxudmFyIFN0YW5kYXJkVGhlbWUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFN0YW5kYXJkVGhlbWUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU3RhbmRhcmRUaGVtZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gU3RhbmRhcmRUaGVtZTtcbn0oVGhlbWUpKTtcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmNsYXNzZXMgPSB7XG4gICAgd2lkZ2V0OiAnZmMtdW50aGVtZWQnLFxuICAgIHdpZGdldEhlYWRlcjogJ2ZjLXdpZGdldC1oZWFkZXInLFxuICAgIHdpZGdldENvbnRlbnQ6ICdmYy13aWRnZXQtY29udGVudCcsXG4gICAgYnV0dG9uR3JvdXA6ICdmYy1idXR0b24tZ3JvdXAnLFxuICAgIGJ1dHRvbjogJ2ZjLWJ1dHRvbiBmYy1idXR0b24tcHJpbWFyeScsXG4gICAgYnV0dG9uQWN0aXZlOiAnZmMtYnV0dG9uLWFjdGl2ZScsXG4gICAgcG9wb3ZlckhlYWRlcjogJ2ZjLXdpZGdldC1oZWFkZXInLFxuICAgIHBvcG92ZXJDb250ZW50OiAnZmMtd2lkZ2V0LWNvbnRlbnQnLFxuICAgIC8vIGRheSBncmlkXG4gICAgaGVhZGVyUm93OiAnZmMtd2lkZ2V0LWhlYWRlcicsXG4gICAgZGF5Um93OiAnZmMtd2lkZ2V0LWNvbnRlbnQnLFxuICAgIC8vIGxpc3Qgdmlld1xuICAgIGxpc3RWaWV3OiAnZmMtd2lkZ2V0LWNvbnRlbnQnXG59O1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuYmFzZUljb25DbGFzcyA9ICdmYy1pY29uJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25DbGFzc2VzID0ge1xuICAgIGNsb3NlOiAnZmMtaWNvbi14JyxcbiAgICBwcmV2OiAnZmMtaWNvbi1jaGV2cm9uLWxlZnQnLFxuICAgIG5leHQ6ICdmYy1pY29uLWNoZXZyb24tcmlnaHQnLFxuICAgIHByZXZZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1sZWZ0JyxcbiAgICBuZXh0WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtcmlnaHQnXG59O1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlT3B0aW9uID0gJ2J1dHRvbkljb25zJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25PdmVycmlkZUN1c3RvbUJ1dHRvbk9wdGlvbiA9ICdpY29uJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25PdmVycmlkZVByZWZpeCA9ICdmYy1pY29uLSc7XG5cbnZhciBDYWxlbmRhciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYWxlbmRhcihlbCwgb3ZlcnJpZGVzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYnVpbGRDb21wb25lbnRDb250ZXh0ID0gbWVtb2l6ZShidWlsZENvbXBvbmVudENvbnRleHQkMSk7XG4gICAgICAgIHRoaXMucGFyc2VSYXdMb2NhbGVzID0gbWVtb2l6ZShwYXJzZVJhd0xvY2FsZXMpO1xuICAgICAgICB0aGlzLmJ1aWxkTG9jYWxlID0gbWVtb2l6ZShidWlsZExvY2FsZSk7XG4gICAgICAgIHRoaXMuYnVpbGREYXRlRW52ID0gbWVtb2l6ZShidWlsZERhdGVFbnYpO1xuICAgICAgICB0aGlzLmJ1aWxkVGhlbWUgPSBtZW1vaXplKGJ1aWxkVGhlbWUpO1xuICAgICAgICB0aGlzLmJ1aWxkRXZlbnRVaVNpbmdsZUJhc2UgPSBtZW1vaXplKHRoaXMuX2J1aWxkRXZlbnRVaVNpbmdsZUJhc2UpO1xuICAgICAgICB0aGlzLmJ1aWxkU2VsZWN0aW9uQ29uZmlnID0gbWVtb2l6ZSh0aGlzLl9idWlsZFNlbGVjdGlvbkNvbmZpZyk7XG4gICAgICAgIHRoaXMuYnVpbGRFdmVudFVpQnlTb3VyY2UgPSBtZW1vaXplT3V0cHV0KGJ1aWxkRXZlbnRVaUJ5U291cmNlLCBpc1Byb3BzRXF1YWwpO1xuICAgICAgICB0aGlzLmJ1aWxkRXZlbnRVaUJhc2VzID0gbWVtb2l6ZShidWlsZEV2ZW50VWlCYXNlcyk7XG4gICAgICAgIHRoaXMuaW50ZXJhY3Rpb25zU3RvcmUgPSB7fTtcbiAgICAgICAgdGhpcy5hY3Rpb25RdWV1ZSA9IFtdO1xuICAgICAgICB0aGlzLmlzUmVkdWNpbmcgPSBmYWxzZTtcbiAgICAgICAgLy8gaXNEaXNwbGF5aW5nOiBib29sZWFuID0gZmFsc2UgLy8gaW5zdGFsbGVkIGluIERPTT8gYWNjZXB0aW5nIHJlbmRlcnM/XG4gICAgICAgIHRoaXMubmVlZHNSZXJlbmRlciA9IGZhbHNlOyAvLyBuZWVkcyBhIHJlbmRlcj9cbiAgICAgICAgdGhpcy5pc1JlbmRlcmluZyA9IGZhbHNlOyAvLyBjdXJyZW50bHkgaW4gdGhlIGV4ZWN1dGVSZW5kZXIgZnVuY3Rpb24/XG4gICAgICAgIHRoaXMucmVuZGVyaW5nUGF1c2VEZXB0aCA9IDA7XG4gICAgICAgIHRoaXMuYnVpbGREZWxheWVkUmVyZW5kZXIgPSBtZW1vaXplKGJ1aWxkRGVsYXllZFJlcmVuZGVyKTtcbiAgICAgICAgdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzID0ge307XG4gICAgICAgIHRoaXMuaXNWaWV3VXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzRGF0ZXNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNFdmVudHNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgICAgdGhpcy5vcHRpb25zTWFuYWdlciA9IG5ldyBPcHRpb25zTWFuYWdlcihvdmVycmlkZXMgfHwge30pO1xuICAgICAgICB0aGlzLnBsdWdpblN5c3RlbSA9IG5ldyBQbHVnaW5TeXN0ZW0oKTtcbiAgICAgICAgLy8gb25seSBkbyBvbmNlLiBkb24ndCBkbyBpbiBoYW5kbGVPcHRpb25zLiBiZWNhdXNlIGNhbid0IHJlbW92ZSBwbHVnaW5zXG4gICAgICAgIHRoaXMuYWRkUGx1Z2luSW5wdXRzKHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQucGx1Z2lucyB8fCBbXSk7XG4gICAgICAgIHRoaXMuaGFuZGxlT3B0aW9ucyh0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkKTtcbiAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ19pbml0Jyk7IC8vIGZvciB0ZXN0c1xuICAgICAgICB0aGlzLmh5ZHJhdGUoKTtcbiAgICAgICAgdGhpcy5jYWxlbmRhckludGVyYWN0aW9ucyA9IHRoaXMucGx1Z2luU3lzdGVtLmhvb2tzLmNhbGVuZGFySW50ZXJhY3Rpb25zXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChjYWxlbmRhckludGVyYWN0aW9uQ2xhc3MpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgY2FsZW5kYXJJbnRlcmFjdGlvbkNsYXNzKF90aGlzKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5hZGRQbHVnaW5JbnB1dHMgPSBmdW5jdGlvbiAocGx1Z2luSW5wdXRzKSB7XG4gICAgICAgIHZhciBwbHVnaW5EZWZzID0gcmVmaW5lUGx1Z2luRGVmcyhwbHVnaW5JbnB1dHMpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHBsdWdpbkRlZnNfMSA9IHBsdWdpbkRlZnM7IF9pIDwgcGx1Z2luRGVmc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHBsdWdpbkRlZiA9IHBsdWdpbkRlZnNfMVtfaV07XG4gICAgICAgICAgICB0aGlzLnBsdWdpblN5c3RlbS5hZGQocGx1Z2luRGVmKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KENhbGVuZGFyLnByb3RvdHlwZSwgXCJ2aWV3XCIsIHtcbiAgICAgICAgLy8gcHVibGljIEFQSVxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbXBvbmVudCA/IHRoaXMuY29tcG9uZW50LnZpZXcgOiBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICAvLyBQdWJsaWMgQVBJIGZvciByZW5kZXJpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jb21wb25lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50ID0gbmV3IENhbGVuZGFyQ29tcG9uZW50KHRoaXMuZWwpO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJhYmxlRXZlbnRTdG9yZSA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgICAgICAgICAgdGhpcy5iaW5kSGFuZGxlcnMoKTtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZVJlbmRlcigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0UmVyZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCkge1xuICAgICAgICAgICAgdGhpcy51bmJpbmRIYW5kbGVycygpO1xuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQuZGVzdHJveSgpOyAvLyBkb24ndCBudWxsLW91dC4gaW4gY2FzZSBBUEkgbmVlZHMgYWNjZXNzXG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IG51bGw7IC8vIHVtbSA/Pz9cbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmNhbGVuZGFySW50ZXJhY3Rpb25zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5kZXN0cm95KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignX2Rlc3Ryb3llZCcpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBIYW5kbGVyc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmJpbmRIYW5kbGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gZXZlbnQgZGVsZWdhdGlvbiBmb3IgbmF2IGxpbmtzXG4gICAgICAgIHRoaXMucmVtb3ZlTmF2TGlua0xpc3RlbmVyID0gbGlzdGVuQnlTZWxlY3Rvcih0aGlzLmVsLCAnY2xpY2snLCAnYVtkYXRhLWdvdG9dJywgZnVuY3Rpb24gKGV2LCBhbmNob3JFbCkge1xuICAgICAgICAgICAgdmFyIGdvdG9PcHRpb25zID0gYW5jaG9yRWwuZ2V0QXR0cmlidXRlKCdkYXRhLWdvdG8nKTtcbiAgICAgICAgICAgIGdvdG9PcHRpb25zID0gZ290b09wdGlvbnMgPyBKU09OLnBhcnNlKGdvdG9PcHRpb25zKSA6IHt9O1xuICAgICAgICAgICAgdmFyIGRhdGVFbnYgPSBfdGhpcy5kYXRlRW52O1xuICAgICAgICAgICAgdmFyIGRhdGVNYXJrZXIgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihnb3RvT3B0aW9ucy5kYXRlKTtcbiAgICAgICAgICAgIHZhciB2aWV3VHlwZSA9IGdvdG9PcHRpb25zLnR5cGU7XG4gICAgICAgICAgICAvLyBwcm9wZXJ0eSBsaWtlIFwibmF2TGlua0RheUNsaWNrXCIuIG1pZ2h0IGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb25cbiAgICAgICAgICAgIHZhciBjdXN0b21BY3Rpb24gPSBfdGhpcy52aWV3T3B0KCduYXZMaW5rJyArIGNhcGl0YWxpc2VGaXJzdExldHRlcih2aWV3VHlwZSkgKyAnQ2xpY2snKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3VzdG9tQWN0aW9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgY3VzdG9tQWN0aW9uKGRhdGVFbnYudG9EYXRlKGRhdGVNYXJrZXIpLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1c3RvbUFjdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdmlld1R5cGUgPSBjdXN0b21BY3Rpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnpvb21UbyhkYXRlTWFya2VyLCB2aWV3VHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy5vcHQoJ2hhbmRsZVdpbmRvd1Jlc2l6ZScpKSB7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy53aW5kb3dSZXNpemVQcm94eSA9IGRlYm91bmNlKC8vIHByZXZlbnRzIHJhcGlkIGNhbGxzXG4gICAgICAgICAgICB0aGlzLndpbmRvd1Jlc2l6ZS5iaW5kKHRoaXMpLCB0aGlzLm9wdCgnd2luZG93UmVzaXplRGVsYXknKSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudW5iaW5kSGFuZGxlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTmF2TGlua0xpc3RlbmVyKCk7XG4gICAgICAgIGlmICh0aGlzLndpbmRvd1Jlc2l6ZVByb3h5KSB7XG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy53aW5kb3dSZXNpemVQcm94eSk7XG4gICAgICAgICAgICB0aGlzLndpbmRvd1Jlc2l6ZVByb3h5ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gRGlzcGF0Y2hlclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmh5ZHJhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB0aGlzLmJ1aWxkSW5pdGlhbFN0YXRlKCk7XG4gICAgICAgIHZhciByYXdTb3VyY2VzID0gdGhpcy5vcHQoJ2V2ZW50U291cmNlcycpIHx8IFtdO1xuICAgICAgICB2YXIgc2luZ2xlUmF3U291cmNlID0gdGhpcy5vcHQoJ2V2ZW50cycpO1xuICAgICAgICB2YXIgc291cmNlcyA9IFtdOyAvLyBwYXJzZWRcbiAgICAgICAgaWYgKHNpbmdsZVJhd1NvdXJjZSkge1xuICAgICAgICAgICAgcmF3U291cmNlcy51bnNoaWZ0KHNpbmdsZVJhd1NvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByYXdTb3VyY2VzXzEgPSByYXdTb3VyY2VzOyBfaSA8IHJhd1NvdXJjZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByYXdTb3VyY2UgPSByYXdTb3VyY2VzXzFbX2ldO1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHBhcnNlRXZlbnRTb3VyY2UocmF3U291cmNlLCB0aGlzKTtcbiAgICAgICAgICAgIGlmIChzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VzLnB1c2goc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJhdGNoUmVuZGVyaW5nKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHsgdHlwZTogJ0lOSVQnIH0pOyAvLyBwYXNzIGluIHNvdXJjZXMgaGVyZT9cbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHsgdHlwZTogJ0FERF9FVkVOVF9TT1VSQ0VTJywgc291cmNlczogc291cmNlcyB9KTtcbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX1ZJRVdfVFlQRScsXG4gICAgICAgICAgICAgICAgdmlld1R5cGU6IF90aGlzLm9wdCgnZGVmYXVsdFZpZXcnKSB8fCBfdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3MuZGVmYXVsdFZpZXdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5idWlsZEluaXRpYWxTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZpZXdUeXBlOiBudWxsLFxuICAgICAgICAgICAgbG9hZGluZ0xldmVsOiAwLFxuICAgICAgICAgICAgZXZlbnRTb3VyY2VMb2FkaW5nTGV2ZWw6IDAsXG4gICAgICAgICAgICBjdXJyZW50RGF0ZTogdGhpcy5nZXRJbml0aWFsRGF0ZSgpLFxuICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IG51bGwsXG4gICAgICAgICAgICBldmVudFNvdXJjZXM6IHt9LFxuICAgICAgICAgICAgZXZlbnRTdG9yZTogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICBkYXRlU2VsZWN0aW9uOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246ICcnLFxuICAgICAgICAgICAgZXZlbnREcmFnOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IG51bGxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5kaXNwYXRjaCA9IGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgdGhpcy5hY3Rpb25RdWV1ZS5wdXNoKGFjdGlvbik7XG4gICAgICAgIGlmICghdGhpcy5pc1JlZHVjaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmlzUmVkdWNpbmcgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIG9sZFN0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmFjdGlvblF1ZXVlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSB0aGlzLnJlZHVjZSh0aGlzLnN0YXRlLCB0aGlzLmFjdGlvblF1ZXVlLnNoaWZ0KCksIHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG5ld1N0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgICAgIHRoaXMuaXNSZWR1Y2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKCFvbGRTdGF0ZS5sb2FkaW5nTGV2ZWwgJiYgbmV3U3RhdGUubG9hZGluZ0xldmVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ2xvYWRpbmcnLCBbdHJ1ZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob2xkU3RhdGUubG9hZGluZ0xldmVsICYmICFuZXdTdGF0ZS5sb2FkaW5nTGV2ZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignbG9hZGluZycsIFtmYWxzZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHZpZXcgPSB0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC52aWV3O1xuICAgICAgICAgICAgaWYgKG9sZFN0YXRlLmV2ZW50U3RvcmUgIT09IG5ld1N0YXRlLmV2ZW50U3RvcmUpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkU3RhdGUuZXZlbnRTdG9yZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzRXZlbnRzVXBkYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9sZFN0YXRlLmRhdGVQcm9maWxlICE9PSBuZXdTdGF0ZS5kYXRlUHJvZmlsZSkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRTdGF0ZS5kYXRlUHJvZmlsZSAmJiB2aWV3KSB7IC8vIHdoeSB3b3VsZCB2aWV3IGJlIG51bGwhP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignZGF0ZXNEZXN0cm95JywgW1xuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWw6IHZpZXcuZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaXNEYXRlc1VwZGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9sZFN0YXRlLnZpZXdUeXBlICE9PSBuZXdTdGF0ZS52aWV3VHlwZSkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRTdGF0ZS52aWV3VHlwZSAmJiB2aWV3KSB7IC8vIHdoeSB3b3VsZCB2aWV3IGJlIG51bGwhP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcigndmlld1NrZWxldG9uRGVzdHJveScsIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsOiB2aWV3LmVsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmlzVmlld1VwZGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0UmVyZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlZHVjZSA9IGZ1bmN0aW9uIChzdGF0ZSwgYWN0aW9uLCBjYWxlbmRhcikge1xuICAgICAgICByZXR1cm4gcmVkdWNlKHN0YXRlLCBhY3Rpb24sIGNhbGVuZGFyKTtcbiAgICB9O1xuICAgIC8vIFJlbmRlciBRdWV1ZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlcXVlc3RSZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5uZWVkc1JlcmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5kZWxheWVkUmVyZW5kZXIoKTsgLy8gd2lsbCBjYWxsIGEgZGVib3VuY2VkLXZlcnNpb24gb2YgdHJ5UmVyZW5kZXJcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50cnlSZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50ICYmIC8vIG11c3QgYmUgYWNjZXB0aW5nIHJlbmRlcnNcbiAgICAgICAgICAgIHRoaXMubmVlZHNSZXJlbmRlciAmJiAvLyBpbmRpY2F0ZXMgdGhhdCBhIHJlcmVuZGVyIHdhcyByZXF1ZXN0ZWRcbiAgICAgICAgICAgICF0aGlzLnJlbmRlcmluZ1BhdXNlRGVwdGggJiYgLy8gbm90IHBhdXNlZFxuICAgICAgICAgICAgIXRoaXMuaXNSZW5kZXJpbmcgLy8gbm90IGN1cnJlbnRseSBpbiB0aGUgcmVuZGVyIGxvb3BcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGVSZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmJhdGNoUmVuZGVyaW5nID0gZnVuY3Rpb24gKGZ1bmMpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJpbmdQYXVzZURlcHRoKys7XG4gICAgICAgIGZ1bmMoKTtcbiAgICAgICAgdGhpcy5yZW5kZXJpbmdQYXVzZURlcHRoLS07XG4gICAgICAgIGlmICh0aGlzLm5lZWRzUmVyZW5kZXIpIHtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdFJlcmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJlbmRlcmluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmV4ZWN1dGVSZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGNsZWFyIHRoZXNlIEJFRk9SRSB0aGUgcmVuZGVyIHNvIHRoYXQgbmV3IHZhbHVlcyB3aWxsIGFjY3VtdWxhdGUgZHVyaW5nIHJlbmRlclxuICAgICAgICB0aGlzLm5lZWRzUmVyZW5kZXIgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1JlbmRlcmluZyA9IHRydWU7XG4gICAgICAgIHRoaXMucmVuZGVyQ29tcG9uZW50KCk7XG4gICAgICAgIHRoaXMuaXNSZW5kZXJpbmcgPSBmYWxzZTtcbiAgICAgICAgLy8gcmVjZWl2ZWQgYSByZXJlbmRlciByZXF1ZXN0IHdoaWxlIHJlbmRlcmluZ1xuICAgICAgICBpZiAodGhpcy5uZWVkc1JlcmVuZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF5ZWRSZXJlbmRlcigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKlxuICAgIGRvbid0IGNhbGwgdGhpcyBkaXJlY3RseS4gdXNlIGV4ZWN1dGVSZW5kZXIgaW5zdGVhZFxuICAgICovXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlbmRlckNvbXBvbmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgc3RhdGUgPSBfYS5zdGF0ZSwgY29tcG9uZW50ID0gX2EuY29tcG9uZW50O1xuICAgICAgICB2YXIgdmlld1R5cGUgPSBzdGF0ZS52aWV3VHlwZTtcbiAgICAgICAgdmFyIHZpZXdTcGVjID0gdGhpcy52aWV3U3BlY3Nbdmlld1R5cGVdO1xuICAgICAgICBpZiAoIXZpZXdTcGVjKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJWaWV3IHR5cGUgXFxcIlwiICsgdmlld1R5cGUgKyBcIlxcXCIgaXMgbm90IHZhbGlkXCIpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGV2ZW50IHNvdXJjZXMgYXJlIHN0aWxsIGxvYWRpbmcgYW5kIHByb2dyZXNzaXZlIHJlbmRlcmluZyBoYXNuJ3QgYmVlbiBlbmFibGVkLFxuICAgICAgICAvLyBrZWVwIHJlbmRlcmluZyB0aGUgbGFzdCBmdWxseSBsb2FkZWQgc2V0IG9mIGV2ZW50c1xuICAgICAgICB2YXIgcmVuZGVyYWJsZUV2ZW50U3RvcmUgPSB0aGlzLnJlbmRlcmFibGVFdmVudFN0b3JlID1cbiAgICAgICAgICAgIChzdGF0ZS5ldmVudFNvdXJjZUxvYWRpbmdMZXZlbCAmJiAhdGhpcy5vcHQoJ3Byb2dyZXNzaXZlRXZlbnRSZW5kZXJpbmcnKSkgP1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyYWJsZUV2ZW50U3RvcmUgOlxuICAgICAgICAgICAgICAgIHN0YXRlLmV2ZW50U3RvcmU7XG4gICAgICAgIHZhciBldmVudFVpU2luZ2xlQmFzZSA9IHRoaXMuYnVpbGRFdmVudFVpU2luZ2xlQmFzZSh2aWV3U3BlYy5vcHRpb25zKTtcbiAgICAgICAgdmFyIGV2ZW50VWlCeVNvdXJjZSA9IHRoaXMuYnVpbGRFdmVudFVpQnlTb3VyY2Uoc3RhdGUuZXZlbnRTb3VyY2VzKTtcbiAgICAgICAgdmFyIGV2ZW50VWlCYXNlcyA9IHRoaXMuZXZlbnRVaUJhc2VzID0gdGhpcy5idWlsZEV2ZW50VWlCYXNlcyhyZW5kZXJhYmxlRXZlbnRTdG9yZS5kZWZzLCBldmVudFVpU2luZ2xlQmFzZSwgZXZlbnRVaUJ5U291cmNlKTtcbiAgICAgICAgY29tcG9uZW50LnJlY2VpdmVQcm9wcyhfX2Fzc2lnbih7fSwgc3RhdGUsIHsgdmlld1NwZWM6IHZpZXdTcGVjLCBkYXRlUHJvZmlsZUdlbmVyYXRvcjogdGhpcy5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdLCBkYXRlUHJvZmlsZTogc3RhdGUuZGF0ZVByb2ZpbGUsIGV2ZW50U3RvcmU6IHJlbmRlcmFibGVFdmVudFN0b3JlLCBldmVudFVpQmFzZXM6IGV2ZW50VWlCYXNlcywgZGF0ZVNlbGVjdGlvbjogc3RhdGUuZGF0ZVNlbGVjdGlvbiwgZXZlbnRTZWxlY3Rpb246IHN0YXRlLmV2ZW50U2VsZWN0aW9uLCBldmVudERyYWc6IHN0YXRlLmV2ZW50RHJhZywgZXZlbnRSZXNpemU6IHN0YXRlLmV2ZW50UmVzaXplIH0pLCB0aGlzLmJ1aWxkQ29tcG9uZW50Q29udGV4dCh0aGlzLnRoZW1lLCB0aGlzLmRhdGVFbnYsIHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQpKTtcbiAgICAgICAgaWYgKHRoaXMuaXNWaWV3VXBkYXRlZCkge1xuICAgICAgICAgICAgdGhpcy5pc1ZpZXdVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcigndmlld1NrZWxldG9uUmVuZGVyJywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmlldzogY29tcG9uZW50LnZpZXcsXG4gICAgICAgICAgICAgICAgICAgIGVsOiBjb21wb25lbnQudmlldy5lbFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzRGF0ZXNVcGRhdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzRGF0ZXNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignZGF0ZXNSZW5kZXInLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB2aWV3OiBjb21wb25lbnQudmlldyxcbiAgICAgICAgICAgICAgICAgICAgZWw6IGNvbXBvbmVudC52aWV3LmVsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNFdmVudHNVcGRhdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzRXZlbnRzVXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVsZWFzZUFmdGVyU2l6aW5nVHJpZ2dlcnMoKTtcbiAgICB9O1xuICAgIC8vIE9wdGlvbnNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5zZXRPcHRpb24gPSBmdW5jdGlvbiAobmFtZSwgdmFsKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdGhpcy5tdXRhdGVPcHRpb25zKChfYSA9IHt9LCBfYVtuYW1lXSA9IHZhbCwgX2EpLCBbXSwgdHJ1ZSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0T3B0aW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWRbbmFtZV07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUub3B0ID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWRbbmFtZV07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudmlld09wdCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdPcHRzKClbbmFtZV07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudmlld09wdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdTcGVjc1t0aGlzLnN0YXRlLnZpZXdUeXBlXS5vcHRpb25zO1xuICAgIH07XG4gICAgLypcbiAgICBoYW5kbGVzIG9wdGlvbiBjaGFuZ2VzIChsaWtlIGEgZGlmZilcbiAgICAqL1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5tdXRhdGVPcHRpb25zID0gZnVuY3Rpb24gKHVwZGF0ZXMsIHJlbW92YWxzLCBpc0R5bmFtaWMsIGRlZXBFcXVhbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY2hhbmdlSGFuZGxlcnMgPSB0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5vcHRpb25DaGFuZ2VIYW5kbGVycztcbiAgICAgICAgdmFyIG5vcm1hbFVwZGF0ZXMgPSB7fTtcbiAgICAgICAgdmFyIHNwZWNpYWxVcGRhdGVzID0ge307XG4gICAgICAgIHZhciBvbGREYXRlRW52ID0gdGhpcy5kYXRlRW52OyAvLyBkbyB0aGlzIGJlZm9yZSBoYW5kbGVPcHRpb25zXG4gICAgICAgIHZhciBpc1RpbWVab25lRGlydHkgPSBmYWxzZTtcbiAgICAgICAgdmFyIGlzU2l6ZURpcnR5ID0gZmFsc2U7XG4gICAgICAgIHZhciBhbnlEaWZmaWN1bHRPcHRpb25zID0gQm9vbGVhbihyZW1vdmFscy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBuYW1lXzEgaW4gdXBkYXRlcykge1xuICAgICAgICAgICAgaWYgKGNoYW5nZUhhbmRsZXJzW25hbWVfMV0pIHtcbiAgICAgICAgICAgICAgICBzcGVjaWFsVXBkYXRlc1tuYW1lXzFdID0gdXBkYXRlc1tuYW1lXzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9ybWFsVXBkYXRlc1tuYW1lXzFdID0gdXBkYXRlc1tuYW1lXzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIG5hbWVfMiBpbiBub3JtYWxVcGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoL14oaGVpZ2h0fGNvbnRlbnRIZWlnaHR8YXNwZWN0UmF0aW8pJC8udGVzdChuYW1lXzIpKSB7XG4gICAgICAgICAgICAgICAgaXNTaXplRGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoL14oZGVmYXVsdERhdGV8ZGVmYXVsdFZpZXcpJC8udGVzdChuYW1lXzIpKSA7XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbnlEaWZmaWN1bHRPcHRpb25zID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZV8yID09PSAndGltZVpvbmUnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzVGltZVpvbmVEaXJ0eSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMub3B0aW9uc01hbmFnZXIubXV0YXRlKG5vcm1hbFVwZGF0ZXMsIHJlbW92YWxzLCBpc0R5bmFtaWMpO1xuICAgICAgICBpZiAoYW55RGlmZmljdWx0T3B0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVPcHRpb25zKHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYmF0Y2hSZW5kZXJpbmcoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGFueURpZmZpY3VsdE9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNUaW1lWm9uZURpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfVElNRVpPTkUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZUVudjogb2xkRGF0ZUVudlxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLyogSEFDS1xuICAgICAgICAgICAgICAgIGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgY2FsbGluZyB0aGlzLnJlcXVlc3RSZXJlbmRlcigpXG4gICAgICAgICAgICAgICAgYnV0IHJlY29tcHV0ZXMgdGhlIHN0YXRlJ3MgZGF0ZVByb2ZpbGVcbiAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9WSUVXX1RZUEUnLFxuICAgICAgICAgICAgICAgICAgICB2aWV3VHlwZTogX3RoaXMuc3RhdGUudmlld1R5cGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlzU2l6ZURpcnR5KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gc3BlY2lhbCB1cGRhdGVzXG4gICAgICAgICAgICBpZiAoZGVlcEVxdWFsKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgbmFtZV8zIGluIHNwZWNpYWxVcGRhdGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZUhhbmRsZXJzW25hbWVfM10oc3BlY2lhbFVwZGF0ZXNbbmFtZV8zXSwgX3RoaXMsIGRlZXBFcXVhbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8qXG4gICAgcmVidWlsZHMgdGhpbmdzIGJhc2VkIG9mZiBvZiBhIGNvbXBsZXRlIHNldCBvZiByZWZpbmVkIG9wdGlvbnNcbiAgICAqL1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5oYW5kbGVPcHRpb25zID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHBsdWdpbkhvb2tzID0gdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3M7XG4gICAgICAgIHRoaXMuZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbihvcHRpb25zLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5kZWZhdWx0VGltZWRFdmVudER1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24ob3B0aW9ucy5kZWZhdWx0VGltZWRFdmVudER1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5kZWxheWVkUmVyZW5kZXIgPSB0aGlzLmJ1aWxkRGVsYXllZFJlcmVuZGVyKG9wdGlvbnMucmVyZW5kZXJEZWxheSk7XG4gICAgICAgIHRoaXMudGhlbWUgPSB0aGlzLmJ1aWxkVGhlbWUob3B0aW9ucyk7XG4gICAgICAgIHZhciBhdmFpbGFibGUgPSB0aGlzLnBhcnNlUmF3TG9jYWxlcyhvcHRpb25zLmxvY2FsZXMpO1xuICAgICAgICB0aGlzLmF2YWlsYWJsZVJhd0xvY2FsZXMgPSBhdmFpbGFibGUubWFwO1xuICAgICAgICB2YXIgbG9jYWxlID0gdGhpcy5idWlsZExvY2FsZShvcHRpb25zLmxvY2FsZSB8fCBhdmFpbGFibGUuZGVmYXVsdENvZGUsIGF2YWlsYWJsZS5tYXApO1xuICAgICAgICB0aGlzLmRhdGVFbnYgPSB0aGlzLmJ1aWxkRGF0ZUVudihsb2NhbGUsIG9wdGlvbnMudGltZVpvbmUsIHBsdWdpbkhvb2tzLm5hbWVkVGltZVpvbmVkSW1wbCwgb3B0aW9ucy5maXJzdERheSwgb3B0aW9ucy53ZWVrTnVtYmVyQ2FsY3VsYXRpb24sIG9wdGlvbnMud2Vla0xhYmVsLCBwbHVnaW5Ib29rcy5jbWRGb3JtYXR0ZXIpO1xuICAgICAgICB0aGlzLnNlbGVjdGlvbkNvbmZpZyA9IHRoaXMuYnVpbGRTZWxlY3Rpb25Db25maWcob3B0aW9ucyk7IC8vIG5lZWRzIGRhdGVFbnYuIGRvIGFmdGVyIDooXG4gICAgICAgIC8vIGluZWZmZWNpZW50IHRvIGRvIGV2ZXJ5IHRpbWU/XG4gICAgICAgIHRoaXMudmlld1NwZWNzID0gYnVpbGRWaWV3U3BlY3MocGx1Z2luSG9va3Mudmlld3MsIHRoaXMub3B0aW9uc01hbmFnZXIpO1xuICAgICAgICAvLyBpbmVmZmVjaWVudCB0byBkbyBldmVyeSB0aW1lP1xuICAgICAgICB0aGlzLmRhdGVQcm9maWxlR2VuZXJhdG9ycyA9IG1hcEhhc2godGhpcy52aWV3U3BlY3MsIGZ1bmN0aW9uICh2aWV3U3BlYykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyB2aWV3U3BlYy5jbGFzcy5wcm90b3R5cGUuZGF0ZVByb2ZpbGVHZW5lcmF0b3JDbGFzcyh2aWV3U3BlYywgX3RoaXMpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRBdmFpbGFibGVMb2NhbGVDb2RlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuYXZhaWxhYmxlUmF3TG9jYWxlcyk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuX2J1aWxkU2VsZWN0aW9uQ29uZmlnID0gZnVuY3Rpb24gKHJhd09wdHMpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NTY29wZWRVaVByb3BzKCdzZWxlY3QnLCByYXdPcHRzLCB0aGlzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5fYnVpbGRFdmVudFVpU2luZ2xlQmFzZSA9IGZ1bmN0aW9uIChyYXdPcHRzKSB7XG4gICAgICAgIGlmIChyYXdPcHRzLmVkaXRhYmxlKSB7IC8vIHNvICdlZGl0YWJsZScgYWZmZWN0ZWQgZXZlbnRzXG4gICAgICAgICAgICByYXdPcHRzID0gX19hc3NpZ24oe30sIHJhd09wdHMsIHsgZXZlbnRFZGl0YWJsZTogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvY2Vzc1Njb3BlZFVpUHJvcHMoJ2V2ZW50JywgcmF3T3B0cywgdGhpcyk7XG4gICAgfTtcbiAgICAvLyBUcmlnZ2VyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuaGFzUHVibGljSGFuZGxlcnMgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNIYW5kbGVycyhuYW1lKSB8fFxuICAgICAgICAgICAgdGhpcy5vcHQobmFtZSk7IC8vIGhhbmRsZXIgc3BlY2lmaWVkIGluIG9wdGlvbnNcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wdWJsaWNseVRyaWdnZXIgPSBmdW5jdGlvbiAobmFtZSwgYXJncykge1xuICAgICAgICB2YXIgb3B0SGFuZGxlciA9IHRoaXMub3B0KG5hbWUpO1xuICAgICAgICB0aGlzLnRyaWdnZXJXaXRoKG5hbWUsIHRoaXMsIGFyZ3MpO1xuICAgICAgICBpZiAob3B0SGFuZGxlcikge1xuICAgICAgICAgICAgcmV0dXJuIG9wdEhhbmRsZXIuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wdWJsaWNseVRyaWdnZXJBZnRlclNpemluZyA9IGZ1bmN0aW9uIChuYW1lLCBhcmdzKSB7XG4gICAgICAgIHZhciBhZnRlclNpemluZ1RyaWdnZXJzID0gdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzO1xuICAgICAgICAoYWZ0ZXJTaXppbmdUcmlnZ2Vyc1tuYW1lXSB8fCAoYWZ0ZXJTaXppbmdUcmlnZ2Vyc1tuYW1lXSA9IFtdKSkucHVzaChhcmdzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWxlYXNlQWZ0ZXJTaXppbmdUcmlnZ2VycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFmdGVyU2l6aW5nVHJpZ2dlcnMgPSB0aGlzLmFmdGVyU2l6aW5nVHJpZ2dlcnM7XG4gICAgICAgIGZvciAodmFyIG5hbWVfNCBpbiBhZnRlclNpemluZ1RyaWdnZXJzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gYWZ0ZXJTaXppbmdUcmlnZ2Vyc1tuYW1lXzRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKG5hbWVfNCwgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzID0ge307XG4gICAgfTtcbiAgICAvLyBWaWV3XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBSZXR1cm5zIGEgYm9vbGVhbiBhYm91dCB3aGV0aGVyIHRoZSB2aWV3IGlzIG9rYXkgdG8gaW5zdGFudGlhdGUgYXQgc29tZSBwb2ludFxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5pc1ZhbGlkVmlld1R5cGUgPSBmdW5jdGlvbiAodmlld1R5cGUpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy52aWV3U3BlY3Nbdmlld1R5cGVdKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5jaGFuZ2VWaWV3ID0gZnVuY3Rpb24gKHZpZXdUeXBlLCBkYXRlT3JSYW5nZSkge1xuICAgICAgICB2YXIgZGF0ZU1hcmtlciA9IG51bGw7XG4gICAgICAgIGlmIChkYXRlT3JSYW5nZSkge1xuICAgICAgICAgICAgaWYgKGRhdGVPclJhbmdlLnN0YXJ0ICYmIGRhdGVPclJhbmdlLmVuZCkgeyAvLyBhIHJhbmdlXG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zTWFuYWdlci5tdXRhdGUoeyB2aXNpYmxlUmFuZ2U6IGRhdGVPclJhbmdlIH0sIFtdKTsgLy8gd2lsbCBub3QgcmVyZW5kZXJcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZU9wdGlvbnModGhpcy5vcHRpb25zTWFuYWdlci5jb21wdXRlZCk7IC8vIC4uLmJ1dCB5dWNrXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8gYSBkYXRlXG4gICAgICAgICAgICAgICAgZGF0ZU1hcmtlciA9IHRoaXMuZGF0ZUVudi5jcmVhdGVNYXJrZXIoZGF0ZU9yUmFuZ2UpOyAvLyBqdXN0IGxpa2UgZ290b0RhdGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9WSUVXX1RZUEUnLFxuICAgICAgICAgICAgdmlld1R5cGU6IHZpZXdUeXBlLFxuICAgICAgICAgICAgZGF0ZU1hcmtlcjogZGF0ZU1hcmtlclxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIEZvcmNlcyBuYXZpZ2F0aW9uIHRvIGEgdmlldyBmb3IgdGhlIGdpdmVuIGRhdGUuXG4gICAgLy8gYHZpZXdUeXBlYCBjYW4gYmUgYSBzcGVjaWZpYyB2aWV3IG5hbWUgb3IgYSBnZW5lcmljIG9uZSBsaWtlIFwid2Vla1wiIG9yIFwiZGF5XCIuXG4gICAgLy8gbmVlZHMgdG8gY2hhbmdlXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnpvb21UbyA9IGZ1bmN0aW9uIChkYXRlTWFya2VyLCB2aWV3VHlwZSkge1xuICAgICAgICB2YXIgc3BlYztcbiAgICAgICAgdmlld1R5cGUgPSB2aWV3VHlwZSB8fCAnZGF5JzsgLy8gZGF5IGlzIGRlZmF1bHQgem9vbVxuICAgICAgICBzcGVjID0gdGhpcy52aWV3U3BlY3Nbdmlld1R5cGVdIHx8XG4gICAgICAgICAgICB0aGlzLmdldFVuaXRWaWV3U3BlYyh2aWV3VHlwZSk7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgaWYgKHNwZWMpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdTRVRfVklFV19UWVBFJyxcbiAgICAgICAgICAgICAgICB2aWV3VHlwZTogc3BlYy50eXBlLFxuICAgICAgICAgICAgICAgIGRhdGVNYXJrZXI6IGRhdGVNYXJrZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgICAgICBkYXRlTWFya2VyOiBkYXRlTWFya2VyXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gR2l2ZW4gYSBkdXJhdGlvbiBzaW5ndWxhciB1bml0LCBsaWtlIFwid2Vla1wiIG9yIFwiZGF5XCIsIGZpbmRzIGEgbWF0Y2hpbmcgdmlldyBzcGVjLlxuICAgIC8vIFByZWZlcmVuY2UgaXMgZ2l2ZW4gdG8gdmlld3MgdGhhdCBoYXZlIGNvcnJlc3BvbmRpbmcgYnV0dG9ucy5cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0VW5pdFZpZXdTcGVjID0gZnVuY3Rpb24gKHVuaXQpIHtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50O1xuICAgICAgICB2YXIgdmlld1R5cGVzID0gW107XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgc3BlYztcbiAgICAgICAgLy8gcHV0IHZpZXdzIHRoYXQgaGF2ZSBidXR0b25zIGZpcnN0LiB0aGVyZSB3aWxsIGJlIGR1cGxpY2F0ZXMsIGJ1dCBvaFxuICAgICAgICBpZiAoY29tcG9uZW50LmhlYWRlcikge1xuICAgICAgICAgICAgdmlld1R5cGVzLnB1c2guYXBwbHkodmlld1R5cGVzLCBjb21wb25lbnQuaGVhZGVyLnZpZXdzV2l0aEJ1dHRvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb21wb25lbnQuZm9vdGVyKSB7XG4gICAgICAgICAgICB2aWV3VHlwZXMucHVzaC5hcHBseSh2aWV3VHlwZXMsIGNvbXBvbmVudC5mb290ZXIudmlld3NXaXRoQnV0dG9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgdmlld1R5cGUgaW4gdGhpcy52aWV3U3BlY3MpIHtcbiAgICAgICAgICAgIHZpZXdUeXBlcy5wdXNoKHZpZXdUeXBlKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdmlld1R5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzcGVjID0gdGhpcy52aWV3U3BlY3Nbdmlld1R5cGVzW2ldXTtcbiAgICAgICAgICAgIGlmIChzcGVjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNwZWMuc2luZ2xlVW5pdCA9PT0gdW5pdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3BlYztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEN1cnJlbnQgRGF0ZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldEluaXRpYWxEYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGVmYXVsdERhdGVJbnB1dCA9IHRoaXMub3B0KCdkZWZhdWx0RGF0ZScpO1xuICAgICAgICAvLyBjb21wdXRlIHRoZSBpbml0aWFsIGFtYmlnLXRpbWV6b25lIGRhdGVcbiAgICAgICAgaWYgKGRlZmF1bHREYXRlSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi5jcmVhdGVNYXJrZXIoZGVmYXVsdERhdGVJbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXROb3coKTsgLy8gZ2V0Tm93IGFscmVhZHkgcmV0dXJucyB1bnpvbmVkXG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wcmV2ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUFJFVicgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUubmV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ05FWFQnIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnByZXZZZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZGF0ZUVudi5hZGRZZWFycyh0aGlzLnN0YXRlLmN1cnJlbnREYXRlLCAtMSlcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUubmV4dFllYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnU0VUX0RBVEUnLFxuICAgICAgICAgICAgZGF0ZU1hcmtlcjogdGhpcy5kYXRlRW52LmFkZFllYXJzKHRoaXMuc3RhdGUuY3VycmVudERhdGUsIDEpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnRvZGF5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZ2V0Tm93KClcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ290b0RhdGUgPSBmdW5jdGlvbiAoem9uZWREYXRlSW5wdXQpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdTRVRfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiB0aGlzLmRhdGVFbnYuY3JlYXRlTWFya2VyKHpvbmVkRGF0ZUlucHV0KVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5pbmNyZW1lbnREYXRlID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBlbHNlLCB3YXJuIGFib3V0IGludmFsaWQgaW5wdXQ/XG4gICAgICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX0RBVEUnLFxuICAgICAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZGF0ZUVudi5hZGQodGhpcy5zdGF0ZS5jdXJyZW50RGF0ZSwgZGVsdGEpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZm9yIGV4dGVybmFsIEFQSVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXREYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRlRW52LnRvRGF0ZSh0aGlzLnN0YXRlLmN1cnJlbnREYXRlKTtcbiAgICB9O1xuICAgIC8vIERhdGUgRm9ybWF0dGluZyBVdGlsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmZvcm1hdERhdGUgPSBmdW5jdGlvbiAoZCwgZm9ybWF0dGVyKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoZGF0ZUVudi5jcmVhdGVNYXJrZXIoZCksIGNyZWF0ZUZvcm1hdHRlcihmb3JtYXR0ZXIpKTtcbiAgICB9O1xuICAgIC8vIGBzZXR0aW5nc2AgaXMgZm9yIGZvcm1hdHRlciBBTkQgaXNFbmRFeGNsdXNpdmVcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZm9ybWF0UmFuZ2UgPSBmdW5jdGlvbiAoZDAsIGQxLCBzZXR0aW5ncykge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2UoZGF0ZUVudi5jcmVhdGVNYXJrZXIoZDApLCBkYXRlRW52LmNyZWF0ZU1hcmtlcihkMSksIGNyZWF0ZUZvcm1hdHRlcihzZXR0aW5ncywgdGhpcy5vcHQoJ2RlZmF1bHRSYW5nZVNlcGFyYXRvcicpKSwgc2V0dGluZ3MpO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmZvcm1hdElzbyA9IGZ1bmN0aW9uIChkLCBvbWl0VGltZSkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0SXNvKGRhdGVFbnYuY3JlYXRlTWFya2VyKGQpLCB7IG9taXRUaW1lOiBvbWl0VGltZSB9KTtcbiAgICB9O1xuICAgIC8vIFNpemluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLndpbmRvd1Jlc2l6ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICBpZiAoIXRoaXMuaXNIYW5kbGluZ1dpbmRvd1Jlc2l6ZSAmJlxuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgJiYgLy8gd2h5P1xuICAgICAgICAgICAgZXYudGFyZ2V0ID09PSB3aW5kb3cgLy8gbm90IGEganF1aSByZXNpemUgZXZlbnRcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmlzSGFuZGxpbmdXaW5kb3dSZXNpemUgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVTaXplKCk7XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignd2luZG93UmVzaXplJywgW3RoaXMudmlld10pO1xuICAgICAgICAgICAgdGhpcy5pc0hhbmRsaW5nV2luZG93UmVzaXplID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5jb21wb25lbnQpIHsgLy8gd2hlbj9cbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LnVwZGF0ZVNpemUodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIENvbXBvbmVudCBSZWdpc3RyYXRpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50ID0gZnVuY3Rpb24gKGNvbXBvbmVudCwgc2V0dGluZ3NJbnB1dCkge1xuICAgICAgICB2YXIgc2V0dGluZ3MgPSBwYXJzZUludGVyYWN0aW9uU2V0dGluZ3MoY29tcG9uZW50LCBzZXR0aW5nc0lucHV0KTtcbiAgICAgICAgdmFyIERFRkFVTFRfSU5URVJBQ1RJT05TID0gW1xuICAgICAgICAgICAgRXZlbnRDbGlja2luZyxcbiAgICAgICAgICAgIEV2ZW50SG92ZXJpbmdcbiAgICAgICAgXTtcbiAgICAgICAgdmFyIGludGVyYWN0aW9uQ2xhc3NlcyA9IERFRkFVTFRfSU5URVJBQ1RJT05TLmNvbmNhdCh0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5jb21wb25lbnRJbnRlcmFjdGlvbnMpO1xuICAgICAgICB2YXIgaW50ZXJhY3Rpb25zID0gaW50ZXJhY3Rpb25DbGFzc2VzLm1hcChmdW5jdGlvbiAoaW50ZXJhY3Rpb25DbGFzcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBpbnRlcmFjdGlvbkNsYXNzKHNldHRpbmdzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW50ZXJhY3Rpb25zU3RvcmVbY29tcG9uZW50LnVpZF0gPSBpbnRlcmFjdGlvbnM7XG4gICAgICAgIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZVtjb21wb25lbnQudWlkXSA9IHNldHRpbmdzO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnVucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCA9IGZ1bmN0aW9uIChjb21wb25lbnQpIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuaW50ZXJhY3Rpb25zU3RvcmVbY29tcG9uZW50LnVpZF07IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBfYVtfaV07XG4gICAgICAgICAgICBsaXN0ZW5lci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIHRoaXMuaW50ZXJhY3Rpb25zU3RvcmVbY29tcG9uZW50LnVpZF07XG4gICAgICAgIGRlbGV0ZSBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmVbY29tcG9uZW50LnVpZF07XG4gICAgfTtcbiAgICAvLyBEYXRlIFNlbGVjdGlvbiAvIEV2ZW50IFNlbGVjdGlvbiAvIERheUNsaWNrXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyB0aGlzIHB1YmxpYyBtZXRob2QgcmVjZWl2ZXMgc3RhcnQvZW5kIGRhdGVzIGluIGFueSBmb3JtYXQsIHdpdGggYW55IHRpbWV6b25lXG4gICAgLy8gTk9URTogYXJncyB3ZXJlIGNoYW5nZWQgZnJvbSB2M1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5zZWxlY3QgPSBmdW5jdGlvbiAoZGF0ZU9yT2JqLCBlbmREYXRlKSB7XG4gICAgICAgIHZhciBzZWxlY3Rpb25JbnB1dDtcbiAgICAgICAgaWYgKGVuZERhdGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGRhdGVPck9iai5zdGFydCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uSW5wdXQgPSBkYXRlT3JPYmo7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb25JbnB1dCA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IGRhdGVPck9iaixcbiAgICAgICAgICAgICAgICAgICAgZW5kOiBudWxsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbklucHV0ID0ge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBkYXRlT3JPYmosXG4gICAgICAgICAgICAgICAgZW5kOiBlbmREYXRlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBzZWxlY3Rpb24gPSBwYXJzZURhdGVTcGFuKHNlbGVjdGlvbklucHV0LCB0aGlzLmRhdGVFbnYsIGNyZWF0ZUR1cmF0aW9uKHsgZGF5czogMSB9KSAvLyBUT0RPOiBjYWNoZSB0aGlzP1xuICAgICAgICApO1xuICAgICAgICBpZiAoc2VsZWN0aW9uKSB7IC8vIHRocm93IHBhcnNlIGVycm9yIG90aGVyd2lzZT9cbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnU0VMRUNUX0RBVEVTJywgc2VsZWN0aW9uOiBzZWxlY3Rpb24gfSk7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXJEYXRlU2VsZWN0KHNlbGVjdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHB1YmxpYyBtZXRob2RcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudW5zZWxlY3QgPSBmdW5jdGlvbiAocGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmRhdGVTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRUxFQ1RfREFURVMnIH0pO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyRGF0ZVVuc2VsZWN0KHBldik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50cmlnZ2VyRGF0ZVNlbGVjdCA9IGZ1bmN0aW9uIChzZWxlY3Rpb24sIHBldikge1xuICAgICAgICB2YXIgYXJnID0gX19hc3NpZ24oe30sIHRoaXMuYnVpbGREYXRlU3BhbkFwaShzZWxlY3Rpb24pLCB7IGpzRXZlbnQ6IHBldiA/IHBldi5vcmlnRXZlbnQgOiBudWxsLCB2aWV3OiB0aGlzLnZpZXcgfSk7XG4gICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCdzZWxlY3QnLCBbYXJnXSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudHJpZ2dlckRhdGVVbnNlbGVjdCA9IGZ1bmN0aW9uIChwZXYpIHtcbiAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ3Vuc2VsZWN0JywgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGpzRXZlbnQ6IHBldiA/IHBldi5vcmlnRXZlbnQgOiBudWxsLFxuICAgICAgICAgICAgICAgIHZpZXc6IHRoaXMudmlld1xuICAgICAgICAgICAgfVxuICAgICAgICBdKTtcbiAgICB9O1xuICAgIC8vIFRPRE86IHJlY2VpdmUgcGV2P1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50cmlnZ2VyRGF0ZUNsaWNrID0gZnVuY3Rpb24gKGRhdGVTcGFuLCBkYXlFbCwgdmlldywgZXYpIHtcbiAgICAgICAgdmFyIGFyZyA9IF9fYXNzaWduKHt9LCB0aGlzLmJ1aWxkRGF0ZVBvaW50QXBpKGRhdGVTcGFuKSwgeyBkYXlFbDogZGF5RWwsIGpzRXZlbnQ6IGV2LCAvLyBJcyB0aGlzIGFsd2F5cyBhIG1vdXNlIGV2ZW50PyBTZWUgIzQ2NTVcbiAgICAgICAgICAgIHZpZXc6IHZpZXcgfSk7XG4gICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCdkYXRlQ2xpY2snLCBbYXJnXSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYnVpbGREYXRlUG9pbnRBcGkgPSBmdW5jdGlvbiAoZGF0ZVNwYW4pIHtcbiAgICAgICAgdmFyIHByb3BzID0ge307XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5kYXRlUG9pbnRUcmFuc2Zvcm1zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IF9hW19pXTtcbiAgICAgICAgICAgIF9fYXNzaWduKHByb3BzLCB0cmFuc2Zvcm0oZGF0ZVNwYW4sIHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICBfX2Fzc2lnbihwcm9wcywgYnVpbGREYXRlUG9pbnRBcGkoZGF0ZVNwYW4sIHRoaXMuZGF0ZUVudikpO1xuICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYnVpbGREYXRlU3BhbkFwaSA9IGZ1bmN0aW9uIChkYXRlU3Bhbikge1xuICAgICAgICB2YXIgcHJvcHMgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMucGx1Z2luU3lzdGVtLmhvb2tzLmRhdGVTcGFuVHJhbnNmb3JtczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSBfYVtfaV07XG4gICAgICAgICAgICBfX2Fzc2lnbihwcm9wcywgdHJhbnNmb3JtKGRhdGVTcGFuLCB0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgX19hc3NpZ24ocHJvcHMsIGJ1aWxkRGF0ZVNwYW5BcGkoZGF0ZVNwYW4sIHRoaXMuZGF0ZUVudikpO1xuICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgfTtcbiAgICAvLyBEYXRlIFV0aWxzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBSZXR1cm5zIGEgRGF0ZU1hcmtlciBmb3IgdGhlIGN1cnJlbnQgZGF0ZSwgYXMgZGVmaW5lZCBieSB0aGUgY2xpZW50J3MgY29tcHV0ZXIgb3IgZnJvbSB0aGUgYG5vd2Agb3B0aW9uXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldE5vdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vdyA9IHRoaXMub3B0KCdub3cnKTtcbiAgICAgICAgaWYgKHR5cGVvZiBub3cgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG5vdyA9IG5vdygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub3cgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi5jcmVhdGVOb3dNYXJrZXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5kYXRlRW52LmNyZWF0ZU1hcmtlcihub3cpO1xuICAgIH07XG4gICAgLy8gRXZlbnQtRGF0ZSBVdGlsaXRpZXNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEdpdmVuIGFuIGV2ZW50J3MgYWxsRGF5IHN0YXR1cyBhbmQgc3RhcnQgZGF0ZSwgcmV0dXJuIHdoYXQgaXRzIGZhbGxiYWNrIGVuZCBkYXRlIHNob3VsZCBiZS5cbiAgICAvLyBUT0RPOiByZW5hbWUgdG8gY29tcHV0ZURlZmF1bHRFdmVudEVuZFxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXREZWZhdWx0RXZlbnRFbmQgPSBmdW5jdGlvbiAoYWxsRGF5LCBtYXJrZXIpIHtcbiAgICAgICAgdmFyIGVuZCA9IG1hcmtlcjtcbiAgICAgICAgaWYgKGFsbERheSkge1xuICAgICAgICAgICAgZW5kID0gc3RhcnRPZkRheShlbmQpO1xuICAgICAgICAgICAgZW5kID0gdGhpcy5kYXRlRW52LmFkZChlbmQsIHRoaXMuZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZW5kID0gdGhpcy5kYXRlRW52LmFkZChlbmQsIHRoaXMuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVuZDtcbiAgICB9O1xuICAgIC8vIFB1YmxpYyBFdmVudHMgQVBJXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYWRkRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnRJbnB1dCwgc291cmNlSW5wdXQpIHtcbiAgICAgICAgaWYgKGV2ZW50SW5wdXQgaW5zdGFuY2VvZiBFdmVudEFwaSkge1xuICAgICAgICAgICAgdmFyIGRlZiA9IGV2ZW50SW5wdXQuX2RlZjtcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGV2ZW50SW5wdXQuX2luc3RhbmNlO1xuICAgICAgICAgICAgLy8gbm90IGFscmVhZHkgcHJlc2VudD8gZG9uJ3Qgd2FudCB0byBhZGQgYW4gb2xkIHNuYXBzaG90XG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuZXZlbnRTdG9yZS5kZWZzW2RlZi5kZWZJZF0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ0FERF9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFR1cGxlVG9TdG9yZSh7IGRlZjogZGVmLCBpbnN0YW5jZTogaW5zdGFuY2UgfSkgLy8gVE9ETzogYmV0dGVyIHV0aWwgZm9yIHR3byBhcmdzP1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50SW5wdXQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNvdXJjZUlkO1xuICAgICAgICBpZiAoc291cmNlSW5wdXQgaW5zdGFuY2VvZiBFdmVudFNvdXJjZUFwaSkge1xuICAgICAgICAgICAgc291cmNlSWQgPSBzb3VyY2VJbnB1dC5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHNvdXJjZUlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2VBcGkgPSB0aGlzLmdldEV2ZW50U291cmNlQnlJZChzb3VyY2VJbnB1dCk7IC8vIFRPRE86IHVzZSBhbiBpbnRlcm5hbCBmdW5jdGlvblxuICAgICAgICAgICAgaWYgKCFzb3VyY2VBcGkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0NvdWxkIG5vdCBmaW5kIGFuIGV2ZW50IHNvdXJjZSB3aXRoIElEIFwiJyArIHNvdXJjZUlucHV0ICsgJ1wiJyk7IC8vIFRPRE86IHRlc3RcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHNvdXJjZUlkID0gc291cmNlQXBpLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR1cGxlID0gcGFyc2VFdmVudChldmVudElucHV0LCBzb3VyY2VJZCwgdGhpcyk7XG4gICAgICAgIGlmICh0dXBsZSkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ0FERF9FVkVOVFMnLFxuICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50VHVwbGVUb1N0b3JlKHR1cGxlKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50QXBpKHRoaXMsIHR1cGxlLmRlZiwgdHVwbGUuZGVmLnJlY3VycmluZ0RlZiA/IG51bGwgOiB0dXBsZS5pbnN0YW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvLyBUT0RPOiBvcHRpbWl6ZVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRFdmVudEJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5zdGF0ZS5ldmVudFN0b3JlLCBkZWZzID0gX2EuZGVmcywgaW5zdGFuY2VzID0gX2EuaW5zdGFuY2VzO1xuICAgICAgICBpZCA9IFN0cmluZyhpZCk7XG4gICAgICAgIGZvciAodmFyIGRlZklkIGluIGRlZnMpIHtcbiAgICAgICAgICAgIHZhciBkZWYgPSBkZWZzW2RlZklkXTtcbiAgICAgICAgICAgIGlmIChkZWYucHVibGljSWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRlZi5yZWN1cnJpbmdEZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudEFwaSh0aGlzLCBkZWYsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaW5zdGFuY2VJZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnN0YW5jZS5kZWZJZCA9PT0gZGVmLmRlZklkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudEFwaSh0aGlzLCBkZWYsIGluc3RhbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuc3RhdGUuZXZlbnRTdG9yZSwgZGVmcyA9IF9hLmRlZnMsIGluc3RhbmNlcyA9IF9hLmluc3RhbmNlcztcbiAgICAgICAgdmFyIGV2ZW50QXBpcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGluc3RhbmNlc1tpZF07XG4gICAgICAgICAgICB2YXIgZGVmID0gZGVmc1tpbnN0YW5jZS5kZWZJZF07XG4gICAgICAgICAgICBldmVudEFwaXMucHVzaChuZXcgRXZlbnRBcGkodGhpcywgZGVmLCBpbnN0YW5jZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBldmVudEFwaXM7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVtb3ZlQWxsRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ1JFTU9WRV9BTExfRVZFTlRTJyB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZXJlbmRlckV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdSRVNFVF9FVkVOVFMnIH0pO1xuICAgIH07XG4gICAgLy8gUHVibGljIEV2ZW50IFNvdXJjZXMgQVBJXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0RXZlbnRTb3VyY2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc291cmNlSGFzaCA9IHRoaXMuc3RhdGUuZXZlbnRTb3VyY2VzO1xuICAgICAgICB2YXIgc291cmNlQXBpcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpbnRlcm5hbElkIGluIHNvdXJjZUhhc2gpIHtcbiAgICAgICAgICAgIHNvdXJjZUFwaXMucHVzaChuZXcgRXZlbnRTb3VyY2VBcGkodGhpcywgc291cmNlSGFzaFtpbnRlcm5hbElkXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzb3VyY2VBcGlzO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldEV2ZW50U291cmNlQnlJZCA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICB2YXIgc291cmNlSGFzaCA9IHRoaXMuc3RhdGUuZXZlbnRTb3VyY2VzO1xuICAgICAgICBpZCA9IFN0cmluZyhpZCk7XG4gICAgICAgIGZvciAodmFyIHNvdXJjZUlkIGluIHNvdXJjZUhhc2gpIHtcbiAgICAgICAgICAgIGlmIChzb3VyY2VIYXNoW3NvdXJjZUlkXS5wdWJsaWNJZCA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlQXBpKHRoaXMsIHNvdXJjZUhhc2hbc291cmNlSWRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5hZGRFdmVudFNvdXJjZSA9IGZ1bmN0aW9uIChzb3VyY2VJbnB1dCkge1xuICAgICAgICBpZiAoc291cmNlSW5wdXQgaW5zdGFuY2VvZiBFdmVudFNvdXJjZUFwaSkge1xuICAgICAgICAgICAgLy8gbm90IGFscmVhZHkgcHJlc2VudD8gZG9uJ3Qgd2FudCB0byBhZGQgYW4gb2xkIHNuYXBzaG90XG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuZXZlbnRTb3VyY2VzW3NvdXJjZUlucHV0LmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWRdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdBRERfRVZFTlRfU09VUkNFUycsXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZXM6IFtzb3VyY2VJbnB1dC5pbnRlcm5hbEV2ZW50U291cmNlXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZUlucHV0O1xuICAgICAgICB9XG4gICAgICAgIHZhciBldmVudFNvdXJjZSA9IHBhcnNlRXZlbnRTb3VyY2Uoc291cmNlSW5wdXQsIHRoaXMpO1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2UpIHsgLy8gVE9ETzogZXJyb3Igb3RoZXJ3aXNlP1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdBRERfRVZFTlRfU09VUkNFUycsIHNvdXJjZXM6IFtldmVudFNvdXJjZV0gfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlQXBpKHRoaXMsIGV2ZW50U291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZW1vdmVBbGxFdmVudFNvdXJjZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUkVNT1ZFX0FMTF9FVkVOVF9TT1VSQ0VTJyB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWZldGNoRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ0ZFVENIX0VWRU5UX1NPVVJDRVMnIH0pO1xuICAgIH07XG4gICAgLy8gU2Nyb2xsXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuc2Nyb2xsVG9UaW1lID0gZnVuY3Rpb24gKHRpbWVJbnB1dCkge1xuICAgICAgICB2YXIgZHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbih0aW1lSW5wdXQpO1xuICAgICAgICBpZiAoZHVyYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LnZpZXcuc2Nyb2xsVG9EdXJhdGlvbihkdXJhdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBDYWxlbmRhcjtcbn0oKSk7XG5FbWl0dGVyTWl4aW4ubWl4SW50byhDYWxlbmRhcik7XG4vLyBmb3IgbWVtb2l6ZXJzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYnVpbGRDb21wb25lbnRDb250ZXh0JDEodGhlbWUsIGRhdGVFbnYsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IENvbXBvbmVudENvbnRleHQodGhpcywgdGhlbWUsIGRhdGVFbnYsIG9wdGlvbnMsIG51bGwpO1xufVxuZnVuY3Rpb24gYnVpbGREYXRlRW52KGxvY2FsZSwgdGltZVpvbmUsIG5hbWVkVGltZVpvbmVJbXBsLCBmaXJzdERheSwgd2Vla051bWJlckNhbGN1bGF0aW9uLCB3ZWVrTGFiZWwsIGNtZEZvcm1hdHRlcikge1xuICAgIHJldHVybiBuZXcgRGF0ZUVudih7XG4gICAgICAgIGNhbGVuZGFyU3lzdGVtOiAnZ3JlZ29yeScsXG4gICAgICAgIHRpbWVab25lOiB0aW1lWm9uZSxcbiAgICAgICAgbmFtZWRUaW1lWm9uZUltcGw6IG5hbWVkVGltZVpvbmVJbXBsLFxuICAgICAgICBsb2NhbGU6IGxvY2FsZSxcbiAgICAgICAgd2Vla051bWJlckNhbGN1bGF0aW9uOiB3ZWVrTnVtYmVyQ2FsY3VsYXRpb24sXG4gICAgICAgIGZpcnN0RGF5OiBmaXJzdERheSxcbiAgICAgICAgd2Vla0xhYmVsOiB3ZWVrTGFiZWwsXG4gICAgICAgIGNtZEZvcm1hdHRlcjogY21kRm9ybWF0dGVyXG4gICAgfSk7XG59XG5mdW5jdGlvbiBidWlsZFRoZW1lKGNhbGVuZGFyT3B0aW9ucykge1xuICAgIHZhciB0aGVtZUNsYXNzID0gdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3MudGhlbWVDbGFzc2VzW2NhbGVuZGFyT3B0aW9ucy50aGVtZVN5c3RlbV0gfHwgU3RhbmRhcmRUaGVtZTtcbiAgICByZXR1cm4gbmV3IHRoZW1lQ2xhc3MoY2FsZW5kYXJPcHRpb25zKTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRGVsYXllZFJlcmVuZGVyKHdhaXQpIHtcbiAgICB2YXIgZnVuYyA9IHRoaXMudHJ5UmVyZW5kZXIuYmluZCh0aGlzKTtcbiAgICBpZiAod2FpdCAhPSBudWxsKSB7XG4gICAgICAgIGZ1bmMgPSBkZWJvdW5jZShmdW5jLCB3YWl0KTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmM7XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50VWlCeVNvdXJjZShldmVudFNvdXJjZXMpIHtcbiAgICByZXR1cm4gbWFwSGFzaChldmVudFNvdXJjZXMsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gZXZlbnRTb3VyY2UudWk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50VWlCYXNlcyhldmVudERlZnMsIGV2ZW50VWlTaW5nbGVCYXNlLCBldmVudFVpQnlTb3VyY2UpIHtcbiAgICB2YXIgZXZlbnRVaUJhc2VzID0geyAnJzogZXZlbnRVaVNpbmdsZUJhc2UgfTtcbiAgICBmb3IgKHZhciBkZWZJZCBpbiBldmVudERlZnMpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50RGVmc1tkZWZJZF07XG4gICAgICAgIGlmIChkZWYuc291cmNlSWQgJiYgZXZlbnRVaUJ5U291cmNlW2RlZi5zb3VyY2VJZF0pIHtcbiAgICAgICAgICAgIGV2ZW50VWlCYXNlc1tkZWZJZF0gPSBldmVudFVpQnlTb3VyY2VbZGVmLnNvdXJjZUlkXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXZlbnRVaUJhc2VzO1xufVxuXG52YXIgVmlldyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoVmlldywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBWaWV3KHZpZXdTcGVjLCBwYXJlbnRFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLXZpZXcgZmMtJyArIHZpZXdTcGVjLnR5cGUgKyAnLXZpZXcnIH0pKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yZW5kZXJEYXRlc01lbSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMucmVuZGVyRGF0ZXNXcmFwLCBfdGhpcy51bnJlbmRlckRhdGVzV3JhcCk7XG4gICAgICAgIF90aGlzLnJlbmRlckJ1c2luZXNzSG91cnNNZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckJ1c2luZXNzSG91cnMsIF90aGlzLnVucmVuZGVyQnVzaW5lc3NIb3VycywgW190aGlzLnJlbmRlckRhdGVzTWVtXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckRhdGVTZWxlY3Rpb25NZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckRhdGVTZWxlY3Rpb25XcmFwLCBfdGhpcy51bnJlbmRlckRhdGVTZWxlY3Rpb25XcmFwLCBbX3RoaXMucmVuZGVyRGF0ZXNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRzTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJFdmVudHMsIF90aGlzLnVucmVuZGVyRXZlbnRzLCBbX3RoaXMucmVuZGVyRGF0ZXNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRTZWxlY3Rpb25NZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uV3JhcCwgX3RoaXMudW5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAsIFtfdGhpcy5yZW5kZXJFdmVudHNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnREcmFnTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJFdmVudERyYWdXcmFwLCBfdGhpcy51bnJlbmRlckV2ZW50RHJhZ1dyYXAsIFtfdGhpcy5yZW5kZXJEYXRlc01lbV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFJlc2l6ZU1lbSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMucmVuZGVyRXZlbnRSZXNpemVXcmFwLCBfdGhpcy51bnJlbmRlckV2ZW50UmVzaXplV3JhcCwgW190aGlzLnJlbmRlckRhdGVzTWVtXSk7XG4gICAgICAgIF90aGlzLnZpZXdTcGVjID0gdmlld1NwZWM7XG4gICAgICAgIF90aGlzLnR5cGUgPSB2aWV3U3BlYy50eXBlO1xuICAgICAgICBwYXJlbnRFbC5hcHBlbmRDaGlsZChfdGhpcy5lbCk7XG4gICAgICAgIF90aGlzLmluaXRpYWxpemUoKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBWaWV3LnByb3RvdHlwZS5pbml0aWFsaXplID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFZpZXcucHJvdG90eXBlLCBcImFjdGl2ZVN0YXJ0XCIsIHtcbiAgICAgICAgLy8gRGF0ZSBTZXR0aW5nL1Vuc2V0dGluZ1xuICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZGF0ZUVudi50b0RhdGUodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZS5zdGFydCk7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShWaWV3LnByb3RvdHlwZSwgXCJhY3RpdmVFbmRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZGF0ZUVudi50b0RhdGUodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZS5lbmQpO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoVmlldy5wcm90b3R5cGUsIFwiY3VycmVudFN0YXJ0XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYudG9EYXRlKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0KTtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFZpZXcucHJvdG90eXBlLCBcImN1cnJlbnRFbmRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZGF0ZUVudi50b0RhdGUodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2UuZW5kKTtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgLy8gR2VuZXJhbCBSZW5kZXJpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgICAgICB0aGlzLnJlbmRlckRhdGVzTWVtKHByb3BzLmRhdGVQcm9maWxlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJCdXNpbmVzc0hvdXJzTWVtKHByb3BzLmJ1c2luZXNzSG91cnMpO1xuICAgICAgICB0aGlzLnJlbmRlckRhdGVTZWxlY3Rpb25NZW0ocHJvcHMuZGF0ZVNlbGVjdGlvbik7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnRzTWVtKHByb3BzLmV2ZW50U3RvcmUpO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uTWVtKHByb3BzLmV2ZW50U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudERyYWdNZW0ocHJvcHMuZXZlbnREcmFnKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZU1lbShwcm9wcy5ldmVudFJlc2l6ZSk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5iZWZvcmVVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkU2Nyb2xsKHRoaXMucXVlcnlTY3JvbGwoKSk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJEYXRlc01lbS51bnJlbmRlcigpOyAvLyBzaG91bGQgdW5yZW5kZXIgZXZlcnl0aGluZyBlbHNlXG4gICAgfTtcbiAgICAvLyBTaXppbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnVwZGF0ZVNpemUgPSBmdW5jdGlvbiAoaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0bykge1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzLmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIGlmIChpc1Jlc2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5hZGRTY3JvbGwodGhpcy5xdWVyeVNjcm9sbCgpKTsgLy8gTk9URTogc2FtZSBjb2RlIGFzIGluIGJlZm9yZVVwZGF0ZVxuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Jlc2l6ZSB8fCAvLyBIQUNLUy4uLlxuICAgICAgICAgICAgY2FsZW5kYXIuaXNWaWV3VXBkYXRlZCB8fFxuICAgICAgICAgICAgY2FsZW5kYXIuaXNEYXRlc1VwZGF0ZWQgfHxcbiAgICAgICAgICAgIGNhbGVuZGFyLmlzRXZlbnRzVXBkYXRlZCkge1xuICAgICAgICAgICAgLy8gc29ydCBvZiB0aGUgY2F0Y2gtYWxsIHNpemluZ1xuICAgICAgICAgICAgLy8gYW55dGhpbmcgdGhhdCBtaWdodCBjYXVzZSBkaW1lbnNpb24gY2hhbmdlc1xuICAgICAgICAgICAgdGhpcy51cGRhdGVCYXNlU2l6ZShpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOT1RFOiBwb3BTY3JvbGwgaXMgY2FsbGVkIGJ5IENhbGVuZGFyQ29tcG9uZW50XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51cGRhdGVCYXNlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKSB7XG4gICAgfTtcbiAgICAvLyBEYXRlIFJlbmRlcmluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRGF0ZXNXcmFwID0gZnVuY3Rpb24gKGRhdGVQcm9maWxlKSB7XG4gICAgICAgIHRoaXMucmVuZGVyRGF0ZXMoZGF0ZVByb2ZpbGUpO1xuICAgICAgICB0aGlzLmFkZFNjcm9sbCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogY3JlYXRlRHVyYXRpb24odGhpcy5jb250ZXh0Lm9wdGlvbnMuc2Nyb2xsVGltZSlcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckRhdGVzV3JhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdG9wTm93SW5kaWNhdG9yKCk7XG4gICAgICAgIHRoaXMudW5yZW5kZXJEYXRlcygpO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRGF0ZXMgPSBmdW5jdGlvbiAoZGF0ZVByb2ZpbGUpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckRhdGVzID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgIC8vIEJ1c2luZXNzIEhvdXJzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJCdXNpbmVzc0hvdXJzID0gZnVuY3Rpb24gKGJ1c2luZXNzSG91cnMpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckJ1c2luZXNzSG91cnMgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgLy8gRGF0ZSBTZWxlY3Rpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckRhdGVTZWxlY3Rpb25XcmFwID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xuICAgICAgICBpZiAoc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckRhdGVTZWxlY3Rpb24oc2VsZWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJEYXRlU2VsZWN0aW9uV3JhcCA9IGZ1bmN0aW9uIChzZWxlY3Rpb24pIHtcbiAgICAgICAgaWYgKHNlbGVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckRhdGVTZWxlY3Rpb24oc2VsZWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRGF0ZVNlbGVjdGlvbiA9IGZ1bmN0aW9uIChzZWxlY3Rpb24pIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckRhdGVTZWxlY3Rpb24gPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7IH07XG4gICAgLy8gRXZlbnQgUmVuZGVyaW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudHMgPSBmdW5jdGlvbiAoZXZlbnRTdG9yZSkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRzID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgIC8vIHV0aWwgZm9yIHN1YmNsYXNzZXNcbiAgICBWaWV3LnByb3RvdHlwZS5zbGljZUV2ZW50cyA9IGZ1bmN0aW9uIChldmVudFN0b3JlLCBhbGxEYXkpIHtcbiAgICAgICAgdmFyIHByb3BzID0gdGhpcy5wcm9wcztcbiAgICAgICAgcmV0dXJuIHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBwcm9wcy5ldmVudFVpQmFzZXMsIHByb3BzLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBhbGxEYXkgPyB0aGlzLmNvbnRleHQubmV4dERheVRocmVzaG9sZCA6IG51bGwpLmZnO1xuICAgIH07XG4gICAgLy8gRXZlbnQgU2VsZWN0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbihpbnN0YW5jZUlkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckV2ZW50U2VsZWN0aW9uKGluc3RhbmNlSWQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IGZ1bmN0aW9uIChpbnN0YW5jZUlkKSB7IH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IGZ1bmN0aW9uIChpbnN0YW5jZUlkKSB7IH07XG4gICAgLy8gRXZlbnQgRHJhZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnREcmFnV3JhcCA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyRXZlbnREcmFnKHN0YXRlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudERyYWdXcmFwID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckV2ZW50RHJhZyhzdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnREcmFnID0gZnVuY3Rpb24gKHN0YXRlKSB7IH07XG4gICAgLy8gRXZlbnQgUmVzaXplXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFJlc2l6ZVdyYXAgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckV2ZW50UmVzaXplKHN0YXRlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudFJlc2l6ZVdyYXAgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLnVucmVuZGVyRXZlbnRSZXNpemUoc3RhdGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFJlc2l6ZSA9IGZ1bmN0aW9uIChzdGF0ZSkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRSZXNpemUgPSBmdW5jdGlvbiAoc3RhdGUpIHsgfTtcbiAgICAvKiBOb3cgSW5kaWNhdG9yXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAvLyBJbW1lZGlhdGVseSByZW5kZXIgdGhlIGN1cnJlbnQgdGltZSBpbmRpY2F0b3IgYW5kIGJlZ2lucyByZS1yZW5kZXJpbmcgaXQgYXQgYW4gaW50ZXJ2YWwsXG4gICAgLy8gd2hpY2ggaXMgZGVmaW5lZCBieSB0aGlzLmdldE5vd0luZGljYXRvclVuaXQoKS5cbiAgICAvLyBUT0RPOiBzb21laG93IGRvIHRoaXMgZm9yIHRoZSBjdXJyZW50IHdob2xlIGRheSdzIGJhY2tncm91bmQgdG9vXG4gICAgLy8gVVNBR0U6IG11c3QgYmUgY2FsbGVkIG1hbnVhbGx5IGZyb20gc3ViY2xhc3NlcycgcmVuZGVyIG1ldGhvZHMhIGRvbid0IG5lZWQgdG8gY2FsbCBzdG9wTm93SW5kaWNhdG9yIHRob1xuICAgIFZpZXcucHJvdG90eXBlLnN0YXJ0Tm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKGRhdGVQcm9maWxlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIGRhdGVFbnYgPSBfYS5kYXRlRW52LCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIHVuaXQ7XG4gICAgICAgIHZhciB1cGRhdGU7XG4gICAgICAgIHZhciBkZWxheTsgLy8gbXMgd2FpdCB2YWx1ZVxuICAgICAgICBpZiAob3B0aW9ucy5ub3dJbmRpY2F0b3IgJiYgIXRoaXMuaW5pdGlhbE5vd0RhdGUpIHtcbiAgICAgICAgICAgIHVuaXQgPSB0aGlzLmdldE5vd0luZGljYXRvclVuaXQoZGF0ZVByb2ZpbGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKTtcbiAgICAgICAgICAgIGlmICh1bml0KSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlID0gdGhpcy51cGRhdGVOb3dJbmRpY2F0b3IuYmluZCh0aGlzKTtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRpYWxOb3dEYXRlID0gY2FsZW5kYXIuZ2V0Tm93KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsTm93UXVlcmllZE1zID0gbmV3IERhdGUoKS52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgLy8gd2FpdCB1bnRpbCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBuZXh0IGludGVydmFsXG4gICAgICAgICAgICAgICAgZGVsYXkgPSBkYXRlRW52LmFkZChkYXRlRW52LnN0YXJ0T2YodGhpcy5pbml0aWFsTm93RGF0ZSwgdW5pdCksIGNyZWF0ZUR1cmF0aW9uKDEsIHVuaXQpKS52YWx1ZU9mKCkgLSB0aGlzLmluaXRpYWxOb3dEYXRlLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBtYXliZSBhbHdheXMgdXNlIHNldFRpbWVvdXQsIHdhaXRpbmcgdW50aWwgc3RhcnQgb2YgbmV4dCB1bml0XG4gICAgICAgICAgICAgICAgdGhpcy5ub3dJbmRpY2F0b3JUaW1lb3V0SUQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubm93SW5kaWNhdG9yVGltZW91dElEID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1bml0ID09PSAnc2Vjb25kJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXkgPSAxMDAwOyAvLyBldmVyeSBzZWNvbmRcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5ID0gMTAwMCAqIDYwOyAvLyBvdGhlcndpc2UsIGV2ZXJ5IG1pbnV0ZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm5vd0luZGljYXRvckludGVydmFsSUQgPSBzZXRJbnRlcnZhbCh1cGRhdGUsIGRlbGF5KTsgLy8gdXBkYXRlIGV2ZXJ5IGludGVydmFsXG4gICAgICAgICAgICAgICAgfSwgZGVsYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmVuZGVyaW5nIHdpbGwgYmUgaW5pdGlhdGVkIGluIHVwZGF0ZVNpemVcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gcmVyZW5kZXJzIHRoZSBub3cgaW5kaWNhdG9yLCBjb21wdXRpbmcgdGhlIG5ldyBjdXJyZW50IHRpbWUgZnJvbSB0aGUgYW1vdW50IG9mIHRpbWUgdGhhdCBoYXMgcGFzc2VkXG4gICAgLy8gc2luY2UgdGhlIGluaXRpYWwgZ2V0Tm93IGNhbGwuXG4gICAgVmlldy5wcm90b3R5cGUudXBkYXRlTm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSAmJiAvLyBhIHdheSB0byBkZXRlcm1pbmUgaWYgZGF0ZXMgd2VyZSByZW5kZXJlZCB5ZXRcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbE5vd0RhdGUgLy8gYWN0aXZhdGVkIGJlZm9yZT9cbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnVucmVuZGVyTm93SW5kaWNhdG9yKCk7IC8vIHdvbid0IHVucmVuZGVyIGlmIHVubmVjZXNzYXJ5XG4gICAgICAgICAgICB0aGlzLnJlbmRlck5vd0luZGljYXRvcihhZGRNcyh0aGlzLmluaXRpYWxOb3dEYXRlLCBuZXcgRGF0ZSgpLnZhbHVlT2YoKSAtIHRoaXMuaW5pdGlhbE5vd1F1ZXJpZWRNcykpO1xuICAgICAgICAgICAgdGhpcy5pc05vd0luZGljYXRvclJlbmRlcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gSW1tZWRpYXRlbHkgdW5yZW5kZXJzIHRoZSB2aWV3J3MgY3VycmVudCB0aW1lIGluZGljYXRvciBhbmQgc3RvcHMgYW55IHJlLXJlbmRlcmluZyB0aW1lcnMuXG4gICAgLy8gV29uJ3QgY2F1c2Ugc2lkZSBlZmZlY3RzIGlmIGluZGljYXRvciBpc24ndCByZW5kZXJlZC5cbiAgICBWaWV3LnByb3RvdHlwZS5zdG9wTm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ub3dJbmRpY2F0b3JUaW1lb3V0SUQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLm5vd0luZGljYXRvclRpbWVvdXRJRCk7XG4gICAgICAgICAgICB0aGlzLm5vd0luZGljYXRvclRpbWVvdXRJRCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubm93SW5kaWNhdG9ySW50ZXJ2YWxJRCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLm5vd0luZGljYXRvckludGVydmFsSUQpO1xuICAgICAgICAgICAgdGhpcy5ub3dJbmRpY2F0b3JJbnRlcnZhbElEID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc05vd0luZGljYXRvclJlbmRlcmVkKSB7XG4gICAgICAgICAgICB0aGlzLnVucmVuZGVyTm93SW5kaWNhdG9yKCk7XG4gICAgICAgICAgICB0aGlzLmlzTm93SW5kaWNhdG9yUmVuZGVyZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuZ2V0Tm93SW5kaWNhdG9yVW5pdCA9IGZ1bmN0aW9uIChkYXRlUHJvZmlsZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpIHtcbiAgICAgICAgLy8gc3ViY2xhc3NlcyBzaG91bGQgaW1wbGVtZW50XG4gICAgfTtcbiAgICAvLyBSZW5kZXJzIGEgY3VycmVudCB0aW1lIGluZGljYXRvciBhdCB0aGUgZ2l2ZW4gZGF0ZXRpbWVcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJOb3dJbmRpY2F0b3IgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICAvLyBTVUJDTEFTU0VTIE1VU1QgUEFTUyBUTyBDSElMRFJFTiFcbiAgICB9O1xuICAgIC8vIFVuZG9lcyB0aGUgcmVuZGVyaW5nIGFjdGlvbnMgZnJvbSByZW5kZXJOb3dJbmRpY2F0b3JcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlck5vd0luZGljYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gU1VCQ0xBU1NFUyBNVVNUIFBBU1MgVE8gQ0hJTERSRU4hXG4gICAgfTtcbiAgICAvKiBTY3JvbGxlclxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgVmlldy5wcm90b3R5cGUuYWRkU2Nyb2xsID0gZnVuY3Rpb24gKHNjcm9sbCwgaXNGb3JjZWQpIHtcbiAgICAgICAgaWYgKGlzRm9yY2VkKSB7XG4gICAgICAgICAgICBzY3JvbGwuaXNGb3JjZWQgPSBpc0ZvcmNlZDtcbiAgICAgICAgfVxuICAgICAgICBfX2Fzc2lnbih0aGlzLnF1ZXVlZFNjcm9sbCB8fCAodGhpcy5xdWV1ZWRTY3JvbGwgPSB7fSksIHNjcm9sbCk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5wb3BTY3JvbGwgPSBmdW5jdGlvbiAoaXNSZXNpemUpIHtcbiAgICAgICAgdGhpcy5hcHBseVF1ZXVlZFNjcm9sbChpc1Jlc2l6ZSk7XG4gICAgICAgIHRoaXMucXVldWVkU2Nyb2xsID0gbnVsbDtcbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLmFwcGx5UXVldWVkU2Nyb2xsID0gZnVuY3Rpb24gKGlzUmVzaXplKSB7XG4gICAgICAgIGlmICh0aGlzLnF1ZXVlZFNjcm9sbCkge1xuICAgICAgICAgICAgdGhpcy5hcHBseVNjcm9sbCh0aGlzLnF1ZXVlZFNjcm9sbCwgaXNSZXNpemUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5xdWVyeVNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNjcm9sbCA9IHt9O1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSkgeyAvLyBkYXRlcyByZW5kZXJlZCB5ZXQ/XG4gICAgICAgICAgICBfX2Fzc2lnbihzY3JvbGwsIHRoaXMucXVlcnlEYXRlU2Nyb2xsKCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzY3JvbGw7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5hcHBseVNjcm9sbCA9IGZ1bmN0aW9uIChzY3JvbGwsIGlzUmVzaXplKSB7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IHNjcm9sbC5kdXJhdGlvbiwgaXNGb3JjZWQgPSBzY3JvbGwuaXNGb3JjZWQ7XG4gICAgICAgIGlmIChkdXJhdGlvbiAhPSBudWxsICYmICFpc0ZvcmNlZCkge1xuICAgICAgICAgICAgZGVsZXRlIHNjcm9sbC5kdXJhdGlvbjtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLmRhdGVQcm9maWxlKSB7IC8vIGRhdGVzIHJlbmRlcmVkIHlldD9cbiAgICAgICAgICAgICAgICBfX2Fzc2lnbihzY3JvbGwsIHRoaXMuY29tcHV0ZURhdGVTY3JvbGwoZHVyYXRpb24pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSkgeyAvLyBkYXRlcyByZW5kZXJlZCB5ZXQ/XG4gICAgICAgICAgICB0aGlzLmFwcGx5RGF0ZVNjcm9sbChzY3JvbGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5jb21wdXRlRGF0ZVNjcm9sbCA9IGZ1bmN0aW9uIChkdXJhdGlvbikge1xuICAgICAgICByZXR1cm4ge307IC8vIHN1YmNsYXNzZXMgbXVzdCBpbXBsZW1lbnRcbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnF1ZXJ5RGF0ZVNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHt9OyAvLyBzdWJjbGFzc2VzIG11c3QgaW1wbGVtZW50XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5hcHBseURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoc2Nyb2xsKSB7XG4gICAgICAgIC8vIHN1YmNsYXNzZXMgbXVzdCBpbXBsZW1lbnRcbiAgICB9O1xuICAgIC8vIGZvciBBUElcbiAgICBWaWV3LnByb3RvdHlwZS5zY3JvbGxUb0R1cmF0aW9uID0gZnVuY3Rpb24gKGR1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuYXBwbHlTY3JvbGwoeyBkdXJhdGlvbjogZHVyYXRpb24gfSwgZmFsc2UpO1xuICAgIH07XG4gICAgcmV0dXJuIFZpZXc7XG59KERhdGVDb21wb25lbnQpKTtcbkVtaXR0ZXJNaXhpbi5taXhJbnRvKFZpZXcpO1xuVmlldy5wcm90b3R5cGUudXNlc01pbk1heFRpbWUgPSBmYWxzZTtcblZpZXcucHJvdG90eXBlLmRhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3MgPSBEYXRlUHJvZmlsZUdlbmVyYXRvcjtcblxudmFyIEZnRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGZ0V2ZW50UmVuZGVyZXIoKSB7XG4gICAgICAgIHRoaXMuc2VncyA9IFtdO1xuICAgICAgICB0aGlzLmlzU2l6ZURpcnR5ID0gZmFsc2U7XG4gICAgfVxuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VncyA9IGZ1bmN0aW9uIChjb250ZXh0LCBzZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRoaXMucmFuZ2VVcGRhdGVkKCk7IC8vIGNhbGxlZCB0b28gZnJlcXVlbnRseSA6KFxuICAgICAgICAvLyByZW5kZXIgYW4gYC5lbGAgb24gZWFjaCBzZWdcbiAgICAgICAgLy8gcmV0dXJucyBhIHN1YnNldCBvZiB0aGUgc2Vncy4gc2VncyB0aGF0IHdlcmUgYWN0dWFsbHkgcmVuZGVyZWRcbiAgICAgICAgc2VncyA9IHRoaXMucmVuZGVyU2VnRWxzKHNlZ3MsIG1pcnJvckluZm8pO1xuICAgICAgICB0aGlzLnNlZ3MgPSBzZWdzO1xuICAgICAgICB0aGlzLmF0dGFjaFNlZ3Moc2VncywgbWlycm9ySW5mbyk7XG4gICAgICAgIHRoaXMuaXNTaXplRGlydHkgPSB0cnVlO1xuICAgICAgICB0cmlnZ2VyUmVuZGVyZWRTZWdzKHRoaXMuY29udGV4dCwgdGhpcy5zZWdzLCBCb29sZWFuKG1pcnJvckluZm8pKTtcbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUudW5yZW5kZXIgPSBmdW5jdGlvbiAoY29udGV4dCwgX3NlZ3MsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdHJpZ2dlcldpbGxSZW1vdmVTZWdzKHRoaXMuY29udGV4dCwgdGhpcy5zZWdzLCBCb29sZWFuKG1pcnJvckluZm8pKTtcbiAgICAgICAgdGhpcy5kZXRhY2hTZWdzKHRoaXMuc2Vncyk7XG4gICAgICAgIHRoaXMuc2VncyA9IFtdO1xuICAgIH07XG4gICAgLy8gVXBkYXRlcyB2YWx1ZXMgdGhhdCByZWx5IG9uIG9wdGlvbnMgYW5kIGFsc28gcmVsYXRlIHRvIHJhbmdlXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yYW5nZVVwZGF0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvcHRpb25zID0gdGhpcy5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIHZhciBkaXNwbGF5RXZlbnRUaW1lO1xuICAgICAgICB2YXIgZGlzcGxheUV2ZW50RW5kO1xuICAgICAgICB0aGlzLmV2ZW50VGltZUZvcm1hdCA9IGNyZWF0ZUZvcm1hdHRlcihvcHRpb25zLmV2ZW50VGltZUZvcm1hdCB8fCB0aGlzLmNvbXB1dGVFdmVudFRpbWVGb3JtYXQoKSwgb3B0aW9ucy5kZWZhdWx0UmFuZ2VTZXBhcmF0b3IpO1xuICAgICAgICBkaXNwbGF5RXZlbnRUaW1lID0gb3B0aW9ucy5kaXNwbGF5RXZlbnRUaW1lO1xuICAgICAgICBpZiAoZGlzcGxheUV2ZW50VGltZSA9PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwbGF5RXZlbnRUaW1lID0gdGhpcy5jb21wdXRlRGlzcGxheUV2ZW50VGltZSgpOyAvLyBtaWdodCBiZSBiYXNlZCBvZmYgb2YgcmFuZ2VcbiAgICAgICAgfVxuICAgICAgICBkaXNwbGF5RXZlbnRFbmQgPSBvcHRpb25zLmRpc3BsYXlFdmVudEVuZDtcbiAgICAgICAgaWYgKGRpc3BsYXlFdmVudEVuZCA9PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwbGF5RXZlbnRFbmQgPSB0aGlzLmNvbXB1dGVEaXNwbGF5RXZlbnRFbmQoKTsgLy8gbWlnaHQgYmUgYmFzZWQgb2ZmIG9mIHJhbmdlXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwbGF5RXZlbnRUaW1lID0gZGlzcGxheUV2ZW50VGltZTtcbiAgICAgICAgdGhpcy5kaXNwbGF5RXZlbnRFbmQgPSBkaXNwbGF5RXZlbnRFbmQ7XG4gICAgfTtcbiAgICAvLyBSZW5kZXJzIGFuZCBhc3NpZ25zIGFuIGBlbGAgcHJvcGVydHkgZm9yIGVhY2ggZm9yZWdyb3VuZCBldmVudCBzZWdtZW50LlxuICAgIC8vIE9ubHkgcmV0dXJucyBzZWdtZW50cyB0aGF0IHN1Y2Nlc3NmdWxseSByZW5kZXJlZC5cbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLnJlbmRlclNlZ0VscyA9IGZ1bmN0aW9uIChzZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHZhciBodG1sID0gJyc7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBpZiAoc2Vncy5sZW5ndGgpIHsgLy8gZG9uJ3QgYnVpbGQgYW4gZW1wdHkgaHRtbCBzdHJpbmdcbiAgICAgICAgICAgIC8vIGJ1aWxkIGEgbGFyZ2UgY29uY2F0ZW5hdGlvbiBvZiBldmVudCBzZWdtZW50IEhUTUxcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSB0aGlzLnJlbmRlclNlZ0h0bWwoc2Vnc1tpXSwgbWlycm9ySW5mbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBHcmFiIGluZGl2aWR1YWwgZWxlbWVudHMgZnJvbSB0aGUgY29tYmluZWQgSFRNTCBzdHJpbmcuIFVzZSBlYWNoIGFzIHRoZSBkZWZhdWx0IHJlbmRlcmluZy5cbiAgICAgICAgICAgIC8vIFRoZW4sIGNvbXB1dGUgdGhlICdlbCcgZm9yIGVhY2ggc2VnbWVudC4gQW4gZWwgbWlnaHQgYmUgbnVsbCBpZiB0aGUgZXZlbnRSZW5kZXIgY2FsbGJhY2sgcmV0dXJuZWQgZmFsc2UuXG4gICAgICAgICAgICBodG1sVG9FbGVtZW50cyhodG1sKS5mb3JFYWNoKGZ1bmN0aW9uIChlbCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciBzZWcgPSBzZWdzW2ldO1xuICAgICAgICAgICAgICAgIGlmIChlbCkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwgPSBlbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlZ3MgPSBmaWx0ZXJTZWdzVmlhRWxzKHRoaXMuY29udGV4dCwgc2VncywgQm9vbGVhbihtaXJyb3JJbmZvKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICAvLyBHZW5lcmljIHV0aWxpdHkgZm9yIGdlbmVyYXRpbmcgdGhlIEhUTUwgY2xhc3NOYW1lcyBmb3IgYW4gZXZlbnQgc2VnbWVudCdzIGVsZW1lbnRcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmdldFNlZ0NsYXNzZXMgPSBmdW5jdGlvbiAoc2VnLCBpc0RyYWdnYWJsZSwgaXNSZXNpemFibGUsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIGNsYXNzZXMgPSBbXG4gICAgICAgICAgICAnZmMtZXZlbnQnLFxuICAgICAgICAgICAgc2VnLmlzU3RhcnQgPyAnZmMtc3RhcnQnIDogJ2ZjLW5vdC1zdGFydCcsXG4gICAgICAgICAgICBzZWcuaXNFbmQgPyAnZmMtZW5kJyA6ICdmYy1ub3QtZW5kJ1xuICAgICAgICBdLmNvbmNhdChzZWcuZXZlbnRSYW5nZS51aS5jbGFzc05hbWVzKTtcbiAgICAgICAgaWYgKGlzRHJhZ2dhYmxlKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLWRyYWdnYWJsZScpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Jlc2l6YWJsZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1yZXNpemFibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWlycm9ySW5mbykge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1taXJyb3InKTtcbiAgICAgICAgICAgIGlmIChtaXJyb3JJbmZvLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLWRyYWdnaW5nJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWlycm9ySW5mby5pc1Jlc2l6aW5nKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1yZXNpemluZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbGFzc2VzO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZSB0aGUgdGV4dCB0aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQgb24gYW4gZXZlbnQncyBlbGVtZW50LlxuICAgIC8vIGByYW5nZWAgY2FuIGJlIHRoZSBFdmVudCBvYmplY3QgaXRzZWxmLCBvciBzb21ldGhpbmcgcmFuZ2UtbGlrZSwgd2l0aCBhdCBsZWFzdCBhIGBzdGFydGAuXG4gICAgLy8gSWYgZXZlbnQgdGltZXMgYXJlIGRpc2FibGVkLCBvciB0aGUgZXZlbnQgaGFzIG5vIHRpbWUsIHdpbGwgcmV0dXJuIGEgYmxhbmsgc3RyaW5nLlxuICAgIC8vIElmIG5vdCBzcGVjaWZpZWQsIGZvcm1hdHRlciB3aWxsIGRlZmF1bHQgdG8gdGhlIGV2ZW50VGltZUZvcm1hdCBzZXR0aW5nLFxuICAgIC8vIGFuZCBkaXNwbGF5RW5kIHdpbGwgZGVmYXVsdCB0byB0aGUgZGlzcGxheUV2ZW50RW5kIHNldHRpbmcuXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5nZXRUaW1lVGV4dCA9IGZ1bmN0aW9uIChldmVudFJhbmdlLCBmb3JtYXR0ZXIsIGRpc3BsYXlFbmQpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50UmFuZ2UuZGVmLCBpbnN0YW5jZSA9IGV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRUaW1lVGV4dChpbnN0YW5jZS5yYW5nZS5zdGFydCwgZGVmLmhhc0VuZCA/IGluc3RhbmNlLnJhbmdlLmVuZCA6IG51bGwsIGRlZi5hbGxEYXksIGZvcm1hdHRlciwgZGlzcGxheUVuZCwgaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sIGluc3RhbmNlLmZvcmNlZEVuZFR6byk7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLl9nZXRUaW1lVGV4dCA9IGZ1bmN0aW9uIChzdGFydCwgZW5kLCBhbGxEYXksIGZvcm1hdHRlciwgZGlzcGxheUVuZCwgZm9yY2VkU3RhcnRUem8sIGZvcmNlZEVuZFR6bykge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuY29udGV4dC5kYXRlRW52O1xuICAgICAgICBpZiAoZm9ybWF0dGVyID09IG51bGwpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IHRoaXMuZXZlbnRUaW1lRm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaXNwbGF5RW5kID09IG51bGwpIHtcbiAgICAgICAgICAgIGRpc3BsYXlFbmQgPSB0aGlzLmRpc3BsYXlFdmVudEVuZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5kaXNwbGF5RXZlbnRUaW1lICYmICFhbGxEYXkpIHtcbiAgICAgICAgICAgIGlmIChkaXNwbGF5RW5kICYmIGVuZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdFJhbmdlKHN0YXJ0LCBlbmQsIGZvcm1hdHRlciwge1xuICAgICAgICAgICAgICAgICAgICBmb3JjZWRTdGFydFR6bzogZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICAgICAgICAgIGZvcmNlZEVuZFR6bzogZm9yY2VkRW5kVHpvXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoc3RhcnQsIGZvcm1hdHRlciwge1xuICAgICAgICAgICAgICAgICAgICBmb3JjZWRUem86IGZvcmNlZFN0YXJ0VHpvXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRXZlbnRUaW1lRm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG91cjogJ251bWVyaWMnLFxuICAgICAgICAgICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgICAgICAgICBvbWl0WmVyb01pbnV0ZTogdHJ1ZVxuICAgICAgICB9O1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRGlzcGxheUV2ZW50VGltZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVEaXNwbGF5RXZlbnRFbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgLy8gVXRpbGl0eSBmb3IgZ2VuZXJhdGluZyBldmVudCBza2luLXJlbGF0ZWQgQ1NTIHByb3BlcnRpZXNcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmdldFNraW5Dc3MgPSBmdW5jdGlvbiAodWkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogdWkuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgJ2JvcmRlci1jb2xvcic6IHVpLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgY29sb3I6IHVpLnRleHRDb2xvclxuICAgICAgICB9O1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5zb3J0RXZlbnRTZWdzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIHNwZWNzID0gdGhpcy5jb250ZXh0LmV2ZW50T3JkZXJTcGVjcztcbiAgICAgICAgdmFyIG9ianMgPSBzZWdzLm1hcChidWlsZFNlZ0NvbXBhcmVPYmopO1xuICAgICAgICBvYmpzLnNvcnQoZnVuY3Rpb24gKG9iajAsIG9iajEpIHtcbiAgICAgICAgICAgIHJldHVybiBjb21wYXJlQnlGaWVsZFNwZWNzKG9iajAsIG9iajEsIHNwZWNzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBvYmpzLm1hcChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgcmV0dXJuIGMuX3NlZztcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVTaXplcyA9IGZ1bmN0aW9uIChmb3JjZSkge1xuICAgICAgICBpZiAoZm9yY2UgfHwgdGhpcy5pc1NpemVEaXJ0eSkge1xuICAgICAgICAgICAgdGhpcy5jb21wdXRlU2VnU2l6ZXModGhpcy5zZWdzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TaXplcyA9IGZ1bmN0aW9uIChmb3JjZSkge1xuICAgICAgICBpZiAoZm9yY2UgfHwgdGhpcy5pc1NpemVEaXJ0eSkge1xuICAgICAgICAgICAgdGhpcy5hc3NpZ25TZWdTaXplcyh0aGlzLnNlZ3MpO1xuICAgICAgICAgICAgdGhpcy5pc1NpemVEaXJ0eSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVTZWdTaXplcyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmFzc2lnblNlZ1NpemVzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICB9O1xuICAgIC8vIE1hbmlwdWxhdGlvbiBvbiByZW5kZXJlZCBzZWdzXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5oaWRlQnlIYXNoID0gZnVuY3Rpb24gKGhhc2gpIHtcbiAgICAgICAgaWYgKGhhc2gpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNlZ3M7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlZyA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzaFtzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5zaG93QnlIYXNoID0gZnVuY3Rpb24gKGhhc2gpIHtcbiAgICAgICAgaWYgKGhhc2gpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNlZ3M7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlZyA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzaFtzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwuc3R5bGUudmlzaWJpbGl0eSA9ICcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5zZWxlY3RCeUluc3RhbmNlSWQgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2VnczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VnID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlID0gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50SW5zdGFuY2UgJiYgZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkID09PSBpbnN0YW5jZUlkICYmXG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbCAvLyBuZWNlc3Nhcnk/XG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbC5jbGFzc0xpc3QuYWRkKCdmYy1zZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS51bnNlbGVjdEJ5SW5zdGFuY2VJZCA9IGZ1bmN0aW9uIChpbnN0YW5jZUlkKSB7XG4gICAgICAgIGlmIChpbnN0YW5jZUlkKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zZWdzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBzZWcgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKHNlZy5lbCkgeyAvLyBuZWNlc3Nhcnk/XG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbC5jbGFzc0xpc3QucmVtb3ZlKCdmYy1zZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEZnRXZlbnRSZW5kZXJlcjtcbn0oKSk7XG4vLyByZXR1cm5zIGEgb2JqZWN0IHdpdGggYWxsIHByaW1pdGl2ZSBwcm9wcyB0aGF0IGNhbiBiZSBjb21wYXJlZFxuZnVuY3Rpb24gYnVpbGRTZWdDb21wYXJlT2JqKHNlZykge1xuICAgIHZhciBldmVudERlZiA9IHNlZy5ldmVudFJhbmdlLmRlZjtcbiAgICB2YXIgcmFuZ2UgPSBzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5yYW5nZTtcbiAgICB2YXIgc3RhcnQgPSByYW5nZS5zdGFydCA/IHJhbmdlLnN0YXJ0LnZhbHVlT2YoKSA6IDA7IC8vIFRPRE86IGJldHRlciBzdXBwb3J0IGZvciBvcGVuLXJhbmdlIGV2ZW50c1xuICAgIHZhciBlbmQgPSByYW5nZS5lbmQgPyByYW5nZS5lbmQudmFsdWVPZigpIDogMDsgLy8gXCJcbiAgICByZXR1cm4gX19hc3NpZ24oe30sIGV2ZW50RGVmLmV4dGVuZGVkUHJvcHMsIGV2ZW50RGVmLCB7IGlkOiBldmVudERlZi5wdWJsaWNJZCwgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICBlbmQ6IGVuZCwgZHVyYXRpb246IGVuZCAtIHN0YXJ0LCBhbGxEYXk6IE51bWJlcihldmVudERlZi5hbGxEYXkpLCBfc2VnOiBzZWcgLy8gZm9yIGxhdGVyIHJldHJpZXZhbFxuICAgICB9KTtcbn1cblxuLypcblRPRE86IHdoZW4gcmVmYWN0b3JpbmcgdGhpcyBjbGFzcywgbWFrZSBhIG5ldyBGaWxsUmVuZGVyZXIgaW5zdGFuY2UgZm9yIGVhY2ggYHR5cGVgXG4qL1xudmFyIEZpbGxSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGaWxsUmVuZGVyZXIoKSB7XG4gICAgICAgIHRoaXMuZmlsbFNlZ1RhZyA9ICdkaXYnO1xuICAgICAgICB0aGlzLmRpcnR5U2l6ZUZsYWdzID0ge307XG4gICAgICAgIHRoaXMuY29udGFpbmVyRWxzQnlUeXBlID0ge307XG4gICAgICAgIHRoaXMuc2Vnc0J5VHlwZSA9IHt9O1xuICAgIH1cbiAgICBGaWxsUmVuZGVyZXIucHJvdG90eXBlLmdldFNlZ3NCeVR5cGUgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWdzQnlUeXBlW3R5cGVdIHx8IFtdO1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdzID0gZnVuY3Rpb24gKHR5cGUsIGNvbnRleHQsIHNlZ3MpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB2YXIgcmVuZGVyZWRTZWdzID0gdGhpcy5yZW5kZXJTZWdFbHModHlwZSwgc2Vncyk7IC8vIGFzc2lnbmVzIGAuZWxgIHRvIGVhY2ggc2VnLiByZXR1cm5zIHN1Y2Nlc3NmdWxseSByZW5kZXJlZCBzZWdzXG4gICAgICAgIHZhciBjb250YWluZXJFbHMgPSB0aGlzLmF0dGFjaFNlZ3ModHlwZSwgcmVuZGVyZWRTZWdzKTtcbiAgICAgICAgaWYgKGNvbnRhaW5lckVscykge1xuICAgICAgICAgICAgKF9hID0gKHRoaXMuY29udGFpbmVyRWxzQnlUeXBlW3R5cGVdIHx8ICh0aGlzLmNvbnRhaW5lckVsc0J5VHlwZVt0eXBlXSA9IFtdKSkpLnB1c2guYXBwbHkoX2EsIGNvbnRhaW5lckVscyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWdzQnlUeXBlW3R5cGVdID0gcmVuZGVyZWRTZWdzO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2JnRXZlbnQnKSB7XG4gICAgICAgICAgICB0cmlnZ2VyUmVuZGVyZWRTZWdzKGNvbnRleHQsIHJlbmRlcmVkU2VncywgZmFsc2UpOyAvLyBpc01pcnJvcj1mYWxzZVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlydHlTaXplRmxhZ3NbdHlwZV0gPSB0cnVlO1xuICAgIH07XG4gICAgLy8gVW5yZW5kZXJzIGEgc3BlY2lmaWMgdHlwZSBvZiBmaWxsIHRoYXQgaXMgY3VycmVudGx5IHJlbmRlcmVkIG9uIHRoZSBncmlkXG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS51bnJlbmRlciA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBzZWdzID0gdGhpcy5zZWdzQnlUeXBlW3R5cGVdO1xuICAgICAgICBpZiAoc2Vncykge1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdiZ0V2ZW50Jykge1xuICAgICAgICAgICAgICAgIHRyaWdnZXJXaWxsUmVtb3ZlU2Vncyhjb250ZXh0LCBzZWdzLCBmYWxzZSk7IC8vIGlzTWlycm9yPWZhbHNlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRldGFjaFNlZ3ModHlwZSwgc2Vncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJlbmRlcnMgYW5kIGFzc2lnbnMgYW4gYGVsYCBwcm9wZXJ0eSBmb3IgZWFjaCBmaWxsIHNlZ21lbnQuIEdlbmVyaWMgZW5vdWdoIHRvIHdvcmsgd2l0aCBkaWZmZXJlbnQgdHlwZXMuXG4gICAgLy8gT25seSByZXR1cm5zIHNlZ21lbnRzIHRoYXQgc3VjY2Vzc2Z1bGx5IHJlbmRlcmVkLlxuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnRWxzID0gZnVuY3Rpb24gKHR5cGUsIHNlZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGh0bWwgPSAnJztcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGlmIChzZWdzLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gYnVpbGQgYSBsYXJnZSBjb25jYXRlbmF0aW9uIG9mIHNlZ21lbnQgSFRNTFxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBodG1sICs9IHRoaXMucmVuZGVyU2VnSHRtbCh0eXBlLCBzZWdzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEdyYWIgaW5kaXZpZHVhbCBlbGVtZW50cyBmcm9tIHRoZSBjb21iaW5lZCBIVE1MIHN0cmluZy4gVXNlIGVhY2ggYXMgdGhlIGRlZmF1bHQgcmVuZGVyaW5nLlxuICAgICAgICAgICAgLy8gVGhlbiwgY29tcHV0ZSB0aGUgJ2VsJyBmb3IgZWFjaCBzZWdtZW50LlxuICAgICAgICAgICAgaHRtbFRvRWxlbWVudHMoaHRtbCkuZm9yRWFjaChmdW5jdGlvbiAoZWwsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmVsID0gZWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ2JnRXZlbnQnKSB7XG4gICAgICAgICAgICAgICAgc2VncyA9IGZpbHRlclNlZ3NWaWFFbHModGhpcy5jb250ZXh0LCBzZWdzLCBmYWxzZSAvLyBpc01pcnJvci4gYmFja2dyb3VuZCBldmVudHMgY2FuIG5ldmVyIGJlIG1pcnJvciBlbGVtZW50c1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBjb3JyZWN0IGVsZW1lbnQgdHlwZT8gKHdvdWxkIGJlIGJhZCBpZiBhIG5vbi1URCB3ZXJlIGluc2VydGVkIGludG8gYSB0YWJsZSBmb3IgZXhhbXBsZSlcbiAgICAgICAgICAgIHNlZ3MgPSBzZWdzLmZpbHRlcihmdW5jdGlvbiAoc2VnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnRNYXRjaGVzKHNlZy5lbCwgX3RoaXMuZmlsbFNlZ1RhZyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VncztcbiAgICB9O1xuICAgIC8vIEJ1aWxkcyB0aGUgSFRNTCBuZWVkZWQgZm9yIG9uZSBmaWxsIHNlZ21lbnQuIEdlbmVyaWMgZW5vdWdoIHRvIHdvcmsgd2l0aCBkaWZmZXJlbnQgdHlwZXMuXG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdIdG1sID0gZnVuY3Rpb24gKHR5cGUsIHNlZykge1xuICAgICAgICB2YXIgY3NzID0gbnVsbDtcbiAgICAgICAgdmFyIGNsYXNzTmFtZXMgPSBbXTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdoaWdobGlnaHQnICYmIHR5cGUgIT09ICdidXNpbmVzc0hvdXJzJykge1xuICAgICAgICAgICAgY3NzID0ge1xuICAgICAgICAgICAgICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogc2VnLmV2ZW50UmFuZ2UudWkuYmFja2dyb3VuZENvbG9yXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlICE9PSAnaGlnaGxpZ2h0Jykge1xuICAgICAgICAgICAgY2xhc3NOYW1lcyA9IGNsYXNzTmFtZXMuY29uY2F0KHNlZy5ldmVudFJhbmdlLnVpLmNsYXNzTmFtZXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtYmdldmVudCcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy0nICsgdHlwZS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJzwnICsgdGhpcy5maWxsU2VnVGFnICtcbiAgICAgICAgICAgIChjbGFzc05hbWVzLmxlbmd0aCA/ICcgY2xhc3M9XCInICsgY2xhc3NOYW1lcy5qb2luKCcgJykgKyAnXCInIDogJycpICtcbiAgICAgICAgICAgIChjc3MgPyAnIHN0eWxlPVwiJyArIGNzc1RvU3RyKGNzcykgKyAnXCInIDogJycpICtcbiAgICAgICAgICAgICc+PC8nICsgdGhpcy5maWxsU2VnVGFnICsgJz4nO1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5kZXRhY2hTZWdzID0gZnVuY3Rpb24gKHR5cGUsIHNlZ3MpIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lckVscyA9IHRoaXMuY29udGFpbmVyRWxzQnlUeXBlW3R5cGVdO1xuICAgICAgICBpZiAoY29udGFpbmVyRWxzKSB7XG4gICAgICAgICAgICBjb250YWluZXJFbHMuZm9yRWFjaChyZW1vdmVFbGVtZW50KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNvbnRhaW5lckVsc0J5VHlwZVt0eXBlXTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlU2l6ZXMgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICAgICAgZm9yICh2YXIgdHlwZSBpbiB0aGlzLnNlZ3NCeVR5cGUpIHtcbiAgICAgICAgICAgIGlmIChmb3JjZSB8fCB0aGlzLmRpcnR5U2l6ZUZsYWdzW3R5cGVdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wdXRlU2VnU2l6ZXModGhpcy5zZWdzQnlUeXBlW3R5cGVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TaXplcyA9IGZ1bmN0aW9uIChmb3JjZSkge1xuICAgICAgICBmb3IgKHZhciB0eXBlIGluIHRoaXMuc2Vnc0J5VHlwZSkge1xuICAgICAgICAgICAgaWYgKGZvcmNlIHx8IHRoaXMuZGlydHlTaXplRmxhZ3NbdHlwZV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFzc2lnblNlZ1NpemVzKHRoaXMuc2Vnc0J5VHlwZVt0eXBlXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXJ0eVNpemVGbGFncyA9IHt9O1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlU2VnU2l6ZXMgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TZWdTaXplcyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgfTtcbiAgICByZXR1cm4gRmlsbFJlbmRlcmVyO1xufSgpKTtcblxudmFyIE5hbWVkVGltZVpvbmVJbXBsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE5hbWVkVGltZVpvbmVJbXBsKHRpbWVab25lTmFtZSkge1xuICAgICAgICB0aGlzLnRpbWVab25lTmFtZSA9IHRpbWVab25lTmFtZTtcbiAgICB9XG4gICAgcmV0dXJuIE5hbWVkVGltZVpvbmVJbXBsO1xufSgpKTtcblxuLypcbkFuIGFic3RyYWN0aW9uIGZvciBhIGRyYWdnaW5nIGludGVyYWN0aW9uIG9yaWdpbmF0aW5nIG9uIGFuIGV2ZW50LlxuRG9lcyBoaWdoZXItbGV2ZWwgdGhpbmdzIHRoYW4gUG9pbnRlckRyYWdnZXIsIHN1Y2ggYXMgcG9zc2libHk6XG4tIGEgXCJtaXJyb3JcIiB0aGF0IG1vdmVzIHdpdGggdGhlIHBvaW50ZXJcbi0gYSBtaW5pbXVtIG51bWJlciBvZiBwaXhlbHMgb3Igb3RoZXIgY3JpdGVyaWEgZm9yIGEgdHJ1ZSBkcmFnIHRvIGJlZ2luXG5cbnN1YmNsYXNzZXMgbXVzdCBlbWl0OlxuLSBwb2ludGVyZG93blxuLSBkcmFnc3RhcnRcbi0gZHJhZ21vdmVcbi0gcG9pbnRlcnVwXG4tIGRyYWdlbmRcbiovXG52YXIgRWxlbWVudERyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEVsZW1lbnREcmFnZ2luZyhlbCkge1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlck1peGluKCk7XG4gICAgfVxuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9ySXNWaXNpYmxlID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgLy8gb3B0aW9uYWwgaWYgc3ViY2xhc3MgZG9lc24ndCB3YW50IHRvIHN1cHBvcnQgYSBtaXJyb3JcbiAgICB9O1xuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9yTmVlZHNSZXZlcnQgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICAvLyBvcHRpb25hbCBpZiBzdWJjbGFzcyBkb2Vzbid0IHdhbnQgdG8gc3VwcG9ydCBhIG1pcnJvclxuICAgIH07XG4gICAgRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRBdXRvU2Nyb2xsRW5hYmxlZCA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIC8vIG9wdGlvbmFsXG4gICAgfTtcbiAgICByZXR1cm4gRWxlbWVudERyYWdnaW5nO1xufSgpKTtcblxuZnVuY3Rpb24gZm9ybWF0RGF0ZShkYXRlSW5wdXQsIHNldHRpbmdzKSB7XG4gICAgaWYgKHNldHRpbmdzID09PSB2b2lkIDApIHsgc2V0dGluZ3MgPSB7fTsgfVxuICAgIHZhciBkYXRlRW52ID0gYnVpbGREYXRlRW52JDEoc2V0dGluZ3MpO1xuICAgIHZhciBmb3JtYXR0ZXIgPSBjcmVhdGVGb3JtYXR0ZXIoc2V0dGluZ3MpO1xuICAgIHZhciBkYXRlTWV0YSA9IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShkYXRlSW5wdXQpO1xuICAgIGlmICghZGF0ZU1ldGEpIHsgLy8gVE9ETzogd2FybmluZz9cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoZGF0ZU1ldGEubWFya2VyLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgZm9yY2VkVHpvOiBkYXRlTWV0YS5mb3JjZWRUem9cbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGZvcm1hdFJhbmdlKHN0YXJ0SW5wdXQsIGVuZElucHV0LCBzZXR0aW5ncyAvLyBtaXh0dXJlIG9mIGVudiBhbmQgZm9ybWF0dGVyIHNldHRpbmdzXG4pIHtcbiAgICB2YXIgZGF0ZUVudiA9IGJ1aWxkRGF0ZUVudiQxKHR5cGVvZiBzZXR0aW5ncyA9PT0gJ29iamVjdCcgJiYgc2V0dGluZ3MgPyBzZXR0aW5ncyA6IHt9KTsgLy8gcGFzcyBpbiBpZiBub24tbnVsbCBvYmplY3RcbiAgICB2YXIgZm9ybWF0dGVyID0gY3JlYXRlRm9ybWF0dGVyKHNldHRpbmdzLCBnbG9iYWxEZWZhdWx0cy5kZWZhdWx0UmFuZ2VTZXBhcmF0b3IpO1xuICAgIHZhciBzdGFydE1ldGEgPSBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoc3RhcnRJbnB1dCk7XG4gICAgdmFyIGVuZE1ldGEgPSBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoZW5kSW5wdXQpO1xuICAgIGlmICghc3RhcnRNZXRhIHx8ICFlbmRNZXRhKSB7IC8vIFRPRE86IHdhcm5pbmc/XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2Uoc3RhcnRNZXRhLm1hcmtlciwgZW5kTWV0YS5tYXJrZXIsIGZvcm1hdHRlciwge1xuICAgICAgICBmb3JjZWRTdGFydFR6bzogc3RhcnRNZXRhLmZvcmNlZFR6byxcbiAgICAgICAgZm9yY2VkRW5kVHpvOiBlbmRNZXRhLmZvcmNlZFR6byxcbiAgICAgICAgaXNFbmRFeGNsdXNpdmU6IHNldHRpbmdzLmlzRW5kRXhjbHVzaXZlXG4gICAgfSk7XG59XG4vLyBUT0RPOiBtb3JlIERSWSBhbmQgb3B0aW1pemVkXG5mdW5jdGlvbiBidWlsZERhdGVFbnYkMShzZXR0aW5ncykge1xuICAgIHZhciBsb2NhbGUgPSBidWlsZExvY2FsZShzZXR0aW5ncy5sb2NhbGUgfHwgJ2VuJywgcGFyc2VSYXdMb2NhbGVzKFtdKS5tYXApOyAvLyBUT0RPOiBkb24ndCBoYXJkY29kZSAnZW4nIGV2ZXJ5d2hlcmVcbiAgICAvLyBlbnN1cmUgcmVxdWlyZWQgc2V0dGluZ3NcbiAgICBzZXR0aW5ncyA9IF9fYXNzaWduKHsgdGltZVpvbmU6IGdsb2JhbERlZmF1bHRzLnRpbWVab25lLCBjYWxlbmRhclN5c3RlbTogJ2dyZWdvcnknIH0sIHNldHRpbmdzLCB7IGxvY2FsZTogbG9jYWxlIH0pO1xuICAgIHJldHVybiBuZXcgRGF0ZUVudihzZXR0aW5ncyk7XG59XG5cbnZhciBEUkFHX01FVEFfUFJPUFMgPSB7XG4gICAgc3RhcnRUaW1lOiBjcmVhdGVEdXJhdGlvbixcbiAgICBkdXJhdGlvbjogY3JlYXRlRHVyYXRpb24sXG4gICAgY3JlYXRlOiBCb29sZWFuLFxuICAgIHNvdXJjZUlkOiBTdHJpbmdcbn07XG52YXIgRFJBR19NRVRBX0RFRkFVTFRTID0ge1xuICAgIGNyZWF0ZTogdHJ1ZVxufTtcbmZ1bmN0aW9uIHBhcnNlRHJhZ01ldGEocmF3KSB7XG4gICAgdmFyIGxlZnRvdmVyUHJvcHMgPSB7fTtcbiAgICB2YXIgcmVmaW5lZCA9IHJlZmluZVByb3BzKHJhdywgRFJBR19NRVRBX1BST1BTLCBEUkFHX01FVEFfREVGQVVMVFMsIGxlZnRvdmVyUHJvcHMpO1xuICAgIHJlZmluZWQubGVmdG92ZXJQcm9wcyA9IGxlZnRvdmVyUHJvcHM7XG4gICAgcmV0dXJuIHJlZmluZWQ7XG59XG5cbi8vIENvbXB1dGVzIGEgZGVmYXVsdCBjb2x1bW4gaGVhZGVyIGZvcm1hdHRpbmcgc3RyaW5nIGlmIGBjb2xGb3JtYXRgIGlzIG5vdCBleHBsaWNpdGx5IGRlZmluZWRcbmZ1bmN0aW9uIGNvbXB1dGVGYWxsYmFja0hlYWRlckZvcm1hdChkYXRlc1JlcERpc3RpbmN0RGF5cywgZGF5Q250KSB7XG4gICAgLy8gaWYgbW9yZSB0aGFuIG9uZSB3ZWVrIHJvdywgb3IgaWYgdGhlcmUgYXJlIGEgbG90IG9mIGNvbHVtbnMgd2l0aCBub3QgbXVjaCBzcGFjZSxcbiAgICAvLyBwdXQganVzdCB0aGUgZGF5IG51bWJlcnMgd2lsbCBiZSBpbiBlYWNoIGNlbGxcbiAgICBpZiAoIWRhdGVzUmVwRGlzdGluY3REYXlzIHx8IGRheUNudCA+IDEwKSB7XG4gICAgICAgIHJldHVybiB7IHdlZWtkYXk6ICdzaG9ydCcgfTsgLy8gXCJTYXRcIlxuICAgIH1cbiAgICBlbHNlIGlmIChkYXlDbnQgPiAxKSB7XG4gICAgICAgIHJldHVybiB7IHdlZWtkYXk6ICdzaG9ydCcsIG1vbnRoOiAnbnVtZXJpYycsIGRheTogJ251bWVyaWMnLCBvbWl0Q29tbWFzOiB0cnVlIH07IC8vIFwiU2F0IDExLzEyXCJcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB7IHdlZWtkYXk6ICdsb25nJyB9OyAvLyBcIlNhdHVyZGF5XCJcbiAgICB9XG59XG5mdW5jdGlvbiByZW5kZXJEYXRlQ2VsbChkYXRlTWFya2VyLCBkYXRlUHJvZmlsZSwgZGF0ZXNSZXBEaXN0aW5jdERheXMsIGNvbENudCwgY29sSGVhZEZvcm1hdCwgY29udGV4dCwgY29sc3Bhbiwgb3RoZXJBdHRycykge1xuICAgIHZhciBkYXRlRW52ID0gY29udGV4dC5kYXRlRW52LCB0aGVtZSA9IGNvbnRleHQudGhlbWUsIG9wdGlvbnMgPSBjb250ZXh0Lm9wdGlvbnM7XG4gICAgdmFyIGlzRGF0ZVZhbGlkID0gcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgZGF0ZU1hcmtlcik7IC8vIFRPRE86IGNhbGxlZCB0b28gZnJlcXVlbnRseS4gY2FjaGUgc29tZWhvdy5cbiAgICB2YXIgY2xhc3NOYW1lcyA9IFtcbiAgICAgICAgJ2ZjLWRheS1oZWFkZXInLFxuICAgICAgICB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0SGVhZGVyJylcbiAgICBdO1xuICAgIHZhciBpbm5lckh0bWw7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmNvbHVtbkhlYWRlckh0bWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgaW5uZXJIdG1sID0gb3B0aW9ucy5jb2x1bW5IZWFkZXJIdG1sKGRhdGVFbnYudG9EYXRlKGRhdGVNYXJrZXIpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMuY29sdW1uSGVhZGVyVGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBpbm5lckh0bWwgPSBodG1sRXNjYXBlKG9wdGlvbnMuY29sdW1uSGVhZGVyVGV4dChkYXRlRW52LnRvRGF0ZShkYXRlTWFya2VyKSkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaW5uZXJIdG1sID0gaHRtbEVzY2FwZShkYXRlRW52LmZvcm1hdChkYXRlTWFya2VyLCBjb2xIZWFkRm9ybWF0KSk7XG4gICAgfVxuICAgIC8vIGlmIG9ubHkgb25lIHJvdyBvZiBkYXlzLCB0aGUgY2xhc3NOYW1lcyBvbiB0aGUgaGVhZGVyIGNhbiByZXByZXNlbnQgdGhlIHNwZWNpZmljIGRheXMgYmVuZWF0aFxuICAgIGlmIChkYXRlc1JlcERpc3RpbmN0RGF5cykge1xuICAgICAgICBjbGFzc05hbWVzID0gY2xhc3NOYW1lcy5jb25jYXQoXG4gICAgICAgIC8vIGluY2x1ZGVzIHRoZSBkYXktb2Ytd2VlayBjbGFzc1xuICAgICAgICAvLyBub1RoZW1lSGlnaGxpZ2h0PXRydWUgKGRvbid0IGhpZ2hsaWdodCB0aGUgaGVhZGVyKVxuICAgICAgICBnZXREYXlDbGFzc2VzKGRhdGVNYXJrZXIsIGRhdGVQcm9maWxlLCBjb250ZXh0LCB0cnVlKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLScgKyBEQVlfSURTW2RhdGVNYXJrZXIuZ2V0VVRDRGF5KCldKTsgLy8gb25seSBhZGQgdGhlIGRheS1vZi13ZWVrIGNsYXNzXG4gICAgfVxuICAgIHJldHVybiAnJyArXG4gICAgICAgICc8dGggY2xhc3M9XCInICsgY2xhc3NOYW1lcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgKChpc0RhdGVWYWxpZCAmJiBkYXRlc1JlcERpc3RpbmN0RGF5cykgP1xuICAgICAgICAgICAgJyBkYXRhLWRhdGU9XCInICsgZGF0ZUVudi5mb3JtYXRJc28oZGF0ZU1hcmtlciwgeyBvbWl0VGltZTogdHJ1ZSB9KSArICdcIicgOlxuICAgICAgICAgICAgJycpICtcbiAgICAgICAgKGNvbHNwYW4gPiAxID9cbiAgICAgICAgICAgICcgY29sc3Bhbj1cIicgKyBjb2xzcGFuICsgJ1wiJyA6XG4gICAgICAgICAgICAnJykgK1xuICAgICAgICAob3RoZXJBdHRycyA/XG4gICAgICAgICAgICAnICcgKyBvdGhlckF0dHJzIDpcbiAgICAgICAgICAgICcnKSArXG4gICAgICAgICc+JyArXG4gICAgICAgIChpc0RhdGVWYWxpZCA/XG4gICAgICAgICAgICAvLyBkb24ndCBtYWtlIGEgbGluayBpZiB0aGUgaGVhZGluZyBjb3VsZCByZXByZXNlbnQgbXVsdGlwbGUgZGF5cywgb3IgaWYgdGhlcmUncyBvbmx5IG9uZSBkYXkgKGZvcmNlT2ZmKVxuICAgICAgICAgICAgYnVpbGRHb3RvQW5jaG9ySHRtbChvcHRpb25zLCBkYXRlRW52LCB7IGRhdGU6IGRhdGVNYXJrZXIsIGZvcmNlT2ZmOiAhZGF0ZXNSZXBEaXN0aW5jdERheXMgfHwgY29sQ250ID09PSAxIH0sIGlubmVySHRtbCkgOlxuICAgICAgICAgICAgLy8gaWYgbm90IHZhbGlkLCBkaXNwbGF5IHRleHQsIGJ1dCBubyBsaW5rXG4gICAgICAgICAgICBpbm5lckh0bWwpICtcbiAgICAgICAgJzwvdGg+Jztcbn1cblxudmFyIERheUhlYWRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5SGVhZGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUhlYWRlcihwYXJlbnRFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yZW5kZXJTa2VsZXRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclNrZWxldG9uLCBfdGhpcy5fdW5yZW5kZXJTa2VsZXRvbik7XG4gICAgICAgIF90aGlzLnBhcmVudEVsID0gcGFyZW50RWw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5SGVhZGVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGRhdGVzID0gcHJvcHMuZGF0ZXMsIGRhdGVzUmVwRGlzdGluY3REYXlzID0gcHJvcHMuZGF0ZXNSZXBEaXN0aW5jdERheXM7XG4gICAgICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uKGNvbnRleHQpO1xuICAgICAgICBpZiAocHJvcHMucmVuZGVySW50cm9IdG1sKSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHByb3BzLnJlbmRlckludHJvSHRtbCgpKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sSGVhZEZvcm1hdCA9IGNyZWF0ZUZvcm1hdHRlcihjb250ZXh0Lm9wdGlvbnMuY29sdW1uSGVhZGVyRm9ybWF0IHx8XG4gICAgICAgICAgICBjb21wdXRlRmFsbGJhY2tIZWFkZXJGb3JtYXQoZGF0ZXNSZXBEaXN0aW5jdERheXMsIGRhdGVzLmxlbmd0aCkpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIGRhdGVzXzEgPSBkYXRlczsgX2kgPCBkYXRlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGRhdGUgPSBkYXRlc18xW19pXTtcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocmVuZGVyRGF0ZUNlbGwoZGF0ZSwgcHJvcHMuZGF0ZVByb2ZpbGUsIGRhdGVzUmVwRGlzdGluY3REYXlzLCBkYXRlcy5sZW5ndGgsIGNvbEhlYWRGb3JtYXQsIGNvbnRleHQpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29udGV4dC5pc1J0bCkge1xuICAgICAgICAgICAgcGFydHMucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudGhlYWQuaW5uZXJIVE1MID0gJzx0cj4nICsgcGFydHMuam9pbignJykgKyAnPC90cj4nO1xuICAgIH07XG4gICAgRGF5SGVhZGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJTa2VsZXRvbi51bnJlbmRlcigpO1xuICAgIH07XG4gICAgRGF5SGVhZGVyLnByb3RvdHlwZS5fcmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB2YXIgdGhlbWUgPSBjb250ZXh0LnRoZW1lO1xuICAgICAgICB2YXIgcGFyZW50RWwgPSB0aGlzLnBhcmVudEVsO1xuICAgICAgICBwYXJlbnRFbC5pbm5lckhUTUwgPSAnJzsgLy8gYmVjYXVzZSBtaWdodCBiZSBuYnNwXG4gICAgICAgIHBhcmVudEVsLmFwcGVuZENoaWxkKHRoaXMuZWwgPSBodG1sVG9FbGVtZW50KCc8ZGl2IGNsYXNzPVwiZmMtcm93ICcgKyB0aGVtZS5nZXRDbGFzcygnaGVhZGVyUm93JykgKyAnXCI+JyArXG4gICAgICAgICAgICAnPHRhYmxlIGNsYXNzPVwiJyArIHRoZW1lLmdldENsYXNzKCd0YWJsZUdyaWQnKSArICdcIj4nICtcbiAgICAgICAgICAgICc8dGhlYWQ+PC90aGVhZD4nICtcbiAgICAgICAgICAgICc8L3RhYmxlPicgK1xuICAgICAgICAgICAgJzwvZGl2PicpKTtcbiAgICAgICAgdGhpcy50aGVhZCA9IHRoaXMuZWwucXVlcnlTZWxlY3RvcigndGhlYWQnKTtcbiAgICB9O1xuICAgIERheUhlYWRlci5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5lbCk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5SGVhZGVyO1xufShDb21wb25lbnQpKTtcblxudmFyIERheVNlcmllcyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEYXlTZXJpZXMocmFuZ2UsIGRhdGVQcm9maWxlR2VuZXJhdG9yKSB7XG4gICAgICAgIHZhciBkYXRlID0gcmFuZ2Uuc3RhcnQ7XG4gICAgICAgIHZhciBlbmQgPSByYW5nZS5lbmQ7XG4gICAgICAgIHZhciBpbmRpY2VzID0gW107XG4gICAgICAgIHZhciBkYXRlcyA9IFtdO1xuICAgICAgICB2YXIgZGF5SW5kZXggPSAtMTtcbiAgICAgICAgd2hpbGUgKGRhdGUgPCBlbmQpIHsgLy8gbG9vcCBlYWNoIGRheSBmcm9tIHN0YXJ0IHRvIGVuZFxuICAgICAgICAgICAgaWYgKGRhdGVQcm9maWxlR2VuZXJhdG9yLmlzSGlkZGVuRGF5KGRhdGUpKSB7XG4gICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKGRheUluZGV4ICsgMC41KTsgLy8gbWFyayB0aGF0IGl0J3MgYmV0d2VlbiBpbmRpY2VzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkYXlJbmRleCsrO1xuICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChkYXlJbmRleCk7XG4gICAgICAgICAgICAgICAgZGF0ZXMucHVzaChkYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRhdGUgPSBhZGREYXlzKGRhdGUsIDEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGF0ZXMgPSBkYXRlcztcbiAgICAgICAgdGhpcy5pbmRpY2VzID0gaW5kaWNlcztcbiAgICAgICAgdGhpcy5jbnQgPSBkYXRlcy5sZW5ndGg7XG4gICAgfVxuICAgIERheVNlcmllcy5wcm90b3R5cGUuc2xpY2VSYW5nZSA9IGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgICB2YXIgZmlyc3RJbmRleCA9IHRoaXMuZ2V0RGF0ZURheUluZGV4KHJhbmdlLnN0YXJ0KTsgLy8gaW5jbHVzaXZlIGZpcnN0IGluZGV4XG4gICAgICAgIHZhciBsYXN0SW5kZXggPSB0aGlzLmdldERhdGVEYXlJbmRleChhZGREYXlzKHJhbmdlLmVuZCwgLTEpKTsgLy8gaW5jbHVzaXZlIGxhc3QgaW5kZXhcbiAgICAgICAgdmFyIGNsaXBwZWRGaXJzdEluZGV4ID0gTWF0aC5tYXgoMCwgZmlyc3RJbmRleCk7XG4gICAgICAgIHZhciBjbGlwcGVkTGFzdEluZGV4ID0gTWF0aC5taW4odGhpcy5jbnQgLSAxLCBsYXN0SW5kZXgpO1xuICAgICAgICAvLyBkZWFsIHdpdGggaW4tYmV0d2VlbiBpbmRpY2VzXG4gICAgICAgIGNsaXBwZWRGaXJzdEluZGV4ID0gTWF0aC5jZWlsKGNsaXBwZWRGaXJzdEluZGV4KTsgLy8gaW4tYmV0d2VlbiBzdGFydHMgcm91bmQgdG8gbmV4dCBjZWxsXG4gICAgICAgIGNsaXBwZWRMYXN0SW5kZXggPSBNYXRoLmZsb29yKGNsaXBwZWRMYXN0SW5kZXgpOyAvLyBpbi1iZXR3ZWVuIGVuZHMgcm91bmQgdG8gcHJldiBjZWxsXG4gICAgICAgIGlmIChjbGlwcGVkRmlyc3RJbmRleCA8PSBjbGlwcGVkTGFzdEluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGZpcnN0SW5kZXg6IGNsaXBwZWRGaXJzdEluZGV4LFxuICAgICAgICAgICAgICAgIGxhc3RJbmRleDogY2xpcHBlZExhc3RJbmRleCxcbiAgICAgICAgICAgICAgICBpc1N0YXJ0OiBmaXJzdEluZGV4ID09PSBjbGlwcGVkRmlyc3RJbmRleCxcbiAgICAgICAgICAgICAgICBpc0VuZDogbGFzdEluZGV4ID09PSBjbGlwcGVkTGFzdEluZGV4XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgZGF0ZSwgcmV0dXJucyBpdHMgY2hyb25vbG9jaWFsIGNlbGwtaW5kZXggZnJvbSB0aGUgZmlyc3QgY2VsbCBvZiB0aGUgZ3JpZC5cbiAgICAvLyBJZiB0aGUgZGF0ZSBsaWVzIGJldHdlZW4gY2VsbHMgKGJlY2F1c2Ugb2YgaGlkZGVuRGF5cyksIHJldHVybnMgYSBmbG9hdGluZy1wb2ludCB2YWx1ZSBiZXR3ZWVuIG9mZnNldHMuXG4gICAgLy8gSWYgYmVmb3JlIHRoZSBmaXJzdCBvZmZzZXQsIHJldHVybnMgYSBuZWdhdGl2ZSBudW1iZXIuXG4gICAgLy8gSWYgYWZ0ZXIgdGhlIGxhc3Qgb2Zmc2V0LCByZXR1cm5zIGFuIG9mZnNldCBwYXN0IHRoZSBsYXN0IGNlbGwgb2Zmc2V0LlxuICAgIC8vIE9ubHkgd29ya3MgZm9yICpzdGFydCogZGF0ZXMgb2YgY2VsbHMuIFdpbGwgbm90IHdvcmsgZm9yIGV4Y2x1c2l2ZSBlbmQgZGF0ZXMgZm9yIGNlbGxzLlxuICAgIERheVNlcmllcy5wcm90b3R5cGUuZ2V0RGF0ZURheUluZGV4ID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgdmFyIGluZGljZXMgPSB0aGlzLmluZGljZXM7XG4gICAgICAgIHZhciBkYXlPZmZzZXQgPSBNYXRoLmZsb29yKGRpZmZEYXlzKHRoaXMuZGF0ZXNbMF0sIGRhdGUpKTtcbiAgICAgICAgaWYgKGRheU9mZnNldCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBpbmRpY2VzWzBdIC0gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkYXlPZmZzZXQgPj0gaW5kaWNlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV0gKyAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGluZGljZXNbZGF5T2Zmc2V0XTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERheVNlcmllcztcbn0oKSk7XG5cbnZhciBEYXlUYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEYXlUYWJsZShkYXlTZXJpZXMsIGJyZWFrT25XZWVrcykge1xuICAgICAgICB2YXIgZGF0ZXMgPSBkYXlTZXJpZXMuZGF0ZXM7XG4gICAgICAgIHZhciBkYXlzUGVyUm93O1xuICAgICAgICB2YXIgZmlyc3REYXk7XG4gICAgICAgIHZhciByb3dDbnQ7XG4gICAgICAgIGlmIChicmVha09uV2Vla3MpIHtcbiAgICAgICAgICAgIC8vIGNvdW50IGNvbHVtbnMgdW50aWwgdGhlIGRheS1vZi13ZWVrIHJlcGVhdHNcbiAgICAgICAgICAgIGZpcnN0RGF5ID0gZGF0ZXNbMF0uZ2V0VVRDRGF5KCk7XG4gICAgICAgICAgICBmb3IgKGRheXNQZXJSb3cgPSAxOyBkYXlzUGVyUm93IDwgZGF0ZXMubGVuZ3RoOyBkYXlzUGVyUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZXNbZGF5c1BlclJvd10uZ2V0VVRDRGF5KCkgPT09IGZpcnN0RGF5KSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJvd0NudCA9IE1hdGguY2VpbChkYXRlcy5sZW5ndGggLyBkYXlzUGVyUm93KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJvd0NudCA9IDE7XG4gICAgICAgICAgICBkYXlzUGVyUm93ID0gZGF0ZXMubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucm93Q250ID0gcm93Q250O1xuICAgICAgICB0aGlzLmNvbENudCA9IGRheXNQZXJSb3c7XG4gICAgICAgIHRoaXMuZGF5U2VyaWVzID0gZGF5U2VyaWVzO1xuICAgICAgICB0aGlzLmNlbGxzID0gdGhpcy5idWlsZENlbGxzKCk7XG4gICAgICAgIHRoaXMuaGVhZGVyRGF0ZXMgPSB0aGlzLmJ1aWxkSGVhZGVyRGF0ZXMoKTtcbiAgICB9XG4gICAgRGF5VGFibGUucHJvdG90eXBlLmJ1aWxkQ2VsbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dzID0gW107XG4gICAgICAgIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IHRoaXMucm93Q250OyByb3crKykge1xuICAgICAgICAgICAgdmFyIGNlbGxzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBjb2wgPSAwOyBjb2wgPCB0aGlzLmNvbENudDsgY29sKyspIHtcbiAgICAgICAgICAgICAgICBjZWxscy5wdXNoKHRoaXMuYnVpbGRDZWxsKHJvdywgY29sKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByb3dzLnB1c2goY2VsbHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dzO1xuICAgIH07XG4gICAgRGF5VGFibGUucHJvdG90eXBlLmJ1aWxkQ2VsbCA9IGZ1bmN0aW9uIChyb3csIGNvbCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0ZTogdGhpcy5kYXlTZXJpZXMuZGF0ZXNbcm93ICogdGhpcy5jb2xDbnQgKyBjb2xdXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBEYXlUYWJsZS5wcm90b3R5cGUuYnVpbGRIZWFkZXJEYXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGVzID0gW107XG4gICAgICAgIGZvciAodmFyIGNvbCA9IDA7IGNvbCA8IHRoaXMuY29sQ250OyBjb2wrKykge1xuICAgICAgICAgICAgZGF0ZXMucHVzaCh0aGlzLmNlbGxzWzBdW2NvbF0uZGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGVzO1xuICAgIH07XG4gICAgRGF5VGFibGUucHJvdG90eXBlLnNsaWNlUmFuZ2UgPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgICAgICAgdmFyIGNvbENudCA9IHRoaXMuY29sQ250O1xuICAgICAgICB2YXIgc2VyaWVzU2VnID0gdGhpcy5kYXlTZXJpZXMuc2xpY2VSYW5nZShyYW5nZSk7XG4gICAgICAgIHZhciBzZWdzID0gW107XG4gICAgICAgIGlmIChzZXJpZXNTZWcpIHtcbiAgICAgICAgICAgIHZhciBmaXJzdEluZGV4ID0gc2VyaWVzU2VnLmZpcnN0SW5kZXgsIGxhc3RJbmRleCA9IHNlcmllc1NlZy5sYXN0SW5kZXg7XG4gICAgICAgICAgICB2YXIgaW5kZXggPSBmaXJzdEluZGV4O1xuICAgICAgICAgICAgd2hpbGUgKGluZGV4IDw9IGxhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciByb3cgPSBNYXRoLmZsb29yKGluZGV4IC8gY29sQ250KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gTWF0aC5taW4oKHJvdyArIDEpICogY29sQ250LCBsYXN0SW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgICBzZWdzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICByb3c6IHJvdyxcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RDb2w6IGluZGV4ICUgY29sQ250LFxuICAgICAgICAgICAgICAgICAgICBsYXN0Q29sOiAobmV4dEluZGV4IC0gMSkgJSBjb2xDbnQsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IHNlcmllc1NlZy5pc1N0YXJ0ICYmIGluZGV4ID09PSBmaXJzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogc2VyaWVzU2VnLmlzRW5kICYmIChuZXh0SW5kZXggLSAxKSA9PT0gbGFzdEluZGV4XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5VGFibGU7XG59KCkpO1xuXG52YXIgU2xpY2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNsaWNlcigpIHtcbiAgICAgICAgdGhpcy5zbGljZUJ1c2luZXNzSG91cnMgPSBtZW1vaXplKHRoaXMuX3NsaWNlQnVzaW5lc3NIb3Vycyk7XG4gICAgICAgIHRoaXMuc2xpY2VEYXRlU2VsZWN0aW9uID0gbWVtb2l6ZSh0aGlzLl9zbGljZURhdGVTcGFuKTtcbiAgICAgICAgdGhpcy5zbGljZUV2ZW50U3RvcmUgPSBtZW1vaXplKHRoaXMuX3NsaWNlRXZlbnRTdG9yZSk7XG4gICAgICAgIHRoaXMuc2xpY2VFdmVudERyYWcgPSBtZW1vaXplKHRoaXMuX3NsaWNlSW50ZXJhY3Rpb24pO1xuICAgICAgICB0aGlzLnNsaWNlRXZlbnRSZXNpemUgPSBtZW1vaXplKHRoaXMuX3NsaWNlSW50ZXJhY3Rpb24pO1xuICAgIH1cbiAgICBTbGljZXIucHJvdG90eXBlLnNsaWNlUHJvcHMgPSBmdW5jdGlvbiAocHJvcHMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjYWxlbmRhciwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSA1OyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDVdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXZlbnRVaUJhc2VzID0gcHJvcHMuZXZlbnRVaUJhc2VzO1xuICAgICAgICB2YXIgZXZlbnRTZWdzID0gdGhpcy5zbGljZUV2ZW50U3RvcmUuYXBwbHkodGhpcywgW3Byb3BzLmV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvblNlZ3M6IHRoaXMuc2xpY2VEYXRlU2VsZWN0aW9uLmFwcGx5KHRoaXMsIFtwcm9wcy5kYXRlU2VsZWN0aW9uLCBldmVudFVpQmFzZXMsIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpLFxuICAgICAgICAgICAgYnVzaW5lc3NIb3VyU2VnczogdGhpcy5zbGljZUJ1c2luZXNzSG91cnMuYXBwbHkodGhpcywgW3Byb3BzLmJ1c2luZXNzSG91cnMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjYWxlbmRhciwgY29tcG9uZW50XS5jb25jYXQoZXh0cmFBcmdzKSksXG4gICAgICAgICAgICBmZ0V2ZW50U2VnczogZXZlbnRTZWdzLmZnLFxuICAgICAgICAgICAgYmdFdmVudFNlZ3M6IGV2ZW50U2Vncy5iZyxcbiAgICAgICAgICAgIGV2ZW50RHJhZzogdGhpcy5zbGljZUV2ZW50RHJhZy5hcHBseSh0aGlzLCBbcHJvcHMuZXZlbnREcmFnLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKSxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplOiB0aGlzLnNsaWNlRXZlbnRSZXNpemUuYXBwbHkodGhpcywgW3Byb3BzLmV2ZW50UmVzaXplLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKSxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvblxuICAgICAgICB9OyAvLyBUT0RPOiBnaXZlIGludGVyYWN0aW9uU2Vncz9cbiAgICB9O1xuICAgIFNsaWNlci5wcm90b3R5cGUuc2xpY2VOb3dEYXRlID0gZnVuY3Rpb24gKC8vIGRvZXMgbm90IG1lbW9pemVcbiAgICBkYXRlLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIGV4dHJhQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDI7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgZXh0cmFBcmdzW19pIC0gMl0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zbGljZURhdGVTcGFuLmFwcGx5KHRoaXMsIFt7IHJhbmdlOiB7IHN0YXJ0OiBkYXRlLCBlbmQ6IGFkZE1zKGRhdGUsIDEpIH0sIGFsbERheTogZmFsc2UgfSxcbiAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgY29tcG9uZW50XS5jb25jYXQoZXh0cmFBcmdzKSk7XG4gICAgfTtcbiAgICBTbGljZXIucHJvdG90eXBlLl9zbGljZUJ1c2luZXNzSG91cnMgPSBmdW5jdGlvbiAoYnVzaW5lc3NIb3VycywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNhbGVuZGFyLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIGV4dHJhQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDU7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgZXh0cmFBcmdzW19pIC0gNV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmICghYnVzaW5lc3NIb3Vycykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zbGljZUV2ZW50U3RvcmUuYXBwbHkodGhpcywgW2V4cGFuZFJlY3VycmluZyhidXNpbmVzc0hvdXJzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBjYWxlbmRhciksXG4gICAgICAgICAgICB7fSxcbiAgICAgICAgICAgIGRhdGVQcm9maWxlLFxuICAgICAgICAgICAgbmV4dERheVRocmVzaG9sZCxcbiAgICAgICAgICAgIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpLmJnO1xuICAgIH07XG4gICAgU2xpY2VyLnByb3RvdHlwZS5fc2xpY2VFdmVudFN0b3JlID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbXBvbmVudCkge1xuICAgICAgICB2YXIgZXh0cmFBcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gNTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBleHRyYUFyZ3NbX2kgLSA1XSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50U3RvcmUpIHtcbiAgICAgICAgICAgIHZhciByYW5nZVJlcyA9IHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGNvbXB1dGVBY3RpdmVSYW5nZShkYXRlUHJvZmlsZSwgQm9vbGVhbihuZXh0RGF5VGhyZXNob2xkKSksIG5leHREYXlUaHJlc2hvbGQpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBiZzogdGhpcy5zbGljZUV2ZW50UmFuZ2VzKHJhbmdlUmVzLmJnLCBjb21wb25lbnQsIGV4dHJhQXJncyksXG4gICAgICAgICAgICAgICAgZmc6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5mZywgY29tcG9uZW50LCBleHRyYUFyZ3MpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHsgYmc6IFtdLCBmZzogW10gfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2xpY2VyLnByb3RvdHlwZS5fc2xpY2VJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbiwgZXZlbnRVaUJhc2VzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSA1OyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDVdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWludGVyYWN0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmFuZ2VSZXMgPSBzbGljZUV2ZW50U3RvcmUoaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cywgZXZlbnRVaUJhc2VzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBuZXh0RGF5VGhyZXNob2xkKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNlZ3M6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5mZywgY29tcG9uZW50LCBleHRyYUFyZ3MpLFxuICAgICAgICAgICAgYWZmZWN0ZWRJbnN0YW5jZXM6IGludGVyYWN0aW9uLmFmZmVjdGVkRXZlbnRzLmluc3RhbmNlcyxcbiAgICAgICAgICAgIGlzRXZlbnQ6IGludGVyYWN0aW9uLmlzRXZlbnQsXG4gICAgICAgICAgICBzb3VyY2VTZWc6IGludGVyYWN0aW9uLm9yaWdTZWdcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFNsaWNlci5wcm90b3R5cGUuX3NsaWNlRGF0ZVNwYW4gPSBmdW5jdGlvbiAoZGF0ZVNwYW4sIGV2ZW50VWlCYXNlcywgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAzOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDNdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWRhdGVTcGFuKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBmYWJyaWNhdGVFdmVudFJhbmdlKGRhdGVTcGFuLCBldmVudFVpQmFzZXMsIGNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyKTtcbiAgICAgICAgdmFyIHNlZ3MgPSB0aGlzLnNsaWNlUmFuZ2UuYXBwbHkodGhpcywgW2RhdGVTcGFuLnJhbmdlXS5jb25jYXQoZXh0cmFBcmdzKSk7XG4gICAgICAgIGZvciAodmFyIF9hID0gMCwgc2Vnc18xID0gc2VnczsgX2EgPCBzZWdzXzEubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18xW19hXTtcbiAgICAgICAgICAgIHNlZy5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgICBzZWcuZXZlbnRSYW5nZSA9IGV2ZW50UmFuZ2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICAvKlxuICAgIFwiY29tcGxldGVcIiBzZWcgbWVhbnMgaXQgaGFzIGNvbXBvbmVudCBhbmQgZXZlbnRSYW5nZVxuICAgICovXG4gICAgU2xpY2VyLnByb3RvdHlwZS5zbGljZUV2ZW50UmFuZ2VzID0gZnVuY3Rpb24gKGV2ZW50UmFuZ2VzLCBjb21wb25lbnQsIC8vIFRPRE86IGtpbGxcbiAgICBleHRyYUFyZ3MpIHtcbiAgICAgICAgdmFyIHNlZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBldmVudFJhbmdlc18xID0gZXZlbnRSYW5nZXM7IF9pIDwgZXZlbnRSYW5nZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gZXZlbnRSYW5nZXNfMVtfaV07XG4gICAgICAgICAgICBzZWdzLnB1c2guYXBwbHkoc2VncywgdGhpcy5zbGljZUV2ZW50UmFuZ2UoZXZlbnRSYW5nZSwgY29tcG9uZW50LCBleHRyYUFyZ3MpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VncztcbiAgICB9O1xuICAgIC8qXG4gICAgXCJjb21wbGV0ZVwiIHNlZyBtZWFucyBpdCBoYXMgY29tcG9uZW50IGFuZCBldmVudFJhbmdlXG4gICAgKi9cbiAgICBTbGljZXIucHJvdG90eXBlLnNsaWNlRXZlbnRSYW5nZSA9IGZ1bmN0aW9uIChldmVudFJhbmdlLCBjb21wb25lbnQsIC8vIFRPRE86IGtpbGxcbiAgICBleHRyYUFyZ3MpIHtcbiAgICAgICAgdmFyIHNlZ3MgPSB0aGlzLnNsaWNlUmFuZ2UuYXBwbHkodGhpcywgW2V2ZW50UmFuZ2UucmFuZ2VdLmNvbmNhdChleHRyYUFyZ3MpKTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBzZWdzXzIgPSBzZWdzOyBfaSA8IHNlZ3NfMi5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzZWcgPSBzZWdzXzJbX2ldO1xuICAgICAgICAgICAgc2VnLmNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICAgICAgICAgIHNlZy5ldmVudFJhbmdlID0gZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIHNlZy5pc1N0YXJ0ID0gZXZlbnRSYW5nZS5pc1N0YXJ0ICYmIHNlZy5pc1N0YXJ0O1xuICAgICAgICAgICAgc2VnLmlzRW5kID0gZXZlbnRSYW5nZS5pc0VuZCAmJiBzZWcuaXNFbmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICByZXR1cm4gU2xpY2VyO1xufSgpKTtcbi8qXG5mb3IgaW5jb3Jwb3JhdGluZyBtaW5UaW1lL21heFRpbWUgaWYgYXBwcm9wcmlhdGVcblRPRE86IHNob3VsZCBiZSBwYXJ0IG9mIERhdGVQcm9maWxlIVxuVGltZWxpbmVEYXRlUHJvZmlsZSBhbHJlYWR5IGRvZXMgdGhpcyBidHdcbiovXG5mdW5jdGlvbiBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIGlzQ29tcG9uZW50QWxsRGF5KSB7XG4gICAgdmFyIHJhbmdlID0gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2U7XG4gICAgaWYgKGlzQ29tcG9uZW50QWxsRGF5KSB7XG4gICAgICAgIHJldHVybiByYW5nZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IGFkZE1zKHJhbmdlLnN0YXJ0LCBkYXRlUHJvZmlsZS5taW5UaW1lLm1pbGxpc2Vjb25kcyksXG4gICAgICAgIGVuZDogYWRkTXMocmFuZ2UuZW5kLCBkYXRlUHJvZmlsZS5tYXhUaW1lLm1pbGxpc2Vjb25kcyAtIDg2NGU1KSAvLyA4NjRlNSA9IG1zIGluIGEgZGF5XG4gICAgfTtcbn1cblxuLy8gZXhwb3J0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbnZhciB2ZXJzaW9uID0gJzQuNC4yJztcblxuZXhwb3J0IHsgQ2FsZW5kYXIsIENvbXBvbmVudCwgQ29tcG9uZW50Q29udGV4dCwgRGF0ZUNvbXBvbmVudCwgRGF0ZUVudiwgRGF0ZVByb2ZpbGVHZW5lcmF0b3IsIERheUhlYWRlciwgRGF5U2VyaWVzLCBEYXlUYWJsZSwgRWxlbWVudERyYWdnaW5nLCBFbGVtZW50U2Nyb2xsQ29udHJvbGxlciwgRW1pdHRlck1peGluLCBFdmVudEFwaSwgRmdFdmVudFJlbmRlcmVyLCBGaWxsUmVuZGVyZXIsIEludGVyYWN0aW9uLCBNaXhpbiwgTmFtZWRUaW1lWm9uZUltcGwsIFBvc2l0aW9uQ2FjaGUsIFNjcm9sbENvbXBvbmVudCwgU2Nyb2xsQ29udHJvbGxlciwgU2xpY2VyLCBTcGxpdHRlciwgVGhlbWUsIFZpZXcsIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIsIGFkZERheXMsIGFkZER1cmF0aW9ucywgYWRkTXMsIGFkZFdlZWtzLCBhbGxvd0NvbnRleHRNZW51LCBhbGxvd1NlbGVjdGlvbiwgYXBwZW5kVG9FbGVtZW50LCBhcHBseUFsbCwgYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZSwgYXBwbHlTdHlsZSwgYXBwbHlTdHlsZVByb3AsIGFzUm91Z2hNaW51dGVzLCBhc1JvdWdoTXMsIGFzUm91Z2hTZWNvbmRzLCBidWlsZEdvdG9BbmNob3JIdG1sLCBidWlsZFNlZ0NvbXBhcmVPYmosIGNhcGl0YWxpc2VGaXJzdExldHRlciwgY29tYmluZUV2ZW50VWlzLCBjb21wYXJlQnlGaWVsZFNwZWMsIGNvbXBhcmVCeUZpZWxkU3BlY3MsIGNvbXBhcmVOdW1iZXJzLCBjb21wZW5zYXRlU2Nyb2xsLCBjb21wdXRlQ2xpcHBpbmdSZWN0LCBjb21wdXRlRWRnZXMsIGNvbXB1dGVFdmVudERyYWdnYWJsZSwgY29tcHV0ZUV2ZW50RW5kUmVzaXphYmxlLCBjb21wdXRlRXZlbnRTdGFydFJlc2l6YWJsZSwgY29tcHV0ZUZhbGxiYWNrSGVhZGVyRm9ybWF0LCBjb21wdXRlSGVpZ2h0QW5kTWFyZ2lucywgY29tcHV0ZUlubmVyUmVjdCwgY29tcHV0ZVJlY3QsIGNvbXB1dGVWaXNpYmxlRGF5UmFuZ2UsIGNvbmZpZywgY29uc3RyYWluUG9pbnQsIGNyZWF0ZUR1cmF0aW9uLCBjcmVhdGVFbGVtZW50LCBjcmVhdGVFbXB0eUV2ZW50U3RvcmUsIGNyZWF0ZUV2ZW50SW5zdGFuY2UsIGNyZWF0ZUZvcm1hdHRlciwgY3JlYXRlUGx1Z2luLCBjc3NUb1N0ciwgZGVib3VuY2UsIGRpZmZEYXRlcywgZGlmZkRheUFuZFRpbWUsIGRpZmZEYXlzLCBkaWZmUG9pbnRzLCBkaWZmV2Vla3MsIGRpZmZXaG9sZURheXMsIGRpZmZXaG9sZVdlZWtzLCBkaXNhYmxlQ3Vyc29yLCBkaXN0cmlidXRlSGVpZ2h0LCBlbGVtZW50Q2xvc2VzdCwgZWxlbWVudE1hdGNoZXMsIGVuYWJsZUN1cnNvciwgZXZlbnRUdXBsZVRvU3RvcmUsIGZpbHRlckV2ZW50U3RvcmVEZWZzLCBmaWx0ZXJIYXNoLCBmaW5kQ2hpbGRyZW4sIGZpbmRFbGVtZW50cywgZmxleGlibGVDb21wYXJlLCBmb3JjZUNsYXNzTmFtZSwgZm9ybWF0RGF0ZSwgZm9ybWF0SXNvVGltZVN0cmluZywgZm9ybWF0UmFuZ2UsIGdldEFsbERheUh0bWwsIGdldENsaXBwaW5nUGFyZW50cywgZ2V0RGF5Q2xhc3NlcywgZ2V0RWxTZWcsIGdldFJlY3RDZW50ZXIsIGdldFJlbGV2YW50RXZlbnRzLCBnbG9iYWxEZWZhdWx0cywgZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yLCBoYXNCZ1JlbmRlcmluZywgaHRtbEVzY2FwZSwgaHRtbFRvRWxlbWVudCwgaW5zZXJ0QWZ0ZXJFbGVtZW50LCBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUsIGludGVyYWN0aW9uU2V0dGluZ3NUb1N0b3JlLCBpbnRlcnNlY3RSYW5nZXMsIGludGVyc2VjdFJlY3RzLCBpc0FycmF5c0VxdWFsLCBpc0RhdGVTcGFuc0VxdWFsLCBpc0ludCwgaXNJbnRlcmFjdGlvblZhbGlkLCBpc011bHRpRGF5UmFuZ2UsIGlzUHJvcHNFcXVhbCwgaXNQcm9wc1ZhbGlkLCBpc1NpbmdsZURheSwgaXNWYWxpZERhdGUsIGxpc3RlbkJ5U2VsZWN0b3IsIG1hcEhhc2gsIG1hdGNoQ2VsbFdpZHRocywgbWVtb2l6ZSwgbWVtb2l6ZU91dHB1dCwgbWVtb2l6ZVJlbmRlcmluZywgbWVyZ2VFdmVudFN0b3JlcywgbXVsdGlwbHlEdXJhdGlvbiwgcGFkU3RhcnQsIHBhcnNlQnVzaW5lc3NIb3VycywgcGFyc2VEcmFnTWV0YSwgcGFyc2VFdmVudERlZiwgcGFyc2VGaWVsZFNwZWNzLCBwYXJzZSBhcyBwYXJzZU1hcmtlciwgcG9pbnRJbnNpZGVSZWN0LCBwcmVwZW5kVG9FbGVtZW50LCBwcmV2ZW50Q29udGV4dE1lbnUsIHByZXZlbnREZWZhdWx0LCBwcmV2ZW50U2VsZWN0aW9uLCBwcm9jZXNzU2NvcGVkVWlQcm9wcywgcmFuZ2VDb250YWluc01hcmtlciwgcmFuZ2VDb250YWluc1JhbmdlLCByYW5nZXNFcXVhbCwgcmFuZ2VzSW50ZXJzZWN0LCByZWZpbmVQcm9wcywgcmVtb3ZlRWxlbWVudCwgcmVtb3ZlRXhhY3QsIHJlbmRlckRhdGVDZWxsLCByZXF1ZXN0SnNvbiwgc2xpY2VFdmVudFN0b3JlLCBzdGFydE9mRGF5LCBzdWJ0cmFjdElubmVyRWxIZWlnaHQsIHRyYW5zbGF0ZVJlY3QsIHVuY29tcGVuc2F0ZVNjcm9sbCwgdW5kaXN0cmlidXRlSGVpZ2h0LCB1bnByb21pc2lmeSwgdmVyc2lvbiwgd2hlblRyYW5zaXRpb25Eb25lLCB3aG9sZURpdmlkZUR1cmF0aW9ucyB9O1xuIiwiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luIiwiLyohXG5GdWxsQ2FsZW5kYXIgRGF5IEdyaWQgUGx1Z2luIHY0LjQuMlxuRG9jcyAmIExpY2Vuc2U6IGh0dHBzOi8vZnVsbGNhbGVuZGFyLmlvL1xuKGMpIDIwMTkgQWRhbSBTaGF3XG4qL1xuXG5pbXBvcnQgeyBhZGRXZWVrcywgZGlmZldlZWtzLCBEYXRlUHJvZmlsZUdlbmVyYXRvciwgY3JlYXRlRWxlbWVudCwgbGlzdGVuQnlTZWxlY3RvciwgcmVtb3ZlRWxlbWVudCwgY29tcHV0ZVJlY3QsIGNvbXB1dGVDbGlwcGluZ1JlY3QsIGFwcGx5U3R5bGUsIGNvbXB1dGVFdmVudERyYWdnYWJsZSwgY29tcHV0ZUV2ZW50U3RhcnRSZXNpemFibGUsIGNvbXB1dGVFdmVudEVuZFJlc2l6YWJsZSwgY3NzVG9TdHIsIGh0bWxFc2NhcGUsIEZnRXZlbnRSZW5kZXJlciwgYXBwZW5kVG9FbGVtZW50LCBwcmVwZW5kVG9FbGVtZW50LCBodG1sVG9FbGVtZW50LCBGaWxsUmVuZGVyZXIsIG1lbW9pemVSZW5kZXJpbmcsIGNyZWF0ZUZvcm1hdHRlciwgYWRkRGF5cywgRGF0ZUNvbXBvbmVudCwgcmFuZ2VDb250YWluc01hcmtlciwgZ2V0RGF5Q2xhc3NlcywgZmluZEVsZW1lbnRzLCBQb3NpdGlvbkNhY2hlLCBidWlsZEdvdG9BbmNob3JIdG1sLCBmaW5kQ2hpbGRyZW4sIGluc2VydEFmdGVyRWxlbWVudCwgaW50ZXJzZWN0UmFuZ2VzLCBtZW1vaXplLCBTY3JvbGxDb21wb25lbnQsIG1hdGNoQ2VsbFdpZHRocywgdW5jb21wZW5zYXRlU2Nyb2xsLCBjb21wZW5zYXRlU2Nyb2xsLCBzdWJ0cmFjdElubmVyRWxIZWlnaHQsIGRpc3RyaWJ1dGVIZWlnaHQsIHVuZGlzdHJpYnV0ZUhlaWdodCwgVmlldywgU2xpY2VyLCBEYXlIZWFkZXIsIERheVNlcmllcywgRGF5VGFibGUsIGNyZWF0ZVBsdWdpbiB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZSc7XG5cbi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbnZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn07XG5cbnZhciBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUdyaWREYXRlUHJvZmlsZUdlbmVyYXRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3IoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gQ29tcHV0ZXMgdGhlIGRhdGUgcmFuZ2UgdGhhdCB3aWxsIGJlIHJlbmRlcmVkLlxuICAgIERheUdyaWREYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRSZW5kZXJSYW5nZSA9IGZ1bmN0aW9uIChjdXJyZW50UmFuZ2UsIGN1cnJlbnRSYW5nZVVuaXQsIGlzUmFuZ2VBbGxEYXkpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHZhciByZW5kZXJSYW5nZSA9IF9zdXBlci5wcm90b3R5cGUuYnVpbGRSZW5kZXJSYW5nZS5jYWxsKHRoaXMsIGN1cnJlbnRSYW5nZSwgY3VycmVudFJhbmdlVW5pdCwgaXNSYW5nZUFsbERheSk7XG4gICAgICAgIHZhciBzdGFydCA9IHJlbmRlclJhbmdlLnN0YXJ0O1xuICAgICAgICB2YXIgZW5kID0gcmVuZGVyUmFuZ2UuZW5kO1xuICAgICAgICB2YXIgZW5kT2ZXZWVrO1xuICAgICAgICAvLyB5ZWFyIGFuZCBtb250aCB2aWV3cyBzaG91bGQgYmUgYWxpZ25lZCB3aXRoIHdlZWtzLiB0aGlzIGlzIGFscmVhZHkgZG9uZSBmb3Igd2Vla1xuICAgICAgICBpZiAoL14oeWVhcnxtb250aCkkLy50ZXN0KGN1cnJlbnRSYW5nZVVuaXQpKSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVFbnYuc3RhcnRPZldlZWsoc3RhcnQpO1xuICAgICAgICAgICAgLy8gbWFrZSBlbmQtb2Ytd2VlayBpZiBub3QgYWxyZWFkeVxuICAgICAgICAgICAgZW5kT2ZXZWVrID0gZGF0ZUVudi5zdGFydE9mV2VlayhlbmQpO1xuICAgICAgICAgICAgaWYgKGVuZE9mV2Vlay52YWx1ZU9mKCkgIT09IGVuZC52YWx1ZU9mKCkpIHtcbiAgICAgICAgICAgICAgICBlbmQgPSBhZGRXZWVrcyhlbmRPZldlZWssIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGVuc3VyZSA2IHdlZWtzXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMubW9udGhNb2RlICYmXG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuZml4ZWRXZWVrQ291bnQpIHtcbiAgICAgICAgICAgIHZhciByb3dDbnQgPSBNYXRoLmNlaWwoLy8gY291bGQgYmUgcGFydGlhbCB3ZWVrcyBkdWUgdG8gaGlkZGVuRGF5c1xuICAgICAgICAgICAgZGlmZldlZWtzKHN0YXJ0LCBlbmQpKTtcbiAgICAgICAgICAgIGVuZCA9IGFkZFdlZWtzKGVuZCwgNiAtIHJvd0NudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWREYXRlUHJvZmlsZUdlbmVyYXRvcjtcbn0oRGF0ZVByb2ZpbGVHZW5lcmF0b3IpKTtcblxuLyogQSByZWN0YW5ndWxhciBwYW5lbCB0aGF0IGlzIGFic29sdXRlbHkgcG9zaXRpb25lZCBvdmVyIG90aGVyIGNvbnRlbnRcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuT3B0aW9uczpcbiAgLSBjbGFzc05hbWUgKHN0cmluZylcbiAgLSBjb250ZW50IChIVE1MIHN0cmluZywgZWxlbWVudCwgb3IgZWxlbWVudCBhcnJheSlcbiAgLSBwYXJlbnRFbFxuICAtIHRvcFxuICAtIGxlZnRcbiAgLSByaWdodCAodGhlIHggY29vcmQgb2Ygd2hlcmUgdGhlIHJpZ2h0IGVkZ2Ugc2hvdWxkIGJlLiBub3QgYSBcIkNTU1wiIHJpZ2h0KVxuICAtIGF1dG9IaWRlIChib29sZWFuKVxuICAtIHNob3cgKGNhbGxiYWNrKVxuICAtIGhpZGUgKGNhbGxiYWNrKVxuKi9cbnZhciBQb3BvdmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBvcG92ZXIob3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmlzSGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tYXJnaW4gPSAxMDsgLy8gdGhlIHNwYWNlIHJlcXVpcmVkIGJldHdlZW4gdGhlIHBvcG92ZXIgYW5kIHRoZSBlZGdlcyBvZiB0aGUgc2Nyb2xsIGNvbnRhaW5lclxuICAgICAgICAvLyBUcmlnZ2VyZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgKmFueXdoZXJlKiBpbiB0aGUgZG9jdW1lbnQsIGZvciB0aGUgYXV0b0hpZGUgZmVhdHVyZVxuICAgICAgICB0aGlzLmRvY3VtZW50TW91c2Vkb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICAvLyBvbmx5IGhpZGUgdGhlIHBvcG92ZXIgaWYgdGhlIGNsaWNrIGhhcHBlbmVkIG91dHNpZGUgdGhlIHBvcG92ZXJcbiAgICAgICAgICAgIGlmIChfdGhpcy5lbCAmJiAhX3RoaXMuZWwuY29udGFpbnMoZXYudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB9XG4gICAgLy8gU2hvd3MgdGhlIHBvcG92ZXIgb24gdGhlIHNwZWNpZmllZCBwb3NpdGlvbi4gUmVuZGVycyBpdCBpZiBub3QgYWxyZWFkeVxuICAgIFBvcG92ZXIucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSGlkZGVuKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbC5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICAgICAgICB0aGlzLnBvc2l0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLmlzSGlkZGVuID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIoJ3Nob3cnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gSGlkZXMgdGhlIHBvcG92ZXIsIHRocm91Z2ggQ1NTLCBidXQgZG9lcyBub3QgcmVtb3ZlIGl0IGZyb20gdGhlIERPTVxuICAgIFBvcG92ZXIucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pc0hpZGRlbikge1xuICAgICAgICAgICAgdGhpcy5lbC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgdGhpcy5pc0hpZGRlbiA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIoJ2hpZGUnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gQ3JlYXRlcyBgdGhpcy5lbGAgYW5kIHJlbmRlcnMgY29udGVudCBpbnNpZGUgb2YgaXRcbiAgICBQb3BvdmVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICB2YXIgZWwgPSB0aGlzLmVsID0gY3JlYXRlRWxlbWVudCgnZGl2Jywge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnZmMtcG9wb3ZlciAnICsgKG9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKSxcbiAgICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgdG9wOiAnMCcsXG4gICAgICAgICAgICAgICAgbGVmdDogJzAnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuY29udGVudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgb3B0aW9ucy5jb250ZW50KGVsKTtcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zLnBhcmVudEVsLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgLy8gd2hlbiBhIGNsaWNrIGhhcHBlbnMgb24gYW55dGhpbmcgaW5zaWRlIHdpdGggYSAnZmMtY2xvc2UnIGNsYXNzTmFtZSwgaGlkZSB0aGUgcG9wb3ZlclxuICAgICAgICBsaXN0ZW5CeVNlbGVjdG9yKGVsLCAnY2xpY2snLCAnLmZjLWNsb3NlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5oaWRlKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob3B0aW9ucy5hdXRvSGlkZSkge1xuICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5kb2N1bWVudE1vdXNlZG93bik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEhpZGVzIGFuZCB1bnJlZ2lzdGVycyBhbnkgaGFuZGxlcnNcbiAgICBQb3BvdmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgaWYgKHRoaXMuZWwpIHtcbiAgICAgICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5lbCk7XG4gICAgICAgICAgICB0aGlzLmVsID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmRvY3VtZW50TW91c2Vkb3duKTtcbiAgICB9O1xuICAgIC8vIFBvc2l0aW9ucyB0aGUgcG9wb3ZlciBvcHRpbWFsbHksIHVzaW5nIHRoZSB0b3AvbGVmdC9yaWdodCBvcHRpb25zXG4gICAgUG9wb3Zlci5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICB2YXIgZWwgPSB0aGlzLmVsO1xuICAgICAgICB2YXIgZWxEaW1zID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IC8vIG9ubHkgdXNlZCBmb3Igd2lkdGgsaGVpZ2h0XG4gICAgICAgIHZhciBvcmlnaW4gPSBjb21wdXRlUmVjdChlbC5vZmZzZXRQYXJlbnQpO1xuICAgICAgICB2YXIgY2xpcHBpbmdSZWN0ID0gY29tcHV0ZUNsaXBwaW5nUmVjdChvcHRpb25zLnBhcmVudEVsKTtcbiAgICAgICAgdmFyIHRvcDsgLy8gdGhlIFwicG9zaXRpb25cIiAobm90IFwib2Zmc2V0XCIpIHZhbHVlcyBmb3IgdGhlIHBvcG92ZXJcbiAgICAgICAgdmFyIGxlZnQ7IC8vXG4gICAgICAgIC8vIGNvbXB1dGUgdG9wIGFuZCBsZWZ0XG4gICAgICAgIHRvcCA9IG9wdGlvbnMudG9wIHx8IDA7XG4gICAgICAgIGlmIChvcHRpb25zLmxlZnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbGVmdCA9IG9wdGlvbnMubGVmdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLnJpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGxlZnQgPSBvcHRpb25zLnJpZ2h0IC0gZWxEaW1zLndpZHRoOyAvLyBkZXJpdmUgdGhlIGxlZnQgdmFsdWUgZnJvbSB0aGUgcmlnaHQgdmFsdWVcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxlZnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnN0cmFpbiB0byB0aGUgdmlldyBwb3J0LiBpZiBjb25zdHJhaW5lZCBieSB0d28gZWRnZXMsIGdpdmUgcHJlY2VkZW5jZSB0byB0b3AvbGVmdFxuICAgICAgICB0b3AgPSBNYXRoLm1pbih0b3AsIGNsaXBwaW5nUmVjdC5ib3R0b20gLSBlbERpbXMuaGVpZ2h0IC0gdGhpcy5tYXJnaW4pO1xuICAgICAgICB0b3AgPSBNYXRoLm1heCh0b3AsIGNsaXBwaW5nUmVjdC50b3AgKyB0aGlzLm1hcmdpbik7XG4gICAgICAgIGxlZnQgPSBNYXRoLm1pbihsZWZ0LCBjbGlwcGluZ1JlY3QucmlnaHQgLSBlbERpbXMud2lkdGggLSB0aGlzLm1hcmdpbik7XG4gICAgICAgIGxlZnQgPSBNYXRoLm1heChsZWZ0LCBjbGlwcGluZ1JlY3QubGVmdCArIHRoaXMubWFyZ2luKTtcbiAgICAgICAgYXBwbHlTdHlsZShlbCwge1xuICAgICAgICAgICAgdG9wOiB0b3AgLSBvcmlnaW4udG9wLFxuICAgICAgICAgICAgbGVmdDogbGVmdCAtIG9yaWdpbi5sZWZ0XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gVHJpZ2dlcnMgYSBjYWxsYmFjay4gQ2FsbHMgYSBmdW5jdGlvbiBpbiB0aGUgb3B0aW9uIGhhc2ggb2YgdGhlIHNhbWUgbmFtZS5cbiAgICAvLyBBcmd1bWVudHMgYmV5b25kIHRoZSBmaXJzdCBgbmFtZWAgYXJlIGZvcndhcmRlZCBvbi5cbiAgICAvLyBUT0RPOiBiZXR0ZXIgY29kZSByZXVzZSBmb3IgdGhpcy4gUmVwZWF0IGNvZGVcbiAgICAvLyBjYW4ga2lsbCB0aGlzPz8/XG4gICAgUG9wb3Zlci5wcm90b3R5cGUudHJpZ2dlciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnNbbmFtZV0pIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9uc1tuYW1lXS5hcHBseSh0aGlzLCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFBvcG92ZXI7XG59KCkpO1xuXG4vKiBFdmVudC1yZW5kZXJpbmcgbWV0aG9kcyBmb3IgdGhlIERheUdyaWQgY2xhc3Ncbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLy8gXCJTaW1wbGVcIiBpcyBiYWQgYSBuYW1lLiBoYXMgbm90aGluZyB0byBkbyB3aXRoIFNpbXBsZURheUdyaWRcbnZhciBTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gQnVpbGRzIHRoZSBIVE1MIHRvIGJlIHVzZWQgZm9yIHRoZSBkZWZhdWx0IGVsZW1lbnQgZm9yIGFuIGluZGl2aWR1YWwgc2VnbWVudFxuICAgIFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdIdG1sID0gZnVuY3Rpb24gKHNlZywgbWlycm9ySW5mbykge1xuICAgICAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBzZWcuZXZlbnRSYW5nZTtcbiAgICAgICAgdmFyIGV2ZW50RGVmID0gZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgIHZhciBldmVudFVpID0gZXZlbnRSYW5nZS51aTtcbiAgICAgICAgdmFyIGFsbERheSA9IGV2ZW50RGVmLmFsbERheTtcbiAgICAgICAgdmFyIGlzRHJhZ2dhYmxlID0gY29tcHV0ZUV2ZW50RHJhZ2dhYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKTtcbiAgICAgICAgdmFyIGlzUmVzaXphYmxlRnJvbVN0YXJ0ID0gYWxsRGF5ICYmIHNlZy5pc1N0YXJ0ICYmIGNvbXB1dGVFdmVudFN0YXJ0UmVzaXphYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKTtcbiAgICAgICAgdmFyIGlzUmVzaXphYmxlRnJvbUVuZCA9IGFsbERheSAmJiBzZWcuaXNFbmQgJiYgY29tcHV0ZUV2ZW50RW5kUmVzaXphYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKTtcbiAgICAgICAgdmFyIGNsYXNzZXMgPSB0aGlzLmdldFNlZ0NsYXNzZXMoc2VnLCBpc0RyYWdnYWJsZSwgaXNSZXNpemFibGVGcm9tU3RhcnQgfHwgaXNSZXNpemFibGVGcm9tRW5kLCBtaXJyb3JJbmZvKTtcbiAgICAgICAgdmFyIHNraW5Dc3MgPSBjc3NUb1N0cih0aGlzLmdldFNraW5Dc3MoZXZlbnRVaSkpO1xuICAgICAgICB2YXIgdGltZUh0bWwgPSAnJztcbiAgICAgICAgdmFyIHRpbWVUZXh0O1xuICAgICAgICB2YXIgdGl0bGVIdG1sO1xuICAgICAgICBjbGFzc2VzLnVuc2hpZnQoJ2ZjLWRheS1ncmlkLWV2ZW50JywgJ2ZjLWgtZXZlbnQnKTtcbiAgICAgICAgLy8gT25seSBkaXNwbGF5IGEgdGltZWQgZXZlbnRzIHRpbWUgaWYgaXQgaXMgdGhlIHN0YXJ0aW5nIHNlZ21lbnRcbiAgICAgICAgaWYgKHNlZy5pc1N0YXJ0KSB7XG4gICAgICAgICAgICB0aW1lVGV4dCA9IHRoaXMuZ2V0VGltZVRleHQoZXZlbnRSYW5nZSk7XG4gICAgICAgICAgICBpZiAodGltZVRleHQpIHtcbiAgICAgICAgICAgICAgICB0aW1lSHRtbCA9ICc8c3BhbiBjbGFzcz1cImZjLXRpbWVcIj4nICsgaHRtbEVzY2FwZSh0aW1lVGV4dCkgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGl0bGVIdG1sID1cbiAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cImZjLXRpdGxlXCI+JyArXG4gICAgICAgICAgICAgICAgKGh0bWxFc2NhcGUoZXZlbnREZWYudGl0bGUgfHwgJycpIHx8ICcmbmJzcDsnKSArIC8vIHdlIGFsd2F5cyB3YW50IG9uZSBsaW5lIG9mIGhlaWdodFxuICAgICAgICAgICAgICAgICc8L3NwYW4+JztcbiAgICAgICAgcmV0dXJuICc8YSBjbGFzcz1cIicgKyBjbGFzc2VzLmpvaW4oJyAnKSArICdcIicgK1xuICAgICAgICAgICAgKGV2ZW50RGVmLnVybCA/XG4gICAgICAgICAgICAgICAgJyBocmVmPVwiJyArIGh0bWxFc2NhcGUoZXZlbnREZWYudXJsKSArICdcIicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAoc2tpbkNzcyA/XG4gICAgICAgICAgICAgICAgJyBzdHlsZT1cIicgKyBza2luQ3NzICsgJ1wiJyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgICc+JyArXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLWNvbnRlbnRcIj4nICtcbiAgICAgICAgICAgIChjb250ZXh0Lm9wdGlvbnMuZGlyID09PSAncnRsJyA/XG4gICAgICAgICAgICAgICAgdGl0bGVIdG1sICsgJyAnICsgdGltZUh0bWwgOiAvLyBwdXQgYSBuYXR1cmFsIHNwYWNlIGluIGJldHdlZW5cbiAgICAgICAgICAgICAgICB0aW1lSHRtbCArICcgJyArIHRpdGxlSHRtbCAvL1xuICAgICAgICAgICAgKSArXG4gICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAoaXNSZXNpemFibGVGcm9tU3RhcnQgP1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtcmVzaXplciBmYy1zdGFydC1yZXNpemVyXCI+PC9kaXY+JyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgIChpc1Jlc2l6YWJsZUZyb21FbmQgP1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtcmVzaXplciBmYy1lbmQtcmVzaXplclwiPjwvZGl2PicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAnPC9hPic7XG4gICAgfTtcbiAgICAvLyBDb21wdXRlcyBhIGRlZmF1bHQgZXZlbnQgdGltZSBmb3JtYXR0aW5nIHN0cmluZyBpZiBgZXZlbnRUaW1lRm9ybWF0YCBpcyBub3QgZXhwbGljaXRseSBkZWZpbmVkXG4gICAgU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVFdmVudFRpbWVGb3JtYXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBob3VyOiAnbnVtZXJpYycsXG4gICAgICAgICAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICAgICAgICAgIG9taXRaZXJvTWludXRlOiB0cnVlLFxuICAgICAgICAgICAgbWVyaWRpZW06ICduYXJyb3cnXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZURpc3BsYXlFdmVudEVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBUT0RPOiBzb21laG93IGNvbnNpZGVyIHRoZSBvcmlnaW5hdGluZyBEYXlHcmlkJ3MgY29sdW1uIGNvdW50XG4gICAgfTtcbiAgICByZXR1cm4gU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXI7XG59KEZnRXZlbnRSZW5kZXJlcikpO1xuXG4vKiBFdmVudC1yZW5kZXJpbmcgbWV0aG9kcyBmb3IgdGhlIERheUdyaWQgY2xhc3Ncbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xudmFyIERheUdyaWRFdmVudFJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkRXZlbnRSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkRXZlbnRSZW5kZXJlcihkYXlHcmlkKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmRheUdyaWQgPSBkYXlHcmlkO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIC8vIFJlbmRlcnMgdGhlIGdpdmVuIGZvcmVncm91bmQgZXZlbnQgc2VnbWVudHMgb250byB0aGUgZ3JpZFxuICAgIERheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5hdHRhY2hTZWdzID0gZnVuY3Rpb24gKHNlZ3MsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSB0aGlzLnJvd1N0cnVjdHMgPSB0aGlzLnJlbmRlclNlZ1Jvd3Moc2Vncyk7XG4gICAgICAgIC8vIGFwcGVuZCB0byBlYWNoIHJvdydzIGNvbnRlbnQgc2tlbGV0b25cbiAgICAgICAgdGhpcy5kYXlHcmlkLnJvd0Vscy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlLCBpKSB7XG4gICAgICAgICAgICByb3dOb2RlLnF1ZXJ5U2VsZWN0b3IoJy5mYy1jb250ZW50LXNrZWxldG9uID4gdGFibGUnKS5hcHBlbmRDaGlsZChyb3dTdHJ1Y3RzW2ldLnRib2R5RWwpO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gcmVtb3ZlcyB0aGUgXCJtb3JlLi5cIiBldmVudHMgcG9wb3ZlclxuICAgICAgICBpZiAoIW1pcnJvckluZm8pIHtcbiAgICAgICAgICAgIHRoaXMuZGF5R3JpZC5yZW1vdmVTZWdQb3BvdmVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFVucmVuZGVycyBhbGwgY3VycmVudGx5IHJlbmRlcmVkIGZvcmVncm91bmQgZXZlbnQgc2VnbWVudHNcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZGV0YWNoU2VncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSB0aGlzLnJvd1N0cnVjdHMgfHwgW107XG4gICAgICAgIHZhciByb3dTdHJ1Y3Q7XG4gICAgICAgIHdoaWxlICgocm93U3RydWN0ID0gcm93U3RydWN0cy5wb3AoKSkpIHtcbiAgICAgICAgICAgIHJlbW92ZUVsZW1lbnQocm93U3RydWN0LnRib2R5RWwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucm93U3RydWN0cyA9IG51bGw7XG4gICAgfTtcbiAgICAvLyBVc2VzIHRoZSBnaXZlbiBldmVudHMgYXJyYXkgdG8gZ2VuZXJhdGUgPHRib2R5PiBlbGVtZW50cyB0aGF0IHNob3VsZCBiZSBhcHBlbmRlZCB0byBlYWNoIHJvdydzIGNvbnRlbnQgc2tlbGV0b24uXG4gICAgLy8gUmV0dXJucyBhbiBhcnJheSBvZiByb3dTdHJ1Y3Qgb2JqZWN0cyAoc2VlIHRoZSBib3R0b20gb2YgYHJlbmRlclNlZ1Jvd2ApLlxuICAgIC8vIFBSRUNPTkRJVElPTjogZWFjaCBzZWdtZW50IHNob3VkIGFscmVhZHkgaGF2ZSBhIHJlbmRlcmVkIGFuZCBhc3NpZ25lZCBgLmVsYFxuICAgIERheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdSb3dzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSBbXTtcbiAgICAgICAgdmFyIHNlZ1Jvd3M7XG4gICAgICAgIHZhciByb3c7XG4gICAgICAgIHNlZ1Jvd3MgPSB0aGlzLmdyb3VwU2VnUm93cyhzZWdzKTsgLy8gZ3JvdXAgaW50byBuZXN0ZWQgYXJyYXlzXG4gICAgICAgIC8vIGl0ZXJhdGUgZWFjaCByb3cgb2Ygc2VnbWVudCBncm91cGluZ3NcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCBzZWdSb3dzLmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgIHJvd1N0cnVjdHMucHVzaCh0aGlzLnJlbmRlclNlZ1Jvdyhyb3csIHNlZ1Jvd3Nbcm93XSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dTdHJ1Y3RzO1xuICAgIH07XG4gICAgLy8gR2l2ZW4gYSByb3cgIyBhbmQgYW4gYXJyYXkgb2Ygc2VnbWVudHMgYWxsIGluIHRoZSBzYW1lIHJvdywgcmVuZGVyIGEgPHRib2R5PiBlbGVtZW50LCBhIHNrZWxldG9uIHRoYXQgY29udGFpbnNcbiAgICAvLyB0aGUgc2VnbWVudHMuIFJldHVybnMgb2JqZWN0IHdpdGggYSBidW5jaCBvZiBpbnRlcm5hbCBkYXRhIGFib3V0IGhvdyB0aGUgcmVuZGVyIHdhcyBjYWxjdWxhdGVkLlxuICAgIC8vIE5PVEU6IG1vZGlmaWVzIHJvd1NlZ3NcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnUm93ID0gZnVuY3Rpb24gKHJvdywgcm93U2Vncykge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgY29sQ250ID0gZGF5R3JpZC5jb2xDbnQ7XG4gICAgICAgIHZhciBzZWdMZXZlbHMgPSB0aGlzLmJ1aWxkU2VnTGV2ZWxzKHJvd1NlZ3MpOyAvLyBncm91cCBpbnRvIHN1Yi1hcnJheXMgb2YgbGV2ZWxzXG4gICAgICAgIHZhciBsZXZlbENudCA9IE1hdGgubWF4KDEsIHNlZ0xldmVscy5sZW5ndGgpOyAvLyBlbnN1cmUgYXQgbGVhc3Qgb25lIGxldmVsXG4gICAgICAgIHZhciB0Ym9keSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3Rib2R5Jyk7XG4gICAgICAgIHZhciBzZWdNYXRyaXggPSBbXTsgLy8gbG9va3VwIGZvciB3aGljaCBzZWdtZW50cyBhcmUgcmVuZGVyZWQgaW50byB3aGljaCBsZXZlbCtjb2wgY2VsbHNcbiAgICAgICAgdmFyIGNlbGxNYXRyaXggPSBbXTsgLy8gbG9va3VwIGZvciBhbGwgPHRkPiBlbGVtZW50cyBvZiB0aGUgbGV2ZWwrY29sIG1hdHJpeFxuICAgICAgICB2YXIgbG9uZUNlbGxNYXRyaXggPSBbXTsgLy8gbG9va3VwIGZvciA8dGQ+IGVsZW1lbnRzIHRoYXQgb25seSB0YWtlIHVwIGEgc2luZ2xlIGNvbHVtblxuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGxldmVsU2VncztcbiAgICAgICAgdmFyIGNvbDtcbiAgICAgICAgdmFyIHRyO1xuICAgICAgICB2YXIgajtcbiAgICAgICAgdmFyIHNlZztcbiAgICAgICAgdmFyIHRkO1xuICAgICAgICAvLyBwb3B1bGF0ZXMgZW1wdHkgY2VsbHMgZnJvbSB0aGUgY3VycmVudCBjb2x1bW4gKGBjb2xgKSB0byBgZW5kQ29sYFxuICAgICAgICBmdW5jdGlvbiBlbXB0eUNlbGxzVW50aWwoZW5kQ29sKSB7XG4gICAgICAgICAgICB3aGlsZSAoY29sIDwgZW5kQ29sKSB7XG4gICAgICAgICAgICAgICAgLy8gdHJ5IHRvIGdyYWIgYSBjZWxsIGZyb20gdGhlIGxldmVsIGFib3ZlIGFuZCBleHRlbmQgaXRzIHJvd3NwYW4uIG90aGVyd2lzZSwgY3JlYXRlIGEgZnJlc2ggY2VsbFxuICAgICAgICAgICAgICAgIHRkID0gKGxvbmVDZWxsTWF0cml4W2kgLSAxXSB8fCBbXSlbY29sXTtcbiAgICAgICAgICAgICAgICBpZiAodGQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGQucm93U3BhbiA9ICh0ZC5yb3dTcGFuIHx8IDEpICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGQnKTtcbiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjZWxsTWF0cml4W2ldW2NvbF0gPSB0ZDtcbiAgICAgICAgICAgICAgICBsb25lQ2VsbE1hdHJpeFtpXVtjb2xdID0gdGQ7XG4gICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxldmVsQ250OyBpKyspIHsgLy8gaXRlcmF0ZSB0aHJvdWdoIGFsbCBsZXZlbHNcbiAgICAgICAgICAgIGxldmVsU2VncyA9IHNlZ0xldmVsc1tpXTtcbiAgICAgICAgICAgIGNvbCA9IDA7XG4gICAgICAgICAgICB0ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RyJyk7XG4gICAgICAgICAgICBzZWdNYXRyaXgucHVzaChbXSk7XG4gICAgICAgICAgICBjZWxsTWF0cml4LnB1c2goW10pO1xuICAgICAgICAgICAgbG9uZUNlbGxNYXRyaXgucHVzaChbXSk7XG4gICAgICAgICAgICAvLyBsZXZlbENudCBtaWdodCBiZSAxIGV2ZW4gdGhvdWdoIHRoZXJlIGFyZSBubyBhY3R1YWwgbGV2ZWxzLiBwcm90ZWN0IGFnYWluc3QgdGhpcy5cbiAgICAgICAgICAgIC8vIHRoaXMgc2luZ2xlIGVtcHR5IHJvdyBpcyB1c2VmdWwgZm9yIHN0eWxpbmcuXG4gICAgICAgICAgICBpZiAobGV2ZWxTZWdzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGxldmVsU2Vncy5sZW5ndGg7IGorKykgeyAvLyBpdGVyYXRlIHRocm91Z2ggc2VnbWVudHMgaW4gbGV2ZWxcbiAgICAgICAgICAgICAgICAgICAgc2VnID0gbGV2ZWxTZWdzW2pdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcubGFzdENvbCkgOiBzZWcuZmlyc3RDb2w7XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcuZmlyc3RDb2wpIDogc2VnLmxhc3RDb2w7XG4gICAgICAgICAgICAgICAgICAgIGVtcHR5Q2VsbHNVbnRpbChsZWZ0Q29sKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIGEgY29udGFpbmVyIHRoYXQgb2NjdXBpZXMgb3IgbW9yZSBjb2x1bW5zLiBhcHBlbmQgdGhlIGV2ZW50IGVsZW1lbnQuXG4gICAgICAgICAgICAgICAgICAgIHRkID0gY3JlYXRlRWxlbWVudCgndGQnLCB7IGNsYXNzTmFtZTogJ2ZjLWV2ZW50LWNvbnRhaW5lcicgfSwgc2VnLmVsKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRDb2wgIT09IHJpZ2h0Q29sKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZC5jb2xTcGFuID0gcmlnaHRDb2wgLSBsZWZ0Q29sICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHsgLy8gYSBzaW5nbGUtY29sdW1uIHNlZ21lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvbmVDZWxsTWF0cml4W2ldW2NvbF0gPSB0ZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY29sIDw9IHJpZ2h0Q29sKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjZWxsTWF0cml4W2ldW2NvbF0gPSB0ZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlZ01hdHJpeFtpXVtjb2xdID0gc2VnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVtcHR5Q2VsbHNVbnRpbChjb2xDbnQpOyAvLyBmaW5pc2ggb2ZmIHRoZSByb3dcbiAgICAgICAgICAgIHZhciBpbnRyb0h0bWwgPSBkYXlHcmlkLnJlbmRlclByb3BzLnJlbmRlckludHJvSHRtbCgpO1xuICAgICAgICAgICAgaWYgKGludHJvSHRtbCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1J0bCkge1xuICAgICAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQodHIsIGludHJvSHRtbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwcmVwZW5kVG9FbGVtZW50KHRyLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRib2R5LmFwcGVuZENoaWxkKHRyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICB0Ym9keUVsOiB0Ym9keSxcbiAgICAgICAgICAgIGNlbGxNYXRyaXg6IGNlbGxNYXRyaXgsXG4gICAgICAgICAgICBzZWdNYXRyaXg6IHNlZ01hdHJpeCxcbiAgICAgICAgICAgIHNlZ0xldmVsczogc2VnTGV2ZWxzLFxuICAgICAgICAgICAgc2Vnczogcm93U2Vnc1xuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gU3RhY2tzIGEgZmxhdCBhcnJheSBvZiBzZWdtZW50cywgd2hpY2ggYXJlIGFsbCBhc3N1bWVkIHRvIGJlIGluIHRoZSBzYW1lIHJvdywgaW50byBzdWJhcnJheXMgb2YgdmVydGljYWwgbGV2ZWxzLlxuICAgIC8vIE5PVEU6IG1vZGlmaWVzIHNlZ3NcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuYnVpbGRTZWdMZXZlbHMgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciBjb2xDbnQgPSB0aGlzLmRheUdyaWQuY29sQ250O1xuICAgICAgICB2YXIgbGV2ZWxzID0gW107XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgc2VnO1xuICAgICAgICB2YXIgajtcbiAgICAgICAgLy8gR2l2ZSBwcmVmZXJlbmNlIHRvIGVsZW1lbnRzIHdpdGggY2VydGFpbiBjcml0ZXJpYSwgc28gdGhleSBoYXZlXG4gICAgICAgIC8vIGEgY2hhbmNlIHRvIGJlIGNsb3NlciB0byB0aGUgdG9wLlxuICAgICAgICBzZWdzID0gdGhpcy5zb3J0RXZlbnRTZWdzKHNlZ3MpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgIC8vIGxvb3AgdGhyb3VnaCBsZXZlbHMsIHN0YXJ0aW5nIHdpdGggdGhlIHRvcG1vc3QsIHVudGlsIHRoZSBzZWdtZW50IGRvZXNuJ3QgY29sbGlkZSB3aXRoIG90aGVyIHNlZ21lbnRzXG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbGV2ZWxzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0RheVNlZ0NvbGxpc2lvbihzZWcsIGxldmVsc1tqXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYGpgIG5vdyBob2xkcyB0aGUgZGVzaXJlZCBzdWJyb3cgaW5kZXhcbiAgICAgICAgICAgIHNlZy5sZXZlbCA9IGo7XG4gICAgICAgICAgICBzZWcubGVmdENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcubGFzdENvbCkgOiBzZWcuZmlyc3RDb2w7IC8vIGZvciBzb3J0aW5nIG9ubHlcbiAgICAgICAgICAgIHNlZy5yaWdodENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcuZmlyc3RDb2wpIDogc2VnLmxhc3RDb2wgLy8gZm9yIHNvcnRpbmcgb25seVxuICAgICAgICAgICAgO1xuICAgICAgICAgICAgKGxldmVsc1tqXSB8fCAobGV2ZWxzW2pdID0gW10pKS5wdXNoKHNlZyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb3JkZXIgc2VnbWVudHMgbGVmdC10by1yaWdodC4gdmVyeSBpbXBvcnRhbnQgaWYgY2FsZW5kYXIgaXMgUlRMXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZXZlbHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGxldmVsc1tqXS5zb3J0KGNvbXBhcmVEYXlTZWdDb2xzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGV2ZWxzO1xuICAgIH07XG4gICAgLy8gR2l2ZW4gYSBmbGF0IGFycmF5IG9mIHNlZ21lbnRzLCByZXR1cm4gYW4gYXJyYXkgb2Ygc3ViLWFycmF5cywgZ3JvdXBlZCBieSBlYWNoIHNlZ21lbnQncyByb3dcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZ3JvdXBTZWdSb3dzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIHNlZ1Jvd3MgPSBbXTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmRheUdyaWQucm93Q250OyBpKyspIHtcbiAgICAgICAgICAgIHNlZ1Jvd3MucHVzaChbXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNlZ1Jvd3Nbc2Vnc1tpXS5yb3ddLnB1c2goc2Vnc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ1Jvd3M7XG4gICAgfTtcbiAgICAvLyBDb21wdXRlcyBhIGRlZmF1bHQgYGRpc3BsYXlFdmVudEVuZGAgdmFsdWUgaWYgb25lIGlzIG5vdCBleHBsaWNsdHkgZGVmaW5lZFxuICAgIERheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRGlzcGxheUV2ZW50RW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlHcmlkLmNvbENudCA9PT0gMTsgLy8gd2UnbGwgbGlrZWx5IGhhdmUgc3BhY2UgaWYgdGhlcmUncyBvbmx5IG9uZSBkYXlcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkRXZlbnRSZW5kZXJlcjtcbn0oU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIpKTtcbi8vIENvbXB1dGVzIHdoZXRoZXIgdHdvIHNlZ21lbnRzJyBjb2x1bW5zIGNvbGxpZGUuIFRoZXkgYXJlIGFzc3VtZWQgdG8gYmUgaW4gdGhlIHNhbWUgcm93LlxuZnVuY3Rpb24gaXNEYXlTZWdDb2xsaXNpb24oc2VnLCBvdGhlclNlZ3MpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgb3RoZXJTZWc7XG4gICAgZm9yIChpID0gMDsgaSA8IG90aGVyU2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvdGhlclNlZyA9IG90aGVyU2Vnc1tpXTtcbiAgICAgICAgaWYgKG90aGVyU2VnLmZpcnN0Q29sIDw9IHNlZy5sYXN0Q29sICYmXG4gICAgICAgICAgICBvdGhlclNlZy5sYXN0Q29sID49IHNlZy5maXJzdENvbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuLy8gQSBjbXAgZnVuY3Rpb24gZm9yIGRldGVybWluaW5nIHRoZSBsZWZ0bW9zdCBldmVudFxuZnVuY3Rpb24gY29tcGFyZURheVNlZ0NvbHMoYSwgYikge1xuICAgIHJldHVybiBhLmxlZnRDb2wgLSBiLmxlZnRDb2w7XG59XG5cbnZhciBEYXlHcmlkTWlycm9yUmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUdyaWRNaXJyb3JSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkTWlycm9yUmVuZGVyZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgRGF5R3JpZE1pcnJvclJlbmRlcmVyLnByb3RvdHlwZS5hdHRhY2hTZWdzID0gZnVuY3Rpb24gKHNlZ3MsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIHNvdXJjZVNlZyA9IG1pcnJvckluZm8uc291cmNlU2VnO1xuICAgICAgICB2YXIgcm93U3RydWN0cyA9IHRoaXMucm93U3RydWN0cyA9IHRoaXMucmVuZGVyU2VnUm93cyhzZWdzKTtcbiAgICAgICAgLy8gaW5qZWN0IGVhY2ggbmV3IGV2ZW50IHNrZWxldG9uIGludG8gZWFjaCBhc3NvY2lhdGVkIHJvd1xuICAgICAgICB0aGlzLmRheUdyaWQucm93RWxzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUsIHJvdykge1xuICAgICAgICAgICAgdmFyIHNrZWxldG9uRWwgPSBodG1sVG9FbGVtZW50KCc8ZGl2IGNsYXNzPVwiZmMtbWlycm9yLXNrZWxldG9uXCI+PHRhYmxlPjwvdGFibGU+PC9kaXY+Jyk7IC8vIHdpbGwgYmUgYWJzb2x1dGVseSBwb3NpdGlvbmVkXG4gICAgICAgICAgICB2YXIgc2tlbGV0b25Ub3BFbDtcbiAgICAgICAgICAgIHZhciBza2VsZXRvblRvcDtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIGFuIG9yaWdpbmFsIHNlZ21lbnQsIG1hdGNoIHRoZSB0b3AgcG9zaXRpb24uIE90aGVyd2lzZSwgcHV0IGl0IGF0IHRoZSByb3cncyB0b3AgbGV2ZWxcbiAgICAgICAgICAgIGlmIChzb3VyY2VTZWcgJiYgc291cmNlU2VnLnJvdyA9PT0gcm93KSB7XG4gICAgICAgICAgICAgICAgc2tlbGV0b25Ub3BFbCA9IHNvdXJjZVNlZy5lbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHNrZWxldG9uVG9wRWwgPSByb3dOb2RlLnF1ZXJ5U2VsZWN0b3IoJy5mYy1jb250ZW50LXNrZWxldG9uIHRib2R5Jyk7XG4gICAgICAgICAgICAgICAgaWYgKCFza2VsZXRvblRvcEVsKSB7IC8vIHdoZW4gbm8gZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgIHNrZWxldG9uVG9wRWwgPSByb3dOb2RlLnF1ZXJ5U2VsZWN0b3IoJy5mYy1jb250ZW50LXNrZWxldG9uIHRhYmxlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2tlbGV0b25Ub3AgPSBza2VsZXRvblRvcEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtXG4gICAgICAgICAgICAgICAgcm93Tm9kZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3A7IC8vIHRoZSBvZmZzZXRQYXJlbnQgb3JpZ2luXG4gICAgICAgICAgICBza2VsZXRvbkVsLnN0eWxlLnRvcCA9IHNrZWxldG9uVG9wICsgJ3B4JztcbiAgICAgICAgICAgIHNrZWxldG9uRWwucXVlcnlTZWxlY3RvcigndGFibGUnKS5hcHBlbmRDaGlsZChyb3dTdHJ1Y3RzW3Jvd10udGJvZHlFbCk7XG4gICAgICAgICAgICByb3dOb2RlLmFwcGVuZENoaWxkKHNrZWxldG9uRWwpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkTWlycm9yUmVuZGVyZXI7XG59KERheUdyaWRFdmVudFJlbmRlcmVyKSk7XG5cbnZhciBFTVBUWV9DRUxMX0hUTUwgPSAnPHRkIHN0eWxlPVwicG9pbnRlci1ldmVudHM6bm9uZVwiPjwvdGQ+JztcbnZhciBEYXlHcmlkRmlsbFJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkRmlsbFJlbmRlcmVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUdyaWRGaWxsUmVuZGVyZXIoZGF5R3JpZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5maWxsU2VnVGFnID0gJ3RkJzsgLy8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgdGFnIG5hbWVcbiAgICAgICAgX3RoaXMuZGF5R3JpZCA9IGRheUdyaWQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5R3JpZEZpbGxSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VncyA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0LCBzZWdzKSB7XG4gICAgICAgIC8vIGRvbid0IHJlbmRlciB0aW1lZCBiYWNrZ3JvdW5kIGV2ZW50c1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2JnRXZlbnQnKSB7XG4gICAgICAgICAgICBzZWdzID0gc2Vncy5maWx0ZXIoZnVuY3Rpb24gKHNlZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWcuZXZlbnRSYW5nZS5kZWYuYWxsRGF5O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZW5kZXJTZWdzLmNhbGwodGhpcywgdHlwZSwgY29udGV4dCwgc2Vncyk7XG4gICAgfTtcbiAgICBEYXlHcmlkRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5hdHRhY2hTZWdzID0gZnVuY3Rpb24gKHR5cGUsIHNlZ3MpIHtcbiAgICAgICAgdmFyIGVscyA9IFtdO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHNlZztcbiAgICAgICAgdmFyIHNrZWxldG9uRWw7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzZWcgPSBzZWdzW2ldO1xuICAgICAgICAgICAgc2tlbGV0b25FbCA9IHRoaXMucmVuZGVyRmlsbFJvdyh0eXBlLCBzZWcpO1xuICAgICAgICAgICAgdGhpcy5kYXlHcmlkLnJvd0Vsc1tzZWcucm93XS5hcHBlbmRDaGlsZChza2VsZXRvbkVsKTtcbiAgICAgICAgICAgIGVscy5wdXNoKHNrZWxldG9uRWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbHM7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgbmVlZGVkIGZvciBvbmUgcm93IG9mIGEgZmlsbC4gUmVxdWlyZXMgdGhlIHNlZydzIGVsIHRvIGJlIHJlbmRlcmVkLlxuICAgIERheUdyaWRGaWxsUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlckZpbGxSb3cgPSBmdW5jdGlvbiAodHlwZSwgc2VnKSB7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciBjb2xDbnQgPSBkYXlHcmlkLmNvbENudDtcbiAgICAgICAgdmFyIGxlZnRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmxhc3RDb2wpIDogc2VnLmZpcnN0Q29sO1xuICAgICAgICB2YXIgcmlnaHRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmZpcnN0Q29sKSA6IHNlZy5sYXN0Q29sO1xuICAgICAgICB2YXIgc3RhcnRDb2wgPSBsZWZ0Q29sO1xuICAgICAgICB2YXIgZW5kQ29sID0gcmlnaHRDb2wgKyAxO1xuICAgICAgICB2YXIgY2xhc3NOYW1lO1xuICAgICAgICB2YXIgc2tlbGV0b25FbDtcbiAgICAgICAgdmFyIHRyRWw7XG4gICAgICAgIGlmICh0eXBlID09PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSA9ICdiZ2V2ZW50JztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSA9IHR5cGUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBza2VsZXRvbkVsID0gaHRtbFRvRWxlbWVudCgnPGRpdiBjbGFzcz1cImZjLScgKyBjbGFzc05hbWUgKyAnLXNrZWxldG9uXCI+JyArXG4gICAgICAgICAgICAnPHRhYmxlPjx0cj48L3RyPjwvdGFibGU+JyArXG4gICAgICAgICAgICAnPC9kaXY+Jyk7XG4gICAgICAgIHRyRWwgPSBza2VsZXRvbkVsLmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0cicpWzBdO1xuICAgICAgICBpZiAoc3RhcnRDb2wgPiAwKSB7XG4gICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQodHJFbCwgXG4gICAgICAgICAgICAvLyB3aWxsIGNyZWF0ZSAoc3RhcnRDb2wgKyAxKSB0ZCdzXG4gICAgICAgICAgICBuZXcgQXJyYXkoc3RhcnRDb2wgKyAxKS5qb2luKEVNUFRZX0NFTExfSFRNTCkpO1xuICAgICAgICB9XG4gICAgICAgIHNlZy5lbC5jb2xTcGFuID0gZW5kQ29sIC0gc3RhcnRDb2w7XG4gICAgICAgIHRyRWwuYXBwZW5kQ2hpbGQoc2VnLmVsKTtcbiAgICAgICAgaWYgKGVuZENvbCA8IGNvbENudCkge1xuICAgICAgICAgICAgYXBwZW5kVG9FbGVtZW50KHRyRWwsIFxuICAgICAgICAgICAgLy8gd2lsbCBjcmVhdGUgKGNvbENudCAtIGVuZENvbCkgdGQnc1xuICAgICAgICAgICAgbmV3IEFycmF5KGNvbENudCAtIGVuZENvbCArIDEpLmpvaW4oRU1QVFlfQ0VMTF9IVE1MKSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGludHJvSHRtbCA9IGRheUdyaWQucmVuZGVyUHJvcHMucmVuZGVySW50cm9IdG1sKCk7XG4gICAgICAgIGlmIChpbnRyb0h0bWwpIHtcbiAgICAgICAgICAgIGlmIChpc1J0bCkge1xuICAgICAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudCh0ckVsLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcHJlcGVuZFRvRWxlbWVudCh0ckVsLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBza2VsZXRvbkVsO1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWRGaWxsUmVuZGVyZXI7XG59KEZpbGxSZW5kZXJlcikpO1xuXG52YXIgRGF5VGlsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5VGlsZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlUaWxlKGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGVsKSB8fCB0aGlzO1xuICAgICAgICB2YXIgZXZlbnRSZW5kZXJlciA9IF90aGlzLmV2ZW50UmVuZGVyZXIgPSBuZXcgRGF5VGlsZUV2ZW50UmVuZGVyZXIoX3RoaXMpO1xuICAgICAgICB2YXIgcmVuZGVyRnJhbWUgPSBfdGhpcy5yZW5kZXJGcmFtZSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlckZyYW1lKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRmdFdmVudHMgPSBtZW1vaXplUmVuZGVyaW5nKGV2ZW50UmVuZGVyZXIucmVuZGVyU2Vncy5iaW5kKGV2ZW50UmVuZGVyZXIpLCBldmVudFJlbmRlcmVyLnVucmVuZGVyLmJpbmQoZXZlbnRSZW5kZXJlciksIFtyZW5kZXJGcmFtZV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5zZWxlY3RCeUluc3RhbmNlSWQuYmluZChldmVudFJlbmRlcmVyKSwgZXZlbnRSZW5kZXJlci51bnNlbGVjdEJ5SW5zdGFuY2VJZC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbX3RoaXMucmVuZGVyRmdFdmVudHNdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnREcmFnID0gbWVtb2l6ZVJlbmRlcmluZyhldmVudFJlbmRlcmVyLmhpZGVCeUhhc2guYmluZChldmVudFJlbmRlcmVyKSwgZXZlbnRSZW5kZXJlci5zaG93QnlIYXNoLmJpbmQoZXZlbnRSZW5kZXJlciksIFtyZW5kZXJGcmFtZV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFJlc2l6ZSA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5oaWRlQnlIYXNoLmJpbmQoZXZlbnRSZW5kZXJlciksIGV2ZW50UmVuZGVyZXIuc2hvd0J5SGFzaC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbcmVuZGVyRnJhbWVdKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlUaWxlLnByb3RvdHlwZS5maXJzdENvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICBjb250ZXh0LmNhbGVuZGFyLnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcywge1xuICAgICAgICAgICAgZWw6IHRoaXMuZWwsXG4gICAgICAgICAgICB1c2VFdmVudENlbnRlcjogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJGcmFtZShwcm9wcy5kYXRlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJGZ0V2ZW50cyhjb250ZXh0LCBwcm9wcy5mZ1NlZ3MpO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uKHByb3BzLmV2ZW50U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudERyYWcocHJvcHMuZXZlbnREcmFnSW5zdGFuY2VzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZShwcm9wcy5ldmVudFJlc2l6ZUluc3RhbmNlcyk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJGcmFtZS51bnJlbmRlcigpOyAvLyBzaG91bGQgdW5yZW5kZXIgZXZlcnl0aGluZyBlbHNlXG4gICAgICAgIHRoaXMuY29udGV4dC5jYWxlbmRhci51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcyk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5fcmVuZGVyRnJhbWUgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIHRoZW1lID0gX2EudGhlbWUsIGRhdGVFbnYgPSBfYS5kYXRlRW52LCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIHRpdGxlID0gZGF0ZUVudi5mb3JtYXQoZGF0ZSwgY3JlYXRlRm9ybWF0dGVyKG9wdGlvbnMuZGF5UG9wb3ZlckZvcm1hdCkgLy8gVE9ETzogY2FjaGVcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5lbC5pbm5lckhUTUwgPVxuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1oZWFkZXIgJyArIHRoZW1lLmdldENsYXNzKCdwb3BvdmVySGVhZGVyJykgKyAnXCI+JyArXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiZmMtdGl0bGVcIj4nICtcbiAgICAgICAgICAgICAgICBodG1sRXNjYXBlKHRpdGxlKSArXG4gICAgICAgICAgICAgICAgJzwvc3Bhbj4nICtcbiAgICAgICAgICAgICAgICAnPHNwYW4gY2xhc3M9XCJmYy1jbG9zZSAnICsgdGhlbWUuZ2V0SWNvbkNsYXNzKCdjbG9zZScpICsgJ1wiPjwvc3Bhbj4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1ib2R5ICcgKyB0aGVtZS5nZXRDbGFzcygncG9wb3ZlckNvbnRlbnQnKSArICdcIj4nICtcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLWV2ZW50LWNvbnRhaW5lclwiPjwvZGl2PicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICB0aGlzLnNlZ0NvbnRhaW5lckVsID0gdGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZmMtZXZlbnQtY29udGFpbmVyJyk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5xdWVyeUhpdCA9IGZ1bmN0aW9uIChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wLCBlbFdpZHRoLCBlbEhlaWdodCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMucHJvcHMuZGF0ZTsgLy8gSEFDS1xuICAgICAgICBpZiAocG9zaXRpb25MZWZ0IDwgZWxXaWR0aCAmJiBwb3NpdGlvblRvcCA8IGVsSGVpZ2h0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudDogdGhpcyxcbiAgICAgICAgICAgICAgICBkYXRlU3Bhbjoge1xuICAgICAgICAgICAgICAgICAgICBhbGxEYXk6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHJhbmdlOiB7IHN0YXJ0OiBkYXRlLCBlbmQ6IGFkZERheXMoZGF0ZSwgMSkgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGF5RWw6IHRoaXMuZWwsXG4gICAgICAgICAgICAgICAgcmVjdDoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBlbFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IGVsSGVpZ2h0XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsYXllcjogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERheVRpbGU7XG59KERhdGVDb21wb25lbnQpKTtcbnZhciBEYXlUaWxlRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5VGlsZUV2ZW50UmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5VGlsZUV2ZW50UmVuZGVyZXIoZGF5VGlsZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5kYXlUaWxlID0gZGF5VGlsZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlUaWxlRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuYXR0YWNoU2VncyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18xID0gc2VnczsgX2kgPCBzZWdzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18xW19pXTtcbiAgICAgICAgICAgIHRoaXMuZGF5VGlsZS5zZWdDb250YWluZXJFbC5hcHBlbmRDaGlsZChzZWcuZWwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXlUaWxlRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZGV0YWNoU2VncyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18yID0gc2VnczsgX2kgPCBzZWdzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18yW19pXTtcbiAgICAgICAgICAgIHJlbW92ZUVsZW1lbnQoc2VnLmVsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERheVRpbGVFdmVudFJlbmRlcmVyO1xufShTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlcikpO1xuXG52YXIgRGF5QmdSb3cgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRGF5QmdSb3coY29udGV4dCkge1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgIH1cbiAgICBEYXlCZ1Jvdy5wcm90b3R5cGUucmVuZGVySHRtbCA9IGZ1bmN0aW9uIChwcm9wcykge1xuICAgICAgICB2YXIgcGFydHMgPSBbXTtcbiAgICAgICAgaWYgKHByb3BzLnJlbmRlckludHJvSHRtbCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChwcm9wcy5yZW5kZXJJbnRyb0h0bWwoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHByb3BzLmNlbGxzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGNlbGwgPSBfYVtfaV07XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHJlbmRlckNlbGxIdG1sKGNlbGwuZGF0ZSwgcHJvcHMuZGF0ZVByb2ZpbGUsIHRoaXMuY29udGV4dCwgY2VsbC5odG1sQXR0cnMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXByb3BzLmNlbGxzLmxlbmd0aCkge1xuICAgICAgICAgICAgcGFydHMucHVzaCgnPHRkIGNsYXNzPVwiZmMtZGF5ICcgKyB0aGlzLmNvbnRleHQudGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSArICdcIj48L3RkPicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbnRleHQub3B0aW9ucy5kaXIgPT09ICdydGwnKSB7XG4gICAgICAgICAgICBwYXJ0cy5yZXZlcnNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICc8dHI+JyArIHBhcnRzLmpvaW4oJycpICsgJzwvdHI+JztcbiAgICB9O1xuICAgIHJldHVybiBEYXlCZ1Jvdztcbn0oKSk7XG5mdW5jdGlvbiByZW5kZXJDZWxsSHRtbChkYXRlLCBkYXRlUHJvZmlsZSwgY29udGV4dCwgb3RoZXJBdHRycykge1xuICAgIHZhciBkYXRlRW52ID0gY29udGV4dC5kYXRlRW52LCB0aGVtZSA9IGNvbnRleHQudGhlbWU7XG4gICAgdmFyIGlzRGF0ZVZhbGlkID0gcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgZGF0ZSk7IC8vIFRPRE86IGNhbGxlZCB0b28gZnJlcXVlbnRseS4gY2FjaGUgc29tZWhvdy5cbiAgICB2YXIgY2xhc3NlcyA9IGdldERheUNsYXNzZXMoZGF0ZSwgZGF0ZVByb2ZpbGUsIGNvbnRleHQpO1xuICAgIGNsYXNzZXMudW5zaGlmdCgnZmMtZGF5JywgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSk7XG4gICAgcmV0dXJuICc8dGQgY2xhc3M9XCInICsgY2xhc3Nlcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgKGlzRGF0ZVZhbGlkID9cbiAgICAgICAgICAgICcgZGF0YS1kYXRlPVwiJyArIGRhdGVFbnYuZm9ybWF0SXNvKGRhdGUsIHsgb21pdFRpbWU6IHRydWUgfSkgKyAnXCInIDpcbiAgICAgICAgICAgICcnKSArXG4gICAgICAgIChvdGhlckF0dHJzID9cbiAgICAgICAgICAgICcgJyArIG90aGVyQXR0cnMgOlxuICAgICAgICAgICAgJycpICtcbiAgICAgICAgJz48L3RkPic7XG59XG5cbnZhciBEQVlfTlVNX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7IGRheTogJ251bWVyaWMnIH0pO1xudmFyIFdFRUtfTlVNX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7IHdlZWs6ICdudW1lcmljJyB9KTtcbnZhciBEYXlHcmlkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUdyaWQoZWwsIHJlbmRlclByb3BzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGVsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5ib3R0b21Db29yZFBhZGRpbmcgPSAwOyAvLyBoYWNrIGZvciBleHRlbmRpbmcgdGhlIGhpdCBhcmVhIGZvciB0aGUgbGFzdCByb3cgb2YgdGhlIGNvb3JkaW5hdGUgZ3JpZFxuICAgICAgICBfdGhpcy5pc0NlbGxTaXplc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnJlbmRlclByb3BzID0gcmVuZGVyUHJvcHM7XG4gICAgICAgIHZhciBldmVudFJlbmRlcmVyID0gX3RoaXMuZXZlbnRSZW5kZXJlciA9IG5ldyBEYXlHcmlkRXZlbnRSZW5kZXJlcihfdGhpcyk7XG4gICAgICAgIHZhciBmaWxsUmVuZGVyZXIgPSBfdGhpcy5maWxsUmVuZGVyZXIgPSBuZXcgRGF5R3JpZEZpbGxSZW5kZXJlcihfdGhpcyk7XG4gICAgICAgIF90aGlzLm1pcnJvclJlbmRlcmVyID0gbmV3IERheUdyaWRNaXJyb3JSZW5kZXJlcihfdGhpcyk7XG4gICAgICAgIHZhciByZW5kZXJDZWxscyA9IF90aGlzLnJlbmRlckNlbGxzID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyQ2VsbHMsIF90aGlzLl91bnJlbmRlckNlbGxzKTtcbiAgICAgICAgX3RoaXMucmVuZGVyQnVzaW5lc3NIb3VycyA9IG1lbW9pemVSZW5kZXJpbmcoZmlsbFJlbmRlcmVyLnJlbmRlclNlZ3MuYmluZChmaWxsUmVuZGVyZXIsICdidXNpbmVzc0hvdXJzJyksIGZpbGxSZW5kZXJlci51bnJlbmRlci5iaW5kKGZpbGxSZW5kZXJlciwgJ2J1c2luZXNzSG91cnMnKSwgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckRhdGVTZWxlY3Rpb24gPSBtZW1vaXplUmVuZGVyaW5nKGZpbGxSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZmlsbFJlbmRlcmVyLCAnaGlnaGxpZ2h0JyksIGZpbGxSZW5kZXJlci51bnJlbmRlci5iaW5kKGZpbGxSZW5kZXJlciwgJ2hpZ2hsaWdodCcpLCBbcmVuZGVyQ2VsbHNdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyQmdFdmVudHMgPSBtZW1vaXplUmVuZGVyaW5nKGZpbGxSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZmlsbFJlbmRlcmVyLCAnYmdFdmVudCcpLCBmaWxsUmVuZGVyZXIudW5yZW5kZXIuYmluZChmaWxsUmVuZGVyZXIsICdiZ0V2ZW50JyksIFtyZW5kZXJDZWxsc10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJGZ0V2ZW50cyA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZXZlbnRSZW5kZXJlciksIGV2ZW50UmVuZGVyZXIudW5yZW5kZXIuYmluZChldmVudFJlbmRlcmVyKSwgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uID0gbWVtb2l6ZVJlbmRlcmluZyhldmVudFJlbmRlcmVyLnNlbGVjdEJ5SW5zdGFuY2VJZC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBldmVudFJlbmRlcmVyLnVuc2VsZWN0QnlJbnN0YW5jZUlkLmJpbmQoZXZlbnRSZW5kZXJlciksIFtfdGhpcy5yZW5kZXJGZ0V2ZW50c10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudERyYWcgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLl9yZW5kZXJFdmVudERyYWcsIF90aGlzLl91bnJlbmRlckV2ZW50RHJhZywgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50UmVzaXplID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyRXZlbnRSZXNpemUsIF90aGlzLl91bnJlbmRlckV2ZW50UmVzaXplLCBbcmVuZGVyQ2VsbHNdKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGNlbGxzID0gcHJvcHMuY2VsbHM7XG4gICAgICAgIHRoaXMucm93Q250ID0gY2VsbHMubGVuZ3RoO1xuICAgICAgICB0aGlzLmNvbENudCA9IGNlbGxzWzBdLmxlbmd0aDtcbiAgICAgICAgdGhpcy5yZW5kZXJDZWxscyhjZWxscywgcHJvcHMuaXNSaWdpZCk7XG4gICAgICAgIHRoaXMucmVuZGVyQnVzaW5lc3NIb3Vycyhjb250ZXh0LCBwcm9wcy5idXNpbmVzc0hvdXJTZWdzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uKGNvbnRleHQsIHByb3BzLmRhdGVTZWxlY3Rpb25TZWdzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJCZ0V2ZW50cyhjb250ZXh0LCBwcm9wcy5iZ0V2ZW50U2Vncyk7XG4gICAgICAgIHRoaXMucmVuZGVyRmdFdmVudHMoY29udGV4dCwgcHJvcHMuZmdFdmVudFNlZ3MpO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uKHByb3BzLmV2ZW50U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudERyYWcocHJvcHMuZXZlbnREcmFnKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZShwcm9wcy5ldmVudFJlc2l6ZSk7XG4gICAgICAgIGlmICh0aGlzLnNlZ1BvcG92ZXJUaWxlKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNlZ1BvcG92ZXJUaWxlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLnJlbmRlckNlbGxzLnVucmVuZGVyKCk7IC8vIHdpbGwgdW5yZW5kZXIgZXZlcnl0aGluZyBlbHNlXG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRDZWxsUmFuZ2UgPSBmdW5jdGlvbiAocm93LCBjb2wpIHtcbiAgICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5wcm9wcy5jZWxsc1tyb3ddW2NvbF0uZGF0ZTtcbiAgICAgICAgdmFyIGVuZCA9IGFkZERheXMoc3RhcnQsIDEpO1xuICAgICAgICByZXR1cm4geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS51cGRhdGVTZWdQb3BvdmVyVGlsZSA9IGZ1bmN0aW9uIChkYXRlLCBzZWdzKSB7XG4gICAgICAgIHZhciBvd25Qcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICAgIHRoaXMuc2VnUG9wb3ZlclRpbGUucmVjZWl2ZVByb3BzKHtcbiAgICAgICAgICAgIGRhdGU6IGRhdGUgfHwgdGhpcy5zZWdQb3BvdmVyVGlsZS5wcm9wcy5kYXRlLFxuICAgICAgICAgICAgZmdTZWdzOiBzZWdzIHx8IHRoaXMuc2VnUG9wb3ZlclRpbGUucHJvcHMuZmdTZWdzLFxuICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246IG93blByb3BzLmV2ZW50U2VsZWN0aW9uLFxuICAgICAgICAgICAgZXZlbnREcmFnSW5zdGFuY2VzOiBvd25Qcm9wcy5ldmVudERyYWcgPyBvd25Qcm9wcy5ldmVudERyYWcuYWZmZWN0ZWRJbnN0YW5jZXMgOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRSZXNpemVJbnN0YW5jZXM6IG93blByb3BzLmV2ZW50UmVzaXplID8gb3duUHJvcHMuZXZlbnRSZXNpemUuYWZmZWN0ZWRJbnN0YW5jZXMgOiBudWxsXG4gICAgICAgIH0sIHRoaXMuY29udGV4dCk7XG4gICAgfTtcbiAgICAvKiBEYXRlIFJlbmRlcmluZ1xuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3JlbmRlckNlbGxzID0gZnVuY3Rpb24gKGNlbGxzLCBpc1JpZ2lkKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29udGV4dCwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhciwgdmlldyA9IF9hLnZpZXcsIGlzUnRsID0gX2EuaXNSdGwsIGRhdGVFbnYgPSBfYS5kYXRlRW52O1xuICAgICAgICB2YXIgX2IgPSB0aGlzLCByb3dDbnQgPSBfYi5yb3dDbnQsIGNvbENudCA9IF9iLmNvbENudDtcbiAgICAgICAgdmFyIGh0bWwgPSAnJztcbiAgICAgICAgdmFyIHJvdztcbiAgICAgICAgdmFyIGNvbDtcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCByb3dDbnQ7IHJvdysrKSB7XG4gICAgICAgICAgICBodG1sICs9IHRoaXMucmVuZGVyRGF5Um93SHRtbChyb3csIGlzUmlnaWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gaHRtbDtcbiAgICAgICAgdGhpcy5yb3dFbHMgPSBmaW5kRWxlbWVudHModGhpcy5lbCwgJy5mYy1yb3cnKTtcbiAgICAgICAgdGhpcy5jZWxsRWxzID0gZmluZEVsZW1lbnRzKHRoaXMuZWwsICcuZmMtZGF5LCAuZmMtZGlzYWJsZWQtZGF5Jyk7XG4gICAgICAgIGlmIChpc1J0bCkge1xuICAgICAgICAgICAgdGhpcy5jZWxsRWxzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd1Bvc2l0aW9ucyA9IG5ldyBQb3NpdGlvbkNhY2hlKHRoaXMuZWwsIHRoaXMucm93RWxzLCBmYWxzZSwgdHJ1ZSAvLyB2ZXJ0aWNhbFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmNvbFBvc2l0aW9ucyA9IG5ldyBQb3NpdGlvbkNhY2hlKHRoaXMuZWwsIHRoaXMuY2VsbEVscy5zbGljZSgwLCBjb2xDbnQpLCAvLyBvbmx5IHRoZSBmaXJzdCByb3dcbiAgICAgICAgdHJ1ZSwgZmFsc2UgLy8gaG9yaXpvbnRhbFxuICAgICAgICApO1xuICAgICAgICAvLyB0cmlnZ2VyIGRheVJlbmRlciB3aXRoIGVhY2ggY2VsbCdzIGVsZW1lbnRcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCByb3dDbnQ7IHJvdysrKSB7XG4gICAgICAgICAgICBmb3IgKGNvbCA9IDA7IGNvbCA8IGNvbENudDsgY29sKyspIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2RheVJlbmRlcicsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZTogZGF0ZUVudi50b0RhdGUoY2VsbHNbcm93XVtjb2xdLmRhdGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IHRoaXMuZ2V0Q2VsbEVsKHJvdywgY29sKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXNDZWxsU2l6ZXNEaXJ0eSA9IHRydWU7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5fdW5yZW5kZXJDZWxscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVTZWdQb3BvdmVyKCk7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgZm9yIGEgc2luZ2xlIHJvdywgd2hpY2ggaXMgYSBkaXYgdGhhdCB3cmFwcyBhIHRhYmxlLlxuICAgIC8vIGByb3dgIGlzIHRoZSByb3cgbnVtYmVyLlxuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlckRheVJvd0h0bWwgPSBmdW5jdGlvbiAocm93LCBpc1JpZ2lkKSB7XG4gICAgICAgIHZhciB0aGVtZSA9IHRoaXMuY29udGV4dC50aGVtZTtcbiAgICAgICAgdmFyIGNsYXNzZXMgPSBbJ2ZjLXJvdycsICdmYy13ZWVrJywgdGhlbWUuZ2V0Q2xhc3MoJ2RheVJvdycpXTtcbiAgICAgICAgaWYgKGlzUmlnaWQpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtcmlnaWQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYmdSb3cgPSBuZXcgRGF5QmdSb3codGhpcy5jb250ZXh0KTtcbiAgICAgICAgcmV0dXJuICcnICtcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiJyArIGNsYXNzZXMuam9pbignICcpICsgJ1wiPicgK1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1iZ1wiPicgK1xuICAgICAgICAgICAgJzx0YWJsZSBjbGFzcz1cIicgKyB0aGVtZS5nZXRDbGFzcygndGFibGVHcmlkJykgKyAnXCI+JyArXG4gICAgICAgICAgICBiZ1Jvdy5yZW5kZXJIdG1sKHtcbiAgICAgICAgICAgICAgICBjZWxsczogdGhpcy5wcm9wcy5jZWxsc1tyb3ddLFxuICAgICAgICAgICAgICAgIGRhdGVQcm9maWxlOiB0aGlzLnByb3BzLmRhdGVQcm9maWxlLFxuICAgICAgICAgICAgICAgIHJlbmRlckludHJvSHRtbDogdGhpcy5yZW5kZXJQcm9wcy5yZW5kZXJCZ0ludHJvSHRtbFxuICAgICAgICAgICAgfSkgK1xuICAgICAgICAgICAgJzwvdGFibGU+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLWNvbnRlbnQtc2tlbGV0b25cIj4nICtcbiAgICAgICAgICAgICc8dGFibGU+JyArXG4gICAgICAgICAgICAodGhpcy5nZXRJc051bWJlcnNWaXNpYmxlKCkgP1xuICAgICAgICAgICAgICAgICc8dGhlYWQ+JyArXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyTnVtYmVyVHJIdG1sKHJvdykgK1xuICAgICAgICAgICAgICAgICAgICAnPC90aGVhZD4nIDpcbiAgICAgICAgICAgICAgICAnJykgK1xuICAgICAgICAgICAgJzwvdGFibGU+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JztcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmdldElzTnVtYmVyc1Zpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldElzRGF5TnVtYmVyc1Zpc2libGUoKSB8fFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJQcm9wcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlIHx8XG4gICAgICAgICAgICB0aGlzLnJlbmRlclByb3BzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZTtcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmdldElzRGF5TnVtYmVyc1Zpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd0NudCA+IDE7XG4gICAgfTtcbiAgICAvKiBHcmlkIE51bWJlciBSZW5kZXJpbmdcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlck51bWJlclRySHRtbCA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5jb250ZXh0LmlzUnRsO1xuICAgICAgICB2YXIgaW50cm8gPSB0aGlzLnJlbmRlclByb3BzLnJlbmRlck51bWJlckludHJvSHRtbChyb3csIHRoaXMpO1xuICAgICAgICByZXR1cm4gJycgK1xuICAgICAgICAgICAgJzx0cj4nICtcbiAgICAgICAgICAgIChpc1J0bCA/ICcnIDogaW50cm8pICtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyTnVtYmVyQ2VsbHNIdG1sKHJvdykgK1xuICAgICAgICAgICAgKGlzUnRsID8gaW50cm8gOiAnJykgK1xuICAgICAgICAgICAgJzwvdHI+JztcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlck51bWJlckNlbGxzSHRtbCA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGh0bWxzID0gW107XG4gICAgICAgIHZhciBjb2w7XG4gICAgICAgIHZhciBkYXRlO1xuICAgICAgICBmb3IgKGNvbCA9IDA7IGNvbCA8IHRoaXMuY29sQ250OyBjb2wrKykge1xuICAgICAgICAgICAgZGF0ZSA9IHRoaXMucHJvcHMuY2VsbHNbcm93XVtjb2xdLmRhdGU7XG4gICAgICAgICAgICBodG1scy5wdXNoKHRoaXMucmVuZGVyTnVtYmVyQ2VsbEh0bWwoZGF0ZSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbnRleHQuaXNSdGwpIHtcbiAgICAgICAgICAgIGh0bWxzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaHRtbHMuam9pbignJyk7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgZm9yIHRoZSA8dGQ+cyBvZiB0aGUgXCJudW1iZXJcIiByb3cgaW4gdGhlIERheUdyaWQncyBjb250ZW50IHNrZWxldG9uLlxuICAgIC8vIFRoZSBudW1iZXIgcm93IHdpbGwgb25seSBleGlzdCBpZiBlaXRoZXIgZGF5IG51bWJlcnMgb3Igd2VlayBudW1iZXJzIGFyZSB0dXJuZWQgb24uXG4gICAgRGF5R3JpZC5wcm90b3R5cGUucmVuZGVyTnVtYmVyQ2VsbEh0bWwgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGRhdGVFbnYgPSBfYS5kYXRlRW52LCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIGh0bWwgPSAnJztcbiAgICAgICAgdmFyIGlzRGF0ZVZhbGlkID0gcmFuZ2VDb250YWluc01hcmtlcih0aGlzLnByb3BzLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBkYXRlKTsgLy8gVE9ETzogY2FsbGVkIHRvbyBmcmVxdWVudGx5LiBjYWNoZSBzb21laG93LlxuICAgICAgICB2YXIgaXNEYXlOdW1iZXJWaXNpYmxlID0gdGhpcy5nZXRJc0RheU51bWJlcnNWaXNpYmxlKCkgJiYgaXNEYXRlVmFsaWQ7XG4gICAgICAgIHZhciBjbGFzc2VzO1xuICAgICAgICB2YXIgd2Vla0NhbGNGaXJzdERvdztcbiAgICAgICAgaWYgKCFpc0RheU51bWJlclZpc2libGUgJiYgIXRoaXMucmVuZGVyUHJvcHMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSkge1xuICAgICAgICAgICAgLy8gbm8gbnVtYmVycyBpbiBkYXkgY2VsbCAod2VlayBudW1iZXIgbXVzdCBiZSBhbG9uZyB0aGUgc2lkZSlcbiAgICAgICAgICAgIHJldHVybiAnPHRkPjwvdGQ+JzsgLy8gIHdpbGwgY3JlYXRlIGFuIGVtcHR5IHNwYWNlIGFib3ZlIGV2ZW50cyA6KFxuICAgICAgICB9XG4gICAgICAgIGNsYXNzZXMgPSBnZXREYXlDbGFzc2VzKGRhdGUsIHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUsIHRoaXMuY29udGV4dCk7XG4gICAgICAgIGNsYXNzZXMudW5zaGlmdCgnZmMtZGF5LXRvcCcpO1xuICAgICAgICBpZiAodGhpcy5yZW5kZXJQcm9wcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICB3ZWVrQ2FsY0ZpcnN0RG93ID0gZGF0ZUVudi53ZWVrRG93O1xuICAgICAgICB9XG4gICAgICAgIGh0bWwgKz0gJzx0ZCBjbGFzcz1cIicgKyBjbGFzc2VzLmpvaW4oJyAnKSArICdcIicgK1xuICAgICAgICAgICAgKGlzRGF0ZVZhbGlkID9cbiAgICAgICAgICAgICAgICAnIGRhdGEtZGF0ZT1cIicgKyBkYXRlRW52LmZvcm1hdElzbyhkYXRlLCB7IG9taXRUaW1lOiB0cnVlIH0pICsgJ1wiJyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgICc+JztcbiAgICAgICAgaWYgKHRoaXMucmVuZGVyUHJvcHMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSAmJiAoZGF0ZS5nZXRVVENEYXkoKSA9PT0gd2Vla0NhbGNGaXJzdERvdykpIHtcbiAgICAgICAgICAgIGh0bWwgKz0gYnVpbGRHb3RvQW5jaG9ySHRtbChvcHRpb25zLCBkYXRlRW52LCB7IGRhdGU6IGRhdGUsIHR5cGU6ICd3ZWVrJyB9LCB7ICdjbGFzcyc6ICdmYy13ZWVrLW51bWJlcicgfSwgZGF0ZUVudi5mb3JtYXQoZGF0ZSwgV0VFS19OVU1fRk9STUFUKSAvLyBpbm5lciBIVE1MXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0RheU51bWJlclZpc2libGUpIHtcbiAgICAgICAgICAgIGh0bWwgKz0gYnVpbGRHb3RvQW5jaG9ySHRtbChvcHRpb25zLCBkYXRlRW52LCBkYXRlLCB7ICdjbGFzcyc6ICdmYy1kYXktbnVtYmVyJyB9LCBkYXRlRW52LmZvcm1hdChkYXRlLCBEQVlfTlVNX0ZPUk1BVCkgLy8gaW5uZXIgSFRNTFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBodG1sICs9ICc8L3RkPic7XG4gICAgICAgIHJldHVybiBodG1sO1xuICAgIH07XG4gICAgLyogU2l6aW5nXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBEYXlHcmlkLnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKGlzUmVzaXplKSB7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXMuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgZmlsbFJlbmRlcmVyID0gX2EuZmlsbFJlbmRlcmVyLCBldmVudFJlbmRlcmVyID0gX2EuZXZlbnRSZW5kZXJlciwgbWlycm9yUmVuZGVyZXIgPSBfYS5taXJyb3JSZW5kZXJlcjtcbiAgICAgICAgaWYgKGlzUmVzaXplIHx8XG4gICAgICAgICAgICB0aGlzLmlzQ2VsbFNpemVzRGlydHkgfHxcbiAgICAgICAgICAgIGNhbGVuZGFyLmlzRXZlbnRzVXBkYXRlZCAvLyBoYWNrXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5idWlsZFBvc2l0aW9uQ2FjaGVzKCk7XG4gICAgICAgICAgICB0aGlzLmlzQ2VsbFNpemVzRGlydHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmaWxsUmVuZGVyZXIuY29tcHV0ZVNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgZXZlbnRSZW5kZXJlci5jb21wdXRlU2l6ZXMoaXNSZXNpemUpO1xuICAgICAgICBtaXJyb3JSZW5kZXJlci5jb21wdXRlU2l6ZXMoaXNSZXNpemUpO1xuICAgICAgICBmaWxsUmVuZGVyZXIuYXNzaWduU2l6ZXMoaXNSZXNpemUpO1xuICAgICAgICBldmVudFJlbmRlcmVyLmFzc2lnblNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgbWlycm9yUmVuZGVyZXIuYXNzaWduU2l6ZXMoaXNSZXNpemUpO1xuICAgIH07XG4gICAgRGF5R3JpZC5wcm90b3R5cGUuYnVpbGRQb3NpdGlvbkNhY2hlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5idWlsZENvbFBvc2l0aW9ucygpO1xuICAgICAgICB0aGlzLmJ1aWxkUm93UG9zaXRpb25zKCk7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5idWlsZENvbFBvc2l0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb2xQb3NpdGlvbnMuYnVpbGQoKTtcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmJ1aWxkUm93UG9zaXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJvd1Bvc2l0aW9ucy5idWlsZCgpO1xuICAgICAgICB0aGlzLnJvd1Bvc2l0aW9ucy5ib3R0b21zW3RoaXMucm93Q250IC0gMV0gKz0gdGhpcy5ib3R0b21Db29yZFBhZGRpbmc7IC8vIGhhY2tcbiAgICB9O1xuICAgIC8qIEhpdCBTeXN0ZW1cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLnBvc2l0aW9uVG9IaXQgPSBmdW5jdGlvbiAobGVmdFBvc2l0aW9uLCB0b3BQb3NpdGlvbikge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBjb2xQb3NpdGlvbnMgPSBfYS5jb2xQb3NpdGlvbnMsIHJvd1Bvc2l0aW9ucyA9IF9hLnJvd1Bvc2l0aW9ucztcbiAgICAgICAgdmFyIGNvbCA9IGNvbFBvc2l0aW9ucy5sZWZ0VG9JbmRleChsZWZ0UG9zaXRpb24pO1xuICAgICAgICB2YXIgcm93ID0gcm93UG9zaXRpb25zLnRvcFRvSW5kZXgodG9wUG9zaXRpb24pO1xuICAgICAgICBpZiAocm93ICE9IG51bGwgJiYgY29sICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICAgICAgY29sOiBjb2wsXG4gICAgICAgICAgICAgICAgZGF0ZVNwYW46IHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IHRoaXMuZ2V0Q2VsbFJhbmdlKHJvdywgY29sKSxcbiAgICAgICAgICAgICAgICAgICAgYWxsRGF5OiB0cnVlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkYXlFbDogdGhpcy5nZXRDZWxsRWwocm93LCBjb2wpLFxuICAgICAgICAgICAgICAgIHJlbGF0aXZlUmVjdDoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiBjb2xQb3NpdGlvbnMubGVmdHNbY29sXSxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGNvbFBvc2l0aW9ucy5yaWdodHNbY29sXSxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiByb3dQb3NpdGlvbnMudG9wc1tyb3ddLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IHJvd1Bvc2l0aW9ucy5ib3R0b21zW3Jvd11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiBDZWxsIFN5c3RlbVxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgLy8gRllJOiB0aGUgZmlyc3QgY29sdW1uIGlzIHRoZSBsZWZ0bW9zdCBjb2x1bW4sIHJlZ2FyZGxlc3Mgb2YgZGF0ZVxuICAgIERheUdyaWQucHJvdG90eXBlLmdldENlbGxFbCA9IGZ1bmN0aW9uIChyb3csIGNvbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZWxsRWxzW3JvdyAqIHRoaXMuY29sQ250ICsgY29sXTtcbiAgICB9O1xuICAgIC8qIEV2ZW50IERyYWcgVmlzdWFsaXphdGlvblxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3JlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlci5oaWRlQnlIYXNoKHN0YXRlLmFmZmVjdGVkSW5zdGFuY2VzKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbFJlbmRlcmVyLnJlbmRlclNlZ3MoJ2hpZ2hsaWdodCcsIHRoaXMuY29udGV4dCwgc3RhdGUuc2Vncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLl91bnJlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlci5zaG93QnlIYXNoKHN0YXRlLmFmZmVjdGVkSW5zdGFuY2VzKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbFJlbmRlcmVyLnVucmVuZGVyKCdoaWdobGlnaHQnLCB0aGlzLmNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiBFdmVudCBSZXNpemUgVmlzdWFsaXphdGlvblxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3JlbmRlckV2ZW50UmVzaXplID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFJlbmRlcmVyLmhpZGVCeUhhc2goc3RhdGUuYWZmZWN0ZWRJbnN0YW5jZXMpO1xuICAgICAgICAgICAgdGhpcy5maWxsUmVuZGVyZXIucmVuZGVyU2VncygnaGlnaGxpZ2h0JywgdGhpcy5jb250ZXh0LCBzdGF0ZS5zZWdzKTtcbiAgICAgICAgICAgIHRoaXMubWlycm9yUmVuZGVyZXIucmVuZGVyU2Vncyh0aGlzLmNvbnRleHQsIHN0YXRlLnNlZ3MsIHsgaXNSZXNpemluZzogdHJ1ZSwgc291cmNlU2VnOiBzdGF0ZS5zb3VyY2VTZWcgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLl91bnJlbmRlckV2ZW50UmVzaXplID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFJlbmRlcmVyLnNob3dCeUhhc2goc3RhdGUuYWZmZWN0ZWRJbnN0YW5jZXMpO1xuICAgICAgICAgICAgdGhpcy5maWxsUmVuZGVyZXIudW5yZW5kZXIoJ2hpZ2hsaWdodCcsIHRoaXMuY29udGV4dCk7XG4gICAgICAgICAgICB0aGlzLm1pcnJvclJlbmRlcmVyLnVucmVuZGVyKHRoaXMuY29udGV4dCwgc3RhdGUuc2VncywgeyBpc1Jlc2l6aW5nOiB0cnVlLCBzb3VyY2VTZWc6IHN0YXRlLnNvdXJjZVNlZyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyogTW9yZSsgTGluayBQb3BvdmVyXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW1vdmVTZWdQb3BvdmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zZWdQb3BvdmVyKSB7XG4gICAgICAgICAgICB0aGlzLnNlZ1BvcG92ZXIuaGlkZSgpOyAvLyBpbiBoYW5kbGVyLCB3aWxsIGNhbGwgc2VnUG9wb3ZlcidzIHJlbW92ZUVsZW1lbnRcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gTGltaXRzIHRoZSBudW1iZXIgb2YgXCJsZXZlbHNcIiAodmVydGljYWxseSBzdGFja2luZyBsYXllcnMgb2YgZXZlbnRzKSBmb3IgZWFjaCByb3cgb2YgdGhlIGdyaWQuXG4gICAgLy8gYGxldmVsTGltaXRgIGNhbiBiZSBmYWxzZSAoZG9uJ3QgbGltaXQpLCBhIG51bWJlciwgb3IgdHJ1ZSAoc2hvdWxkIGJlIGNvbXB1dGVkKS5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5saW1pdFJvd3MgPSBmdW5jdGlvbiAobGV2ZWxMaW1pdCkge1xuICAgICAgICB2YXIgcm93U3RydWN0cyA9IHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzIHx8IFtdO1xuICAgICAgICB2YXIgcm93OyAvLyByb3cgI1xuICAgICAgICB2YXIgcm93TGV2ZWxMaW1pdDtcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCByb3dTdHJ1Y3RzLmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgIHRoaXMudW5saW1pdFJvdyhyb3cpO1xuICAgICAgICAgICAgaWYgKCFsZXZlbExpbWl0KSB7XG4gICAgICAgICAgICAgICAgcm93TGV2ZWxMaW1pdCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGxldmVsTGltaXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgcm93TGV2ZWxMaW1pdCA9IGxldmVsTGltaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByb3dMZXZlbExpbWl0ID0gdGhpcy5jb21wdXRlUm93TGV2ZWxMaW1pdChyb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJvd0xldmVsTGltaXQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saW1pdFJvdyhyb3csIHJvd0xldmVsTGltaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBDb21wdXRlcyB0aGUgbnVtYmVyIG9mIGxldmVscyBhIHJvdyB3aWxsIGFjY29tb2RhdGUgd2l0aG91dCBnb2luZyBvdXRzaWRlIGl0cyBib3VuZHMuXG4gICAgLy8gQXNzdW1lcyB0aGUgcm93IGlzIFwicmlnaWRcIiAobWFpbnRhaW5zIGEgY29uc3RhbnQgaGVpZ2h0IHJlZ2FyZGxlc3Mgb2Ygd2hhdCBpcyBpbnNpZGUpLlxuICAgIC8vIGByb3dgIGlzIHRoZSByb3cgbnVtYmVyLlxuICAgIERheUdyaWQucHJvdG90eXBlLmNvbXB1dGVSb3dMZXZlbExpbWl0ID0gZnVuY3Rpb24gKHJvdykge1xuICAgICAgICB2YXIgcm93RWwgPSB0aGlzLnJvd0Vsc1tyb3ddOyAvLyB0aGUgY29udGFpbmluZyBcImZha2VcIiByb3cgZGl2XG4gICAgICAgIHZhciByb3dCb3R0b20gPSByb3dFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5ib3R0b207IC8vIHJlbGF0aXZlIHRvIHZpZXdwb3J0IVxuICAgICAgICB2YXIgdHJFbHMgPSBmaW5kQ2hpbGRyZW4odGhpcy5ldmVudFJlbmRlcmVyLnJvd1N0cnVjdHNbcm93XS50Ym9keUVsKTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB0ckVsO1xuICAgICAgICAvLyBSZXZlYWwgb25lIGxldmVsIDx0cj4gYXQgYSB0aW1lIGFuZCBzdG9wIHdoZW4gd2UgZmluZCBvbmUgb3V0IG9mIGJvdW5kc1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdHJFbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyRWwgPSB0ckVsc1tpXTtcbiAgICAgICAgICAgIHRyRWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtbGltaXRlZCcpOyAvLyByZXNldCB0byBvcmlnaW5hbCBzdGF0ZSAocmV2ZWFsKVxuICAgICAgICAgICAgaWYgKHRyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuYm90dG9tID4gcm93Qm90dG9tKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBzaG91bGQgbm90IGxpbWl0IGF0IGFsbFxuICAgIH07XG4gICAgLy8gTGltaXRzIHRoZSBnaXZlbiBncmlkIHJvdyB0byB0aGUgbWF4aW11bSBudW1iZXIgb2YgbGV2ZWxzIGFuZCBpbmplY3RzIFwibW9yZVwiIGxpbmtzIGlmIG5lY2Vzc2FyeS5cbiAgICAvLyBgcm93YCBpcyB0aGUgcm93IG51bWJlci5cbiAgICAvLyBgbGV2ZWxMaW1pdGAgaXMgYSBudW1iZXIgZm9yIHRoZSBtYXhpbXVtIChpbmNsdXNpdmUpIG51bWJlciBvZiBsZXZlbHMgYWxsb3dlZC5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5saW1pdFJvdyA9IGZ1bmN0aW9uIChyb3csIGxldmVsTGltaXQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNvbENudCA9IHRoaXMuY29sQ250O1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciByb3dTdHJ1Y3QgPSB0aGlzLmV2ZW50UmVuZGVyZXIucm93U3RydWN0c1tyb3ddO1xuICAgICAgICB2YXIgbW9yZU5vZGVzID0gW107IC8vIGFycmF5IG9mIFwibW9yZVwiIDxhPiBsaW5rcyBhbmQgPHRkPiBET00gbm9kZXNcbiAgICAgICAgdmFyIGNvbCA9IDA7IC8vIGNvbCAjLCBsZWZ0LXRvLXJpZ2h0IChub3QgY2hyb25vbG9naWNhbGx5KVxuICAgICAgICB2YXIgbGV2ZWxTZWdzOyAvLyBhcnJheSBvZiBzZWdtZW50IG9iamVjdHMgaW4gdGhlIGxhc3QgYWxsb3dhYmxlIGxldmVsLCBvcmRlcmVkIGxlZnQtdG8tcmlnaHRcbiAgICAgICAgdmFyIGNlbGxNYXRyaXg7IC8vIGEgbWF0cml4IChieSBsZXZlbCwgdGhlbiBjb2x1bW4pIG9mIGFsbCA8dGQ+IGVsZW1lbnRzIGluIHRoZSByb3dcbiAgICAgICAgdmFyIGxpbWl0ZWROb2RlczsgLy8gYXJyYXkgb2YgdGVtcG9yYXJpbHkgaGlkZGVuIGxldmVsIDx0cj4gYW5kIHNlZ21lbnQgPHRkPiBET00gbm9kZXNcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBzZWc7XG4gICAgICAgIHZhciBzZWdzQmVsb3c7IC8vIGFycmF5IG9mIHNlZ21lbnQgb2JqZWN0cyBiZWxvdyBgc2VnYCBpbiB0aGUgY3VycmVudCBgY29sYFxuICAgICAgICB2YXIgdG90YWxTZWdzQmVsb3c7IC8vIHRvdGFsIG51bWJlciBvZiBzZWdtZW50cyBiZWxvdyBgc2VnYCBpbiBhbnkgb2YgdGhlIGNvbHVtbnMgYHNlZ2Agb2NjdXBpZXNcbiAgICAgICAgdmFyIGNvbFNlZ3NCZWxvdzsgLy8gYXJyYXkgb2Ygc2VnbWVudCBhcnJheXMsIGJlbG93IHNlZywgb25lIGZvciBlYWNoIGNvbHVtbiAob2Zmc2V0IGZyb20gc2VncydzIGZpcnN0IGNvbHVtbilcbiAgICAgICAgdmFyIHRkO1xuICAgICAgICB2YXIgcm93U3BhbjtcbiAgICAgICAgdmFyIHNlZ01vcmVOb2RlczsgLy8gYXJyYXkgb2YgXCJtb3JlXCIgPHRkPiBjZWxscyB0aGF0IHdpbGwgc3RhbmQtaW4gZm9yIHRoZSBjdXJyZW50IHNlZydzIGNlbGxcbiAgICAgICAgdmFyIGo7XG4gICAgICAgIHZhciBtb3JlVGQ7XG4gICAgICAgIHZhciBtb3JlV3JhcDtcbiAgICAgICAgdmFyIG1vcmVMaW5rO1xuICAgICAgICAvLyBJdGVyYXRlcyB0aHJvdWdoIGVtcHR5IGxldmVsIGNlbGxzIGFuZCBwbGFjZXMgXCJtb3JlXCIgbGlua3MgaW5zaWRlIGlmIG5lZWQgYmVcbiAgICAgICAgdmFyIGVtcHR5Q2VsbHNVbnRpbCA9IGZ1bmN0aW9uIChlbmRDb2wpIHtcbiAgICAgICAgICAgIHdoaWxlIChjb2wgPCBlbmRDb2wpIHtcbiAgICAgICAgICAgICAgICBzZWdzQmVsb3cgPSBfdGhpcy5nZXRDZWxsU2Vncyhyb3csIGNvbCwgbGV2ZWxMaW1pdCk7XG4gICAgICAgICAgICAgICAgaWYgKHNlZ3NCZWxvdy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGQgPSBjZWxsTWF0cml4W2xldmVsTGltaXQgLSAxXVtjb2xdO1xuICAgICAgICAgICAgICAgICAgICBtb3JlTGluayA9IF90aGlzLnJlbmRlck1vcmVMaW5rKHJvdywgY29sLCBzZWdzQmVsb3cpO1xuICAgICAgICAgICAgICAgICAgICBtb3JlV3JhcCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIG51bGwsIG1vcmVMaW5rKTtcbiAgICAgICAgICAgICAgICAgICAgdGQuYXBwZW5kQ2hpbGQobW9yZVdyYXApO1xuICAgICAgICAgICAgICAgICAgICBtb3JlTm9kZXMucHVzaChtb3JlV3JhcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAobGV2ZWxMaW1pdCAmJiBsZXZlbExpbWl0IDwgcm93U3RydWN0LnNlZ0xldmVscy5sZW5ndGgpIHsgLy8gaXMgaXQgYWN0dWFsbHkgb3ZlciB0aGUgbGltaXQ/XG4gICAgICAgICAgICBsZXZlbFNlZ3MgPSByb3dTdHJ1Y3Quc2VnTGV2ZWxzW2xldmVsTGltaXQgLSAxXTtcbiAgICAgICAgICAgIGNlbGxNYXRyaXggPSByb3dTdHJ1Y3QuY2VsbE1hdHJpeDtcbiAgICAgICAgICAgIGxpbWl0ZWROb2RlcyA9IGZpbmRDaGlsZHJlbihyb3dTdHJ1Y3QudGJvZHlFbCkuc2xpY2UobGV2ZWxMaW1pdCk7IC8vIGdldCBsZXZlbCA8dHI+IGVsZW1lbnRzIHBhc3QgdGhlIGxpbWl0XG4gICAgICAgICAgICBsaW1pdGVkTm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgICAgIG5vZGUuY2xhc3NMaXN0LmFkZCgnZmMtbGltaXRlZCcpOyAvLyBoaWRlIGVsZW1lbnRzIGFuZCBnZXQgYSBzaW1wbGUgRE9NLW5vZGVzIGFycmF5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIGl0ZXJhdGUgdGhvdWdoIHNlZ21lbnRzIGluIHRoZSBsYXN0IGFsbG93YWJsZSBsZXZlbFxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxldmVsU2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNlZyA9IGxldmVsU2Vnc1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVmdENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcubGFzdENvbCkgOiBzZWcuZmlyc3RDb2w7XG4gICAgICAgICAgICAgICAgdmFyIHJpZ2h0Q29sID0gaXNSdGwgPyAoY29sQ250IC0gMSAtIHNlZy5maXJzdENvbCkgOiBzZWcubGFzdENvbDtcbiAgICAgICAgICAgICAgICBlbXB0eUNlbGxzVW50aWwobGVmdENvbCk7IC8vIHByb2Nlc3MgZW1wdHkgY2VsbHMgYmVmb3JlIHRoZSBzZWdtZW50XG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lICphbGwqIHNlZ21lbnRzIGJlbG93IGBzZWdgIHRoYXQgb2NjdXB5IHRoZSBzYW1lIGNvbHVtbnNcbiAgICAgICAgICAgICAgICBjb2xTZWdzQmVsb3cgPSBbXTtcbiAgICAgICAgICAgICAgICB0b3RhbFNlZ3NCZWxvdyA9IDA7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGNvbCA8PSByaWdodENvbCkge1xuICAgICAgICAgICAgICAgICAgICBzZWdzQmVsb3cgPSB0aGlzLmdldENlbGxTZWdzKHJvdywgY29sLCBsZXZlbExpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgY29sU2Vnc0JlbG93LnB1c2goc2Vnc0JlbG93KTtcbiAgICAgICAgICAgICAgICAgICAgdG90YWxTZWdzQmVsb3cgKz0gc2Vnc0JlbG93Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0b3RhbFNlZ3NCZWxvdykgeyAvLyBkbyB3ZSBuZWVkIHRvIHJlcGxhY2UgdGhpcyBzZWdtZW50IHdpdGggb25lIG9yIG1hbnkgXCJtb3JlXCIgbGlua3M/XG4gICAgICAgICAgICAgICAgICAgIHRkID0gY2VsbE1hdHJpeFtsZXZlbExpbWl0IC0gMV1bbGVmdENvbF07IC8vIHRoZSBzZWdtZW50J3MgcGFyZW50IGNlbGxcbiAgICAgICAgICAgICAgICAgICAgcm93U3BhbiA9IHRkLnJvd1NwYW4gfHwgMTtcbiAgICAgICAgICAgICAgICAgICAgc2VnTW9yZU5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgIC8vIG1ha2UgYSByZXBsYWNlbWVudCA8dGQ+IGZvciBlYWNoIGNvbHVtbiB0aGUgc2VnbWVudCBvY2N1cGllcy4gd2lsbCBiZSBvbmUgZm9yIGVhY2ggY29sc3BhblxuICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgY29sU2Vnc0JlbG93Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb3JlVGQgPSBjcmVhdGVFbGVtZW50KCd0ZCcsIHsgY2xhc3NOYW1lOiAnZmMtbW9yZS1jZWxsJywgcm93U3Bhbjogcm93U3BhbiB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlZ3NCZWxvdyA9IGNvbFNlZ3NCZWxvd1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vcmVMaW5rID0gdGhpcy5yZW5kZXJNb3JlTGluayhyb3csIGxlZnRDb2wgKyBqLCBbc2VnXS5jb25jYXQoc2Vnc0JlbG93KSAvLyBjb3VudCBzZWcgYXMgaGlkZGVuIHRvb1xuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vcmVXcmFwID0gY3JlYXRlRWxlbWVudCgnZGl2JywgbnVsbCwgbW9yZUxpbmspO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW9yZVRkLmFwcGVuZENoaWxkKG1vcmVXcmFwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlZ01vcmVOb2Rlcy5wdXNoKG1vcmVUZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb3JlTm9kZXMucHVzaChtb3JlVGQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRkLmNsYXNzTGlzdC5hZGQoJ2ZjLWxpbWl0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0QWZ0ZXJFbGVtZW50KHRkLCBzZWdNb3JlTm9kZXMpO1xuICAgICAgICAgICAgICAgICAgICBsaW1pdGVkTm9kZXMucHVzaCh0ZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW1wdHlDZWxsc1VudGlsKHRoaXMuY29sQ250KTsgLy8gZmluaXNoIG9mZiB0aGUgbGV2ZWxcbiAgICAgICAgICAgIHJvd1N0cnVjdC5tb3JlRWxzID0gbW9yZU5vZGVzOyAvLyBmb3IgZWFzeSB1bmRvaW5nIGxhdGVyXG4gICAgICAgICAgICByb3dTdHJ1Y3QubGltaXRlZEVscyA9IGxpbWl0ZWROb2RlczsgLy8gZm9yIGVhc3kgdW5kb2luZyBsYXRlclxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBSZXZlYWxzIGFsbCBsZXZlbHMgYW5kIHJlbW92ZXMgYWxsIFwibW9yZVwiLXJlbGF0ZWQgZWxlbWVudHMgZm9yIGEgZ3JpZCdzIHJvdy5cbiAgICAvLyBgcm93YCBpcyBhIHJvdyBudW1iZXIuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUudW5saW1pdFJvdyA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdCA9IHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzW3Jvd107XG4gICAgICAgIGlmIChyb3dTdHJ1Y3QubW9yZUVscykge1xuICAgICAgICAgICAgcm93U3RydWN0Lm1vcmVFbHMuZm9yRWFjaChyZW1vdmVFbGVtZW50KTtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5tb3JlRWxzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocm93U3RydWN0LmxpbWl0ZWRFbHMpIHtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5saW1pdGVkRWxzLmZvckVhY2goZnVuY3Rpb24gKGxpbWl0ZWRFbCkge1xuICAgICAgICAgICAgICAgIGxpbWl0ZWRFbC5jbGFzc0xpc3QucmVtb3ZlKCdmYy1saW1pdGVkJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5saW1pdGVkRWxzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gUmVuZGVycyBhbiA8YT4gZWxlbWVudCB0aGF0IHJlcHJlc2VudHMgaGlkZGVuIGV2ZW50IGVsZW1lbnQgZm9yIGEgY2VsbC5cbiAgICAvLyBSZXNwb25zaWJsZSBmb3IgYXR0YWNoaW5nIGNsaWNrIGhhbmRsZXIgYXMgd2VsbC5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXJNb3JlTGluayA9IGZ1bmN0aW9uIChyb3csIGNvbCwgaGlkZGVuU2Vncykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3LCBkYXRlRW52ID0gX2EuZGF0ZUVudiwgb3B0aW9ucyA9IF9hLm9wdGlvbnMsIGlzUnRsID0gX2EuaXNSdGw7XG4gICAgICAgIHZhciBhID0gY3JlYXRlRWxlbWVudCgnYScsIHsgY2xhc3NOYW1lOiAnZmMtbW9yZScgfSk7XG4gICAgICAgIGEuaW5uZXJUZXh0ID0gdGhpcy5nZXRNb3JlTGlua1RleHQoaGlkZGVuU2Vncy5sZW5ndGgpO1xuICAgICAgICBhLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgY2xpY2tPcHRpb24gPSBvcHRpb25zLmV2ZW50TGltaXRDbGljaztcbiAgICAgICAgICAgIHZhciBfY29sID0gaXNSdGwgPyBfdGhpcy5jb2xDbnQgLSBjb2wgLSAxIDogY29sOyAvLyBIQUNLOiBwcm9wcy5jZWxscyBoYXMgZGlmZmVyZW50IGRpciBzeXN0ZW0/XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IF90aGlzLnByb3BzLmNlbGxzW3Jvd11bX2NvbF0uZGF0ZTtcbiAgICAgICAgICAgIHZhciBtb3JlRWwgPSBldi5jdXJyZW50VGFyZ2V0O1xuICAgICAgICAgICAgdmFyIGRheUVsID0gX3RoaXMuZ2V0Q2VsbEVsKHJvdywgY29sKTtcbiAgICAgICAgICAgIHZhciBhbGxTZWdzID0gX3RoaXMuZ2V0Q2VsbFNlZ3Mocm93LCBjb2wpO1xuICAgICAgICAgICAgLy8gcmVzY29wZSB0aGUgc2VnbWVudHMgdG8gYmUgd2l0aGluIHRoZSBjZWxsJ3MgZGF0ZVxuICAgICAgICAgICAgdmFyIHJlc2xpY2VkQWxsU2VncyA9IF90aGlzLnJlc2xpY2VEYXlTZWdzKGFsbFNlZ3MsIGRhdGUpO1xuICAgICAgICAgICAgdmFyIHJlc2xpY2VkSGlkZGVuU2VncyA9IF90aGlzLnJlc2xpY2VEYXlTZWdzKGhpZGRlblNlZ3MsIGRhdGUpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjbGlja09wdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIC8vIHRoZSByZXR1cm5lZCB2YWx1ZSBjYW4gYmUgYW4gYXRvbWljIG9wdGlvblxuICAgICAgICAgICAgICAgIGNsaWNrT3B0aW9uID0gY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudExpbWl0Q2xpY2snLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IGRhdGVFbnYudG9EYXRlKGRhdGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYWxsRGF5OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF5RWw6IGRheUVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW9yZUVsOiBtb3JlRWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZWdzOiByZXNsaWNlZEFsbFNlZ3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW5TZWdzOiByZXNsaWNlZEhpZGRlblNlZ3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNsaWNrT3B0aW9uID09PSAncG9wb3ZlcicpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zaG93U2VnUG9wb3Zlcihyb3csIGNvbCwgbW9yZUVsLCByZXNsaWNlZEFsbFNlZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGNsaWNrT3B0aW9uID09PSAnc3RyaW5nJykgeyAvLyBhIHZpZXcgbmFtZVxuICAgICAgICAgICAgICAgIGNhbGVuZGFyLnpvb21UbyhkYXRlLCBjbGlja09wdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9O1xuICAgIC8vIFJldmVhbHMgdGhlIHBvcG92ZXIgdGhhdCBkaXNwbGF5cyBhbGwgZXZlbnRzIHdpdGhpbiBhIGNlbGxcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5zaG93U2VnUG9wb3ZlciA9IGZ1bmN0aW9uIChyb3csIGNvbCwgbW9yZUxpbmssIHNlZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldywgdGhlbWUgPSBfYS50aGVtZSwgaXNSdGwgPSBfYS5pc1J0bDtcbiAgICAgICAgdmFyIF9jb2wgPSBpc1J0bCA/IHRoaXMuY29sQ250IC0gY29sIC0gMSA6IGNvbDsgLy8gSEFDSzogcHJvcHMuY2VsbHMgaGFzIGRpZmZlcmVudCBkaXIgc3lzdGVtP1xuICAgICAgICB2YXIgbW9yZVdyYXAgPSBtb3JlTGluay5wYXJlbnROb2RlOyAvLyB0aGUgPGRpdj4gd3JhcHBlciBhcm91bmQgdGhlIDxhPlxuICAgICAgICB2YXIgdG9wRWw7IC8vIHRoZSBlbGVtZW50IHdlIHdhbnQgdG8gbWF0Y2ggdGhlIHRvcCBjb29yZGluYXRlIG9mXG4gICAgICAgIHZhciBvcHRpb25zO1xuICAgICAgICBpZiAodGhpcy5yb3dDbnQgPT09IDEpIHtcbiAgICAgICAgICAgIHRvcEVsID0gdmlldy5lbDsgLy8gd2lsbCBjYXVzZSB0aGUgcG9wb3ZlciB0byBjb3ZlciBhbnkgc29ydCBvZiBoZWFkZXJcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRvcEVsID0gdGhpcy5yb3dFbHNbcm93XTsgLy8gd2lsbCBhbGlnbiB3aXRoIHRvcCBvZiByb3dcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zID0ge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnZmMtbW9yZS1wb3BvdmVyICcgKyB0aGVtZS5nZXRDbGFzcygncG9wb3ZlcicpLFxuICAgICAgICAgICAgcGFyZW50RWw6IHZpZXcuZWwsXG4gICAgICAgICAgICB0b3A6IGNvbXB1dGVSZWN0KHRvcEVsKS50b3AsXG4gICAgICAgICAgICBhdXRvSGlkZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNlZ1BvcG92ZXJUaWxlID0gbmV3IERheVRpbGUoZWwpO1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZVNlZ1BvcG92ZXJUaWxlKF90aGlzLnByb3BzLmNlbGxzW3Jvd11bX2NvbF0uZGF0ZSwgc2Vncyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGlkZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNlZ1BvcG92ZXJUaWxlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZWdQb3BvdmVyVGlsZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2VnUG9wb3Zlci5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2VnUG9wb3ZlciA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIERldGVybWluZSBob3Jpem9udGFsIGNvb3JkaW5hdGUuXG4gICAgICAgIC8vIFdlIHVzZSB0aGUgbW9yZVdyYXAgaW5zdGVhZCBvZiB0aGUgPHRkPiB0byBhdm9pZCBib3JkZXIgY29uZnVzaW9uLlxuICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgIG9wdGlvbnMucmlnaHQgPSBjb21wdXRlUmVjdChtb3JlV3JhcCkucmlnaHQgKyAxOyAvLyArMSB0byBiZSBvdmVyIGNlbGwgYm9yZGVyXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zLmxlZnQgPSBjb21wdXRlUmVjdChtb3JlV3JhcCkubGVmdCAtIDE7IC8vIC0xIHRvIGJlIG92ZXIgY2VsbCBib3JkZXJcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlZ1BvcG92ZXIgPSBuZXcgUG9wb3ZlcihvcHRpb25zKTtcbiAgICAgICAgdGhpcy5zZWdQb3BvdmVyLnNob3coKTtcbiAgICAgICAgY2FsZW5kYXIucmVsZWFzZUFmdGVyU2l6aW5nVHJpZ2dlcnMoKTsgLy8gaGFjayBmb3IgZXZlbnRQb3NpdGlvbmVkXG4gICAgfTtcbiAgICAvLyBHaXZlbiB0aGUgZXZlbnRzIHdpdGhpbiBhbiBhcnJheSBvZiBzZWdtZW50IG9iamVjdHMsIHJlc2xpY2UgdGhlbSB0byBiZSBpbiBhIHNpbmdsZSBkYXlcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZXNsaWNlRGF5U2VncyA9IGZ1bmN0aW9uIChzZWdzLCBkYXlEYXRlKSB7XG4gICAgICAgIHZhciBkYXlTdGFydCA9IGRheURhdGU7XG4gICAgICAgIHZhciBkYXlFbmQgPSBhZGREYXlzKGRheVN0YXJ0LCAxKTtcbiAgICAgICAgdmFyIGRheVJhbmdlID0geyBzdGFydDogZGF5U3RhcnQsIGVuZDogZGF5RW5kIH07XG4gICAgICAgIHZhciBuZXdTZWdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18xID0gc2VnczsgX2kgPCBzZWdzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18xW19pXTtcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gc2VnLmV2ZW50UmFuZ2U7XG4gICAgICAgICAgICB2YXIgb3JpZ1JhbmdlID0gZXZlbnRSYW5nZS5yYW5nZTtcbiAgICAgICAgICAgIHZhciBzbGljZWRSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhvcmlnUmFuZ2UsIGRheVJhbmdlKTtcbiAgICAgICAgICAgIGlmIChzbGljZWRSYW5nZSkge1xuICAgICAgICAgICAgICAgIG5ld1NlZ3MucHVzaChfX2Fzc2lnbih7fSwgc2VnLCB7IGV2ZW50UmFuZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogZXZlbnRSYW5nZS5kZWYsXG4gICAgICAgICAgICAgICAgICAgICAgICB1aTogX19hc3NpZ24oe30sIGV2ZW50UmFuZ2UudWksIHsgZHVyYXRpb25FZGl0YWJsZTogZmFsc2UgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZTogZXZlbnRSYW5nZS5pbnN0YW5jZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlOiBzbGljZWRSYW5nZVxuICAgICAgICAgICAgICAgICAgICB9LCBpc1N0YXJ0OiBzZWcuaXNTdGFydCAmJiBzbGljZWRSYW5nZS5zdGFydC52YWx1ZU9mKCkgPT09IG9yaWdSYW5nZS5zdGFydC52YWx1ZU9mKCksIGlzRW5kOiBzZWcuaXNFbmQgJiYgc2xpY2VkUmFuZ2UuZW5kLnZhbHVlT2YoKSA9PT0gb3JpZ1JhbmdlLmVuZC52YWx1ZU9mKCkgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdTZWdzO1xuICAgIH07XG4gICAgLy8gR2VuZXJhdGVzIHRoZSB0ZXh0IHRoYXQgc2hvdWxkIGJlIGluc2lkZSBhIFwibW9yZVwiIGxpbmssIGdpdmVuIHRoZSBudW1iZXIgb2YgZXZlbnRzIGl0IHJlcHJlc2VudHNcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRNb3JlTGlua1RleHQgPSBmdW5jdGlvbiAobnVtKSB7XG4gICAgICAgIHZhciBvcHQgPSB0aGlzLmNvbnRleHQub3B0aW9ucy5ldmVudExpbWl0VGV4dDtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHQobnVtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnKycgKyBudW0gKyAnICcgKyBvcHQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJldHVybnMgc2VnbWVudHMgd2l0aGluIGEgZ2l2ZW4gY2VsbC5cbiAgICAvLyBJZiBgc3RhcnRMZXZlbGAgaXMgc3BlY2lmaWVkLCByZXR1cm5zIG9ubHkgZXZlbnRzIGluY2x1ZGluZyBhbmQgYmVsb3cgdGhhdCBsZXZlbC4gT3RoZXJ3aXNlIHJldHVybnMgYWxsIHNlZ3MuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuZ2V0Q2VsbFNlZ3MgPSBmdW5jdGlvbiAocm93LCBjb2wsIHN0YXJ0TGV2ZWwpIHtcbiAgICAgICAgdmFyIHNlZ01hdHJpeCA9IHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzW3Jvd10uc2VnTWF0cml4O1xuICAgICAgICB2YXIgbGV2ZWwgPSBzdGFydExldmVsIHx8IDA7XG4gICAgICAgIHZhciBzZWdzID0gW107XG4gICAgICAgIHZhciBzZWc7XG4gICAgICAgIHdoaWxlIChsZXZlbCA8IHNlZ01hdHJpeC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHNlZyA9IHNlZ01hdHJpeFtsZXZlbF1bY29sXTtcbiAgICAgICAgICAgIGlmIChzZWcpIHtcbiAgICAgICAgICAgICAgICBzZWdzLnB1c2goc2VnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldmVsKys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5R3JpZDtcbn0oRGF0ZUNvbXBvbmVudCkpO1xuXG52YXIgV0VFS19OVU1fRk9STUFUJDEgPSBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrOiAnbnVtZXJpYycgfSk7XG4vKiBBbiBhYnN0cmFjdCBjbGFzcyBmb3IgdGhlIGRheWdyaWQgdmlld3MsIGFzIHdlbGwgYXMgbW9udGggdmlldy4gUmVuZGVycyBvbmUgb3IgbW9yZSByb3dzIG9mIGRheSBjZWxscy5cbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLy8gSXQgaXMgYSBtYW5hZ2VyIGZvciBhIERheUdyaWQgc3ViY29tcG9uZW50LCB3aGljaCBkb2VzIG1vc3Qgb2YgdGhlIGhlYXZ5IGxpZnRpbmcuXG4vLyBJdCBpcyByZXNwb25zaWJsZSBmb3IgbWFuYWdpbmcgd2lkdGgvaGVpZ2h0LlxudmFyIEFic3RyYWN0RGF5R3JpZFZpZXcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEFic3RyYWN0RGF5R3JpZFZpZXcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWJzdHJhY3REYXlHcmlkVmlldygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnByb2Nlc3NPcHRpb25zID0gbWVtb2l6ZShfdGhpcy5fcHJvY2Vzc09wdGlvbnMpO1xuICAgICAgICBfdGhpcy5yZW5kZXJTa2VsZXRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclNrZWxldG9uLCBfdGhpcy5fdW5yZW5kZXJTa2VsZXRvbik7XG4gICAgICAgIC8qIEhlYWRlciBSZW5kZXJpbmdcbiAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgd2lsbCBnbyBiZWZvcmUgdGhlIGRheS1vZiB3ZWVrIGhlYWRlciBjZWxsc1xuICAgICAgICBfdGhpcy5yZW5kZXJIZWFkSW50cm9IdG1sID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMuY29udGV4dCwgdGhlbWUgPSBfYS50aGVtZSwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcnICtcbiAgICAgICAgICAgICAgICAgICAgJzx0aCBjbGFzcz1cImZjLXdlZWstbnVtYmVyICcgKyB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0SGVhZGVyJykgKyAnXCIgJyArIF90aGlzLndlZWtOdW1iZXJTdHlsZUF0dHIoKSArICc+JyArXG4gICAgICAgICAgICAgICAgICAgICc8c3Bhbj4nICsgLy8gbmVlZGVkIGZvciBtYXRjaENlbGxXaWR0aHNcbiAgICAgICAgICAgICAgICAgICAgaHRtbEVzY2FwZShvcHRpb25zLndlZWtMYWJlbCkgK1xuICAgICAgICAgICAgICAgICAgICAnPC9zcGFuPicgK1xuICAgICAgICAgICAgICAgICAgICAnPC90aD4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9O1xuICAgICAgICAvKiBEYXkgR3JpZCBSZW5kZXJpbmdcbiAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgd2lsbCBnbyBiZWZvcmUgY29udGVudC1za2VsZXRvbiBjZWxscyB0aGF0IGRpc3BsYXkgdGhlIGRheS93ZWVrIG51bWJlcnNcbiAgICAgICAgX3RoaXMucmVuZGVyRGF5R3JpZE51bWJlckludHJvSHRtbCA9IGZ1bmN0aW9uIChyb3csIGRheUdyaWQpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLmNvbnRleHQsIG9wdGlvbnMgPSBfYS5vcHRpb25zLCBkYXRlRW52ID0gX2EuZGF0ZUVudjtcbiAgICAgICAgICAgIHZhciB3ZWVrU3RhcnQgPSBkYXlHcmlkLnByb3BzLmNlbGxzW3Jvd11bMF0uZGF0ZTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJycgK1xuICAgICAgICAgICAgICAgICAgICAnPHRkIGNsYXNzPVwiZmMtd2Vlay1udW1iZXJcIiAnICsgX3RoaXMud2Vla051bWJlclN0eWxlQXR0cigpICsgJz4nICtcbiAgICAgICAgICAgICAgICAgICAgYnVpbGRHb3RvQW5jaG9ySHRtbCgvLyBhc2lkZSBmcm9tIGxpbmssIGltcG9ydGFudCBmb3IgbWF0Y2hDZWxsV2lkdGhzXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMsIGRhdGVFbnYsIHsgZGF0ZTogd2Vla1N0YXJ0LCB0eXBlOiAnd2VlaycsIGZvcmNlT2ZmOiBkYXlHcmlkLmNvbENudCA9PT0gMSB9LCBkYXRlRW52LmZvcm1hdCh3ZWVrU3RhcnQsIFdFRUtfTlVNX0ZPUk1BVCQxKSAvLyBpbm5lciBIVE1MXG4gICAgICAgICAgICAgICAgICAgICkgK1xuICAgICAgICAgICAgICAgICAgICAnPC90ZD4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9O1xuICAgICAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgdGhhdCBnb2VzIGJlZm9yZSB0aGUgZGF5IGJnIGNlbGxzIGZvciBlYWNoIGRheS1yb3dcbiAgICAgICAgX3RoaXMucmVuZGVyRGF5R3JpZEJnSW50cm9IdG1sID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHRoZW1lID0gX3RoaXMuY29udGV4dC50aGVtZTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJzx0ZCBjbGFzcz1cImZjLXdlZWstbnVtYmVyICcgKyB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0Q29udGVudCcpICsgJ1wiICcgKyBfdGhpcy53ZWVrTnVtYmVyU3R5bGVBdHRyKCkgKyAnPjwvdGQ+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfTtcbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgZ29lcyBiZWZvcmUgZXZlcnkgb3RoZXIgdHlwZSBvZiByb3cgZ2VuZXJhdGVkIGJ5IERheUdyaWQuXG4gICAgICAgIC8vIEFmZmVjdHMgbWlycm9yLXNrZWxldG9uIGFuZCBoaWdobGlnaHQtc2tlbGV0b24gcm93cy5cbiAgICAgICAgX3RoaXMucmVuZGVyRGF5R3JpZEludHJvSHRtbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJzx0ZCBjbGFzcz1cImZjLXdlZWstbnVtYmVyXCIgJyArIF90aGlzLndlZWtOdW1iZXJTdHlsZUF0dHIoKSArICc+PC90ZD4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLl9wcm9jZXNzT3B0aW9ucyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zLndlZWtOdW1iZXJzKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy53ZWVrTnVtYmVyc1dpdGhpbkRheXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNlbGxXZWVrTnVtYmVyc1Zpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNlbGxXZWVrTnVtYmVyc1Zpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnJlbmRlci5jYWxsKHRoaXMsIHByb3BzLCBjb250ZXh0KTtcbiAgICAgICAgdGhpcy5wcm9jZXNzT3B0aW9ucyhjb250ZXh0Lm9wdGlvbnMpO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uKGNvbnRleHQpO1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMucmVuZGVyU2tlbGV0b24udW5yZW5kZXIoKTtcbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLl9yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LmFkZCgnZmMtZGF5R3JpZC12aWV3Jyk7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gdGhpcy5yZW5kZXJTa2VsZXRvbkh0bWwoKTtcbiAgICAgICAgdGhpcy5zY3JvbGxlciA9IG5ldyBTY3JvbGxDb21wb25lbnQoJ2hpZGRlbicsIC8vIG92ZXJmbG93IHhcbiAgICAgICAgJ2F1dG8nIC8vIG92ZXJmbG93IHlcbiAgICAgICAgKTtcbiAgICAgICAgdmFyIGRheUdyaWRDb250YWluZXJFbCA9IHRoaXMuc2Nyb2xsZXIuZWw7XG4gICAgICAgIHRoaXMuZWwucXVlcnlTZWxlY3RvcignLmZjLWJvZHkgPiB0ciA+IHRkJykuYXBwZW5kQ2hpbGQoZGF5R3JpZENvbnRhaW5lckVsKTtcbiAgICAgICAgZGF5R3JpZENvbnRhaW5lckVsLmNsYXNzTGlzdC5hZGQoJ2ZjLWRheS1ncmlkLWNvbnRhaW5lcicpO1xuICAgICAgICB2YXIgZGF5R3JpZEVsID0gY3JlYXRlRWxlbWVudCgnZGl2JywgeyBjbGFzc05hbWU6ICdmYy1kYXktZ3JpZCcgfSk7XG4gICAgICAgIGRheUdyaWRDb250YWluZXJFbC5hcHBlbmRDaGlsZChkYXlHcmlkRWwpO1xuICAgICAgICB0aGlzLmRheUdyaWQgPSBuZXcgRGF5R3JpZChkYXlHcmlkRWwsIHtcbiAgICAgICAgICAgIHJlbmRlck51bWJlckludHJvSHRtbDogdGhpcy5yZW5kZXJEYXlHcmlkTnVtYmVySW50cm9IdG1sLFxuICAgICAgICAgICAgcmVuZGVyQmdJbnRyb0h0bWw6IHRoaXMucmVuZGVyRGF5R3JpZEJnSW50cm9IdG1sLFxuICAgICAgICAgICAgcmVuZGVySW50cm9IdG1sOiB0aGlzLnJlbmRlckRheUdyaWRJbnRyb0h0bWwsXG4gICAgICAgICAgICBjb2xXZWVrTnVtYmVyc1Zpc2libGU6IHRoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlLFxuICAgICAgICAgICAgY2VsbFdlZWtOdW1iZXJzVmlzaWJsZTogdGhpcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtZGF5R3JpZC12aWV3Jyk7XG4gICAgICAgIHRoaXMuZGF5R3JpZC5kZXN0cm95KCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsZXIuZGVzdHJveSgpO1xuICAgIH07XG4gICAgLy8gQnVpbGRzIHRoZSBIVE1MIHNrZWxldG9uIGZvciB0aGUgdmlldy5cbiAgICAvLyBUaGUgZGF5LWdyaWQgY29tcG9uZW50IHdpbGwgcmVuZGVyIGluc2lkZSBvZiBhIGNvbnRhaW5lciBkZWZpbmVkIGJ5IHRoaXMgSFRNTC5cbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5yZW5kZXJTa2VsZXRvbkh0bWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29udGV4dCwgdGhlbWUgPSBfYS50aGVtZSwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgIHJldHVybiAnJyArXG4gICAgICAgICAgICAnPHRhYmxlIGNsYXNzPVwiJyArIHRoZW1lLmdldENsYXNzKCd0YWJsZUdyaWQnKSArICdcIj4nICtcbiAgICAgICAgICAgIChvcHRpb25zLmNvbHVtbkhlYWRlciA/XG4gICAgICAgICAgICAgICAgJzx0aGVhZCBjbGFzcz1cImZjLWhlYWRcIj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzx0cj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzx0ZCBjbGFzcz1cImZjLWhlYWQtY29udGFpbmVyICcgKyB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0SGVhZGVyJykgKyAnXCI+Jm5ic3A7PC90ZD4nICtcbiAgICAgICAgICAgICAgICAgICAgJzwvdHI+JyArXG4gICAgICAgICAgICAgICAgICAgICc8L3RoZWFkPicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAnPHRib2R5IGNsYXNzPVwiZmMtYm9keVwiPicgK1xuICAgICAgICAgICAgJzx0cj4nICtcbiAgICAgICAgICAgICc8dGQgY2xhc3M9XCInICsgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSArICdcIj48L3RkPicgK1xuICAgICAgICAgICAgJzwvdHI+JyArXG4gICAgICAgICAgICAnPC90Ym9keT4nICtcbiAgICAgICAgICAgICc8L3RhYmxlPic7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgYW4gSFRNTCBhdHRyaWJ1dGUgc3RyaW5nIGZvciBzZXR0aW5nIHRoZSB3aWR0aCBvZiB0aGUgd2VlayBudW1iZXIgY29sdW1uLCBpZiBpdCBpcyBrbm93blxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLndlZWtOdW1iZXJTdHlsZUF0dHIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLndlZWtOdW1iZXJXaWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3N0eWxlPVwid2lkdGg6JyArIHRoaXMud2Vla051bWJlcldpZHRoICsgJ3B4XCInO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuICAgIC8vIERldGVybWluZXMgd2hldGhlciBlYWNoIHJvdyBzaG91bGQgaGF2ZSBhIGNvbnN0YW50IGhlaWdodFxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmhhc1JpZ2lkUm93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGV2ZW50TGltaXQgPSB0aGlzLmNvbnRleHQub3B0aW9ucy5ldmVudExpbWl0O1xuICAgICAgICByZXR1cm4gZXZlbnRMaW1pdCAmJiB0eXBlb2YgZXZlbnRMaW1pdCAhPT0gJ251bWJlcic7XG4gICAgfTtcbiAgICAvKiBEaW1lbnNpb25zXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKGlzUmVzaXplLCB2aWV3SGVpZ2h0LCBpc0F1dG8pIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS51cGRhdGVTaXplLmNhbGwodGhpcywgaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0byk7IC8vIHdpbGwgY2FsbCB1cGRhdGVCYXNlU2l6ZS4gaW1wb3J0YW50IHRoYXQgZXhlY3V0ZXMgZmlyc3RcbiAgICAgICAgdGhpcy5kYXlHcmlkLnVwZGF0ZVNpemUoaXNSZXNpemUpO1xuICAgIH07XG4gICAgLy8gUmVmcmVzaGVzIHRoZSBob3Jpem9udGFsIGRpbWVuc2lvbnMgb2YgdGhlIHZpZXdcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS51cGRhdGVCYXNlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKSB7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgZXZlbnRMaW1pdCA9IHRoaXMuY29udGV4dC5vcHRpb25zLmV2ZW50TGltaXQ7XG4gICAgICAgIHZhciBoZWFkUm93RWwgPSB0aGlzLmhlYWRlciA/IHRoaXMuaGVhZGVyLmVsIDogbnVsbDsgLy8gSEFDS1xuICAgICAgICB2YXIgc2Nyb2xsZXJIZWlnaHQ7XG4gICAgICAgIHZhciBzY3JvbGxiYXJXaWR0aHM7XG4gICAgICAgIC8vIGhhY2sgdG8gZ2l2ZSB0aGUgdmlldyBzb21lIGhlaWdodCBwcmlvciB0byBkYXlHcmlkJ3MgY29sdW1ucyBiZWluZyByZW5kZXJlZFxuICAgICAgICAvLyBUT0RPOiBzZXBhcmF0ZSBzZXR0aW5nIGhlaWdodCBmcm9tIHNjcm9sbGVyIFZTIGRheUdyaWQuXG4gICAgICAgIGlmICghZGF5R3JpZC5yb3dFbHMpIHtcbiAgICAgICAgICAgIGlmICghaXNBdXRvKSB7XG4gICAgICAgICAgICAgICAgc2Nyb2xsZXJIZWlnaHQgPSB0aGlzLmNvbXB1dGVTY3JvbGxlckhlaWdodCh2aWV3SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbGVyLnNldEhlaWdodChzY3JvbGxlckhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIHdlZWsgbnVtYmVyIGNlbGxzIHJ1bm5pbmcgZG93biB0aGUgc2lkZSBoYXZlIHRoZSBzYW1lIHdpZHRoLlxuICAgICAgICAgICAgdGhpcy53ZWVrTnVtYmVyV2lkdGggPSBtYXRjaENlbGxXaWR0aHMoZmluZEVsZW1lbnRzKHRoaXMuZWwsICcuZmMtd2Vlay1udW1iZXInKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzZXQgYWxsIGhlaWdodHMgdG8gYmUgbmF0dXJhbFxuICAgICAgICB0aGlzLnNjcm9sbGVyLmNsZWFyKCk7XG4gICAgICAgIGlmIChoZWFkUm93RWwpIHtcbiAgICAgICAgICAgIHVuY29tcGVuc2F0ZVNjcm9sbChoZWFkUm93RWwpO1xuICAgICAgICB9XG4gICAgICAgIGRheUdyaWQucmVtb3ZlU2VnUG9wb3ZlcigpOyAvLyBraWxsIHRoZSBcIm1vcmVcIiBwb3BvdmVyIGlmIGRpc3BsYXllZFxuICAgICAgICAvLyBpcyB0aGUgZXZlbnQgbGltaXQgYSBjb25zdGFudCBsZXZlbCBudW1iZXI/XG4gICAgICAgIGlmIChldmVudExpbWl0ICYmIHR5cGVvZiBldmVudExpbWl0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgZGF5R3JpZC5saW1pdFJvd3MoZXZlbnRMaW1pdCk7IC8vIGxpbWl0IHRoZSBsZXZlbHMgZmlyc3Qgc28gdGhlIGhlaWdodCBjYW4gcmVkaXN0cmlidXRlIGFmdGVyXG4gICAgICAgIH1cbiAgICAgICAgLy8gZGlzdHJpYnV0ZSB0aGUgaGVpZ2h0IHRvIHRoZSByb3dzXG4gICAgICAgIC8vICh2aWV3SGVpZ2h0IGlzIGEgXCJyZWNvbW1lbmRlZFwiIHZhbHVlIGlmIGlzQXV0bylcbiAgICAgICAgc2Nyb2xsZXJIZWlnaHQgPSB0aGlzLmNvbXB1dGVTY3JvbGxlckhlaWdodCh2aWV3SGVpZ2h0KTtcbiAgICAgICAgdGhpcy5zZXRHcmlkSGVpZ2h0KHNjcm9sbGVySGVpZ2h0LCBpc0F1dG8pO1xuICAgICAgICAvLyBpcyB0aGUgZXZlbnQgbGltaXQgZHluYW1pY2FsbHkgY2FsY3VsYXRlZD9cbiAgICAgICAgaWYgKGV2ZW50TGltaXQgJiYgdHlwZW9mIGV2ZW50TGltaXQgIT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBkYXlHcmlkLmxpbWl0Um93cyhldmVudExpbWl0KTsgLy8gbGltaXQgdGhlIGxldmVscyBhZnRlciB0aGUgZ3JpZCdzIHJvdyBoZWlnaHRzIGhhdmUgYmVlbiBzZXRcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzQXV0bykgeyAvLyBzaG91bGQgd2UgZm9yY2UgZGltZW5zaW9ucyBvZiB0aGUgc2Nyb2xsIGNvbnRhaW5lcj9cbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsZXIuc2V0SGVpZ2h0KHNjcm9sbGVySGVpZ2h0KTtcbiAgICAgICAgICAgIHNjcm9sbGJhcldpZHRocyA9IHRoaXMuc2Nyb2xsZXIuZ2V0U2Nyb2xsYmFyV2lkdGhzKCk7XG4gICAgICAgICAgICBpZiAoc2Nyb2xsYmFyV2lkdGhzLmxlZnQgfHwgc2Nyb2xsYmFyV2lkdGhzLnJpZ2h0KSB7IC8vIHVzaW5nIHNjcm9sbGJhcnM/XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRSb3dFbCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wZW5zYXRlU2Nyb2xsKGhlYWRSb3dFbCwgc2Nyb2xsYmFyV2lkdGhzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gZG9pbmcgdGhlIHNjcm9sbGJhciBjb21wZW5zYXRpb24gbWlnaHQgaGF2ZSBjcmVhdGVkIHRleHQgb3ZlcmZsb3cgd2hpY2ggY3JlYXRlZCBtb3JlIGhlaWdodC4gcmVkb1xuICAgICAgICAgICAgICAgIHNjcm9sbGVySGVpZ2h0ID0gdGhpcy5jb21wdXRlU2Nyb2xsZXJIZWlnaHQodmlld0hlaWdodCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxlci5zZXRIZWlnaHQoc2Nyb2xsZXJIZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZ3VhcmFudGVlcyB0aGUgc2FtZSBzY3JvbGxiYXIgd2lkdGhzXG4gICAgICAgICAgICB0aGlzLnNjcm9sbGVyLmxvY2tPdmVyZmxvdyhzY3JvbGxiYXJXaWR0aHMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBnaXZlbiBhIGRlc2lyZWQgdG90YWwgaGVpZ2h0IG9mIHRoZSB2aWV3LCByZXR1cm5zIHdoYXQgdGhlIGhlaWdodCBvZiB0aGUgc2Nyb2xsZXIgc2hvdWxkIGJlXG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuY29tcHV0ZVNjcm9sbGVySGVpZ2h0ID0gZnVuY3Rpb24gKHZpZXdIZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHZpZXdIZWlnaHQgLVxuICAgICAgICAgICAgc3VidHJhY3RJbm5lckVsSGVpZ2h0KHRoaXMuZWwsIHRoaXMuc2Nyb2xsZXIuZWwpOyAvLyBldmVyeXRoaW5nIHRoYXQncyBOT1QgdGhlIHNjcm9sbGVyXG4gICAgfTtcbiAgICAvLyBTZXRzIHRoZSBoZWlnaHQgb2YganVzdCB0aGUgRGF5R3JpZCBjb21wb25lbnQgaW4gdGhpcyB2aWV3XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuc2V0R3JpZEhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQsIGlzQXV0bykge1xuICAgICAgICBpZiAodGhpcy5jb250ZXh0Lm9wdGlvbnMubW9udGhNb2RlKSB7XG4gICAgICAgICAgICAvLyBpZiBhdXRvLCBtYWtlIHRoZSBoZWlnaHQgb2YgZWFjaCByb3cgdGhlIGhlaWdodCB0aGF0IGl0IHdvdWxkIGJlIGlmIHRoZXJlIHdlcmUgNiB3ZWVrc1xuICAgICAgICAgICAgaWYgKGlzQXV0bykge1xuICAgICAgICAgICAgICAgIGhlaWdodCAqPSB0aGlzLmRheUdyaWQucm93Q250IC8gNjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3RyaWJ1dGVIZWlnaHQodGhpcy5kYXlHcmlkLnJvd0VscywgaGVpZ2h0LCAhaXNBdXRvKTsgLy8gaWYgYXV0bywgZG9uJ3QgY29tcGVuc2F0ZSBmb3IgaGVpZ2h0LWhvZ2dpbmcgcm93c1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzQXV0bykge1xuICAgICAgICAgICAgICAgIHVuZGlzdHJpYnV0ZUhlaWdodCh0aGlzLmRheUdyaWQucm93RWxzKTsgLy8gbGV0IHRoZSByb3dzIGJlIHRoZWlyIG5hdHVyYWwgaGVpZ2h0IHdpdGggbm8gZXhwYW5kaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXN0cmlidXRlSGVpZ2h0KHRoaXMuZGF5R3JpZC5yb3dFbHMsIGhlaWdodCwgdHJ1ZSk7IC8vIHRydWUgPSBjb21wZW5zYXRlIGZvciBoZWlnaHQtaG9nZ2luZyByb3dzXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qIFNjcm9sbFxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuY29tcHV0ZURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoZHVyYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIHsgdG9wOiAwIH07XG4gICAgfTtcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5xdWVyeURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7IHRvcDogdGhpcy5zY3JvbGxlci5nZXRTY3JvbGxUb3AoKSB9O1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuYXBwbHlEYXRlU2Nyb2xsID0gZnVuY3Rpb24gKHNjcm9sbCkge1xuICAgICAgICBpZiAoc2Nyb2xsLnRvcCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbGVyLnNldFNjcm9sbFRvcChzY3JvbGwudG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEFic3RyYWN0RGF5R3JpZFZpZXc7XG59KFZpZXcpKTtcbkFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmRhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3MgPSBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3I7XG5cbnZhciBTaW1wbGVEYXlHcmlkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTaW1wbGVEYXlHcmlkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNpbXBsZURheUdyaWQoZGF5R3JpZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBkYXlHcmlkLmVsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zbGljZXIgPSBuZXcgRGF5R3JpZFNsaWNlcigpO1xuICAgICAgICBfdGhpcy5kYXlHcmlkID0gZGF5R3JpZDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTaW1wbGVEYXlHcmlkLnByb3RvdHlwZS5maXJzdENvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICBjb250ZXh0LmNhbGVuZGFyLnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcywgeyBlbDogdGhpcy5kYXlHcmlkLmVsIH0pO1xuICAgIH07XG4gICAgU2ltcGxlRGF5R3JpZC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuY29udGV4dC5jYWxlbmRhci51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcyk7XG4gICAgfTtcbiAgICBTaW1wbGVEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGRheUdyaWQgPSB0aGlzLmRheUdyaWQ7XG4gICAgICAgIHZhciBkYXRlUHJvZmlsZSA9IHByb3BzLmRhdGVQcm9maWxlLCBkYXlUYWJsZSA9IHByb3BzLmRheVRhYmxlO1xuICAgICAgICBkYXlHcmlkLnJlY2VpdmVDb250ZXh0KGNvbnRleHQpOyAvLyBoYWNrIGJlY2F1c2UgY29udGV4dCBpcyB1c2VkIGluIHNsaWNlUHJvcHNcbiAgICAgICAgZGF5R3JpZC5yZWNlaXZlUHJvcHMoX19hc3NpZ24oe30sIHRoaXMuc2xpY2VyLnNsaWNlUHJvcHMocHJvcHMsIGRhdGVQcm9maWxlLCBwcm9wcy5uZXh0RGF5VGhyZXNob2xkLCBjb250ZXh0LmNhbGVuZGFyLCBkYXlHcmlkLCBkYXlUYWJsZSksIHsgZGF0ZVByb2ZpbGU6IGRhdGVQcm9maWxlLCBjZWxsczogZGF5VGFibGUuY2VsbHMsIGlzUmlnaWQ6IHByb3BzLmlzUmlnaWQgfSksIGNvbnRleHQpO1xuICAgIH07XG4gICAgU2ltcGxlRGF5R3JpZC5wcm90b3R5cGUuYnVpbGRQb3NpdGlvbkNhY2hlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXlHcmlkLmJ1aWxkUG9zaXRpb25DYWNoZXMoKTtcbiAgICB9O1xuICAgIFNpbXBsZURheUdyaWQucHJvdG90eXBlLnF1ZXJ5SGl0ID0gZnVuY3Rpb24gKHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3ApIHtcbiAgICAgICAgdmFyIHJhd0hpdCA9IHRoaXMuZGF5R3JpZC5wb3NpdGlvblRvSGl0KHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3ApO1xuICAgICAgICBpZiAocmF3SGl0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudDogdGhpcy5kYXlHcmlkLFxuICAgICAgICAgICAgICAgIGRhdGVTcGFuOiByYXdIaXQuZGF0ZVNwYW4sXG4gICAgICAgICAgICAgICAgZGF5RWw6IHJhd0hpdC5kYXlFbCxcbiAgICAgICAgICAgICAgICByZWN0OiB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IHJhd0hpdC5yZWxhdGl2ZVJlY3QubGVmdCxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IHJhd0hpdC5yZWxhdGl2ZVJlY3QucmlnaHQsXG4gICAgICAgICAgICAgICAgICAgIHRvcDogcmF3SGl0LnJlbGF0aXZlUmVjdC50b3AsXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbTogcmF3SGl0LnJlbGF0aXZlUmVjdC5ib3R0b21cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxheWVyOiAwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gU2ltcGxlRGF5R3JpZDtcbn0oRGF0ZUNvbXBvbmVudCkpO1xudmFyIERheUdyaWRTbGljZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUdyaWRTbGljZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5R3JpZFNsaWNlcigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBEYXlHcmlkU2xpY2VyLnByb3RvdHlwZS5zbGljZVJhbmdlID0gZnVuY3Rpb24gKGRhdGVSYW5nZSwgZGF5VGFibGUpIHtcbiAgICAgICAgcmV0dXJuIGRheVRhYmxlLnNsaWNlUmFuZ2UoZGF0ZVJhbmdlKTtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkU2xpY2VyO1xufShTbGljZXIpKTtcblxudmFyIERheUdyaWRWaWV3ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkVmlldywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkVmlldygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmJ1aWxkRGF5VGFibGUgPSBtZW1vaXplKGJ1aWxkRGF5VGFibGUpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERheUdyaWRWaWV3LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZW5kZXIuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCk7IC8vIHdpbGwgY2FsbCBfcmVuZGVyU2tlbGV0b24vX3VucmVuZGVyU2tlbGV0b25cbiAgICAgICAgdmFyIGRhdGVQcm9maWxlID0gdGhpcy5wcm9wcy5kYXRlUHJvZmlsZTtcbiAgICAgICAgdmFyIGRheVRhYmxlID0gdGhpcy5kYXlUYWJsZSA9XG4gICAgICAgICAgICB0aGlzLmJ1aWxkRGF5VGFibGUoZGF0ZVByb2ZpbGUsIHByb3BzLmRhdGVQcm9maWxlR2VuZXJhdG9yKTtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlci5yZWNlaXZlUHJvcHMoe1xuICAgICAgICAgICAgICAgIGRhdGVQcm9maWxlOiBkYXRlUHJvZmlsZSxcbiAgICAgICAgICAgICAgICBkYXRlczogZGF5VGFibGUuaGVhZGVyRGF0ZXMsXG4gICAgICAgICAgICAgICAgZGF0ZXNSZXBEaXN0aW5jdERheXM6IGRheVRhYmxlLnJvd0NudCA9PT0gMSxcbiAgICAgICAgICAgICAgICByZW5kZXJJbnRyb0h0bWw6IHRoaXMucmVuZGVySGVhZEludHJvSHRtbFxuICAgICAgICAgICAgfSwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zaW1wbGVEYXlHcmlkLnJlY2VpdmVQcm9wcyh7XG4gICAgICAgICAgICBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICBkYXlUYWJsZTogZGF5VGFibGUsXG4gICAgICAgICAgICBidXNpbmVzc0hvdXJzOiBwcm9wcy5idXNpbmVzc0hvdXJzLFxuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvbjogcHJvcHMuZGF0ZVNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IHByb3BzLmV2ZW50U3RvcmUsXG4gICAgICAgICAgICBldmVudFVpQmFzZXM6IHByb3BzLmV2ZW50VWlCYXNlcyxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IHByb3BzLmV2ZW50UmVzaXplLFxuICAgICAgICAgICAgaXNSaWdpZDogdGhpcy5oYXNSaWdpZFJvd3MoKSxcbiAgICAgICAgICAgIG5leHREYXlUaHJlc2hvbGQ6IHRoaXMuY29udGV4dC5uZXh0RGF5VGhyZXNob2xkXG4gICAgICAgIH0sIGNvbnRleHQpO1xuICAgIH07XG4gICAgRGF5R3JpZFZpZXcucHJvdG90eXBlLl9yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuX3JlbmRlclNrZWxldG9uLmNhbGwodGhpcywgY29udGV4dCk7XG4gICAgICAgIGlmIChjb250ZXh0Lm9wdGlvbnMuY29sdW1uSGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlciA9IG5ldyBEYXlIZWFkZXIodGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZmMtaGVhZC1jb250YWluZXInKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zaW1wbGVEYXlHcmlkID0gbmV3IFNpbXBsZURheUdyaWQodGhpcy5kYXlHcmlkKTtcbiAgICB9O1xuICAgIERheUdyaWRWaWV3LnByb3RvdHlwZS5fdW5yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5fdW5yZW5kZXJTa2VsZXRvbi5jYWxsKHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNpbXBsZURheUdyaWQuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWRWaWV3O1xufShBYnN0cmFjdERheUdyaWRWaWV3KSk7XG5mdW5jdGlvbiBidWlsZERheVRhYmxlKGRhdGVQcm9maWxlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcikge1xuICAgIHZhciBkYXlTZXJpZXMgPSBuZXcgRGF5U2VyaWVzKGRhdGVQcm9maWxlLnJlbmRlclJhbmdlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcik7XG4gICAgcmV0dXJuIG5ldyBEYXlUYWJsZShkYXlTZXJpZXMsIC95ZWFyfG1vbnRofHdlZWsvLnRlc3QoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdCkpO1xufVxuXG52YXIgbWFpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgZGVmYXVsdFZpZXc6ICdkYXlHcmlkTW9udGgnLFxuICAgIHZpZXdzOiB7XG4gICAgICAgIGRheUdyaWQ6IERheUdyaWRWaWV3LFxuICAgICAgICBkYXlHcmlkRGF5OiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyBkYXlzOiAxIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5R3JpZFdlZWs6IHtcbiAgICAgICAgICAgIHR5cGU6ICdkYXlHcmlkJyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB7IHdlZWtzOiAxIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5R3JpZE1vbnRoOiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyBtb250aHM6IDEgfSxcbiAgICAgICAgICAgIG1vbnRoTW9kZTogdHJ1ZSxcbiAgICAgICAgICAgIGZpeGVkV2Vla0NvdW50OiB0cnVlXG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgbWFpbjtcbmV4cG9ydCB7IEFic3RyYWN0RGF5R3JpZFZpZXcsIERheUJnUm93LCBEYXlHcmlkLCBEYXlHcmlkU2xpY2VyLCBEYXlHcmlkVmlldywgU2ltcGxlRGF5R3JpZCwgYnVpbGREYXlUYWJsZSBhcyBidWlsZEJhc2ljRGF5VGFibGUgfTtcbiIsIi8qIVxuRnVsbENhbGVuZGFyIEludGVyYWN0aW9uIFBsdWdpbiB2NC40LjJcbkRvY3MgJiBMaWNlbnNlOiBodHRwczovL2Z1bGxjYWxlbmRhci5pby9cbihjKSAyMDE5IEFkYW0gU2hhd1xuKi9cblxuaW1wb3J0IHsgY29uZmlnLCBlbGVtZW50Q2xvc2VzdCwgRW1pdHRlck1peGluLCBhcHBseVN0eWxlLCB3aGVuVHJhbnNpdGlvbkRvbmUsIHJlbW92ZUVsZW1lbnQsIFNjcm9sbENvbnRyb2xsZXIsIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLCBjb21wdXRlSW5uZXJSZWN0LCBXaW5kb3dTY3JvbGxDb250cm9sbGVyLCBwcmV2ZW50U2VsZWN0aW9uLCBwcmV2ZW50Q29udGV4dE1lbnUsIGFsbG93U2VsZWN0aW9uLCBhbGxvd0NvbnRleHRNZW51LCBFbGVtZW50RHJhZ2dpbmcsIGNvbXB1dGVSZWN0LCBnZXRDbGlwcGluZ1BhcmVudHMsIHBvaW50SW5zaWRlUmVjdCwgaXNEYXRlU3BhbnNFcXVhbCwgY29uc3RyYWluUG9pbnQsIGludGVyc2VjdFJlY3RzLCBnZXRSZWN0Q2VudGVyLCBkaWZmUG9pbnRzLCBtYXBIYXNoLCByYW5nZUNvbnRhaW5zUmFuZ2UsIGludGVyYWN0aW9uU2V0dGluZ3NUb1N0b3JlLCBJbnRlcmFjdGlvbiwgZW5hYmxlQ3Vyc29yLCBkaXNhYmxlQ3Vyc29yLCBjb21wYXJlTnVtYmVycywgZ2V0RWxTZWcsIGdldFJlbGV2YW50RXZlbnRzLCBFdmVudEFwaSwgY3JlYXRlRW1wdHlFdmVudFN0b3JlLCBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlLCBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUsIHN0YXJ0T2ZEYXksIGRpZmZEYXRlcywgY3JlYXRlRHVyYXRpb24sIGV2ZW50VHVwbGVUb1N0b3JlLCBpc0ludGVyYWN0aW9uVmFsaWQsIHBhcnNlRHJhZ01ldGEsIGVsZW1lbnRNYXRjaGVzLCBwYXJzZUV2ZW50RGVmLCBjcmVhdGVFdmVudEluc3RhbmNlLCBnbG9iYWxEZWZhdWx0cywgY3JlYXRlUGx1Z2luIH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9jb3JlJztcblxuLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxudmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH07XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufTtcblxuY29uZmlnLnRvdWNoTW91c2VJZ25vcmVXYWl0ID0gNTAwO1xudmFyIGlnbm9yZU1vdXNlRGVwdGggPSAwO1xudmFyIGxpc3RlbmVyQ250ID0gMDtcbnZhciBpc1dpbmRvd1RvdWNoTW92ZUNhbmNlbGxlZCA9IGZhbHNlO1xuLypcblVzZXMgYSBcInBvaW50ZXJcIiBhYnN0cmFjdGlvbiwgd2hpY2ggbW9uaXRvcnMgVUkgZXZlbnRzIGZvciBib3RoIG1vdXNlIGFuZCB0b3VjaC5cblRyYWNrcyB3aGVuIHRoZSBwb2ludGVyIFwiZHJhZ3NcIiBvbiBhIGNlcnRhaW4gZWxlbWVudCwgbWVhbmluZyBkb3duK21vdmUrdXAuXG5cbkFsc28sIHRyYWNrcyBpZiB0aGVyZSB3YXMgdG91Y2gtc2Nyb2xsaW5nLlxuQWxzbywgY2FuIHByZXZlbnQgdG91Y2gtc2Nyb2xsaW5nIGZyb20gaGFwcGVuaW5nLlxuQWxzbywgY2FuIGZpcmUgcG9pbnRlcm1vdmUgZXZlbnRzIHdoZW4gc2Nyb2xsaW5nIGhhcHBlbnMgdW5kZXJuZWF0aCwgZXZlbiB3aGVuIG5vIHJlYWwgcG9pbnRlciBtb3ZlbWVudC5cblxuZW1pdHM6XG4tIHBvaW50ZXJkb3duXG4tIHBvaW50ZXJtb3ZlXG4tIHBvaW50ZXJ1cFxuKi9cbnZhciBQb2ludGVyRHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUG9pbnRlckRyYWdnaW5nKGNvbnRhaW5lckVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3ViamVjdEVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5kb3duRWwgPSBudWxsO1xuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIGRpcmVjdGx5IGFzc2lnbmVkIGJ5IGNhbGxlclxuICAgICAgICB0aGlzLnNlbGVjdG9yID0gJyc7IC8vIHdpbGwgY2F1c2Ugc3ViamVjdEVsIGluIGFsbCBlbWl0dGVkIGV2ZW50cyB0byBiZSB0aGlzIGVsZW1lbnRcbiAgICAgICAgdGhpcy5oYW5kbGVTZWxlY3RvciA9ICcnO1xuICAgICAgICB0aGlzLnNob3VsZElnbm9yZU1vdmUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zaG91bGRXYXRjaFNjcm9sbCA9IHRydWU7IC8vIGZvciBzaW11bGF0aW5nIHBvaW50ZXJtb3ZlIG9uIHNjcm9sbFxuICAgICAgICAvLyBpbnRlcm5hbCBzdGF0ZXNcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNUb3VjaERyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMud2FzVG91Y2hTY3JvbGwgPSBmYWxzZTtcbiAgICAgICAgLy8gTW91c2VcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3VzZSgpICYmXG4gICAgICAgICAgICAgICAgaXNQcmltYXJ5TW91c2VCdXR0b24oZXYpICYmXG4gICAgICAgICAgICAgICAgX3RoaXMudHJ5U3RhcnQoZXYpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBldiA9IF90aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2LCB0cnVlKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgcGV2KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5pbml0U2Nyb2xsV2F0Y2gocGV2KTtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgX3RoaXMuaGFuZGxlTW91c2VNb3ZlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIF90aGlzLmhhbmRsZU1vdXNlVXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlTW92ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIHBldiA9IF90aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2KTtcbiAgICAgICAgICAgIF90aGlzLnJlY29yZENvb3JkcyhwZXYpO1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIHBldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlTW91c2VVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgX3RoaXMuaGFuZGxlTW91c2VNb3ZlKTtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBfdGhpcy5oYW5kbGVNb3VzZVVwKTtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgX3RoaXMuY3JlYXRlRXZlbnRGcm9tTW91c2UoZXYpKTtcbiAgICAgICAgICAgIF90aGlzLmNsZWFudXAoKTsgLy8gY2FsbCBsYXN0IHNvIHRoYXQgcG9pbnRlcnVwIGhhcyBhY2Nlc3MgdG8gcHJvcHNcbiAgICAgICAgfTtcbiAgICAgICAgLy8gVG91Y2hcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICB0aGlzLmhhbmRsZVRvdWNoU3RhcnQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy50cnlTdGFydChldikpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc1RvdWNoRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBwZXYgPSBfdGhpcy5jcmVhdGVFdmVudEZyb21Ub3VjaChldiwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIHBldik7XG4gICAgICAgICAgICAgICAgX3RoaXMuaW5pdFNjcm9sbFdhdGNoKHBldik7XG4gICAgICAgICAgICAgICAgLy8gdW5saWtlIG1vdXNlLCBuZWVkIHRvIGF0dGFjaCB0byB0YXJnZXQsIG5vdCBkb2N1bWVudFxuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS80NTc2MDAxNFxuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSBldi50YXJnZXQ7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBfdGhpcy5oYW5kbGVUb3VjaE1vdmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0YXJnZXQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBfdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoY2FuY2VsJywgX3RoaXMuaGFuZGxlVG91Y2hFbmQpOyAvLyB0cmVhdCBpdCBhcyBhIHRvdWNoIGVuZFxuICAgICAgICAgICAgICAgIC8vIGF0dGFjaCBhIGhhbmRsZXIgdG8gZ2V0IGNhbGxlZCB3aGVuIEFOWSBzY3JvbGwgYWN0aW9uIGhhcHBlbnMgb24gdGhlIHBhZ2UuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB3YXMgaW1wb3NzaWJsZSB0byBkbyB3aXRoIG5vcm1hbCBvbi9vZmYgYmVjYXVzZSAnc2Nyb2xsJyBkb2Vzbid0IGJ1YmJsZS5cbiAgICAgICAgICAgICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMjk1NDU2NS85NjM0MlxuICAgICAgICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBfdGhpcy5oYW5kbGVUb3VjaFNjcm9sbCwgdHJ1ZSAvLyB1c2VDYXB0dXJlXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVUb3VjaE1vdmUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBwZXYgPSBfdGhpcy5jcmVhdGVFdmVudEZyb21Ub3VjaChldik7XG4gICAgICAgICAgICBfdGhpcy5yZWNvcmRDb29yZHMocGV2KTtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcm1vdmUnLCBwZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVRvdWNoRW5kID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykgeyAvLyBkb25lIHRvIGd1YXJkIGFnYWluc3QgdG91Y2hlbmQgZm9sbG93ZWQgYnkgdG91Y2hjYW5jZWxcbiAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZXYudGFyZ2V0O1xuICAgICAgICAgICAgICAgIHRhcmdldC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBfdGhpcy5oYW5kbGVUb3VjaE1vdmUpO1xuICAgICAgICAgICAgICAgIHRhcmdldC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIF90aGlzLmhhbmRsZVRvdWNoRW5kKTtcbiAgICAgICAgICAgICAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCBfdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIF90aGlzLmhhbmRsZVRvdWNoU2Nyb2xsLCB0cnVlKTsgLy8gdXNlQ2FwdHVyZWQ9dHJ1ZVxuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgX3RoaXMuY3JlYXRlRXZlbnRGcm9tVG91Y2goZXYpKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7IC8vIGNhbGwgbGFzdCBzbyB0aGF0IHBvaW50ZXJ1cCBoYXMgYWNjZXNzIHRvIHByb3BzXG4gICAgICAgICAgICAgICAgX3RoaXMuaXNUb3VjaERyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhcnRJZ25vcmluZ01vdXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlVG91Y2hTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy53YXNUb3VjaFNjcm9sbCA9IHRydWU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFnZVggPSAod2luZG93LnBhZ2VYT2Zmc2V0IC0gX3RoaXMucHJldlNjcm9sbFgpICsgX3RoaXMucHJldlBhZ2VYO1xuICAgICAgICAgICAgICAgIHZhciBwYWdlWSA9ICh3aW5kb3cucGFnZVlPZmZzZXQgLSBfdGhpcy5wcmV2U2Nyb2xsWSkgKyBfdGhpcy5wcmV2UGFnZVk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIHtcbiAgICAgICAgICAgICAgICAgICAgb3JpZ0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgaXNUb3VjaDogX3RoaXMuaXNUb3VjaERyYWdnaW5nLFxuICAgICAgICAgICAgICAgICAgICBzdWJqZWN0RWw6IF90aGlzLnN1YmplY3RFbCxcbiAgICAgICAgICAgICAgICAgICAgcGFnZVg6IHBhZ2VYLFxuICAgICAgICAgICAgICAgICAgICBwYWdlWTogcGFnZVksXG4gICAgICAgICAgICAgICAgICAgIGRlbHRhWDogcGFnZVggLSBfdGhpcy5vcmlnUGFnZVgsXG4gICAgICAgICAgICAgICAgICAgIGRlbHRhWTogcGFnZVkgLSBfdGhpcy5vcmlnUGFnZVlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbCA9IGNvbnRhaW5lckVsO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlck1peGluKCk7XG4gICAgICAgIGNvbnRhaW5lckVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuaGFuZGxlTW91c2VEb3duKTtcbiAgICAgICAgY29udGFpbmVyRWwuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuaGFuZGxlVG91Y2hTdGFydCwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgICBsaXN0ZW5lckNyZWF0ZWQoKTtcbiAgICB9XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuaGFuZGxlTW91c2VEb3duKTtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5oYW5kbGVUb3VjaFN0YXJ0LCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gICAgICAgIGxpc3RlbmVyRGVzdHJveWVkKCk7XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLnRyeVN0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHZhciBzdWJqZWN0RWwgPSB0aGlzLnF1ZXJ5U3ViamVjdEVsKGV2KTtcbiAgICAgICAgdmFyIGRvd25FbCA9IGV2LnRhcmdldDtcbiAgICAgICAgaWYgKHN1YmplY3RFbCAmJlxuICAgICAgICAgICAgKCF0aGlzLmhhbmRsZVNlbGVjdG9yIHx8IGVsZW1lbnRDbG9zZXN0KGRvd25FbCwgdGhpcy5oYW5kbGVTZWxlY3RvcikpKSB7XG4gICAgICAgICAgICB0aGlzLnN1YmplY3RFbCA9IHN1YmplY3RFbDtcbiAgICAgICAgICAgIHRoaXMuZG93bkVsID0gZG93bkVsO1xuICAgICAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTsgLy8gZG8gdGhpcyBmaXJzdCBzbyBjYW5jZWxUb3VjaFNjcm9sbCB3aWxsIHdvcmtcbiAgICAgICAgICAgIHRoaXMud2FzVG91Y2hTY3JvbGwgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY2xlYW51cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXNXaW5kb3dUb3VjaE1vdmVDYW5jZWxsZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc3ViamVjdEVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5kb3duRWwgPSBudWxsO1xuICAgICAgICAvLyBrZWVwIHdhc1RvdWNoU2Nyb2xsIGFyb3VuZCBmb3IgbGF0ZXIgYWNjZXNzXG4gICAgICAgIHRoaXMuZGVzdHJveVNjcm9sbFdhdGNoKCk7XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLnF1ZXJ5U3ViamVjdEVsID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudENsb3Nlc3QoZXYudGFyZ2V0LCB0aGlzLnNlbGVjdG9yKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lckVsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLnNob3VsZElnbm9yZU1vdXNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaWdub3JlTW91c2VEZXB0aCB8fCB0aGlzLmlzVG91Y2hEcmFnZ2luZztcbiAgICB9O1xuICAgIC8vIGNhbiBiZSBjYWxsZWQgYnkgdXNlciBvZiB0aGlzIGNsYXNzLCB0byBjYW5jZWwgdG91Y2gtYmFzZWQgc2Nyb2xsaW5nIGZvciB0aGUgY3VycmVudCBkcmFnXG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5jYW5jZWxUb3VjaFNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgaXNXaW5kb3dUb3VjaE1vdmVDYW5jZWxsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBTY3JvbGxpbmcgdGhhdCBzaW11bGF0ZXMgcG9pbnRlcm1vdmVzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuaW5pdFNjcm9sbFdhdGNoID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZFdhdGNoU2Nyb2xsKSB7XG4gICAgICAgICAgICB0aGlzLnJlY29yZENvb3Jkcyhldik7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVTY3JvbGwsIHRydWUpOyAvLyB1c2VDYXB0dXJlPXRydWVcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5yZWNvcmRDb29yZHMgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgaWYgKHRoaXMuc2hvdWxkV2F0Y2hTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMucHJldlBhZ2VYID0gZXYucGFnZVg7XG4gICAgICAgICAgICB0aGlzLnByZXZQYWdlWSA9IGV2LnBhZ2VZO1xuICAgICAgICAgICAgdGhpcy5wcmV2U2Nyb2xsWCA9IHdpbmRvdy5wYWdlWE9mZnNldDtcbiAgICAgICAgICAgIHRoaXMucHJldlNjcm9sbFkgPSB3aW5kb3cucGFnZVlPZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuZGVzdHJveVNjcm9sbFdhdGNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zaG91bGRXYXRjaFNjcm9sbCkge1xuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsLCB0cnVlKTsgLy8gdXNlQ2FwdHVyZWQ9dHJ1ZVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBFdmVudCBOb3JtYWxpemF0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY3JlYXRlRXZlbnRGcm9tTW91c2UgPSBmdW5jdGlvbiAoZXYsIGlzRmlyc3QpIHtcbiAgICAgICAgdmFyIGRlbHRhWCA9IDA7XG4gICAgICAgIHZhciBkZWx0YVkgPSAwO1xuICAgICAgICAvLyBUT0RPOiByZXBlYXQgY29kZVxuICAgICAgICBpZiAoaXNGaXJzdCkge1xuICAgICAgICAgICAgdGhpcy5vcmlnUGFnZVggPSBldi5wYWdlWDtcbiAgICAgICAgICAgIHRoaXMub3JpZ1BhZ2VZID0gZXYucGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkZWx0YVggPSBldi5wYWdlWCAtIHRoaXMub3JpZ1BhZ2VYO1xuICAgICAgICAgICAgZGVsdGFZID0gZXYucGFnZVkgLSB0aGlzLm9yaWdQYWdlWTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3JpZ0V2ZW50OiBldixcbiAgICAgICAgICAgIGlzVG91Y2g6IGZhbHNlLFxuICAgICAgICAgICAgc3ViamVjdEVsOiB0aGlzLnN1YmplY3RFbCxcbiAgICAgICAgICAgIHBhZ2VYOiBldi5wYWdlWCxcbiAgICAgICAgICAgIHBhZ2VZOiBldi5wYWdlWSxcbiAgICAgICAgICAgIGRlbHRhWDogZGVsdGFYLFxuICAgICAgICAgICAgZGVsdGFZOiBkZWx0YVlcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY3JlYXRlRXZlbnRGcm9tVG91Y2ggPSBmdW5jdGlvbiAoZXYsIGlzRmlyc3QpIHtcbiAgICAgICAgdmFyIHRvdWNoZXMgPSBldi50b3VjaGVzO1xuICAgICAgICB2YXIgcGFnZVg7XG4gICAgICAgIHZhciBwYWdlWTtcbiAgICAgICAgdmFyIGRlbHRhWCA9IDA7XG4gICAgICAgIHZhciBkZWx0YVkgPSAwO1xuICAgICAgICAvLyBpZiB0b3VjaCBjb29yZHMgYXZhaWxhYmxlLCBwcmVmZXIsXG4gICAgICAgIC8vIGJlY2F1c2UgRkYgd291bGQgZ2l2ZSBiYWQgZXYucGFnZVggZXYucGFnZVlcbiAgICAgICAgaWYgKHRvdWNoZXMgJiYgdG91Y2hlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHBhZ2VYID0gdG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgICAgIHBhZ2VZID0gdG91Y2hlc1swXS5wYWdlWTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBhZ2VYID0gZXYucGFnZVg7XG4gICAgICAgICAgICBwYWdlWSA9IGV2LnBhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IHJlcGVhdCBjb2RlXG4gICAgICAgIGlmIChpc0ZpcnN0KSB7XG4gICAgICAgICAgICB0aGlzLm9yaWdQYWdlWCA9IHBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5vcmlnUGFnZVkgPSBwYWdlWTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlbHRhWCA9IHBhZ2VYIC0gdGhpcy5vcmlnUGFnZVg7XG4gICAgICAgICAgICBkZWx0YVkgPSBwYWdlWSAtIHRoaXMub3JpZ1BhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBvcmlnRXZlbnQ6IGV2LFxuICAgICAgICAgICAgaXNUb3VjaDogdHJ1ZSxcbiAgICAgICAgICAgIHN1YmplY3RFbDogdGhpcy5zdWJqZWN0RWwsXG4gICAgICAgICAgICBwYWdlWDogcGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogcGFnZVksXG4gICAgICAgICAgICBkZWx0YVg6IGRlbHRhWCxcbiAgICAgICAgICAgIGRlbHRhWTogZGVsdGFZXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gUG9pbnRlckRyYWdnaW5nO1xufSgpKTtcbi8vIFJldHVybnMgYSBib29sZWFuIHdoZXRoZXIgdGhpcyB3YXMgYSBsZWZ0IG1vdXNlIGNsaWNrIGFuZCBubyBjdHJsIGtleSAod2hpY2ggbWVhbnMgcmlnaHQgY2xpY2sgb24gTWFjKVxuZnVuY3Rpb24gaXNQcmltYXJ5TW91c2VCdXR0b24oZXYpIHtcbiAgICByZXR1cm4gZXYuYnV0dG9uID09PSAwICYmICFldi5jdHJsS2V5O1xufVxuLy8gSWdub3JpbmcgZmFrZSBtb3VzZSBldmVudHMgZ2VuZXJhdGVkIGJ5IHRvdWNoXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBzdGFydElnbm9yaW5nTW91c2UoKSB7XG4gICAgaWdub3JlTW91c2VEZXB0aCsrO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZ25vcmVNb3VzZURlcHRoLS07XG4gICAgfSwgY29uZmlnLnRvdWNoTW91c2VJZ25vcmVXYWl0KTtcbn1cbi8vIFdlIHdhbnQgdG8gYXR0YWNoIHRvdWNobW92ZSBhcyBlYXJseSBhcyBwb3NzaWJsZSBmb3IgU2FmYXJpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBsaXN0ZW5lckNyZWF0ZWQoKSB7XG4gICAgaWYgKCEobGlzdGVuZXJDbnQrKykpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIG9uV2luZG93VG91Y2hNb3ZlLCB7IHBhc3NpdmU6IGZhbHNlIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGxpc3RlbmVyRGVzdHJveWVkKCkge1xuICAgIGlmICghKC0tbGlzdGVuZXJDbnQpKSB7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBvbldpbmRvd1RvdWNoTW92ZSwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICB9XG59XG5mdW5jdGlvbiBvbldpbmRvd1RvdWNoTW92ZShldikge1xuICAgIGlmIChpc1dpbmRvd1RvdWNoTW92ZUNhbmNlbGxlZCkge1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cblxuLypcbkFuIGVmZmVjdCBpbiB3aGljaCBhbiBlbGVtZW50IGZvbGxvd3MgdGhlIG1vdmVtZW50IG9mIGEgcG9pbnRlciBhY3Jvc3MgdGhlIHNjcmVlbi5cblRoZSBtb3ZpbmcgZWxlbWVudCBpcyBhIGNsb25lIG9mIHNvbWUgb3RoZXIgZWxlbWVudC5cbk11c3QgY2FsbCBzdGFydCArIGhhbmRsZU1vdmUgKyBzdG9wLlxuKi9cbnZhciBFbGVtZW50TWlycm9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEVsZW1lbnRNaXJyb3IoKSB7XG4gICAgICAgIHRoaXMuaXNWaXNpYmxlID0gZmFsc2U7IC8vIG11c3QgYmUgZXhwbGljaXRseSBlbmFibGVkXG4gICAgICAgIHRoaXMuc291cmNlRWwgPSBudWxsO1xuICAgICAgICB0aGlzLm1pcnJvckVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5zb3VyY2VFbFJlY3QgPSBudWxsOyAvLyBzY3JlZW4gY29vcmRzIHJlbGF0aXZlIHRvIHZpZXdwb3J0XG4gICAgICAgIC8vIG9wdGlvbnMgdGhhdCBjYW4gYmUgc2V0IGRpcmVjdGx5IGJ5IGNhbGxlclxuICAgICAgICB0aGlzLnBhcmVudE5vZGUgPSBkb2N1bWVudC5ib2R5O1xuICAgICAgICB0aGlzLnpJbmRleCA9IDk5OTk7XG4gICAgICAgIHRoaXMucmV2ZXJ0RHVyYXRpb24gPSAwO1xuICAgIH1cbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChzb3VyY2VFbCwgcGFnZVgsIHBhZ2VZKSB7XG4gICAgICAgIHRoaXMuc291cmNlRWwgPSBzb3VyY2VFbDtcbiAgICAgICAgdGhpcy5zb3VyY2VFbFJlY3QgPSB0aGlzLnNvdXJjZUVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLm9yaWdTY3JlZW5YID0gcGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQ7XG4gICAgICAgIHRoaXMub3JpZ1NjcmVlblkgPSBwYWdlWSAtIHdpbmRvdy5wYWdlWU9mZnNldDtcbiAgICAgICAgdGhpcy5kZWx0YVggPSAwO1xuICAgICAgICB0aGlzLmRlbHRhWSA9IDA7XG4gICAgICAgIHRoaXMudXBkYXRlRWxQb3NpdGlvbigpO1xuICAgIH07XG4gICAgRWxlbWVudE1pcnJvci5wcm90b3R5cGUuaGFuZGxlTW92ZSA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgdGhpcy5kZWx0YVggPSAocGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQpIC0gdGhpcy5vcmlnU2NyZWVuWDtcbiAgICAgICAgdGhpcy5kZWx0YVkgPSAocGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQpIC0gdGhpcy5vcmlnU2NyZWVuWTtcbiAgICAgICAgdGhpcy51cGRhdGVFbFBvc2l0aW9uKCk7XG4gICAgfTtcbiAgICAvLyBjYW4gYmUgY2FsbGVkIGJlZm9yZSBzdGFydFxuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLnNldElzVmlzaWJsZSA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIGlmIChib29sKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5taXJyb3JFbC5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaXNWaXNpYmxlID0gYm9vbDsgLy8gbmVlZHMgdG8gaGFwcGVuIGJlZm9yZSB1cGRhdGVFbFBvc2l0aW9uXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVFbFBvc2l0aW9uKCk7IC8vIGJlY2F1c2Ugd2FzIG5vdCB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgaW52aXNpYmxlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5taXJyb3JFbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pcnJvckVsLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaXNWaXNpYmxlID0gYm9vbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gYWx3YXlzIGFzeW5jXG4gICAgRWxlbWVudE1pcnJvci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uIChuZWVkc1JldmVydEFuaW1hdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGRvbmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAobmVlZHNSZXZlcnRBbmltYXRpb24gJiZcbiAgICAgICAgICAgIHRoaXMubWlycm9yRWwgJiZcbiAgICAgICAgICAgIHRoaXMuaXNWaXNpYmxlICYmXG4gICAgICAgICAgICB0aGlzLnJldmVydER1cmF0aW9uICYmIC8vIGlmIDAsIHRyYW5zaXRpb24gd29uJ3Qgd29ya1xuICAgICAgICAgICAgKHRoaXMuZGVsdGFYIHx8IHRoaXMuZGVsdGFZKSAvLyBpZiBzYW1lIGNvb3JkcywgdHJhbnNpdGlvbiB3b24ndCB3b3JrXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5kb1JldmVydEFuaW1hdGlvbihkb25lLCB0aGlzLnJldmVydER1cmF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZG9uZSwgMCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmRvUmV2ZXJ0QW5pbWF0aW9uID0gZnVuY3Rpb24gKGNhbGxiYWNrLCByZXZlcnREdXJhdGlvbikge1xuICAgICAgICB2YXIgbWlycm9yRWwgPSB0aGlzLm1pcnJvckVsO1xuICAgICAgICB2YXIgZmluYWxTb3VyY2VFbFJlY3QgPSB0aGlzLnNvdXJjZUVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyBiZWNhdXNlIGF1dG9zY3JvbGxpbmcgbWlnaHQgaGF2ZSBoYXBwZW5lZFxuICAgICAgICBtaXJyb3JFbC5zdHlsZS50cmFuc2l0aW9uID1cbiAgICAgICAgICAgICd0b3AgJyArIHJldmVydER1cmF0aW9uICsgJ21zLCcgK1xuICAgICAgICAgICAgICAgICdsZWZ0ICcgKyByZXZlcnREdXJhdGlvbiArICdtcyc7XG4gICAgICAgIGFwcGx5U3R5bGUobWlycm9yRWwsIHtcbiAgICAgICAgICAgIGxlZnQ6IGZpbmFsU291cmNlRWxSZWN0LmxlZnQsXG4gICAgICAgICAgICB0b3A6IGZpbmFsU291cmNlRWxSZWN0LnRvcFxuICAgICAgICB9KTtcbiAgICAgICAgd2hlblRyYW5zaXRpb25Eb25lKG1pcnJvckVsLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBtaXJyb3JFbC5zdHlsZS50cmFuc2l0aW9uID0gJyc7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmNsZWFudXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm1pcnJvckVsKSB7XG4gICAgICAgICAgICByZW1vdmVFbGVtZW50KHRoaXMubWlycm9yRWwpO1xuICAgICAgICAgICAgdGhpcy5taXJyb3JFbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zb3VyY2VFbCA9IG51bGw7XG4gICAgfTtcbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS51cGRhdGVFbFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VFbCAmJiB0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmdldE1pcnJvckVsKCksIHtcbiAgICAgICAgICAgICAgICBsZWZ0OiB0aGlzLnNvdXJjZUVsUmVjdC5sZWZ0ICsgdGhpcy5kZWx0YVgsXG4gICAgICAgICAgICAgICAgdG9wOiB0aGlzLnNvdXJjZUVsUmVjdC50b3AgKyB0aGlzLmRlbHRhWVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmdldE1pcnJvckVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc291cmNlRWxSZWN0ID0gdGhpcy5zb3VyY2VFbFJlY3Q7XG4gICAgICAgIHZhciBtaXJyb3JFbCA9IHRoaXMubWlycm9yRWw7XG4gICAgICAgIGlmICghbWlycm9yRWwpIHtcbiAgICAgICAgICAgIG1pcnJvckVsID0gdGhpcy5taXJyb3JFbCA9IHRoaXMuc291cmNlRWwuY2xvbmVOb2RlKHRydWUpOyAvLyBjbG9uZUNoaWxkcmVuPXRydWVcbiAgICAgICAgICAgIC8vIHdlIGRvbid0IHdhbnQgbG9uZyB0YXBzIG9yIGFueSBtb3VzZSBpbnRlcmFjdGlvbiBjYXVzaW5nIHNlbGVjdGlvbi9tZW51cy5cbiAgICAgICAgICAgIC8vIHdvdWxkIHVzZSBwcmV2ZW50U2VsZWN0aW9uKCksIGJ1dCB0aGF0IHByZXZlbnRzIHNlbGVjdHN0YXJ0LCBjYXVzaW5nIHByb2JsZW1zLlxuICAgICAgICAgICAgbWlycm9yRWwuY2xhc3NMaXN0LmFkZCgnZmMtdW5zZWxlY3RhYmxlJyk7XG4gICAgICAgICAgICBtaXJyb3JFbC5jbGFzc0xpc3QuYWRkKCdmYy1kcmFnZ2luZycpO1xuICAgICAgICAgICAgYXBwbHlTdHlsZShtaXJyb3JFbCwge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnZml4ZWQnLFxuICAgICAgICAgICAgICAgIHpJbmRleDogdGhpcy56SW5kZXgsXG4gICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogJycsXG4gICAgICAgICAgICAgICAgYm94U2l6aW5nOiAnYm9yZGVyLWJveCcsXG4gICAgICAgICAgICAgICAgd2lkdGg6IHNvdXJjZUVsUmVjdC5yaWdodCAtIHNvdXJjZUVsUmVjdC5sZWZ0LFxuICAgICAgICAgICAgICAgIGhlaWdodDogc291cmNlRWxSZWN0LmJvdHRvbSAtIHNvdXJjZUVsUmVjdC50b3AsXG4gICAgICAgICAgICAgICAgcmlnaHQ6ICdhdXRvJyxcbiAgICAgICAgICAgICAgICBib3R0b206ICdhdXRvJyxcbiAgICAgICAgICAgICAgICBtYXJnaW46IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5wYXJlbnROb2RlLmFwcGVuZENoaWxkKG1pcnJvckVsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWlycm9yRWw7XG4gICAgfTtcbiAgICByZXR1cm4gRWxlbWVudE1pcnJvcjtcbn0oKSk7XG5cbi8qXG5JcyBhIGNhY2hlIGZvciBhIGdpdmVuIGVsZW1lbnQncyBzY3JvbGwgaW5mb3JtYXRpb24gKGFsbCB0aGUgaW5mbyB0aGF0IFNjcm9sbENvbnRyb2xsZXIgc3RvcmVzKVxuaW4gYWRkaXRpb24gdGhlIFwiY2xpZW50IHJlY3RhbmdsZVwiIG9mIHRoZSBlbGVtZW50Li4gdGhlIGFyZWEgd2l0aGluIHRoZSBzY3JvbGxiYXJzLlxuXG5UaGUgY2FjaGUgY2FuIGJlIGluIG9uZSBvZiB0d28gbW9kZXM6XG4tIGRvZXNMaXN0ZW5pbmc6ZmFsc2UgLSBpZ25vcmVzIHdoZW4gdGhlIGNvbnRhaW5lciBpcyBzY3JvbGxlZCBieSBzb21lb25lIGVsc2Vcbi0gZG9lc0xpc3RlbmluZzp0cnVlIC0gd2F0Y2ggZm9yIHNjcm9sbGluZyBhbmQgdXBkYXRlIHRoZSBjYWNoZVxuKi9cbnZhciBTY3JvbGxHZW9tQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNjcm9sbEdlb21DYWNoZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTY3JvbGxHZW9tQ2FjaGUoc2Nyb2xsQ29udHJvbGxlciwgZG9lc0xpc3RlbmluZykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5oYW5kbGVTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5zY3JvbGxUb3AgPSBfdGhpcy5zY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbFRvcCgpO1xuICAgICAgICAgICAgX3RoaXMuc2Nyb2xsTGVmdCA9IF90aGlzLnNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgX3RoaXMuaGFuZGxlU2Nyb2xsQ2hhbmdlKCk7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLnNjcm9sbENvbnRyb2xsZXIgPSBzY3JvbGxDb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5kb2VzTGlzdGVuaW5nID0gZG9lc0xpc3RlbmluZztcbiAgICAgICAgX3RoaXMuc2Nyb2xsVG9wID0gX3RoaXMub3JpZ1Njcm9sbFRvcCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsVG9wKCk7XG4gICAgICAgIF90aGlzLnNjcm9sbExlZnQgPSBfdGhpcy5vcmlnU2Nyb2xsTGVmdCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsTGVmdCgpO1xuICAgICAgICBfdGhpcy5zY3JvbGxXaWR0aCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsV2lkdGgoKTtcbiAgICAgICAgX3RoaXMuc2Nyb2xsSGVpZ2h0ID0gc2Nyb2xsQ29udHJvbGxlci5nZXRTY3JvbGxIZWlnaHQoKTtcbiAgICAgICAgX3RoaXMuY2xpZW50V2lkdGggPSBzY3JvbGxDb250cm9sbGVyLmdldENsaWVudFdpZHRoKCk7XG4gICAgICAgIF90aGlzLmNsaWVudEhlaWdodCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0Q2xpZW50SGVpZ2h0KCk7XG4gICAgICAgIF90aGlzLmNsaWVudFJlY3QgPSBfdGhpcy5jb21wdXRlQ2xpZW50UmVjdCgpOyAvLyBkbyBsYXN0IGluIGNhc2UgaXQgbmVlZHMgY2FjaGVkIHZhbHVlc1xuICAgICAgICBpZiAoX3RoaXMuZG9lc0xpc3RlbmluZykge1xuICAgICAgICAgICAgX3RoaXMuZ2V0RXZlbnRUYXJnZXQoKS5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBfdGhpcy5oYW5kbGVTY3JvbGwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmdldEV2ZW50VGFyZ2V0KCkucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVTY3JvbGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldFNjcm9sbFRvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsVG9wO1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxMZWZ0O1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5zZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAodG9wKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udHJvbGxlci5zZXRTY3JvbGxUb3AodG9wKTtcbiAgICAgICAgaWYgKCF0aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSBub3QgcmVseWluZyBvbiB0aGUgZWxlbWVudCB0byBub3JtYWxpemUgb3V0LW9mLWJvdW5kcyBzY3JvbGwgdmFsdWVzXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIHNhbml0aXplIG91cnNlbHZlc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxUb3AgPSBNYXRoLm1heChNYXRoLm1pbih0b3AsIHRoaXMuZ2V0TWF4U2Nyb2xsVG9wKCkpLCAwKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICh0b3ApIHtcbiAgICAgICAgdGhpcy5zY3JvbGxDb250cm9sbGVyLnNldFNjcm9sbExlZnQodG9wKTtcbiAgICAgICAgaWYgKCF0aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSBub3QgcmVseWluZyBvbiB0aGUgZWxlbWVudCB0byBub3JtYWxpemUgb3V0LW9mLWJvdW5kcyBzY3JvbGwgdmFsdWVzXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIHNhbml0aXplIG91cnNlbHZlc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxMZWZ0ID0gTWF0aC5tYXgoTWF0aC5taW4odG9wLCB0aGlzLmdldE1heFNjcm9sbExlZnQoKSksIDApO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGxDaGFuZ2UoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRDbGllbnRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50V2lkdGg7XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldENsaWVudEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50SGVpZ2h0O1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRTY3JvbGxXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsV2lkdGg7XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsSGVpZ2h0O1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5oYW5kbGVTY3JvbGxDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICByZXR1cm4gU2Nyb2xsR2VvbUNhY2hlO1xufShTY3JvbGxDb250cm9sbGVyKSk7XG52YXIgRWxlbWVudFNjcm9sbEdlb21DYWNoZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRWxlbWVudFNjcm9sbEdlb21DYWNoZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlKGVsLCBkb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuZXcgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIoZWwpLCBkb2VzTGlzdGVuaW5nKSB8fCB0aGlzO1xuICAgIH1cbiAgICBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRFdmVudFRhcmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsQ29udHJvbGxlci5lbDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmNvbXB1dGVDbGllbnRSZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gY29tcHV0ZUlubmVyUmVjdCh0aGlzLnNjcm9sbENvbnRyb2xsZXIuZWwpO1xuICAgIH07XG4gICAgcmV0dXJuIEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGU7XG59KFNjcm9sbEdlb21DYWNoZSkpO1xudmFyIFdpbmRvd1Njcm9sbEdlb21DYWNoZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoV2luZG93U2Nyb2xsR2VvbUNhY2hlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFdpbmRvd1Njcm9sbEdlb21DYWNoZShkb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuZXcgV2luZG93U2Nyb2xsQ29udHJvbGxlcigpLCBkb2VzTGlzdGVuaW5nKSB8fCB0aGlzO1xuICAgIH1cbiAgICBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldEV2ZW50VGFyZ2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gd2luZG93O1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5jb21wdXRlQ2xpZW50UmVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxlZnQ6IHRoaXMuc2Nyb2xsTGVmdCxcbiAgICAgICAgICAgIHJpZ2h0OiB0aGlzLnNjcm9sbExlZnQgKyB0aGlzLmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgdG9wOiB0aGlzLnNjcm9sbFRvcCxcbiAgICAgICAgICAgIGJvdHRvbTogdGhpcy5zY3JvbGxUb3AgKyB0aGlzLmNsaWVudEhlaWdodFxuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gdGhlIHdpbmRvdyBpcyB0aGUgb25seSBzY3JvbGwgb2JqZWN0IHRoYXQgY2hhbmdlcyBpdCdzIHJlY3RhbmdsZSByZWxhdGl2ZVxuICAgIC8vIHRvIHRoZSBkb2N1bWVudCdzIHRvcGxlZnQgYXMgaXQgc2Nyb2xsc1xuICAgIFdpbmRvd1Njcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuaGFuZGxlU2Nyb2xsQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsaWVudFJlY3QgPSB0aGlzLmNvbXB1dGVDbGllbnRSZWN0KCk7XG4gICAgfTtcbiAgICByZXR1cm4gV2luZG93U2Nyb2xsR2VvbUNhY2hlO1xufShTY3JvbGxHZW9tQ2FjaGUpKTtcblxuLy8gSWYgYXZhaWxhYmxlIHdlIGFyZSB1c2luZyBuYXRpdmUgXCJwZXJmb3JtYW5jZVwiIEFQSSBpbnN0ZWFkIG9mIFwiRGF0ZVwiXG4vLyBSZWFkIG1vcmUgYWJvdXQgaXQgb24gTUROOlxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1BlcmZvcm1hbmNlXG52YXIgZ2V0VGltZSA9IHR5cGVvZiBwZXJmb3JtYW5jZSA9PT0gJ2Z1bmN0aW9uJyA/IHBlcmZvcm1hbmNlLm5vdyA6IERhdGUubm93O1xuLypcbkZvciBhIHBvaW50ZXIgaW50ZXJhY3Rpb24sIGF1dG9tYXRpY2FsbHkgc2Nyb2xscyBjZXJ0YWluIHNjcm9sbCBjb250YWluZXJzIHdoZW4gdGhlIHBvaW50ZXJcbmFwcHJvYWNoZXMgdGhlIGVkZ2UuXG5cblRoZSBjYWxsZXIgbXVzdCBjYWxsIHN0YXJ0ICsgaGFuZGxlTW92ZSArIHN0b3AuXG4qL1xudmFyIEF1dG9TY3JvbGxlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBBdXRvU2Nyb2xsZXIoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIG9wdGlvbnMgdGhhdCBjYW4gYmUgc2V0IGJ5IGNhbGxlclxuICAgICAgICB0aGlzLmlzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuc2Nyb2xsUXVlcnkgPSBbd2luZG93LCAnLmZjLXNjcm9sbGVyJ107XG4gICAgICAgIHRoaXMuZWRnZVRocmVzaG9sZCA9IDUwOyAvLyBwaXhlbHNcbiAgICAgICAgdGhpcy5tYXhWZWxvY2l0eSA9IDMwMDsgLy8gcGl4ZWxzIHBlciBzZWNvbmRcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWCA9IG51bGw7XG4gICAgICAgIHRoaXMucG9pbnRlclNjcmVlblkgPSBudWxsO1xuICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ2FjaGVzID0gbnVsbDtcbiAgICAgICAgLy8gcHJvdGVjdCBhZ2FpbnN0IHRoZSBpbml0aWFsIHBvaW50ZXJkb3duIGJlaW5nIHRvbyBjbG9zZSB0byBhbiBlZGdlIGFuZCBzdGFydGluZyB0aGUgc2Nyb2xsXG4gICAgICAgIHRoaXMuZXZlck1vdmVkVXAgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVyTW92ZWREb3duID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlck1vdmVkTGVmdCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmV2ZXJNb3ZlZFJpZ2h0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYW5pbWF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0FuaW1hdGluZykgeyAvLyB3YXNuJ3QgY2FuY2VsbGVkIGJldHdlZW4gYW5pbWF0aW9uIGNhbGxzXG4gICAgICAgICAgICAgICAgdmFyIGVkZ2UgPSBfdGhpcy5jb21wdXRlQmVzdEVkZ2UoX3RoaXMucG9pbnRlclNjcmVlblggKyB3aW5kb3cucGFnZVhPZmZzZXQsIF90aGlzLnBvaW50ZXJTY3JlZW5ZICsgd2luZG93LnBhZ2VZT2Zmc2V0KTtcbiAgICAgICAgICAgICAgICBpZiAoZWRnZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm93ID0gZ2V0VGltZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5oYW5kbGVTaWRlKGVkZ2UsIChub3cgLSBfdGhpcy5tc1NpbmNlUmVxdWVzdCkgLyAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVxdWVzdEFuaW1hdGlvbihub3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaXNBbmltYXRpbmcgPSBmYWxzZTsgLy8gd2lsbCBzdG9wIGFuaW1hdGlvblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENhY2hlcyA9IHRoaXMuYnVpbGRDYWNoZXMoKTtcbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblggPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFVwID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZERvd24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZXZlck1vdmVkTGVmdCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRSaWdodCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVNb3ZlKHBhZ2VYLCBwYWdlWSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUuaGFuZGxlTW92ZSA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB2YXIgcG9pbnRlclNjcmVlblggPSBwYWdlWCAtIHdpbmRvdy5wYWdlWE9mZnNldDtcbiAgICAgICAgICAgIHZhciBwb2ludGVyU2NyZWVuWSA9IHBhZ2VZIC0gd2luZG93LnBhZ2VZT2Zmc2V0O1xuICAgICAgICAgICAgdmFyIHlEZWx0YSA9IHRoaXMucG9pbnRlclNjcmVlblkgPT09IG51bGwgPyAwIDogcG9pbnRlclNjcmVlblkgLSB0aGlzLnBvaW50ZXJTY3JlZW5ZO1xuICAgICAgICAgICAgdmFyIHhEZWx0YSA9IHRoaXMucG9pbnRlclNjcmVlblggPT09IG51bGwgPyAwIDogcG9pbnRlclNjcmVlblggLSB0aGlzLnBvaW50ZXJTY3JlZW5YO1xuICAgICAgICAgICAgaWYgKHlEZWx0YSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFVwID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHlEZWx0YSA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZERvd24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhEZWx0YSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZExlZnQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoeERlbHRhID4gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlck1vdmVkUmlnaHQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWCA9IHBvaW50ZXJTY3JlZW5YO1xuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWSA9IHBvaW50ZXJTY3JlZW5ZO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzQW5pbWF0aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0FuaW1hdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0QW5pbWF0aW9uKGdldFRpbWUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7IC8vIHdpbGwgc3RvcCBhbmltYXRpb25cbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbENhY2hlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLnJlcXVlc3RBbmltYXRpb24gPSBmdW5jdGlvbiAobm93KSB7XG4gICAgICAgIHRoaXMubXNTaW5jZVJlcXVlc3QgPSBub3c7XG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLmFuaW1hdGUpO1xuICAgIH07XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5oYW5kbGVTaWRlID0gZnVuY3Rpb24gKGVkZ2UsIHNlY29uZHMpIHtcbiAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gZWRnZS5zY3JvbGxDYWNoZTtcbiAgICAgICAgdmFyIGVkZ2VUaHJlc2hvbGQgPSB0aGlzLmVkZ2VUaHJlc2hvbGQ7XG4gICAgICAgIHZhciBpbnZEaXN0YW5jZSA9IGVkZ2VUaHJlc2hvbGQgLSBlZGdlLmRpc3RhbmNlO1xuICAgICAgICB2YXIgdmVsb2NpdHkgPSAvLyB0aGUgY2xvc2VyIHRvIHRoZSBlZGdlLCB0aGUgZmFzdGVyIHdlIHNjcm9sbFxuICAgICAgICAgKGludkRpc3RhbmNlICogaW52RGlzdGFuY2UpIC8gKGVkZ2VUaHJlc2hvbGQgKiBlZGdlVGhyZXNob2xkKSAqIC8vIHF1YWRyYXRpY1xuICAgICAgICAgICAgdGhpcy5tYXhWZWxvY2l0eSAqIHNlY29uZHM7XG4gICAgICAgIHZhciBzaWduID0gMTtcbiAgICAgICAgc3dpdGNoIChlZGdlLm5hbWUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICAgICAgICAgIHNpZ24gPSAtMTtcbiAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgICAgICAgICBzY3JvbGxDYWNoZS5zZXRTY3JvbGxMZWZ0KHNjcm9sbENhY2hlLmdldFNjcm9sbExlZnQoKSArIHZlbG9jaXR5ICogc2lnbik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgICAgICAgIHNpZ24gPSAtMTtcbiAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuc2V0U2Nyb2xsVG9wKHNjcm9sbENhY2hlLmdldFNjcm9sbFRvcCgpICsgdmVsb2NpdHkgKiBzaWduKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gbGVmdC90b3AgYXJlIHJlbGF0aXZlIHRvIGRvY3VtZW50IHRvcGxlZnRcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLmNvbXB1dGVCZXN0RWRnZSA9IGZ1bmN0aW9uIChsZWZ0LCB0b3ApIHtcbiAgICAgICAgdmFyIGVkZ2VUaHJlc2hvbGQgPSB0aGlzLmVkZ2VUaHJlc2hvbGQ7XG4gICAgICAgIHZhciBiZXN0U2lkZSA9IG51bGw7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbENhY2hlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzY3JvbGxDYWNoZSA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciByZWN0ID0gc2Nyb2xsQ2FjaGUuY2xpZW50UmVjdDtcbiAgICAgICAgICAgIHZhciBsZWZ0RGlzdCA9IGxlZnQgLSByZWN0LmxlZnQ7XG4gICAgICAgICAgICB2YXIgcmlnaHREaXN0ID0gcmVjdC5yaWdodCAtIGxlZnQ7XG4gICAgICAgICAgICB2YXIgdG9wRGlzdCA9IHRvcCAtIHJlY3QudG9wO1xuICAgICAgICAgICAgdmFyIGJvdHRvbURpc3QgPSByZWN0LmJvdHRvbSAtIHRvcDtcbiAgICAgICAgICAgIC8vIGNvbXBsZXRlbHkgd2l0aGluIHRoZSByZWN0P1xuICAgICAgICAgICAgaWYgKGxlZnREaXN0ID49IDAgJiYgcmlnaHREaXN0ID49IDAgJiYgdG9wRGlzdCA+PSAwICYmIGJvdHRvbURpc3QgPj0gMCkge1xuICAgICAgICAgICAgICAgIGlmICh0b3BEaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRVcCAmJiBzY3JvbGxDYWNoZS5jYW5TY3JvbGxVcCgpICYmXG4gICAgICAgICAgICAgICAgICAgICghYmVzdFNpZGUgfHwgYmVzdFNpZGUuZGlzdGFuY2UgPiB0b3BEaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGU6IHNjcm9sbENhY2hlLCBuYW1lOiAndG9wJywgZGlzdGFuY2U6IHRvcERpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJvdHRvbURpc3QgPD0gZWRnZVRocmVzaG9sZCAmJiB0aGlzLmV2ZXJNb3ZlZERvd24gJiYgc2Nyb2xsQ2FjaGUuY2FuU2Nyb2xsRG93bigpICYmXG4gICAgICAgICAgICAgICAgICAgICghYmVzdFNpZGUgfHwgYmVzdFNpZGUuZGlzdGFuY2UgPiBib3R0b21EaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGU6IHNjcm9sbENhY2hlLCBuYW1lOiAnYm90dG9tJywgZGlzdGFuY2U6IGJvdHRvbURpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGxlZnREaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRMZWZ0ICYmIHNjcm9sbENhY2hlLmNhblNjcm9sbExlZnQoKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIWJlc3RTaWRlIHx8IGJlc3RTaWRlLmRpc3RhbmNlID4gbGVmdERpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RTaWRlID0geyBzY3JvbGxDYWNoZTogc2Nyb2xsQ2FjaGUsIG5hbWU6ICdsZWZ0JywgZGlzdGFuY2U6IGxlZnREaXN0IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyaWdodERpc3QgPD0gZWRnZVRocmVzaG9sZCAmJiB0aGlzLmV2ZXJNb3ZlZFJpZ2h0ICYmIHNjcm9sbENhY2hlLmNhblNjcm9sbFJpZ2h0KCkgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFiZXN0U2lkZSB8fCBiZXN0U2lkZS5kaXN0YW5jZSA+IHJpZ2h0RGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFNpZGUgPSB7IHNjcm9sbENhY2hlOiBzY3JvbGxDYWNoZSwgbmFtZTogJ3JpZ2h0JywgZGlzdGFuY2U6IHJpZ2h0RGlzdCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmVzdFNpZGU7XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLmJ1aWxkQ2FjaGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5xdWVyeVNjcm9sbEVscygpLm1hcChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbCA9PT0gd2luZG93KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUoZmFsc2UpOyAvLyBmYWxzZSA9IGRvbid0IGxpc3RlbiB0byB1c2VyLWdlbmVyYXRlZCBzY3JvbGxzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUoZWwsIGZhbHNlKTsgLy8gZmFsc2UgPSBkb24ndCBsaXN0ZW4gdG8gdXNlci1nZW5lcmF0ZWQgc2Nyb2xsc1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUucXVlcnlTY3JvbGxFbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlbHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsUXVlcnk7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcXVlcnkgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIHF1ZXJ5ID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIGVscy5wdXNoKHF1ZXJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGVscy5wdXNoLmFwcGx5KGVscywgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChxdWVyeSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxzO1xuICAgIH07XG4gICAgcmV0dXJuIEF1dG9TY3JvbGxlcjtcbn0oKSk7XG5cbi8qXG5Nb25pdG9ycyBkcmFnZ2luZyBvbiBhbiBlbGVtZW50LiBIYXMgYSBudW1iZXIgb2YgaGlnaC1sZXZlbCBmZWF0dXJlczpcbi0gbWluaW11bSBkaXN0YW5jZSByZXF1aXJlZCBiZWZvcmUgZHJhZ2dpbmdcbi0gbWluaW11bSB3YWl0IHRpbWUgKFwiZGVsYXlcIikgYmVmb3JlIGRyYWdnaW5nXG4tIGEgbWlycm9yIGVsZW1lbnQgdGhhdCBmb2xsb3dzIHRoZSBwb2ludGVyXG4qL1xudmFyIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhjb250YWluZXJFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjb250YWluZXJFbCkgfHwgdGhpcztcbiAgICAgICAgLy8gb3B0aW9ucyB0aGF0IGNhbiBiZSBkaXJlY3RseSBzZXQgYnkgY2FsbGVyXG4gICAgICAgIC8vIHRoZSBjYWxsZXIgY2FuIGFsc28gc2V0IHRoZSBQb2ludGVyRHJhZ2dpbmcncyBvcHRpb25zIGFzIHdlbGxcbiAgICAgICAgX3RoaXMuZGVsYXkgPSBudWxsO1xuICAgICAgICBfdGhpcy5taW5EaXN0YW5jZSA9IDA7XG4gICAgICAgIF90aGlzLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IHRydWU7IC8vIHByZXZlbnRzIGRyYWcgZnJvbSBzdGFydGluZyBhbmQgYmxvY2tzIHNjcm9sbGluZyBkdXJpbmcgZHJhZ1xuICAgICAgICBfdGhpcy5taXJyb3JOZWVkc1JldmVydCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc0ludGVyYWN0aW5nID0gZmFsc2U7IC8vIGlzIHRoZSB1c2VyIHZhbGlkbHkgbW92aW5nIHRoZSBwb2ludGVyPyBsYXN0cyB1bnRpbCBwb2ludGVydXBcbiAgICAgICAgX3RoaXMuaXNEcmFnZ2luZyA9IGZhbHNlOyAvLyBpcyBpdCBJTlRFTlRGVUxMWSBkcmFnZ2luZz8gbGFzdHMgdW50aWwgYWZ0ZXIgcmV2ZXJ0IGFuaW1hdGlvblxuICAgICAgICBfdGhpcy5pc0RlbGF5RW5kZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5kZWxheVRpbWVvdXRJZCA9IG51bGw7XG4gICAgICAgIF90aGlzLm9uUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuaXNEcmFnZ2luZykgeyAvLyBzbyBuZXcgZHJhZyBkb2Vzbid0IGhhcHBlbiB3aGlsZSByZXZlcnQgYW5pbWF0aW9uIGlzIGdvaW5nXG4gICAgICAgICAgICAgICAgX3RoaXMuaXNJbnRlcmFjdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNEZWxheUVuZGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHByZXZlbnRTZWxlY3Rpb24oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgcHJldmVudENvbnRleHRNZW51KGRvY3VtZW50LmJvZHkpO1xuICAgICAgICAgICAgICAgIC8vIHByZXZlbnQgbGlua3MgZnJvbSBiZWluZyB2aXNpdGVkIGlmIHRoZXJlJ3MgYW4gZXZlbnR1YWwgZHJhZy5cbiAgICAgICAgICAgICAgICAvLyBhbHNvIHByZXZlbnRzIHNlbGVjdGlvbiBpbiBvbGRlciBicm93c2VycyAobWF5YmU/KS5cbiAgICAgICAgICAgICAgICAvLyBub3QgbmVjZXNzYXJ5IGZvciB0b3VjaCwgYmVzaWRlcywgYnJvd3NlciB3b3VsZCBjb21wbGFpbiBhYm91dCBwYXNzaXZlbmVzcy5cbiAgICAgICAgICAgICAgICBpZiAoIWV2LmlzVG91Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgZXYub3JpZ0V2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcmRvd24nLCBldik7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5wb2ludGVyLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYWN0aW9ucyByZWxhdGVkIHRvIGluaXRpYXRpbmcgZHJhZ3N0YXJ0K2RyYWdtb3ZlK2RyYWdlbmQuLi5cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubWlycm9yLnNldElzVmlzaWJsZShmYWxzZSk7IC8vIHJlc2V0LiBjYWxsZXIgbXVzdCBzZXQtdmlzaWJsZVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5taXJyb3Iuc3RhcnQoZXYuc3ViamVjdEVsLCBldi5wYWdlWCwgZXYucGFnZVkpOyAvLyBtdXN0IGhhcHBlbiBvbiBmaXJzdCBwb2ludGVyIGRvd25cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc3RhcnREZWxheShldik7XG4gICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMubWluRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmhhbmRsZURpc3RhbmNlU3VycGFzc2VkKGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMub25Qb2ludGVyTW92ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmlzSW50ZXJhY3RpbmcpIHsgLy8gaWYgZmFsc2UsIHN0aWxsIHdhaXRpbmcgZm9yIHByZXZpb3VzIGRyYWcncyByZXZlcnRcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJtb3ZlJywgZXYpO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWluRGlzdGFuY2UgPSBfdGhpcy5taW5EaXN0YW5jZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RhbmNlU3EgPSB2b2lkIDA7IC8vIGN1cnJlbnQgZGlzdGFuY2UgZnJvbSB0aGUgb3JpZ2luLCBzcXVhcmVkXG4gICAgICAgICAgICAgICAgICAgIHZhciBkZWx0YVggPSBldi5kZWx0YVgsIGRlbHRhWSA9IGV2LmRlbHRhWTtcbiAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2VTcSA9IGRlbHRhWCAqIGRlbHRhWCArIGRlbHRhWSAqIGRlbHRhWTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRpc3RhbmNlU3EgPj0gbWluRGlzdGFuY2UgKiBtaW5EaXN0YW5jZSkgeyAvLyB1c2UgcHl0aGFnb3JlYW4gdGhlb3JlbVxuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGFuZGxlRGlzdGFuY2VTdXJwYXNzZWQoZXYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGEgcmVhbCBwb2ludGVyIG1vdmU/IChub3Qgb25lIHNpbXVsYXRlZCBieSBzY3JvbGxpbmcpXG4gICAgICAgICAgICAgICAgICAgIGlmIChldi5vcmlnRXZlbnQudHlwZSAhPT0gJ3Njcm9sbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm1pcnJvci5oYW5kbGVNb3ZlKGV2LnBhZ2VYLCBldi5wYWdlWSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hdXRvU2Nyb2xsZXIuaGFuZGxlTW92ZShldi5wYWdlWCwgZXYucGFnZVkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ21vdmUnLCBldik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5vblBvaW50ZXJVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmlzSW50ZXJhY3RpbmcpIHsgLy8gaWYgZmFsc2UsIHN0aWxsIHdhaXRpbmcgZm9yIHByZXZpb3VzIGRyYWcncyByZXZlcnRcbiAgICAgICAgICAgICAgICBfdGhpcy5pc0ludGVyYWN0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYWxsb3dTZWxlY3Rpb24oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgYWxsb3dDb250ZXh0TWVudShkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJ1cCcsIGV2KTsgLy8gY2FuIHBvdGVudGlhbGx5IHNldCBtaXJyb3JOZWVkc1JldmVydFxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmF1dG9TY3JvbGxlci5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRyeVN0b3BEcmFnKGV2KTsgLy8gd2hpY2ggd2lsbCBzdG9wIHRoZSBtaXJyb3JcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmRlbGF5VGltZW91dElkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChfdGhpcy5kZWxheVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRlbGF5VGltZW91dElkID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBwb2ludGVyID0gX3RoaXMucG9pbnRlciA9IG5ldyBQb2ludGVyRHJhZ2dpbmcoY29udGFpbmVyRWwpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgX3RoaXMub25Qb2ludGVyRG93bik7XG4gICAgICAgIHBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcm1vdmUnLCBfdGhpcy5vblBvaW50ZXJNb3ZlKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVydXAnLCBfdGhpcy5vblBvaW50ZXJVcCk7XG4gICAgICAgIF90aGlzLm1pcnJvciA9IG5ldyBFbGVtZW50TWlycm9yKCk7XG4gICAgICAgIF90aGlzLmF1dG9TY3JvbGxlciA9IG5ldyBBdXRvU2Nyb2xsZXIoKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBvaW50ZXIuZGVzdHJveSgpO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc3RhcnREZWxheSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZGVsYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF5VGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZGVsYXlUaW1lb3V0SWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIF90aGlzLmhhbmRsZURlbGF5RW5kKGV2KTtcbiAgICAgICAgICAgIH0sIHRoaXMuZGVsYXkpOyAvLyBub3QgYXNzaWduYWJsZSB0byBudW1iZXIhXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZURlbGF5RW5kKGV2KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuaGFuZGxlRGVsYXlFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgdGhpcy5pc0RlbGF5RW5kZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnRyeVN0YXJ0RHJhZyhldik7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5oYW5kbGVEaXN0YW5jZVN1cnBhc3NlZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICB0aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnRyeVN0YXJ0RHJhZyhldik7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS50cnlTdGFydERyYWcgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNEZWxheUVuZGVkICYmIHRoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnBvaW50ZXIud2FzVG91Y2hTY3JvbGwgfHwgdGhpcy50b3VjaFNjcm9sbEFsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMubWlycm9yTmVlZHNSZXZlcnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9TY3JvbGxlci5zdGFydChldi5wYWdlWCwgZXYucGFnZVkpO1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnc3RhcnQnLCBldik7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudG91Y2hTY3JvbGxBbGxvd2VkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBvaW50ZXIuY2FuY2VsVG91Y2hTY3JvbGwoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnRyeVN0b3BEcmFnID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIC8vIC5zdG9wKCkgaXMgQUxXQVlTIGFzeW5jaHJvbm91cywgd2hpY2ggd2UgTkVFRCBiZWNhdXNlIHdlIHdhbnQgYWxsIHBvaW50ZXJ1cCBldmVudHNcbiAgICAgICAgLy8gdGhhdCBjb21lIGZyb20gdGhlIGRvY3VtZW50IHRvIGZpcmUgYmVmb3JlaGFuZC4gbXVjaCBtb3JlIGNvbnZlbmllbnQgdGhpcyB3YXkuXG4gICAgICAgIHRoaXMubWlycm9yLnN0b3AodGhpcy5taXJyb3JOZWVkc1JldmVydCwgdGhpcy5zdG9wRHJhZy5iaW5kKHRoaXMsIGV2KSAvLyBib3VuZCB3aXRoIGFyZ3NcbiAgICAgICAgKTtcbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnN0b3BEcmFnID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ2VuZCcsIGV2KTtcbiAgICB9O1xuICAgIC8vIGZpbGwgaW4gdGhlIGltcGxlbWVudGF0aW9ucy4uLlxuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldElnbm9yZU1vdmUgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLnBvaW50ZXIuc2hvdWxkSWdub3JlTW92ZSA9IGJvb2w7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRNaXJyb3JJc1Zpc2libGUgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLm1pcnJvci5zZXRJc1Zpc2libGUoYm9vbCk7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRNaXJyb3JOZWVkc1JldmVydCA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIHRoaXMubWlycm9yTmVlZHNSZXZlcnQgPSBib29sO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0QXV0b1Njcm9sbEVuYWJsZWQgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLmF1dG9TY3JvbGxlci5pc0VuYWJsZWQgPSBib29sO1xuICAgIH07XG4gICAgcmV0dXJuIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmc7XG59KEVsZW1lbnREcmFnZ2luZykpO1xuXG4vKlxuV2hlbiB0aGlzIGNsYXNzIGlzIGluc3RhbnRpYXRlZCwgaXQgcmVjb3JkcyB0aGUgb2Zmc2V0IG9mIGFuIGVsZW1lbnQgKHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0b3BsZWZ0KSxcbmFuZCBjb250aW51ZXMgdG8gbW9uaXRvciBzY3JvbGxpbmcsIHVwZGF0aW5nIHRoZSBjYWNoZWQgY29vcmRpbmF0ZXMgaWYgaXQgbmVlZHMgdG8uXG5Eb2VzIG5vdCBhY2Nlc3MgdGhlIERPTSBhZnRlciBpbnN0YW50aWF0aW9uLCBzbyBoaWdobHkgcGVyZm9ybWFudC5cblxuQWxzbyBrZWVwcyB0cmFjayBvZiBhbGwgc2Nyb2xsaW5nL292ZXJmbG93OmhpZGRlbiBjb250YWluZXJzIHRoYXQgYXJlIHBhcmVudHMgb2YgdGhlIGdpdmVuIGVsZW1lbnRcbmFuZCBhbiBkZXRlcm1pbmUgaWYgYSBnaXZlbiBwb2ludCBpcyBpbnNpZGUgdGhlIGNvbWJpbmVkIGNsaXBwaW5nIHJlY3RhbmdsZS5cbiovXG52YXIgT2Zmc2V0VHJhY2tlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBPZmZzZXRUcmFja2VyKGVsKSB7XG4gICAgICAgIHRoaXMub3JpZ1JlY3QgPSBjb21wdXRlUmVjdChlbCk7XG4gICAgICAgIC8vIHdpbGwgd29yayBmaW5lIGZvciBkaXZzIHRoYXQgaGF2ZSBvdmVyZmxvdzpoaWRkZW5cbiAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSBnZXRDbGlwcGluZ1BhcmVudHMoZWwpLm1hcChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRWxlbWVudFNjcm9sbEdlb21DYWNoZShlbCwgdHJ1ZSk7IC8vIGxpc3Rlbj10cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBPZmZzZXRUcmFja2VyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zY3JvbGxDYWNoZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICBzY3JvbGxDYWNoZS5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE9mZnNldFRyYWNrZXIucHJvdG90eXBlLmNvbXB1dGVMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGVmdCA9IHRoaXMub3JpZ1JlY3QubGVmdDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsQ2FjaGVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgbGVmdCArPSBzY3JvbGxDYWNoZS5vcmlnU2Nyb2xsTGVmdCAtIHNjcm9sbENhY2hlLmdldFNjcm9sbExlZnQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGVmdDtcbiAgICB9O1xuICAgIE9mZnNldFRyYWNrZXIucHJvdG90eXBlLmNvbXB1dGVUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0b3AgPSB0aGlzLm9yaWdSZWN0LnRvcDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsQ2FjaGVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgdG9wICs9IHNjcm9sbENhY2hlLm9yaWdTY3JvbGxUb3AgLSBzY3JvbGxDYWNoZS5nZXRTY3JvbGxUb3AoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9wO1xuICAgIH07XG4gICAgT2Zmc2V0VHJhY2tlci5wcm90b3R5cGUuaXNXaXRoaW5DbGlwcGluZyA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgdmFyIHBvaW50ID0geyBsZWZ0OiBwYWdlWCwgdG9wOiBwYWdlWSB9O1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zY3JvbGxDYWNoZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAoIWlzSWdub3JlZENsaXBwaW5nKHNjcm9sbENhY2hlLmdldEV2ZW50VGFyZ2V0KCkpICYmXG4gICAgICAgICAgICAgICAgIXBvaW50SW5zaWRlUmVjdChwb2ludCwgc2Nyb2xsQ2FjaGUuY2xpZW50UmVjdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICByZXR1cm4gT2Zmc2V0VHJhY2tlcjtcbn0oKSk7XG4vLyBjZXJ0YWluIGNsaXBwaW5nIGNvbnRhaW5lcnMgc2hvdWxkIG5ldmVyIGNvbnN0cmFpbiBpbnRlcmFjdGlvbnMsIGxpa2UgPGh0bWw+IGFuZCA8Ym9keT5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mdWxsY2FsZW5kYXIvZnVsbGNhbGVuZGFyL2lzc3Vlcy8zNjE1XG5mdW5jdGlvbiBpc0lnbm9yZWRDbGlwcGluZyhub2RlKSB7XG4gICAgdmFyIHRhZ05hbWUgPSBub2RlLnRhZ05hbWU7XG4gICAgcmV0dXJuIHRhZ05hbWUgPT09ICdIVE1MJyB8fCB0YWdOYW1lID09PSAnQk9EWSc7XG59XG5cbi8qXG5UcmFja3MgbW92ZW1lbnQgb3ZlciBtdWx0aXBsZSBkcm9wcGFibGUgYXJlYXMgKGFrYSBcImhpdHNcIilcbnRoYXQgZXhpc3QgaW4gb25lIG9yIG1vcmUgRGF0ZUNvbXBvbmVudHMuXG5SZWxpZXMgb24gYW4gZXhpc3RpbmcgZHJhZ2dhYmxlLlxuXG5lbWl0czpcbi0gcG9pbnRlcmRvd25cbi0gZHJhZ3N0YXJ0XG4tIGhpdGNoYW5nZSAtIGZpcmVzIGluaXRpYWxseSwgZXZlbiBpZiBub3Qgb3ZlciBhIGhpdFxuLSBwb2ludGVydXBcbi0gKGhpdGNoYW5nZSAtIGFnYWluLCB0byBudWxsLCBpZiBlbmRlZCBvdmVyIGEgaGl0KVxuLSBkcmFnZW5kXG4qL1xudmFyIEhpdERyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEhpdERyYWdnaW5nKGRyYWdnaW5nLCBkcm9wcGFibGVTdG9yZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIHNldCBieSBjYWxsZXJcbiAgICAgICAgdGhpcy51c2VTdWJqZWN0Q2VudGVyID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVxdWlyZUluaXRpYWwgPSB0cnVlOyAvLyBpZiBkb2Vzbid0IHN0YXJ0IG91dCBvbiBhIGhpdCwgd29uJ3QgZW1pdCBhbnkgZXZlbnRzXG4gICAgICAgIHRoaXMuaW5pdGlhbEhpdCA9IG51bGw7XG4gICAgICAgIHRoaXMubW92aW5nSGl0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5maW5hbEhpdCA9IG51bGw7IC8vIHdvbid0IGV2ZXIgYmUgcG9wdWxhdGVkIGlmIHNob3VsZElnbm9yZU1vdmVcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuZHJhZ2dpbmc7XG4gICAgICAgICAgICBfdGhpcy5pbml0aWFsSGl0ID0gbnVsbDtcbiAgICAgICAgICAgIF90aGlzLm1vdmluZ0hpdCA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5maW5hbEhpdCA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5wcmVwYXJlSGl0cygpO1xuICAgICAgICAgICAgX3RoaXMucHJvY2Vzc0ZpcnN0Q29vcmQoZXYpO1xuICAgICAgICAgICAgaWYgKF90aGlzLmluaXRpYWxIaXQgfHwgIV90aGlzLnJlcXVpcmVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZShmYWxzZSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIGV2KTsgLy8gVE9ETzogZmlyZSB0aGlzIGJlZm9yZSBjb21wdXRpbmcgcHJvY2Vzc0ZpcnN0Q29vcmQsIHNvIGxpc3RlbmVycyBjYW4gY2FuY2VsLiB0aGlzIGdldHMgZmlyZWQgYnkgYWxtb3N0IGV2ZXJ5IGhhbmRsZXIgOihcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdzdGFydCcsIGV2KTtcbiAgICAgICAgICAgIF90aGlzLmhhbmRsZU1vdmUoZXYsIHRydWUpOyAvLyBmb3JjZSA9IGZpcmUgZXZlbiBpZiBpbml0aWFsbHkgbnVsbFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdNb3ZlID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdtb3ZlJywgZXYpO1xuICAgICAgICAgICAgX3RoaXMuaGFuZGxlTW92ZShldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlclVwID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5yZWxlYXNlSGl0cygpO1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVydXAnLCBldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLm1vdmluZ0hpdCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignaGl0dXBkYXRlJywgbnVsbCwgdHJ1ZSwgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZmluYWxIaXQgPSBfdGhpcy5tb3ZpbmdIaXQ7XG4gICAgICAgICAgICBfdGhpcy5tb3ZpbmdIaXQgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnZW5kJywgZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmRyb3BwYWJsZVN0b3JlID0gZHJvcHBhYmxlU3RvcmU7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ21vdmUnLCB0aGlzLmhhbmRsZURyYWdNb3ZlKTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcnVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnZW5kJywgdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgdGhpcy5kcmFnZ2luZyA9IGRyYWdnaW5nO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlck1peGluKCk7XG4gICAgfVxuICAgIC8vIHNldHMgaW5pdGlhbEhpdFxuICAgIC8vIHNldHMgY29vcmRBZGp1c3RcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUucHJvY2Vzc0ZpcnN0Q29vcmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgdmFyIG9yaWdQb2ludCA9IHsgbGVmdDogZXYucGFnZVgsIHRvcDogZXYucGFnZVkgfTtcbiAgICAgICAgdmFyIGFkanVzdGVkUG9pbnQgPSBvcmlnUG9pbnQ7XG4gICAgICAgIHZhciBzdWJqZWN0RWwgPSBldi5zdWJqZWN0RWw7XG4gICAgICAgIHZhciBzdWJqZWN0UmVjdDtcbiAgICAgICAgaWYgKHN1YmplY3RFbCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgIHN1YmplY3RSZWN0ID0gY29tcHV0ZVJlY3Qoc3ViamVjdEVsKTtcbiAgICAgICAgICAgIGFkanVzdGVkUG9pbnQgPSBjb25zdHJhaW5Qb2ludChhZGp1c3RlZFBvaW50LCBzdWJqZWN0UmVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluaXRpYWxIaXQgPSB0aGlzLmluaXRpYWxIaXQgPSB0aGlzLnF1ZXJ5SGl0Rm9yT2Zmc2V0KGFkanVzdGVkUG9pbnQubGVmdCwgYWRqdXN0ZWRQb2ludC50b3ApO1xuICAgICAgICBpZiAoaW5pdGlhbEhpdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMudXNlU3ViamVjdENlbnRlciAmJiBzdWJqZWN0UmVjdCkge1xuICAgICAgICAgICAgICAgIHZhciBzbGljZWRTdWJqZWN0UmVjdCA9IGludGVyc2VjdFJlY3RzKHN1YmplY3RSZWN0LCBpbml0aWFsSGl0LnJlY3QpO1xuICAgICAgICAgICAgICAgIGlmIChzbGljZWRTdWJqZWN0UmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZFBvaW50ID0gZ2V0UmVjdENlbnRlcihzbGljZWRTdWJqZWN0UmVjdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jb29yZEFkanVzdCA9IGRpZmZQb2ludHMoYWRqdXN0ZWRQb2ludCwgb3JpZ1BvaW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29vcmRBZGp1c3QgPSB7IGxlZnQ6IDAsIHRvcDogMCB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUuaGFuZGxlTW92ZSA9IGZ1bmN0aW9uIChldiwgZm9yY2VIYW5kbGUpIHtcbiAgICAgICAgdmFyIGhpdCA9IHRoaXMucXVlcnlIaXRGb3JPZmZzZXQoZXYucGFnZVggKyB0aGlzLmNvb3JkQWRqdXN0LmxlZnQsIGV2LnBhZ2VZICsgdGhpcy5jb29yZEFkanVzdC50b3ApO1xuICAgICAgICBpZiAoZm9yY2VIYW5kbGUgfHwgIWlzSGl0c0VxdWFsKHRoaXMubW92aW5nSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICB0aGlzLm1vdmluZ0hpdCA9IGhpdDtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdoaXR1cGRhdGUnLCBoaXQsIGZhbHNlLCBldik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhpdERyYWdnaW5nLnByb3RvdHlwZS5wcmVwYXJlSGl0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vZmZzZXRUcmFja2VycyA9IG1hcEhhc2godGhpcy5kcm9wcGFibGVTdG9yZSwgZnVuY3Rpb24gKGludGVyYWN0aW9uU2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uU2V0dGluZ3MuY29tcG9uZW50LmJ1aWxkUG9zaXRpb25DYWNoZXMoKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgT2Zmc2V0VHJhY2tlcihpbnRlcmFjdGlvblNldHRpbmdzLmVsKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUucmVsZWFzZUhpdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvZmZzZXRUcmFja2VycyA9IHRoaXMub2Zmc2V0VHJhY2tlcnM7XG4gICAgICAgIGZvciAodmFyIGlkIGluIG9mZnNldFRyYWNrZXJzKSB7XG4gICAgICAgICAgICBvZmZzZXRUcmFja2Vyc1tpZF0uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub2Zmc2V0VHJhY2tlcnMgPSB7fTtcbiAgICB9O1xuICAgIEhpdERyYWdnaW5nLnByb3RvdHlwZS5xdWVyeUhpdEZvck9mZnNldCA9IGZ1bmN0aW9uIChvZmZzZXRMZWZ0LCBvZmZzZXRUb3ApIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgZHJvcHBhYmxlU3RvcmUgPSBfYS5kcm9wcGFibGVTdG9yZSwgb2Zmc2V0VHJhY2tlcnMgPSBfYS5vZmZzZXRUcmFja2VycztcbiAgICAgICAgdmFyIGJlc3RIaXQgPSBudWxsO1xuICAgICAgICBmb3IgKHZhciBpZCBpbiBkcm9wcGFibGVTdG9yZSkge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IGRyb3BwYWJsZVN0b3JlW2lkXS5jb21wb25lbnQ7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0VHJhY2tlciA9IG9mZnNldFRyYWNrZXJzW2lkXTtcbiAgICAgICAgICAgIGlmIChvZmZzZXRUcmFja2VyLmlzV2l0aGluQ2xpcHBpbmcob2Zmc2V0TGVmdCwgb2Zmc2V0VG9wKSkge1xuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5MZWZ0ID0gb2Zmc2V0VHJhY2tlci5jb21wdXRlTGVmdCgpO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5Ub3AgPSBvZmZzZXRUcmFja2VyLmNvbXB1dGVUb3AoKTtcbiAgICAgICAgICAgICAgICB2YXIgcG9zaXRpb25MZWZ0ID0gb2Zmc2V0TGVmdCAtIG9yaWdpbkxlZnQ7XG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uVG9wID0gb2Zmc2V0VG9wIC0gb3JpZ2luVG9wO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnUmVjdCA9IG9mZnNldFRyYWNrZXIub3JpZ1JlY3Q7XG4gICAgICAgICAgICAgICAgdmFyIHdpZHRoID0gb3JpZ1JlY3QucmlnaHQgLSBvcmlnUmVjdC5sZWZ0O1xuICAgICAgICAgICAgICAgIHZhciBoZWlnaHQgPSBvcmlnUmVjdC5ib3R0b20gLSBvcmlnUmVjdC50b3A7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIC8vIG11c3QgYmUgd2l0aGluIHRoZSBlbGVtZW50J3MgYm91bmRzXG4gICAgICAgICAgICAgICAgcG9zaXRpb25MZWZ0ID49IDAgJiYgcG9zaXRpb25MZWZ0IDwgd2lkdGggJiZcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25Ub3AgPj0gMCAmJiBwb3NpdGlvblRvcCA8IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaGl0ID0gY29tcG9uZW50LnF1ZXJ5SGl0KHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3AsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGl0ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtYWtlIHN1cmUgdGhlIGhpdCBpcyB3aXRoaW4gYWN0aXZlUmFuZ2UsIG1lYW5pbmcgaXQncyBub3QgYSBkZWFsIGNlbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICFjb21wb25lbnQucHJvcHMuZGF0ZVByb2ZpbGUgfHwgLy8gaGFjayBmb3IgRGF5VGlsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlQ29udGFpbnNSYW5nZShjb21wb25lbnQucHJvcHMuZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGhpdC5kYXRlU3Bhbi5yYW5nZSkpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoIWJlc3RIaXQgfHwgaGl0LmxheWVyID4gYmVzdEhpdC5sYXllcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGJldHRlciB3YXkgdG8gcmUtb3JpZW50IHJlY3RhbmdsZVxuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QubGVmdCArPSBvcmlnaW5MZWZ0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QucmlnaHQgKz0gb3JpZ2luTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpdC5yZWN0LnRvcCArPSBvcmlnaW5Ub3A7XG4gICAgICAgICAgICAgICAgICAgICAgICBoaXQucmVjdC5ib3R0b20gKz0gb3JpZ2luVG9wO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVzdEhpdCA9IGhpdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmVzdEhpdDtcbiAgICB9O1xuICAgIHJldHVybiBIaXREcmFnZ2luZztcbn0oKSk7XG5mdW5jdGlvbiBpc0hpdHNFcXVhbChoaXQwLCBoaXQxKSB7XG4gICAgaWYgKCFoaXQwICYmICFoaXQxKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoQm9vbGVhbihoaXQwKSAhPT0gQm9vbGVhbihoaXQxKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBpc0RhdGVTcGFuc0VxdWFsKGhpdDAuZGF0ZVNwYW4sIGhpdDEuZGF0ZVNwYW4pO1xufVxuXG4vKlxuTW9uaXRvcnMgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYSBzcGVjaWZpYyBkYXRlL3RpbWUgb2YgYSBjb21wb25lbnQuXG5BIHBvaW50ZXJkb3duK3BvaW50ZXJ1cCBvbiB0aGUgc2FtZSBcImhpdFwiIGNvbnN0aXR1dGVzIGEgY2xpY2suXG4qL1xudmFyIERhdGVDbGlja2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF0ZUNsaWNraW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERhdGVDbGlja2luZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nO1xuICAgICAgICAgICAgLy8gZG8gdGhpcyBpbiBwb2ludGVyZG93biAobm90IGRyYWdlbmQpIGJlY2F1c2UgRE9NIG1pZ2h0IGJlIG11dGF0ZWQgYnkgdGhlIHRpbWUgZHJhZ2VuZCBpcyBmaXJlZFxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZSghX3RoaXMuY29tcG9uZW50LmlzVmFsaWREYXRlRG93bkVsKGRyYWdnaW5nLnBvaW50ZXIuZG93bkVsKSk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIHdvbid0IGV2ZW4gZmlyZSBpZiBtb3Zpbmcgd2FzIGlnbm9yZWRcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIHZhciBfYSA9IGNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgICAgIHZhciBwb2ludGVyID0gX3RoaXMuZHJhZ2dpbmcucG9pbnRlcjtcbiAgICAgICAgICAgIGlmICghcG9pbnRlci53YXNUb3VjaFNjcm9sbCkge1xuICAgICAgICAgICAgICAgIHZhciBfYiA9IF90aGlzLmhpdERyYWdnaW5nLCBpbml0aWFsSGl0ID0gX2IuaW5pdGlhbEhpdCwgZmluYWxIaXQgPSBfYi5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbEhpdCAmJiBmaW5hbEhpdCAmJiBpc0hpdHNFcXVhbChpbml0aWFsSGl0LCBmaW5hbEhpdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIudHJpZ2dlckRhdGVDbGljayhpbml0aWFsSGl0LmRhdGVTcGFuLCBpbml0aWFsSGl0LmRheUVsLCB2aWV3LCBldi5vcmlnRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgLy8gd2UgRE8gd2FudCB0byB3YXRjaCBwb2ludGVyIG1vdmVzIGJlY2F1c2Ugb3RoZXJ3aXNlIGZpbmFsSGl0IHdvbid0IGdldCBwb3B1bGF0ZWRcbiAgICAgICAgX3RoaXMuZHJhZ2dpbmcgPSBuZXcgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhjb21wb25lbnQuZWwpO1xuICAgICAgICBfdGhpcy5kcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gZmFsc2U7XG4gICAgICAgIHZhciBoaXREcmFnZ2luZyA9IF90aGlzLmhpdERyYWdnaW5nID0gbmV3IEhpdERyYWdnaW5nKF90aGlzLmRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIF90aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERhdGVDbGlja2luZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF0ZUNsaWNraW5nO1xufShJbnRlcmFjdGlvbikpO1xuXG4vKlxuVHJhY2tzIHdoZW4gdGhlIHVzZXIgc2VsZWN0cyBhIHBvcnRpb24gb2YgdGltZSBvZiBhIGNvbXBvbmVudCxcbmNvbnN0aXR1dGVkIGJ5IGEgZHJhZyBvdmVyIGRhdGUgY2VsbHMsIHdpdGggYSBwb3NzaWJsZSBkZWxheSBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBkcmFnLlxuKi9cbnZhciBEYXRlU2VsZWN0aW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXRlU2VsZWN0aW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERhdGVTZWxlY3Rpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmRyYWdTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMsIGNvbXBvbmVudCA9IF9hLmNvbXBvbmVudCwgZHJhZ2dpbmcgPSBfYS5kcmFnZ2luZztcbiAgICAgICAgICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICAgICAgICAgIHZhciBjYW5TZWxlY3QgPSBvcHRpb25zLnNlbGVjdGFibGUgJiZcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuaXNWYWxpZERhdGVEb3duRWwoZXYub3JpZ0V2ZW50LnRhcmdldCk7XG4gICAgICAgICAgICAvLyBkb24ndCBib3RoZXIgdG8gd2F0Y2ggZXhwZW5zaXZlIG1vdmVzIGlmIGNvbXBvbmVudCB3b24ndCBkbyBzZWxlY3Rpb25cbiAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoIWNhblNlbGVjdCk7XG4gICAgICAgICAgICAvLyBpZiB0b3VjaCwgcmVxdWlyZSB1c2VyIHRvIGhvbGQgZG93blxuICAgICAgICAgICAgZHJhZ2dpbmcuZGVsYXkgPSBldi5pc1RvdWNoID8gZ2V0Q29tcG9uZW50VG91Y2hEZWxheShjb21wb25lbnQpIDogbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5jb21wb25lbnQuY29udGV4dC5jYWxlbmRhci51bnNlbGVjdChldik7IC8vIHVuc2VsZWN0IHByZXZpb3VzIHNlbGVjdGlvbnNcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlSGl0VXBkYXRlID0gZnVuY3Rpb24gKGhpdCwgaXNGaW5hbCkge1xuICAgICAgICAgICAgdmFyIGNhbGVuZGFyID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICB2YXIgZHJhZ1NlbGVjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB2YXIgaXNJbnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoaGl0KSB7XG4gICAgICAgICAgICAgICAgZHJhZ1NlbGVjdGlvbiA9IGpvaW5IaXRzSW50b1NlbGVjdGlvbihfdGhpcy5oaXREcmFnZ2luZy5pbml0aWFsSGl0LCBoaXQsIGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5kYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzKTtcbiAgICAgICAgICAgICAgICBpZiAoIWRyYWdTZWxlY3Rpb24gfHwgIV90aGlzLmNvbXBvbmVudC5pc0RhdGVTZWxlY3Rpb25WYWxpZChkcmFnU2VsZWN0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBkcmFnU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZHJhZ1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1NFTEVDVF9EQVRFUycsIHNlbGVjdGlvbjogZHJhZ1NlbGVjdGlvbiB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFpc0ZpbmFsKSB7IC8vIG9ubHkgdW5zZWxlY3QgaWYgbW92ZWQgYXdheSB3aGlsZSBkcmFnZ2luZ1xuICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VMRUNUX0RBVEVTJyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZW5hYmxlQ3Vyc29yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXNhYmxlQ3Vyc29yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzRmluYWwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kcmFnU2VsZWN0aW9uID0gZHJhZ1NlbGVjdGlvbjsgLy8gb25seSBjbGVhciBpZiBtb3ZlZCBhd2F5IGZyb20gYWxsIGhpdHMgd2hpbGUgZHJhZ2dpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlclVwID0gZnVuY3Rpb24gKHBldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmRyYWdTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBzZWxlY3Rpb24gaXMgYWxyZWFkeSByZW5kZXJlZCwgc28ganVzdCBuZWVkIHRvIHJlcG9ydCBzZWxlY3Rpb25cbiAgICAgICAgICAgICAgICBfdGhpcy5jb21wb25lbnQuY29udGV4dC5jYWxlbmRhci50cmlnZ2VyRGF0ZVNlbGVjdChfdGhpcy5kcmFnU2VsZWN0aW9uLCBwZXYpO1xuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gc2V0dGluZ3MuY29tcG9uZW50O1xuICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29tcG9uZW50LmVsKTtcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGRyYWdnaW5nLm1pbkRpc3RhbmNlID0gb3B0aW9ucy5zZWxlY3RNaW5EaXN0YW5jZSB8fCAwO1xuICAgICAgICBkcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gb3B0aW9ucy5kcmFnU2Nyb2xsO1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSBfdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyhfdGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCBfdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIF90aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIF90aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIF90aGlzLmhhbmRsZVBvaW50ZXJVcCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF0ZVNlbGVjdGluZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF0ZVNlbGVjdGluZztcbn0oSW50ZXJhY3Rpb24pKTtcbmZ1bmN0aW9uIGdldENvbXBvbmVudFRvdWNoRGVsYXkoY29tcG9uZW50KSB7XG4gICAgdmFyIG9wdGlvbnMgPSBjb21wb25lbnQuY29udGV4dC5vcHRpb25zO1xuICAgIHZhciBkZWxheSA9IG9wdGlvbnMuc2VsZWN0TG9uZ1ByZXNzRGVsYXk7XG4gICAgaWYgKGRlbGF5ID09IG51bGwpIHtcbiAgICAgICAgZGVsYXkgPSBvcHRpb25zLmxvbmdQcmVzc0RlbGF5O1xuICAgIH1cbiAgICByZXR1cm4gZGVsYXk7XG59XG5mdW5jdGlvbiBqb2luSGl0c0ludG9TZWxlY3Rpb24oaGl0MCwgaGl0MSwgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycykge1xuICAgIHZhciBkYXRlU3BhbjAgPSBoaXQwLmRhdGVTcGFuO1xuICAgIHZhciBkYXRlU3BhbjEgPSBoaXQxLmRhdGVTcGFuO1xuICAgIHZhciBtcyA9IFtcbiAgICAgICAgZGF0ZVNwYW4wLnJhbmdlLnN0YXJ0LFxuICAgICAgICBkYXRlU3BhbjAucmFuZ2UuZW5kLFxuICAgICAgICBkYXRlU3BhbjEucmFuZ2Uuc3RhcnQsXG4gICAgICAgIGRhdGVTcGFuMS5yYW5nZS5lbmRcbiAgICBdO1xuICAgIG1zLnNvcnQoY29tcGFyZU51bWJlcnMpO1xuICAgIHZhciBwcm9wcyA9IHt9O1xuICAgIGZvciAodmFyIF9pID0gMCwgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyc18xID0gZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyczsgX2kgPCBkYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm1lciA9IGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnNfMVtfaV07XG4gICAgICAgIHZhciByZXMgPSB0cmFuc2Zvcm1lcihoaXQwLCBoaXQxKTtcbiAgICAgICAgaWYgKHJlcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlcykge1xuICAgICAgICAgICAgX19hc3NpZ24ocHJvcHMsIHJlcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHJvcHMucmFuZ2UgPSB7IHN0YXJ0OiBtc1swXSwgZW5kOiBtc1szXSB9O1xuICAgIHByb3BzLmFsbERheSA9IGRhdGVTcGFuMC5hbGxEYXk7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuXG52YXIgRXZlbnREcmFnZ2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRXZlbnREcmFnZ2luZywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFdmVudERyYWdnaW5nKHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHNldHRpbmdzKSB8fCB0aGlzO1xuICAgICAgICAvLyBpbnRlcm5hbCBzdGF0ZVxuICAgICAgICBfdGhpcy5zdWJqZWN0U2VnID0gbnVsbDsgLy8gdGhlIHNlZyBiZWluZyBzZWxlY3RlZC9kcmFnZ2VkXG4gICAgICAgIF90aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuZXZlbnRSYW5nZSA9IG51bGw7XG4gICAgICAgIF90aGlzLnJlbGV2YW50RXZlbnRzID0gbnVsbDsgLy8gdGhlIGV2ZW50cyBiZWluZyBkcmFnZ2VkXG4gICAgICAgIF90aGlzLnJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG51bGw7XG4gICAgICAgIF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgb3JpZ1RhcmdldCA9IGV2Lm9yaWdFdmVudC50YXJnZXQ7XG4gICAgICAgICAgICB2YXIgX2EgPSBfdGhpcywgY29tcG9uZW50ID0gX2EuY29tcG9uZW50LCBkcmFnZ2luZyA9IF9hLmRyYWdnaW5nO1xuICAgICAgICAgICAgdmFyIG1pcnJvciA9IGRyYWdnaW5nLm1pcnJvcjtcbiAgICAgICAgICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICAgICAgICAgIHZhciBpbml0aWFsQ2FsZW5kYXIgPSBjb21wb25lbnQuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgICAgIHZhciBzdWJqZWN0U2VnID0gX3RoaXMuc3ViamVjdFNlZyA9IGdldEVsU2VnKGV2LnN1YmplY3RFbCk7XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IF90aGlzLmV2ZW50UmFuZ2UgPSBzdWJqZWN0U2VnLmV2ZW50UmFuZ2U7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZUlkID0gZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkO1xuICAgICAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBnZXRSZWxldmFudEV2ZW50cyhpbml0aWFsQ2FsZW5kYXIuc3RhdGUuZXZlbnRTdG9yZSwgZXZlbnRJbnN0YW5jZUlkKTtcbiAgICAgICAgICAgIGRyYWdnaW5nLm1pbkRpc3RhbmNlID0gZXYuaXNUb3VjaCA/IDAgOiBvcHRpb25zLmV2ZW50RHJhZ01pbkRpc3RhbmNlO1xuICAgICAgICAgICAgZHJhZ2dpbmcuZGVsYXkgPVxuICAgICAgICAgICAgICAgIC8vIG9ubHkgZG8gYSB0b3VjaCBkZWxheSBpZiB0b3VjaCBhbmQgdGhpcyBldmVudCBoYXNuJ3QgYmVlbiBzZWxlY3RlZCB5ZXRcbiAgICAgICAgICAgICAgICAoZXYuaXNUb3VjaCAmJiBldmVudEluc3RhbmNlSWQgIT09IGNvbXBvbmVudC5wcm9wcy5ldmVudFNlbGVjdGlvbikgP1xuICAgICAgICAgICAgICAgICAgICBnZXRDb21wb25lbnRUb3VjaERlbGF5JDEoY29tcG9uZW50KSA6XG4gICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgICAgICAgICBtaXJyb3IucGFyZW50Tm9kZSA9IGluaXRpYWxDYWxlbmRhci5lbDtcbiAgICAgICAgICAgIG1pcnJvci5yZXZlcnREdXJhdGlvbiA9IG9wdGlvbnMuZHJhZ1JldmVydER1cmF0aW9uO1xuICAgICAgICAgICAgdmFyIGlzVmFsaWQgPSBjb21wb25lbnQuaXNWYWxpZFNlZ0Rvd25FbChvcmlnVGFyZ2V0KSAmJlxuICAgICAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChvcmlnVGFyZ2V0LCAnLmZjLXJlc2l6ZXInKTsgLy8gTk9UIG9uIGEgcmVzaXplclxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZSghaXNWYWxpZCk7XG4gICAgICAgICAgICAvLyBkaXNhYmxlIGRyYWdnaW5nIGZvciBlbGVtZW50cyB0aGF0IGFyZSByZXNpemFibGUgKGllLCBzZWxlY3RhYmxlKVxuICAgICAgICAgICAgLy8gYnV0IGFyZSBub3QgZHJhZ2dhYmxlXG4gICAgICAgICAgICBfdGhpcy5pc0RyYWdnaW5nID0gaXNWYWxpZCAmJlxuICAgICAgICAgICAgICAgIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLWRyYWdnYWJsZScpO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVEcmFnU3RhcnQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBjb250ZXh0ID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQ7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gX3RoaXMuZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlSWQgPSBldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWQ7XG4gICAgICAgICAgICBpZiAoZXYuaXNUb3VjaCkge1xuICAgICAgICAgICAgICAgIC8vIG5lZWQgdG8gc2VsZWN0IGEgZGlmZmVyZW50IGV2ZW50P1xuICAgICAgICAgICAgICAgIGlmIChldmVudEluc3RhbmNlSWQgIT09IF90aGlzLmNvbXBvbmVudC5wcm9wcy5ldmVudFNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnU0VMRUNUX0VWRU5UJywgZXZlbnRJbnN0YW5jZUlkOiBldmVudEluc3RhbmNlSWQgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgbm93IHVzaW5nIG1vdXNlLCBidXQgd2FzIHByZXZpb3VzIHRvdWNoIGludGVyYWN0aW9uLCBjbGVhciBzZWxlY3RlZCBldmVudFxuICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9FVkVOVCcgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhci51bnNlbGVjdChldik7IC8vIHVuc2VsZWN0ICpkYXRlKiBzZWxlY3Rpb25cbiAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudERyYWdTdGFydCcsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLnN1YmplY3RTZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGluaXRpYWxDYWxlbmRhciwgZXZlbnRSYW5nZS5kZWYsIGV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYub3JpZ0V2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlldzogY29udGV4dC52aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlSGl0VXBkYXRlID0gZnVuY3Rpb24gKGhpdCwgaXNGaW5hbCkge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlbGV2YW50RXZlbnRzID0gX3RoaXMucmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbEhpdCA9IF90aGlzLmhpdERyYWdnaW5nLmluaXRpYWxIaXQ7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICAvLyBzdGF0ZXMgYmFzZWQgb24gbmV3IGhpdFxuICAgICAgICAgICAgdmFyIHJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB2YXIgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogcmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBvcmlnU2VnOiBfdGhpcy5zdWJqZWN0U2VnXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGhpdCkge1xuICAgICAgICAgICAgICAgIHZhciByZWNlaXZpbmdDb21wb25lbnQgPSBoaXQuY29tcG9uZW50O1xuICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyID0gcmVjZWl2aW5nQ29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICAgICAgdmFyIHJlY2VpdmluZ09wdGlvbnMgPSByZWNlaXZpbmdDb21wb25lbnQuY29udGV4dC5vcHRpb25zO1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsQ2FsZW5kYXIgPT09IHJlY2VpdmluZ0NhbGVuZGFyIHx8XG4gICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ09wdGlvbnMuZWRpdGFibGUgJiYgcmVjZWl2aW5nT3B0aW9ucy5kcm9wcGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRpb24gPSBjb21wdXRlRXZlbnRNdXRhdGlvbihpbml0aWFsSGl0LCBoaXQsIHJlY2VpdmluZ0NhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2Vycyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtdXRhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZShyZWxldmFudEV2ZW50cywgcmVjZWl2aW5nQ2FsZW5kYXIuZXZlbnRVaUJhc2VzLCBtdXRhdGlvbiwgcmVjZWl2aW5nQ2FsZW5kYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcmVjZWl2aW5nQ29tcG9uZW50LmlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmRpc3BsYXlEcmFnKHJlY2VpdmluZ0NhbGVuZGFyLCBpbnRlcmFjdGlvbik7XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGluaXRpYWxDYWxlbmRhciA9PT0gcmVjZWl2aW5nQ2FsZW5kYXIgJiYgLy8gVE9ETzogd3JpdGUgdGVzdCBmb3IgdGhpc1xuICAgICAgICAgICAgICAgICAgICBpc0hpdHNFcXVhbChpbml0aWFsSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmcuc2V0TWlycm9yTmVlZHNSZXZlcnQoIW11dGF0aW9uKTtcbiAgICAgICAgICAgICAgICAvLyByZW5kZXIgdGhlIG1pcnJvciBpZiBubyBhbHJlYWR5LXJlbmRlcmVkIG1pcnJvclxuICAgICAgICAgICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgc29tZWhvdyB3YWl0IGZvciBkaXNwYXRjaCB0byBndWFyYW50ZWUgcmVuZGVyXG4gICAgICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmcuc2V0TWlycm9ySXNWaXNpYmxlKCFoaXQgfHwgIWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5mYy1taXJyb3InKSk7XG4gICAgICAgICAgICAgICAgLy8gYXNzaWduIHN0YXRlcyBiYXNlZCBvbiBuZXcgaGl0XG4gICAgICAgICAgICAgICAgX3RoaXMucmVjZWl2aW5nQ2FsZW5kYXIgPSByZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgICAgICAgICBfdGhpcy52YWxpZE11dGF0aW9uID0gbXV0YXRpb247XG4gICAgICAgICAgICAgICAgX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbXV0YXRlZFJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyVXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7IC8vIGJlY2F1c2UgaGFuZGxlRHJhZ0VuZCB3b24ndCBmaXJlXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRleHQgPSBfdGhpcy5jb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyXzEgPSBjb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgIHZhciBpbml0aWFsVmlldyA9IGNvbnRleHQudmlldztcbiAgICAgICAgICAgICAgICB2YXIgX2EgPSBfdGhpcywgcmVjZWl2aW5nQ2FsZW5kYXIgPSBfYS5yZWNlaXZpbmdDYWxlbmRhciwgdmFsaWRNdXRhdGlvbiA9IF9hLnZhbGlkTXV0YXRpb247XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50RGVmID0gX3RoaXMuZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50SW5zdGFuY2UgPSBfdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICAgICAgICAgIHZhciBldmVudEFwaSA9IG5ldyBFdmVudEFwaShpbml0aWFsQ2FsZW5kYXJfMSwgZXZlbnREZWYsIGV2ZW50SW5zdGFuY2UpO1xuICAgICAgICAgICAgICAgIHZhciByZWxldmFudEV2ZW50c18xID0gX3RoaXMucmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgdmFyIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgICAgICB2YXIgZmluYWxIaXQgPSBfdGhpcy5oaXREcmFnZ2luZy5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGVhckRyYWcoKTsgLy8gbXVzdCBoYXBwZW4gYWZ0ZXIgcmV2ZXJ0IGFuaW1hdGlvblxuICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLnB1YmxpY2x5VHJpZ2dlcignZXZlbnREcmFnU3RvcCcsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLnN1YmplY3RTZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiBpbml0aWFsVmlld1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbGlkTXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZHJvcHBlZCB3aXRoaW4gc2FtZSBjYWxlbmRhclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVjZWl2aW5nQ2FsZW5kYXIgPT09IGluaXRpYWxDYWxlbmRhcl8xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogbXV0YXRlZFJlbGV2YW50RXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lZCA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYiA9IGluaXRpYWxDYWxlbmRhcl8xLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudERyb3BUcmFuc2Zvcm1lcnM7IF9pIDwgX2IubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybWVyID0gX2JbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9fYXNzaWduKHRyYW5zZm9ybWVkLCB0cmFuc2Zvcm1lcih2YWxpZE11dGF0aW9uLCBpbml0aWFsQ2FsZW5kYXJfMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50RHJvcEFyZyA9IF9fYXNzaWduKHt9LCB0cmFuc2Zvcm1lZCwgeyBlbDogZXYuc3ViamVjdEVsLCBkZWx0YTogdmFsaWRNdXRhdGlvbi5kYXRlc0RlbHRhLCBvbGRFdmVudDogZXZlbnRBcGksIGV2ZW50OiBuZXcgRXZlbnRBcGkoLy8gdGhlIGRhdGEgQUZURVIgdGhlIG11dGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEsIG11dGF0ZWRSZWxldmFudEV2ZW50cy5kZWZzW2V2ZW50RGVmLmRlZklkXSwgZXZlbnRJbnN0YW5jZSA/IG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSA6IG51bGwpLCByZXZlcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiByZWxldmFudEV2ZW50c18xXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCwgdmlldzogaW5pdGlhbFZpZXcgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50RHJvcCcsIFtldmVudERyb3BBcmddKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRyb3BwZWQgaW4gZGlmZmVyZW50IGNhbGVuZGFyXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAocmVjZWl2aW5nQ2FsZW5kYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRMZWF2ZScsIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRFbDogZXYuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGluaXRpYWxWaWV3XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1JFTU9WRV9FVkVOVF9JTlNUQU5DRVMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlczogX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzLmluc3RhbmNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VMRUNUX0VWRU5UJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRJbnN0YW5jZUlkOiBldmVudEluc3RhbmNlLmluc3RhbmNlSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkcm9wQXJnID0gX19hc3NpZ24oe30sIHJlY2VpdmluZ0NhbGVuZGFyLmJ1aWxkRGF0ZVBvaW50QXBpKGZpbmFsSGl0LmRhdGVTcGFuKSwgeyBkcmFnZ2VkRWw6IGV2LnN1YmplY3RFbCwganNFdmVudDogZXYub3JpZ0V2ZW50LCB2aWV3OiBmaW5hbEhpdC5jb21wb25lbnQgLy8gc2hvdWxkIHRoaXMgYmUgZmluYWxIaXQuY29tcG9uZW50LnZpZXc/IFNlZSAjNDY0NFxuICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdkcm9wJywgW2Ryb3BBcmddKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZWNlaXZlJywgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dlZEVsOiBldi5zdWJqZWN0RWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoLy8gdGhlIGRhdGEgQUZURVIgdGhlIG11dGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLCBtdXRhdGVkUmVsZXZhbnRFdmVudHMuZGVmc1tldmVudERlZi5kZWZJZF0sIG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGZpbmFsSGl0LmNvbXBvbmVudCAvLyBzaG91bGQgdGhpcyBiZSBmaW5hbEhpdC5jb21wb25lbnQudmlldz8gU2VlICM0NjQ0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLnB1YmxpY2x5VHJpZ2dlcignX25vRXZlbnREcm9wJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuY2xlYW51cCgpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gX3RoaXMuY29tcG9uZW50O1xuICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29tcG9uZW50LmVsKTtcbiAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9IEV2ZW50RHJhZ2dpbmcuU0VMRUNUT1I7XG4gICAgICAgIGRyYWdnaW5nLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICBkcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gb3B0aW9ucy5kcmFnU2Nyb2xsO1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSBfdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyhfdGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcudXNlU3ViamVjdENlbnRlciA9IHNldHRpbmdzLnVzZUV2ZW50Q2VudGVyO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignaGl0dXBkYXRlJywgX3RoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcnVwJywgX3RoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIF90aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgLy8gcmVuZGVyIGEgZHJhZyBzdGF0ZSBvbiB0aGUgbmV4dCByZWNlaXZpbmdDYWxlbmRhclxuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmRpc3BsYXlEcmFnID0gZnVuY3Rpb24gKG5leHRDYWxlbmRhciwgc3RhdGUpIHtcbiAgICAgICAgdmFyIGluaXRpYWxDYWxlbmRhciA9IHRoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBwcmV2Q2FsZW5kYXIgPSB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyO1xuICAgICAgICAvLyBkb2VzIHRoZSBwcmV2aW91cyBjYWxlbmRhciBuZWVkIHRvIGJlIGNsZWFyZWQ/XG4gICAgICAgIGlmIChwcmV2Q2FsZW5kYXIgJiYgcHJldkNhbGVuZGFyICE9PSBuZXh0Q2FsZW5kYXIpIHtcbiAgICAgICAgICAgIC8vIGRvZXMgdGhlIGluaXRpYWwgY2FsZW5kYXIgbmVlZCB0byBiZSBjbGVhcmVkP1xuICAgICAgICAgICAgLy8gaWYgc28sIGRvbid0IGNsZWFyIGFsbCB0aGUgd2F5LiB3ZSBzdGlsbCBuZWVkIHRvIHRvIGhpZGUgdGhlIGFmZmVjdGVkRXZlbnRzXG4gICAgICAgICAgICBpZiAocHJldkNhbGVuZGFyID09PSBpbml0aWFsQ2FsZW5kYXIpIHtcbiAgICAgICAgICAgICAgICBwcmV2Q2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX0VWRU5UX0RSQUcnLFxuICAgICAgICAgICAgICAgICAgICBzdGF0ZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IHN0YXRlLmFmZmVjdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0V2ZW50OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ1NlZzogc3RhdGUub3JpZ1NlZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gY29tcGxldGVseSBjbGVhciB0aGUgb2xkIGNhbGVuZGFyIGlmIGl0IHdhc24ndCB0aGUgaW5pdGlhbFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcHJldkNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0Q2FsZW5kYXIpIHtcbiAgICAgICAgICAgIG5leHRDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdTRVRfRVZFTlRfRFJBRycsIHN0YXRlOiBzdGF0ZSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnREcmFnZ2luZy5wcm90b3R5cGUuY2xlYXJEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gdGhpcy5jb21wb25lbnQuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgdmFyIHJlY2VpdmluZ0NhbGVuZGFyID0gdGhpcy5yZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgaWYgKHJlY2VpdmluZ0NhbGVuZGFyKSB7XG4gICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGUgaW5pdGlhbCBjYWxlbmRhciBtaWdodCBoYXZlIGFuIGR1bW15IGRyYWcgc3RhdGUgZnJvbSBkaXNwbGF5RHJhZ1xuICAgICAgICBpZiAoaW5pdGlhbENhbGVuZGFyICE9PSByZWNlaXZpbmdDYWxlbmRhcikge1xuICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudERyYWdnaW5nLnByb3RvdHlwZS5jbGVhbnVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnN1YmplY3RTZWcgPSBudWxsO1xuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVudFJhbmdlID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIHRoaXMucmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICB0aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgfTtcbiAgICBFdmVudERyYWdnaW5nLlNFTEVDVE9SID0gJy5mYy1kcmFnZ2FibGUsIC5mYy1yZXNpemFibGUnOyAvLyBUT0RPOiB0ZXN0IHRoaXMgaW4gSUUxMVxuICAgIHJldHVybiBFdmVudERyYWdnaW5nO1xufShJbnRlcmFjdGlvbikpO1xuZnVuY3Rpb24gY29tcHV0ZUV2ZW50TXV0YXRpb24oaGl0MCwgaGl0MSwgbWFzc2FnZXJzKSB7XG4gICAgdmFyIGRhdGVTcGFuMCA9IGhpdDAuZGF0ZVNwYW47XG4gICAgdmFyIGRhdGVTcGFuMSA9IGhpdDEuZGF0ZVNwYW47XG4gICAgdmFyIGRhdGUwID0gZGF0ZVNwYW4wLnJhbmdlLnN0YXJ0O1xuICAgIHZhciBkYXRlMSA9IGRhdGVTcGFuMS5yYW5nZS5zdGFydDtcbiAgICB2YXIgc3RhbmRhcmRQcm9wcyA9IHt9O1xuICAgIGlmIChkYXRlU3BhbjAuYWxsRGF5ICE9PSBkYXRlU3BhbjEuYWxsRGF5KSB7XG4gICAgICAgIHN0YW5kYXJkUHJvcHMuYWxsRGF5ID0gZGF0ZVNwYW4xLmFsbERheTtcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5oYXNFbmQgPSBoaXQxLmNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnMuYWxsRGF5TWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgaWYgKGRhdGVTcGFuMS5hbGxEYXkpIHtcbiAgICAgICAgICAgIC8vIG1lYW5zIGRhdGUxIGlzIGFscmVhZHkgc3RhcnQtb2YtZGF5LFxuICAgICAgICAgICAgLy8gYnV0IGRhdGUwIG5lZWRzIHRvIGJlIGNvbnZlcnRlZFxuICAgICAgICAgICAgZGF0ZTAgPSBzdGFydE9mRGF5KGRhdGUwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgZGVsdGEgPSBkaWZmRGF0ZXMoZGF0ZTAsIGRhdGUxLCBoaXQwLmNvbXBvbmVudC5jb250ZXh0LmRhdGVFbnYsIGhpdDAuY29tcG9uZW50ID09PSBoaXQxLmNvbXBvbmVudCA/XG4gICAgICAgIGhpdDAuY29tcG9uZW50LmxhcmdlVW5pdCA6XG4gICAgICAgIG51bGwpO1xuICAgIGlmIChkZWx0YS5taWxsaXNlY29uZHMpIHsgLy8gaGFzIGhvdXJzL21pbnV0ZXMvc2Vjb25kc1xuICAgICAgICBzdGFuZGFyZFByb3BzLmFsbERheSA9IGZhbHNlO1xuICAgIH1cbiAgICB2YXIgbXV0YXRpb24gPSB7XG4gICAgICAgIGRhdGVzRGVsdGE6IGRlbHRhLFxuICAgICAgICBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzXG4gICAgfTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIG1hc3NhZ2Vyc18xID0gbWFzc2FnZXJzOyBfaSA8IG1hc3NhZ2Vyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgbWFzc2FnZXIgPSBtYXNzYWdlcnNfMVtfaV07XG4gICAgICAgIG1hc3NhZ2VyKG11dGF0aW9uLCBoaXQwLCBoaXQxKTtcbiAgICB9XG4gICAgcmV0dXJuIG11dGF0aW9uO1xufVxuZnVuY3Rpb24gZ2V0Q29tcG9uZW50VG91Y2hEZWxheSQxKGNvbXBvbmVudCkge1xuICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICB2YXIgZGVsYXkgPSBvcHRpb25zLmV2ZW50TG9uZ1ByZXNzRGVsYXk7XG4gICAgaWYgKGRlbGF5ID09IG51bGwpIHtcbiAgICAgICAgZGVsYXkgPSBvcHRpb25zLmxvbmdQcmVzc0RlbGF5O1xuICAgIH1cbiAgICByZXR1cm4gZGVsYXk7XG59XG5cbnZhciBFdmVudERyYWdnaW5nJDEgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEV2ZW50RHJhZ2dpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRXZlbnREcmFnZ2luZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgX3RoaXMuZHJhZ2dpbmdTZWcgPSBudWxsOyAvLyBUT0RPOiByZW5hbWUgdG8gcmVzaXppbmdTZWc/IHN1YmplY3RTZWc/XG4gICAgICAgIF90aGlzLmV2ZW50UmFuZ2UgPSBudWxsO1xuICAgICAgICBfdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIF90aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICBfdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIHZhciBzZWcgPSBfdGhpcy5xdWVyeVNlZyhldik7XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IF90aGlzLmV2ZW50UmFuZ2UgPSBzZWcuZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLm1pbkRpc3RhbmNlID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucy5ldmVudERyYWdNaW5EaXN0YW5jZTtcbiAgICAgICAgICAgIC8vIGlmIHRvdWNoLCBuZWVkIHRvIGJlIHdvcmtpbmcgd2l0aCBhIHNlbGVjdGVkIGV2ZW50XG4gICAgICAgICAgICBfdGhpcy5kcmFnZ2luZy5zZXRJZ25vcmVNb3ZlKCFfdGhpcy5jb21wb25lbnQuaXNWYWxpZFNlZ0Rvd25FbChldi5vcmlnRXZlbnQudGFyZ2V0KSB8fFxuICAgICAgICAgICAgICAgIChldi5pc1RvdWNoICYmIF90aGlzLmNvbXBvbmVudC5wcm9wcy5ldmVudFNlbGVjdGlvbiAhPT0gZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkKSk7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3O1xuICAgICAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBfdGhpcy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBnZXRSZWxldmFudEV2ZW50cyhjYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlLCBfdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWQpO1xuICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmdTZWcgPSBfdGhpcy5xdWVyeVNlZyhldik7XG4gICAgICAgICAgICBjYWxlbmRhci51bnNlbGVjdCgpO1xuICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlc2l6ZVN0YXJ0JywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLmRyYWdnaW5nU2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBldmVudFJhbmdlLmRlZiwgZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVIaXRVcGRhdGUgPSBmdW5jdGlvbiAoaGl0LCBpc0ZpbmFsLCBldikge1xuICAgICAgICAgICAgdmFyIGNhbGVuZGFyID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICB2YXIgcmVsZXZhbnRFdmVudHMgPSBfdGhpcy5yZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIHZhciBpbml0aWFsSGl0ID0gX3RoaXMuaGl0RHJhZ2dpbmcuaW5pdGlhbEhpdDtcbiAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlID0gX3RoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZTtcbiAgICAgICAgICAgIHZhciBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB2YXIgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogcmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBvcmlnU2VnOiBfdGhpcy5kcmFnZ2luZ1NlZ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChoaXQpIHtcbiAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IGNvbXB1dGVNdXRhdGlvbihpbml0aWFsSGl0LCBoaXQsIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLXN0YXJ0LXJlc2l6ZXInKSwgZXZlbnRJbnN0YW5jZS5yYW5nZSwgY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50UmVzaXplSm9pblRyYW5zZm9ybXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG11dGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZShyZWxldmFudEV2ZW50cywgY2FsZW5kYXIuZXZlbnRVaUJhc2VzLCBtdXRhdGlvbiwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBtdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb21wb25lbnQuaXNJbnRlcmFjdGlvblZhbGlkKGludGVyYWN0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtdXRhdGVkUmVsZXZhbnRFdmVudHMpIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdTRVRfRVZFTlRfUkVTSVpFJyxcbiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IGludGVyYWN0aW9uXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9SRVNJWkUnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBlbmFibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpc2FibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNGaW5hbCkge1xuICAgICAgICAgICAgICAgIGlmIChtdXRhdGlvbiAmJiBpc0hpdHNFcXVhbChpbml0aWFsSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG11dGF0aW9uO1xuICAgICAgICAgICAgICAgIF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3O1xuICAgICAgICAgICAgdmFyIGV2ZW50RGVmID0gX3RoaXMuZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZSA9IF90aGlzLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgICAgICB2YXIgZXZlbnRBcGkgPSBuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIGV2ZW50RGVmLCBldmVudEluc3RhbmNlKTtcbiAgICAgICAgICAgIHZhciByZWxldmFudEV2ZW50cyA9IF90aGlzLnJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgdmFyIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZXNpemVTdG9wJywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLmRyYWdnaW5nU2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgaWYgKF90aGlzLnZhbGlkTXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBtdXRhdGVkUmVsZXZhbnRFdmVudHNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50UmVzaXplJywgW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbDogX3RoaXMuZHJhZ2dpbmdTZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydERlbHRhOiBfdGhpcy52YWxpZE11dGF0aW9uLnN0YXJ0RGVsdGEgfHwgY3JlYXRlRHVyYXRpb24oMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBlbmREZWx0YTogX3RoaXMudmFsaWRNdXRhdGlvbi5lbmREZWx0YSB8fCBjcmVhdGVEdXJhdGlvbigwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZFdmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKC8vIHRoZSBkYXRhIEFGVEVSIHRoZSBtdXRhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIsIG11dGF0ZWRSZWxldmFudEV2ZW50cy5kZWZzW2V2ZW50RGVmLmRlZklkXSwgZXZlbnRJbnN0YW5jZSA/IG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSA6IG51bGwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJ0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogcmVsZXZhbnRFdmVudHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignX25vRXZlbnRSZXNpemUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJlc2V0IGFsbCBpbnRlcm5hbCBzdGF0ZVxuICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmdTZWcgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAvLyBva2F5IHRvIGtlZXAgZXZlbnRJbnN0YW5jZSBhcm91bmQuIHVzZWZ1bCB0byBzZXQgaXQgaW4gaGFuZGxlUG9pbnRlckRvd25cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuZHJhZ2dpbmcgPSBuZXcgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhjb21wb25lbnQuZWwpO1xuICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gJy5mYy1yZXNpemVyJztcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGRyYWdnaW5nLmF1dG9TY3JvbGxlci5pc0VuYWJsZWQgPSBjb21wb25lbnQuY29udGV4dC5vcHRpb25zLmRyYWdTY3JvbGw7XG4gICAgICAgIHZhciBoaXREcmFnZ2luZyA9IF90aGlzLmhpdERyYWdnaW5nID0gbmV3IEhpdERyYWdnaW5nKF90aGlzLmRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignaGl0dXBkYXRlJywgX3RoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIF90aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgRXZlbnREcmFnZ2luZy5wcm90b3R5cGUucXVlcnlTZWcgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgcmV0dXJuIGdldEVsU2VnKGVsZW1lbnRDbG9zZXN0KGV2LnN1YmplY3RFbCwgdGhpcy5jb21wb25lbnQuZmdTZWdTZWxlY3RvcikpO1xuICAgIH07XG4gICAgcmV0dXJuIEV2ZW50RHJhZ2dpbmc7XG59KEludGVyYWN0aW9uKSk7XG5mdW5jdGlvbiBjb21wdXRlTXV0YXRpb24oaGl0MCwgaGl0MSwgaXNGcm9tU3RhcnQsIGluc3RhbmNlUmFuZ2UsIHRyYW5zZm9ybXMpIHtcbiAgICB2YXIgZGF0ZUVudiA9IGhpdDAuY29tcG9uZW50LmNvbnRleHQuZGF0ZUVudjtcbiAgICB2YXIgZGF0ZTAgPSBoaXQwLmRhdGVTcGFuLnJhbmdlLnN0YXJ0O1xuICAgIHZhciBkYXRlMSA9IGhpdDEuZGF0ZVNwYW4ucmFuZ2Uuc3RhcnQ7XG4gICAgdmFyIGRlbHRhID0gZGlmZkRhdGVzKGRhdGUwLCBkYXRlMSwgZGF0ZUVudiwgaGl0MC5jb21wb25lbnQubGFyZ2VVbml0KTtcbiAgICB2YXIgcHJvcHMgPSB7fTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHRyYW5zZm9ybXNfMSA9IHRyYW5zZm9ybXM7IF9pIDwgdHJhbnNmb3Jtc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtID0gdHJhbnNmb3Jtc18xW19pXTtcbiAgICAgICAgdmFyIHJlcyA9IHRyYW5zZm9ybShoaXQwLCBoaXQxKTtcbiAgICAgICAgaWYgKHJlcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlcykge1xuICAgICAgICAgICAgX19hc3NpZ24ocHJvcHMsIHJlcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzRnJvbVN0YXJ0KSB7XG4gICAgICAgIGlmIChkYXRlRW52LmFkZChpbnN0YW5jZVJhbmdlLnN0YXJ0LCBkZWx0YSkgPCBpbnN0YW5jZVJhbmdlLmVuZCkge1xuICAgICAgICAgICAgcHJvcHMuc3RhcnREZWx0YSA9IGRlbHRhO1xuICAgICAgICAgICAgcmV0dXJuIHByb3BzO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZiAoZGF0ZUVudi5hZGQoaW5zdGFuY2VSYW5nZS5lbmQsIGRlbHRhKSA+IGluc3RhbmNlUmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgICAgIHByb3BzLmVuZERlbHRhID0gZGVsdGE7XG4gICAgICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbnZhciBVbnNlbGVjdEF1dG8gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVW5zZWxlY3RBdXRvKGNhbGVuZGFyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuaXNSZWNlbnRQb2ludGVyRGF0ZVNlbGVjdCA9IGZhbHNlOyAvLyB3aXNoIHdlIGNvdWxkIHVzZSBhIHNlbGVjdG9yIHRvIGRldGVjdCBkYXRlIHNlbGVjdGlvbiwgYnV0IHVzZXMgaGl0IHN5c3RlbVxuICAgICAgICB0aGlzLm9uU2VsZWN0ID0gZnVuY3Rpb24gKHNlbGVjdEluZm8pIHtcbiAgICAgICAgICAgIGlmIChzZWxlY3RJbmZvLmpzRXZlbnQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc1JlY2VudFBvaW50ZXJEYXRlU2VsZWN0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vbkRvY3VtZW50UG9pbnRlclVwID0gZnVuY3Rpb24gKHBldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIGRvY3VtZW50UG9pbnRlciA9IF9hLmRvY3VtZW50UG9pbnRlcjtcbiAgICAgICAgICAgIHZhciBzdGF0ZSA9IGNhbGVuZGFyLnN0YXRlO1xuICAgICAgICAgICAgLy8gdG91Y2gtc2Nyb2xsaW5nIHNob3VsZCBuZXZlciB1bmZvY3VzIGFueSB0eXBlIG9mIHNlbGVjdGlvblxuICAgICAgICAgICAgaWYgKCFkb2N1bWVudFBvaW50ZXIud2FzVG91Y2hTY3JvbGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZGF0ZVNlbGVjdGlvbiAmJiAvLyBhbiBleGlzdGluZyBkYXRlIHNlbGVjdGlvbj9cbiAgICAgICAgICAgICAgICAgICAgIV90aGlzLmlzUmVjZW50UG9pbnRlckRhdGVTZWxlY3QgLy8gYSBuZXcgcG9pbnRlci1pbml0aWF0ZWQgZGF0ZSBzZWxlY3Rpb24gc2luY2UgbGFzdCBvbkRvY3VtZW50UG9pbnRlclVwP1xuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdW5zZWxlY3RBdXRvID0gY2FsZW5kYXIudmlld09wdCgndW5zZWxlY3RBdXRvJyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB1bnNlbGVjdENhbmNlbCA9IGNhbGVuZGFyLnZpZXdPcHQoJ3Vuc2VsZWN0Q2FuY2VsJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1bnNlbGVjdEF1dG8gJiYgKCF1bnNlbGVjdEF1dG8gfHwgIWVsZW1lbnRDbG9zZXN0KGRvY3VtZW50UG9pbnRlci5kb3duRWwsIHVuc2VsZWN0Q2FuY2VsKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLnVuc2VsZWN0KHBldik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlLmV2ZW50U2VsZWN0aW9uICYmIC8vIGFuIGV4aXN0aW5nIGV2ZW50IHNlbGVjdGVkP1xuICAgICAgICAgICAgICAgICAgICAhZWxlbWVudENsb3Nlc3QoZG9jdW1lbnRQb2ludGVyLmRvd25FbCwgRXZlbnREcmFnZ2luZy5TRUxFQ1RPUikgLy8gaW50ZXJhY3Rpb24gRElETidUIHN0YXJ0IG9uIGFuIGV2ZW50XG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VMRUNUX0VWRU5UJyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5pc1JlY2VudFBvaW50ZXJEYXRlU2VsZWN0ID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICAgICAgdmFyIGRvY3VtZW50UG9pbnRlciA9IHRoaXMuZG9jdW1lbnRQb2ludGVyID0gbmV3IFBvaW50ZXJEcmFnZ2luZyhkb2N1bWVudCk7XG4gICAgICAgIGRvY3VtZW50UG9pbnRlci5zaG91bGRJZ25vcmVNb3ZlID0gdHJ1ZTtcbiAgICAgICAgZG9jdW1lbnRQb2ludGVyLnNob3VsZFdhdGNoU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgIGRvY3VtZW50UG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVydXAnLCB0aGlzLm9uRG9jdW1lbnRQb2ludGVyVXApO1xuICAgICAgICAvKlxuICAgICAgICBUT0RPOiBiZXR0ZXIgd2F5IHRvIGtub3cgYWJvdXQgd2hldGhlciB0aGVyZSB3YXMgYSBzZWxlY3Rpb24gd2l0aCB0aGUgcG9pbnRlclxuICAgICAgICAqL1xuICAgICAgICBjYWxlbmRhci5vbignc2VsZWN0JywgdGhpcy5vblNlbGVjdCk7XG4gICAgfVxuICAgIFVuc2VsZWN0QXV0by5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhci5vZmYoJ3NlbGVjdCcsIHRoaXMub25TZWxlY3QpO1xuICAgICAgICB0aGlzLmRvY3VtZW50UG9pbnRlci5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gVW5zZWxlY3RBdXRvO1xufSgpKTtcblxuLypcbkdpdmVuIGFuIGFscmVhZHkgaW5zdGFudGlhdGVkIGRyYWdnYWJsZSBvYmplY3QgZm9yIG9uZS1vci1tb3JlIGVsZW1lbnRzLFxuSW50ZXJwcmV0cyBhbnkgZHJhZ2dpbmcgYXMgYW4gYXR0ZW1wdCB0byBkcmFnIGFuIGV2ZW50cyB0aGF0IGxpdmVzIG91dHNpZGVcbm9mIGEgY2FsZW5kYXIgb250byBhIGNhbGVuZGFyLlxuKi9cbnZhciBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyhkcmFnZ2luZywgc3VwcGxpZWREcmFnTWV0YSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcm9wcGFibGVFdmVudCA9IG51bGw7IC8vIHdpbGwgZXhpc3QgZm9yIGFsbCBkcmFncywgZXZlbiBpZiBjcmVhdGU6ZmFsc2VcbiAgICAgICAgdGhpcy5zdXBwbGllZERyYWdNZXRhID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnTWV0YSA9IG51bGw7XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5kcmFnTWV0YSA9IF90aGlzLmJ1aWxkRHJhZ01ldGEoZXYuc3ViamVjdEVsKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVIaXRVcGRhdGUgPSBmdW5jdGlvbiAoaGl0LCBpc0ZpbmFsLCBldikge1xuICAgICAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuaGl0RHJhZ2dpbmcuZHJhZ2dpbmc7XG4gICAgICAgICAgICB2YXIgcmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICAgICAgdmFyIGRyb3BwYWJsZUV2ZW50ID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogX3RoaXMuZHJhZ01ldGEuY3JlYXRlLFxuICAgICAgICAgICAgICAgIG9yaWdTZWc6IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoaGl0KSB7XG4gICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIgPSBoaXQuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNhbkRyb3BFbE9uQ2FsZW5kYXIoZXYuc3ViamVjdEVsLCByZWNlaXZpbmdDYWxlbmRhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJvcHBhYmxlRXZlbnQgPSBjb21wdXRlRXZlbnRGb3JEYXRlU3BhbihoaXQuZGF0ZVNwYW4sIF90aGlzLmRyYWdNZXRhLCByZWNlaXZpbmdDYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBldmVudFR1cGxlVG9TdG9yZShkcm9wcGFibGVFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIGlzSW52YWxpZCA9ICFpc0ludGVyYWN0aW9uVmFsaWQoaW50ZXJhY3Rpb24sIHJlY2VpdmluZ0NhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZHJvcHBhYmxlRXZlbnQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZGlzcGxheURyYWcocmVjZWl2aW5nQ2FsZW5kYXIsIGludGVyYWN0aW9uKTtcbiAgICAgICAgICAgIC8vIHNob3cgbWlycm9yIGlmIG5vIGFscmVhZHktcmVuZGVyZWQgbWlycm9yIGVsZW1lbnQgT1IgaWYgd2UgYXJlIHNodXR0aW5nIGRvd24gdGhlIG1pcnJvciAoPylcbiAgICAgICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgc29tZWhvdyB3YWl0IGZvciBkaXNwYXRjaCB0byBndWFyYW50ZWUgcmVuZGVyXG4gICAgICAgICAgICBkcmFnZ2luZy5zZXRNaXJyb3JJc1Zpc2libGUoaXNGaW5hbCB8fCAhZHJvcHBhYmxlRXZlbnQgfHwgIWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5mYy1taXJyb3InKSk7XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgZHJhZ2dpbmcuc2V0TWlycm9yTmVlZHNSZXZlcnQoIWRyb3BwYWJsZUV2ZW50KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZWNlaXZpbmdDYWxlbmRhciA9IHJlY2VpdmluZ0NhbGVuZGFyO1xuICAgICAgICAgICAgICAgIF90aGlzLmRyb3BwYWJsZUV2ZW50ID0gZHJvcHBhYmxlRXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChwZXYpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLCByZWNlaXZpbmdDYWxlbmRhciA9IF9hLnJlY2VpdmluZ0NhbGVuZGFyLCBkcm9wcGFibGVFdmVudCA9IF9hLmRyb3BwYWJsZUV2ZW50O1xuICAgICAgICAgICAgX3RoaXMuY2xlYXJEcmFnKCk7XG4gICAgICAgICAgICBpZiAocmVjZWl2aW5nQ2FsZW5kYXIgJiYgZHJvcHBhYmxlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmluYWxIaXQgPSBfdGhpcy5oaXREcmFnZ2luZy5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICB2YXIgZmluYWxWaWV3ID0gZmluYWxIaXQuY29tcG9uZW50LmNvbnRleHQudmlldztcbiAgICAgICAgICAgICAgICB2YXIgZHJhZ01ldGEgPSBfdGhpcy5kcmFnTWV0YTtcbiAgICAgICAgICAgICAgICB2YXIgYXJnID0gX19hc3NpZ24oe30sIHJlY2VpdmluZ0NhbGVuZGFyLmJ1aWxkRGF0ZVBvaW50QXBpKGZpbmFsSGl0LmRhdGVTcGFuKSwgeyBkcmFnZ2VkRWw6IHBldi5zdWJqZWN0RWwsIGpzRXZlbnQ6IHBldi5vcmlnRXZlbnQsIHZpZXc6IGZpbmFsVmlldyB9KTtcbiAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2Ryb3AnLCBbYXJnXSk7XG4gICAgICAgICAgICAgICAgaWYgKGRyYWdNZXRhLmNyZWF0ZSkge1xuICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50VHVwbGVUb1N0b3JlKGRyb3BwYWJsZUV2ZW50KVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFTEVDVF9FVkVOVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRJbnN0YW5jZUlkOiBkcm9wcGFibGVFdmVudC5pbnN0YW5jZS5pbnN0YW5jZUlkXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBzaWduYWwgdGhhdCBhbiBleHRlcm5hbCBldmVudCBsYW5kZWRcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlY2VpdmUnLCBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dlZEVsOiBwZXYuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkocmVjZWl2aW5nQ2FsZW5kYXIsIGRyb3BwYWJsZUV2ZW50LmRlZiwgZHJvcHBhYmxlRXZlbnQuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGZpbmFsVmlld1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5yZWNlaXZpbmdDYWxlbmRhciA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5kcm9wcGFibGVFdmVudCA9IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBoaXREcmFnZ2luZyA9IHRoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcoZHJhZ2dpbmcsIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLnJlcXVpcmVJbml0aWFsID0gZmFsc2U7IC8vIHdpbGwgc3RhcnQgb3V0c2lkZSBvZiBhIGNvbXBvbmVudFxuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIHRoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIHRoaXMuaGFuZGxlRHJhZ0VuZCk7XG4gICAgICAgIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9IHN1cHBsaWVkRHJhZ01ldGE7XG4gICAgfVxuICAgIEV4dGVybmFsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5idWlsZERyYWdNZXRhID0gZnVuY3Rpb24gKHN1YmplY3RFbCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZURyYWdNZXRhKHRoaXMuc3VwcGxpZWREcmFnTWV0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHBhcnNlRHJhZ01ldGEodGhpcy5zdXBwbGllZERyYWdNZXRhKHN1YmplY3RFbCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGdldERyYWdNZXRhRnJvbUVsKHN1YmplY3RFbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV4dGVybmFsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5kaXNwbGF5RHJhZyA9IGZ1bmN0aW9uIChuZXh0Q2FsZW5kYXIsIHN0YXRlKSB7XG4gICAgICAgIHZhciBwcmV2Q2FsZW5kYXIgPSB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyO1xuICAgICAgICBpZiAocHJldkNhbGVuZGFyICYmIHByZXZDYWxlbmRhciAhPT0gbmV4dENhbGVuZGFyKSB7XG4gICAgICAgICAgICBwcmV2Q2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfRFJBRycgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5leHRDYWxlbmRhcikge1xuICAgICAgICAgICAgbmV4dENhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1NFVF9FVkVOVF9EUkFHJywgc3RhdGU6IHN0YXRlIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuY2xlYXJEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yZWNlaXZpbmdDYWxlbmRhcikge1xuICAgICAgICAgICAgdGhpcy5yZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmNhbkRyb3BFbE9uQ2FsZW5kYXIgPSBmdW5jdGlvbiAoZWwsIHJlY2VpdmluZ0NhbGVuZGFyKSB7XG4gICAgICAgIHZhciBkcm9wQWNjZXB0ID0gcmVjZWl2aW5nQ2FsZW5kYXIub3B0KCdkcm9wQWNjZXB0Jyk7XG4gICAgICAgIGlmICh0eXBlb2YgZHJvcEFjY2VwdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIGRyb3BBY2NlcHQoZWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBkcm9wQWNjZXB0ID09PSAnc3RyaW5nJyAmJiBkcm9wQWNjZXB0KSB7XG4gICAgICAgICAgICByZXR1cm4gQm9vbGVhbihlbGVtZW50TWF0Y2hlcyhlbCwgZHJvcEFjY2VwdCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgcmV0dXJuIEV4dGVybmFsRWxlbWVudERyYWdnaW5nO1xufSgpKTtcbi8vIFV0aWxzIGZvciBjb21wdXRpbmcgZXZlbnQgc3RvcmUgZnJvbSB0aGUgRHJhZ01ldGFcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGNvbXB1dGVFdmVudEZvckRhdGVTcGFuKGRhdGVTcGFuLCBkcmFnTWV0YSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgZGVmUHJvcHMgPSBfX2Fzc2lnbih7fSwgZHJhZ01ldGEubGVmdG92ZXJQcm9wcyk7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5leHRlcm5hbERlZlRyYW5zZm9ybXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBfYVtfaV07XG4gICAgICAgIF9fYXNzaWduKGRlZlByb3BzLCB0cmFuc2Zvcm0oZGF0ZVNwYW4sIGRyYWdNZXRhKSk7XG4gICAgfVxuICAgIHZhciBkZWYgPSBwYXJzZUV2ZW50RGVmKGRlZlByb3BzLCBkcmFnTWV0YS5zb3VyY2VJZCwgZGF0ZVNwYW4uYWxsRGF5LCBjYWxlbmRhci5vcHQoJ2ZvcmNlRXZlbnREdXJhdGlvbicpIHx8IEJvb2xlYW4oZHJhZ01ldGEuZHVyYXRpb24pLCAvLyBoYXNFbmRcbiAgICBjYWxlbmRhcik7XG4gICAgdmFyIHN0YXJ0ID0gZGF0ZVNwYW4ucmFuZ2Uuc3RhcnQ7XG4gICAgLy8gb25seSByZWx5IG9uIHRpbWUgaW5mbyBpZiBkcm9wIHpvbmUgaXMgYWxsLWRheSxcbiAgICAvLyBvdGhlcndpc2UsIHdlIGFscmVhZHkga25vdyB0aGUgdGltZVxuICAgIGlmIChkYXRlU3Bhbi5hbGxEYXkgJiYgZHJhZ01ldGEuc3RhcnRUaW1lKSB7XG4gICAgICAgIHN0YXJ0ID0gY2FsZW5kYXIuZGF0ZUVudi5hZGQoc3RhcnQsIGRyYWdNZXRhLnN0YXJ0VGltZSk7XG4gICAgfVxuICAgIHZhciBlbmQgPSBkcmFnTWV0YS5kdXJhdGlvbiA/XG4gICAgICAgIGNhbGVuZGFyLmRhdGVFbnYuYWRkKHN0YXJ0LCBkcmFnTWV0YS5kdXJhdGlvbikgOlxuICAgICAgICBjYWxlbmRhci5nZXREZWZhdWx0RXZlbnRFbmQoZGF0ZVNwYW4uYWxsRGF5LCBzdGFydCk7XG4gICAgdmFyIGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9KTtcbiAgICByZXR1cm4geyBkZWY6IGRlZiwgaW5zdGFuY2U6IGluc3RhbmNlIH07XG59XG4vLyBVdGlscyBmb3IgZXh0cmFjdGluZyBkYXRhIGZyb20gZWxlbWVudFxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gZ2V0RHJhZ01ldGFGcm9tRWwoZWwpIHtcbiAgICB2YXIgc3RyID0gZ2V0RW1iZWRkZWRFbERhdGEoZWwsICdldmVudCcpO1xuICAgIHZhciBvYmogPSBzdHIgP1xuICAgICAgICBKU09OLnBhcnNlKHN0cikgOlxuICAgICAgICB7IGNyZWF0ZTogZmFsc2UgfTsgLy8gaWYgbm8gZW1iZWRkZWQgZGF0YSwgYXNzdW1lIG5vIGV2ZW50IGNyZWF0aW9uXG4gICAgcmV0dXJuIHBhcnNlRHJhZ01ldGEob2JqKTtcbn1cbmNvbmZpZy5kYXRhQXR0clByZWZpeCA9ICcnO1xuZnVuY3Rpb24gZ2V0RW1iZWRkZWRFbERhdGEoZWwsIG5hbWUpIHtcbiAgICB2YXIgcHJlZml4ID0gY29uZmlnLmRhdGFBdHRyUHJlZml4O1xuICAgIHZhciBwcmVmaXhlZE5hbWUgPSAocHJlZml4ID8gcHJlZml4ICsgJy0nIDogJycpICsgbmFtZTtcbiAgICByZXR1cm4gZWwuZ2V0QXR0cmlidXRlKCdkYXRhLScgKyBwcmVmaXhlZE5hbWUpIHx8ICcnO1xufVxuXG4vKlxuTWFrZXMgYW4gZWxlbWVudCAodGhhdCBpcyAqZXh0ZXJuYWwqIHRvIGFueSBjYWxlbmRhcikgZHJhZ2dhYmxlLlxuQ2FuIHBhc3MgaW4gZGF0YSB0aGF0IGRldGVybWluZXMgaG93IGFuIGV2ZW50IHdpbGwgYmUgY3JlYXRlZCB3aGVuIGRyb3BwZWQgb250byBhIGNhbGVuZGFyLlxuTGV2ZXJhZ2VzIEZ1bGxDYWxlbmRhcidzIGludGVybmFsIGRyYWctbi1kcm9wIGZ1bmN0aW9uYWxpdHkgV0lUSE9VVCBhIHRoaXJkLXBhcnR5IGRyYWcgc3lzdGVtLlxuKi9cbnZhciBFeHRlcm5hbERyYWdnYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFeHRlcm5hbERyYWdnYWJsZShlbCwgc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHNldHRpbmdzID09PSB2b2lkIDApIHsgc2V0dGluZ3MgPSB7fTsgfVxuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgZHJhZ2dpbmcgPSBfdGhpcy5kcmFnZ2luZztcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLnNldHRpbmdzLCBtaW5EaXN0YW5jZSA9IF9hLm1pbkRpc3RhbmNlLCBsb25nUHJlc3NEZWxheSA9IF9hLmxvbmdQcmVzc0RlbGF5O1xuICAgICAgICAgICAgZHJhZ2dpbmcubWluRGlzdGFuY2UgPVxuICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlICE9IG51bGwgP1xuICAgICAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSA6XG4gICAgICAgICAgICAgICAgICAgIChldi5pc1RvdWNoID8gMCA6IGdsb2JhbERlZmF1bHRzLmV2ZW50RHJhZ01pbkRpc3RhbmNlKTtcbiAgICAgICAgICAgIGRyYWdnaW5nLmRlbGF5ID1cbiAgICAgICAgICAgICAgICBldi5pc1RvdWNoID8gLy8gVE9ETzogZXZlbnR1YWxseSByZWFkIGV2ZW50TG9uZ1ByZXNzRGVsYXkgaW5zdGVhZCB2dnZcbiAgICAgICAgICAgICAgICAgICAgKGxvbmdQcmVzc0RlbGF5ICE9IG51bGwgPyBsb25nUHJlc3NEZWxheSA6IGdsb2JhbERlZmF1bHRzLmxvbmdQcmVzc0RlbGF5KSA6XG4gICAgICAgICAgICAgICAgICAgIDA7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoZXYuaXNUb3VjaCAmJlxuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLmRlbGF5ICYmXG4gICAgICAgICAgICAgICAgZXYuc3ViamVjdEVsLmNsYXNzTGlzdC5jb250YWlucygnZmMtZXZlbnQnKSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLm1pcnJvci5nZXRNaXJyb3JFbCgpLmNsYXNzTGlzdC5hZGQoJ2ZjLXNlbGVjdGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcbiAgICAgICAgdmFyIGRyYWdnaW5nID0gdGhpcy5kcmFnZ2luZyA9IG5ldyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nKGVsKTtcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGlmIChzZXR0aW5ncy5pdGVtU2VsZWN0b3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9IHNldHRpbmdzLml0ZW1TZWxlY3RvcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2V0dGluZ3MuYXBwZW5kVG8gIT0gbnVsbCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcubWlycm9yLnBhcmVudE5vZGUgPSBzZXR0aW5ncy5hcHBlbmRUbzsgLy8gVE9ETzogd3JpdGUgdGVzdHNcbiAgICAgICAgfVxuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIG5ldyBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyhkcmFnZ2luZywgc2V0dGluZ3MuZXZlbnREYXRhKTtcbiAgICB9XG4gICAgRXh0ZXJuYWxEcmFnZ2FibGUucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIEV4dGVybmFsRHJhZ2dhYmxlO1xufSgpKTtcblxuLypcbkRldGVjdHMgd2hlbiBhICpUSElSRC1QQVJUWSogZHJhZy1uLWRyb3Agc3lzdGVtIGludGVyYWN0cyB3aXRoIGVsZW1lbnRzLlxuVGhlIHRoaXJkLXBhcnR5IHN5c3RlbSBpcyByZXNwb25zaWJsZSBmb3IgZHJhd2luZyB0aGUgdmlzdWFscyBlZmZlY3RzIG9mIHRoZSBkcmFnLlxuVGhpcyBjbGFzcyBzaW1wbHkgbW9uaXRvcnMgZm9yIHBvaW50ZXIgbW92ZW1lbnRzIGFuZCBmaXJlcyBldmVudHMuXG5JdCBhbHNvIGhhcyB0aGUgYWJpbGl0eSB0byBoaWRlIHRoZSBtb3ZpbmcgZWxlbWVudCAodGhlIFwibWlycm9yXCIpIGR1cmluZyB0aGUgZHJhZy5cbiovXG52YXIgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEluZmVycmVkRWxlbWVudERyYWdnaW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEluZmVycmVkRWxlbWVudERyYWdnaW5nKGNvbnRhaW5lckVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNvbnRhaW5lckVsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zaG91bGRJZ25vcmVNb3ZlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLm1pcnJvclNlbGVjdG9yID0gJyc7XG4gICAgICAgIF90aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG51bGw7XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgZXYpO1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgLy8gZmlyZSBkcmFnc3RhcnQgcmlnaHQgYXdheS4gZG9lcyBub3Qgc3VwcG9ydCBkZWxheSBvciBtaW4tZGlzdGFuY2VcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdzdGFydCcsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlck1vdmUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuc2hvdWxkSWdub3JlTW92ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ21vdmUnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVydXAnLCBldik7XG4gICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAvLyBmaXJlIGRyYWdlbmQgcmlnaHQgYXdheS4gZG9lcyBub3Qgc3VwcG9ydCBhIHJldmVydCBhbmltYXRpb25cbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdlbmQnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBwb2ludGVyID0gX3RoaXMucG9pbnRlciA9IG5ldyBQb2ludGVyRHJhZ2dpbmcoY29udGFpbmVyRWwpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJtb3ZlJywgX3RoaXMuaGFuZGxlUG9pbnRlck1vdmUpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIF90aGlzLmhhbmRsZVBvaW50ZXJVcCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucG9pbnRlci5kZXN0cm95KCk7XG4gICAgfTtcbiAgICBJbmZlcnJlZEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0SWdub3JlTW92ZSA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIHRoaXMuc2hvdWxkSWdub3JlTW92ZSA9IGJvb2w7XG4gICAgfTtcbiAgICBJbmZlcnJlZEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9ySXNWaXNpYmxlID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgaWYgKGJvb2wpIHtcbiAgICAgICAgICAgIC8vIHJlc3RvcmUgYSBwcmV2aW91c2x5IGhpZGRlbiBlbGVtZW50LlxuICAgICAgICAgICAgLy8gdXNlIHRoZSByZWZlcmVuY2UgaW4gY2FzZSB0aGUgc2VsZWN0b3IgY2xhc3MgaGFzIGFscmVhZHkgYmVlbiByZW1vdmVkLlxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudE1pcnJvckVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TWlycm9yRWwuc3R5bGUudmlzaWJpbGl0eSA9ICcnO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudE1pcnJvckVsID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBtaXJyb3JFbCA9IHRoaXMubWlycm9yU2VsZWN0b3IgP1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5taXJyb3JTZWxlY3RvcikgOlxuICAgICAgICAgICAgICAgIG51bGw7XG4gICAgICAgICAgICBpZiAobWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG1pcnJvckVsO1xuICAgICAgICAgICAgICAgIG1pcnJvckVsLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEluZmVycmVkRWxlbWVudERyYWdnaW5nO1xufShFbGVtZW50RHJhZ2dpbmcpKTtcblxuLypcbkJyaWRnZXMgdGhpcmQtcGFydHkgZHJhZy1uLWRyb3Agc3lzdGVtcyB3aXRoIEZ1bGxDYWxlbmRhci5cbk11c3QgYmUgaW5zdGFudGlhdGVkIGFuZCBkZXN0cm95ZWQgYnkgY2FsbGVyLlxuKi9cbnZhciBUaGlyZFBhcnR5RHJhZ2dhYmxlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFRoaXJkUGFydHlEcmFnZ2FibGUoY29udGFpbmVyT3JTZXR0aW5ncywgc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lckVsID0gZG9jdW1lbnQ7XG4gICAgICAgIGlmIChcbiAgICAgICAgLy8gd2lzaCB3ZSBjb3VsZCBqdXN0IHRlc3QgaW5zdGFuY2VvZiBFdmVudFRhcmdldCwgYnV0IGRvZXNuJ3Qgd29yayBpbiBJRTExXG4gICAgICAgIGNvbnRhaW5lck9yU2V0dGluZ3MgPT09IGRvY3VtZW50IHx8XG4gICAgICAgICAgICBjb250YWluZXJPclNldHRpbmdzIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgICAgY29udGFpbmVyRWwgPSBjb250YWluZXJPclNldHRpbmdzO1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBzZXR0aW5ncyB8fCB7fTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzID0gKGNvbnRhaW5lck9yU2V0dGluZ3MgfHwge30pO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IHRoaXMuZHJhZ2dpbmcgPSBuZXcgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcoY29udGFpbmVyRWwpO1xuICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzLml0ZW1TZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGRyYWdnaW5nLnBvaW50ZXIuc2VsZWN0b3IgPSBzZXR0aW5ncy5pdGVtU2VsZWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29udGFpbmVyRWwgPT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gJ1tkYXRhLWV2ZW50XSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy5taXJyb3JTZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGRyYWdnaW5nLm1pcnJvclNlbGVjdG9yID0gc2V0dGluZ3MubWlycm9yU2VsZWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgbmV3IEV4dGVybmFsRWxlbWVudERyYWdnaW5nKGRyYWdnaW5nLCBzZXR0aW5ncy5ldmVudERhdGEpO1xuICAgIH1cbiAgICBUaGlyZFBhcnR5RHJhZ2dhYmxlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRyYWdnaW5nLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIHJldHVybiBUaGlyZFBhcnR5RHJhZ2dhYmxlO1xufSgpKTtcblxudmFyIG1haW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIGNvbXBvbmVudEludGVyYWN0aW9uczogW0RhdGVDbGlja2luZywgRGF0ZVNlbGVjdGluZywgRXZlbnREcmFnZ2luZywgRXZlbnREcmFnZ2luZyQxXSxcbiAgICBjYWxlbmRhckludGVyYWN0aW9uczogW1Vuc2VsZWN0QXV0b10sXG4gICAgZWxlbWVudERyYWdnaW5nSW1wbDogRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZ1xufSk7XG5cbmV4cG9ydCBkZWZhdWx0IG1haW47XG5leHBvcnQgeyBFeHRlcm5hbERyYWdnYWJsZSBhcyBEcmFnZ2FibGUsIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcsIFBvaW50ZXJEcmFnZ2luZywgVGhpcmRQYXJ0eURyYWdnYWJsZSB9O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGlzQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtY2FsbGFibGUnKTtcbnZhciB0cnlUb1N0cmluZyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90cnktdG8tc3RyaW5nJyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xuXG4vLyBgQXNzZXJ0OiBJc0NhbGxhYmxlKGFyZ3VtZW50KSBpcyB0cnVlYFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgaWYgKGlzQ2FsbGFibGUoYXJndW1lbnQpKSByZXR1cm4gYXJndW1lbnQ7XG4gIHRocm93IG5ldyAkVHlwZUVycm9yKHRyeVRvU3RyaW5nKGFyZ3VtZW50KSArICcgaXMgbm90IGEgZnVuY3Rpb24nKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtb2JqZWN0Jyk7XG5cbnZhciAkU3RyaW5nID0gU3RyaW5nO1xudmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7XG5cbi8vIGBBc3NlcnQ6IFR5cGUoYXJndW1lbnQpIGlzIE9iamVjdGBcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gIGlmIChpc09iamVjdChhcmd1bWVudCkpIHJldHVybiBhcmd1bWVudDtcbiAgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJFN0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBhbiBvYmplY3QnKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG5cbnZhciB0b1N0cmluZyA9IHVuY3VycnlUaGlzKHt9LnRvU3RyaW5nKTtcbnZhciBzdHJpbmdTbGljZSA9IHVuY3VycnlUaGlzKCcnLnNsaWNlKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIHN0cmluZ1NsaWNlKHRvU3RyaW5nKGl0KSwgOCwgLTEpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tc3RyaW5nLXRhZy1zdXBwb3J0Jyk7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xudmFyIGNsYXNzb2ZSYXcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcbnZhciB3ZWxsS25vd25TeW1ib2wgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvd2VsbC1rbm93bi1zeW1ib2wnKTtcblxudmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7XG52YXIgJE9iamVjdCA9IE9iamVjdDtcblxuLy8gRVMzIHdyb25nIGhlcmVcbnZhciBDT1JSRUNUX0FSR1VNRU5UUyA9IGNsYXNzb2ZSYXcoZnVuY3Rpb24gKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpID09PSAnQXJndW1lbnRzJztcblxuLy8gZmFsbGJhY2sgZm9yIElFMTEgU2NyaXB0IEFjY2VzcyBEZW5pZWQgZXJyb3JcbnZhciB0cnlHZXQgPSBmdW5jdGlvbiAoaXQsIGtleSkge1xuICB0cnkge1xuICAgIHJldHVybiBpdFtrZXldO1xuICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9XG59O1xuXG4vLyBnZXR0aW5nIHRhZyBmcm9tIEVTNisgYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgXG5tb2R1bGUuZXhwb3J0cyA9IFRPX1NUUklOR19UQUdfU1VQUE9SVCA/IGNsYXNzb2ZSYXcgOiBmdW5jdGlvbiAoaXQpIHtcbiAgdmFyIE8sIHRhZywgcmVzdWx0O1xuICByZXR1cm4gaXQgPT09IHVuZGVmaW5lZCA/ICdVbmRlZmluZWQnIDogaXQgPT09IG51bGwgPyAnTnVsbCdcbiAgICAvLyBAQHRvU3RyaW5nVGFnIGNhc2VcbiAgICA6IHR5cGVvZiAodGFnID0gdHJ5R2V0KE8gPSAkT2JqZWN0KGl0KSwgVE9fU1RSSU5HX1RBRykpID09ICdzdHJpbmcnID8gdGFnXG4gICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgOiBDT1JSRUNUX0FSR1VNRU5UUyA/IGNsYXNzb2ZSYXcoTylcbiAgICAvLyBFUzMgYXJndW1lbnRzIGZhbGxiYWNrXG4gICAgOiAocmVzdWx0ID0gY2xhc3NvZlJhdyhPKSkgPT09ICdPYmplY3QnICYmIGlzQ2FsbGFibGUoTy5jYWxsZWUpID8gJ0FyZ3VtZW50cycgOiByZXN1bHQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZGVmaW5lUHJvcGVydHlNb2R1bGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWRlZmluZS1wcm9wZXJ0eScpO1xudmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9jcmVhdGUtcHJvcGVydHktZGVzY3JpcHRvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERFU0NSSVBUT1JTID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICByZXR1cm4gZGVmaW5lUHJvcGVydHlNb2R1bGUuZihvYmplY3QsIGtleSwgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDEsIHZhbHVlKSk7XG59IDogZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gb2JqZWN0O1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLFxuICAgIGNvbmZpZ3VyYWJsZTogIShiaXRtYXAgJiAyKSxcbiAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZTogdmFsdWVcbiAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xudmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL29iamVjdC1kZWZpbmUtcHJvcGVydHknKTtcbnZhciBtYWtlQnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9tYWtlLWJ1aWx0LWluJyk7XG52YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVmaW5lLWdsb2JhbC1wcm9wZXJ0eScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBrZXksIHZhbHVlLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9O1xuICB2YXIgc2ltcGxlID0gb3B0aW9ucy5lbnVtZXJhYmxlO1xuICB2YXIgbmFtZSA9IG9wdGlvbnMubmFtZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uYW1lIDoga2V5O1xuICBpZiAoaXNDYWxsYWJsZSh2YWx1ZSkpIG1ha2VCdWlsdEluKHZhbHVlLCBuYW1lLCBvcHRpb25zKTtcbiAgaWYgKG9wdGlvbnMuZ2xvYmFsKSB7XG4gICAgaWYgKHNpbXBsZSkgT1trZXldID0gdmFsdWU7XG4gICAgZWxzZSBkZWZpbmVHbG9iYWxQcm9wZXJ0eShrZXksIHZhbHVlKTtcbiAgfSBlbHNlIHtcbiAgICB0cnkge1xuICAgICAgaWYgKCFvcHRpb25zLnVuc2FmZSkgZGVsZXRlIE9ba2V5XTtcbiAgICAgIGVsc2UgaWYgKE9ba2V5XSkgc2ltcGxlID0gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9XG4gICAgaWYgKHNpbXBsZSkgT1trZXldID0gdmFsdWU7XG4gICAgZWxzZSBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKE8sIGtleSwge1xuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6ICFvcHRpb25zLm5vbkNvbmZpZ3VyYWJsZSxcbiAgICAgIHdyaXRhYmxlOiAhb3B0aW9ucy5ub25Xcml0YWJsZVxuICAgIH0pO1xuICB9IHJldHVybiBPO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZVxudmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gIHRyeSB7XG4gICAgZGVmaW5lUHJvcGVydHkoZ2xvYmFsLCBrZXksIHsgdmFsdWU6IHZhbHVlLCBjb25maWd1cmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGdsb2JhbFtrZXldID0gdmFsdWU7XG4gIH0gcmV0dXJuIHZhbHVlO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xuXG4vLyBEZXRlY3QgSUU4J3MgaW5jb21wbGV0ZSBkZWZpbmVQcm9wZXJ0eSBpbXBsZW1lbnRhdGlvblxubW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pWzFdICE9PSA3O1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW9iamVjdCcpO1xuXG52YXIgZG9jdW1lbnQgPSBnbG9iYWwuZG9jdW1lbnQ7XG4vLyB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBpcyAnb2JqZWN0JyBpbiBvbGQgSUVcbnZhciBFWElTVFMgPSBpc09iamVjdChkb2N1bWVudCkgJiYgaXNPYmplY3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBFWElTVFMgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGl0KSA6IHt9O1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gdHlwZW9mIG5hdmlnYXRvciAhPSAndW5kZWZpbmVkJyAmJiBTdHJpbmcobmF2aWdhdG9yLnVzZXJBZ2VudCkgfHwgJyc7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHVzZXJBZ2VudCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9lbmdpbmUtdXNlci1hZ2VudCcpO1xuXG52YXIgcHJvY2VzcyA9IGdsb2JhbC5wcm9jZXNzO1xudmFyIERlbm8gPSBnbG9iYWwuRGVubztcbnZhciB2ZXJzaW9ucyA9IHByb2Nlc3MgJiYgcHJvY2Vzcy52ZXJzaW9ucyB8fCBEZW5vICYmIERlbm8udmVyc2lvbjtcbnZhciB2OCA9IHZlcnNpb25zICYmIHZlcnNpb25zLnY4O1xudmFyIG1hdGNoLCB2ZXJzaW9uO1xuXG5pZiAodjgpIHtcbiAgbWF0Y2ggPSB2OC5zcGxpdCgnLicpO1xuICAvLyBpbiBvbGQgQ2hyb21lLCB2ZXJzaW9ucyBvZiBWOCBpc24ndCBWOCA9IENocm9tZSAvIDEwXG4gIC8vIGJ1dCB0aGVpciBjb3JyZWN0IHZlcnNpb25zIGFyZSBub3QgaW50ZXJlc3RpbmcgZm9yIHVzXG4gIHZlcnNpb24gPSBtYXRjaFswXSA+IDAgJiYgbWF0Y2hbMF0gPCA0ID8gMSA6ICsobWF0Y2hbMF0gKyBtYXRjaFsxXSk7XG59XG5cbi8vIEJyb3dzZXJGUyBOb2RlSlMgYHByb2Nlc3NgIHBvbHlmaWxsIGluY29ycmVjdGx5IHNldCBgLnY4YCB0byBgMC4wYFxuLy8gc28gY2hlY2sgYHVzZXJBZ2VudGAgZXZlbiBpZiBgLnY4YCBleGlzdHMsIGJ1dCAwXG5pZiAoIXZlcnNpb24gJiYgdXNlckFnZW50KSB7XG4gIG1hdGNoID0gdXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLyk7XG4gIGlmICghbWF0Y2ggfHwgbWF0Y2hbMV0gPj0gNzQpIHtcbiAgICBtYXRjaCA9IHVzZXJBZ2VudC5tYXRjaCgvQ2hyb21lXFwvKFxcZCspLyk7XG4gICAgaWYgKG1hdGNoKSB2ZXJzaW9uID0gK21hdGNoWzFdO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdmVyc2lvbjtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGV4ZWMpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gISFleGVjKCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tZnVuY3Rpb24tcHJvdG90eXBlLWJpbmQgLS0gc2FmZVxuICB2YXIgdGVzdCA9IChmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH0pLmJpbmQoKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXByb3RvdHlwZS1idWlsdGlucyAtLSBzYWZlXG4gIHJldHVybiB0eXBlb2YgdGVzdCAhPSAnZnVuY3Rpb24nIHx8IHRlc3QuaGFzT3duUHJvcGVydHkoJ3Byb3RvdHlwZScpO1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgTkFUSVZFX0JJTkQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tYmluZC1uYXRpdmUnKTtcblxudmFyIGNhbGwgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbDtcblxubW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfQklORCA/IGNhbGwuYmluZChjYWxsKSA6IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGNhbGwuYXBwbHkoY2FsbCwgYXJndW1lbnRzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xuXG52YXIgRnVuY3Rpb25Qcm90b3R5cGUgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWdldG93bnByb3BlcnR5ZGVzY3JpcHRvciAtLSBzYWZlXG52YXIgZ2V0RGVzY3JpcHRvciA9IERFU0NSSVBUT1JTICYmIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG5cbnZhciBFWElTVFMgPSBoYXNPd24oRnVuY3Rpb25Qcm90b3R5cGUsICduYW1lJyk7XG4vLyBhZGRpdGlvbmFsIHByb3RlY3Rpb24gZnJvbSBtaW5pZmllZCAvIG1hbmdsZWQgLyBkcm9wcGVkIGZ1bmN0aW9uIG5hbWVzXG52YXIgUFJPUEVSID0gRVhJU1RTICYmIChmdW5jdGlvbiBzb21ldGhpbmcoKSB7IC8qIGVtcHR5ICovIH0pLm5hbWUgPT09ICdzb21ldGhpbmcnO1xudmFyIENPTkZJR1VSQUJMRSA9IEVYSVNUUyAmJiAoIURFU0NSSVBUT1JTIHx8IChERVNDUklQVE9SUyAmJiBnZXREZXNjcmlwdG9yKEZ1bmN0aW9uUHJvdG90eXBlLCAnbmFtZScpLmNvbmZpZ3VyYWJsZSkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgRVhJU1RTOiBFWElTVFMsXG4gIFBST1BFUjogUFJPUEVSLFxuICBDT05GSUdVUkFCTEU6IENPTkZJR1VSQUJMRVxufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBOQVRJVkVfQklORCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi1iaW5kLW5hdGl2ZScpO1xuXG52YXIgRnVuY3Rpb25Qcm90b3R5cGUgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG52YXIgY2FsbCA9IEZ1bmN0aW9uUHJvdG90eXBlLmNhbGw7XG52YXIgdW5jdXJyeVRoaXNXaXRoQmluZCA9IE5BVElWRV9CSU5EICYmIEZ1bmN0aW9uUHJvdG90eXBlLmJpbmQuYmluZChjYWxsLCBjYWxsKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfQklORCA/IHVuY3VycnlUaGlzV2l0aEJpbmQgOiBmdW5jdGlvbiAoZm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gY2FsbC5hcHBseShmbiwgYXJndW1lbnRzKTtcbiAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtY2FsbGFibGUnKTtcblxudmFyIGFGdW5jdGlvbiA9IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICByZXR1cm4gaXNDYWxsYWJsZShhcmd1bWVudCkgPyBhcmd1bWVudCA6IHVuZGVmaW5lZDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWVzcGFjZSwgbWV0aG9kKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGFGdW5jdGlvbihnbG9iYWxbbmFtZXNwYWNlXSkgOiBnbG9iYWxbbmFtZXNwYWNlXSAmJiBnbG9iYWxbbmFtZXNwYWNlXVttZXRob2RdO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYS1jYWxsYWJsZScpO1xudmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW51bGwtb3ItdW5kZWZpbmVkJyk7XG5cbi8vIGBHZXRNZXRob2RgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXRtZXRob2Rcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFYsIFApIHtcbiAgdmFyIGZ1bmMgPSBWW1BdO1xuICByZXR1cm4gaXNOdWxsT3JVbmRlZmluZWQoZnVuYykgPyB1bmRlZmluZWQgOiBhQ2FsbGFibGUoZnVuYyk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNoZWNrID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCAmJiBpdC5NYXRoID09PSBNYXRoICYmIGl0O1xufTtcblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzg2I2lzc3VlY29tbWVudC0xMTU3NTkwMjhcbm1vZHVsZS5leHBvcnRzID1cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLWdsb2JhbC10aGlzIC0tIHNhZmVcbiAgY2hlY2sodHlwZW9mIGdsb2JhbFRoaXMgPT0gJ29iamVjdCcgJiYgZ2xvYmFsVGhpcykgfHxcbiAgY2hlY2sodHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB3aW5kb3cpIHx8XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLWdsb2JhbHMgLS0gc2FmZVxuICBjaGVjayh0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmKSB8fFxuICBjaGVjayh0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCkgfHxcbiAgY2hlY2sodHlwZW9mIHRoaXMgPT0gJ29iamVjdCcgJiYgdGhpcykgfHxcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jIC0tIGZhbGxiYWNrXG4gIChmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9KSgpIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tb2JqZWN0Jyk7XG5cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IHVuY3VycnlUaGlzKHt9Lmhhc093blByb3BlcnR5KTtcblxuLy8gYEhhc093blByb3BlcnR5YCBhYnN0cmFjdCBvcGVyYXRpb25cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaGFzb3ducHJvcGVydHlcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtaGFzb3duIC0tIHNhZmVcbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0Lmhhc093biB8fCBmdW5jdGlvbiBoYXNPd24oaXQsIGtleSkge1xuICByZXR1cm4gaGFzT3duUHJvcGVydHkodG9PYmplY3QoaXQpLCBrZXkpO1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0ge307XG4iLCIndXNlIHN0cmljdCc7XG52YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZG9jdW1lbnQtY3JlYXRlLWVsZW1lbnQnKTtcblxuLy8gVGhhbmtzIHRvIElFOCBmb3IgaXRzIGZ1bm55IGRlZmluZVByb3BlcnR5XG5tb2R1bGUuZXhwb3J0cyA9ICFERVNDUklQVE9SUyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3JlYXRlRWxlbWVudCgnZGl2JyksICdhJywge1xuICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfVxuICB9KS5hICE9PSA3O1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xudmFyIHN0b3JlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NoYXJlZC1zdG9yZScpO1xuXG52YXIgZnVuY3Rpb25Ub1N0cmluZyA9IHVuY3VycnlUaGlzKEZ1bmN0aW9uLnRvU3RyaW5nKTtcblxuLy8gdGhpcyBoZWxwZXIgYnJva2VuIGluIGBjb3JlLWpzQDMuNC4xLTMuNC40YCwgc28gd2UgY2FuJ3QgdXNlIGBzaGFyZWRgIGhlbHBlclxuaWYgKCFpc0NhbGxhYmxlKHN0b3JlLmluc3BlY3RTb3VyY2UpKSB7XG4gIHN0b3JlLmluc3BlY3RTb3VyY2UgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb25Ub1N0cmluZyhpdCk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RvcmUuaW5zcGVjdFNvdXJjZTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBOQVRJVkVfV0VBS19NQVAgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvd2Vhay1tYXAtYmFzaWMtZGV0ZWN0aW9uJyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW9iamVjdCcpO1xudmFyIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9jcmVhdGUtbm9uLWVudW1lcmFibGUtcHJvcGVydHknKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xudmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQtc3RvcmUnKTtcbnZhciBzaGFyZWRLZXkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvc2hhcmVkLWtleScpO1xudmFyIGhpZGRlbktleXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGlkZGVuLWtleXMnKTtcblxudmFyIE9CSkVDVF9BTFJFQURZX0lOSVRJQUxJWkVEID0gJ09iamVjdCBhbHJlYWR5IGluaXRpYWxpemVkJztcbnZhciBUeXBlRXJyb3IgPSBnbG9iYWwuVHlwZUVycm9yO1xudmFyIFdlYWtNYXAgPSBnbG9iYWwuV2Vha01hcDtcbnZhciBzZXQsIGdldCwgaGFzO1xuXG52YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaGFzKGl0KSA/IGdldChpdCkgOiBzZXQoaXQsIHt9KTtcbn07XG5cbnZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkge1xuICByZXR1cm4gZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIHN0YXRlO1xuICAgIGlmICghaXNPYmplY3QoaXQpIHx8IChzdGF0ZSA9IGdldChpdCkpLnR5cGUgIT09IFRZUEUpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0luY29tcGF0aWJsZSByZWNlaXZlciwgJyArIFRZUEUgKyAnIHJlcXVpcmVkJyk7XG4gICAgfSByZXR1cm4gc3RhdGU7XG4gIH07XG59O1xuXG5pZiAoTkFUSVZFX1dFQUtfTUFQIHx8IHNoYXJlZC5zdGF0ZSkge1xuICB2YXIgc3RvcmUgPSBzaGFyZWQuc3RhdGUgfHwgKHNoYXJlZC5zdGF0ZSA9IG5ldyBXZWFrTWFwKCkpO1xuICAvKiBlc2xpbnQtZGlzYWJsZSBuby1zZWxmLWFzc2lnbiAtLSBwcm90b3R5cGUgbWV0aG9kcyBwcm90ZWN0aW9uICovXG4gIHN0b3JlLmdldCA9IHN0b3JlLmdldDtcbiAgc3RvcmUuaGFzID0gc3RvcmUuaGFzO1xuICBzdG9yZS5zZXQgPSBzdG9yZS5zZXQ7XG4gIC8qIGVzbGludC1lbmFibGUgbm8tc2VsZi1hc3NpZ24gLS0gcHJvdG90eXBlIG1ldGhvZHMgcHJvdGVjdGlvbiAqL1xuICBzZXQgPSBmdW5jdGlvbiAoaXQsIG1ldGFkYXRhKSB7XG4gICAgaWYgKHN0b3JlLmhhcyhpdCkpIHRocm93IG5ldyBUeXBlRXJyb3IoT0JKRUNUX0FMUkVBRFlfSU5JVElBTElaRUQpO1xuICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0O1xuICAgIHN0b3JlLnNldChpdCwgbWV0YWRhdGEpO1xuICAgIHJldHVybiBtZXRhZGF0YTtcbiAgfTtcbiAgZ2V0ID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgcmV0dXJuIHN0b3JlLmdldChpdCkgfHwge307XG4gIH07XG4gIGhhcyA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBzdG9yZS5oYXMoaXQpO1xuICB9O1xufSBlbHNlIHtcbiAgdmFyIFNUQVRFID0gc2hhcmVkS2V5KCdzdGF0ZScpO1xuICBoaWRkZW5LZXlzW1NUQVRFXSA9IHRydWU7XG4gIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHtcbiAgICBpZiAoaGFzT3duKGl0LCBTVEFURSkpIHRocm93IG5ldyBUeXBlRXJyb3IoT0JKRUNUX0FMUkVBRFlfSU5JVElBTElaRUQpO1xuICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0O1xuICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShpdCwgU1RBVEUsIG1ldGFkYXRhKTtcbiAgICByZXR1cm4gbWV0YWRhdGE7XG4gIH07XG4gIGdldCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBoYXNPd24oaXQsIFNUQVRFKSA/IGl0W1NUQVRFXSA6IHt9O1xuICB9O1xuICBoYXMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gaGFzT3duKGl0LCBTVEFURSk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6IHNldCxcbiAgZ2V0OiBnZXQsXG4gIGhhczogaGFzLFxuICBlbmZvcmNlOiBlbmZvcmNlLFxuICBnZXR0ZXJGb3I6IGdldHRlckZvclxufTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtSXNIVE1MRERBLWludGVybmFsLXNsb3RcbnZhciBkb2N1bWVudEFsbCA9IHR5cGVvZiBkb2N1bWVudCA9PSAnb2JqZWN0JyAmJiBkb2N1bWVudC5hbGw7XG5cbi8vIGBJc0NhbGxhYmxlYCBhYnN0cmFjdCBvcGVyYXRpb25cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXNjYWxsYWJsZVxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vbm8tdHlwZW9mLXVuZGVmaW5lZCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xubW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgZG9jdW1lbnRBbGwgPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnRBbGwgIT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbicgfHwgYXJndW1lbnQgPT09IGRvY3VtZW50QWxsO1xufSA6IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbic7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gd2UgY2FuJ3QgdXNlIGp1c3QgYGl0ID09IG51bGxgIHNpbmNlIG9mIGBkb2N1bWVudC5hbGxgIHNwZWNpYWwgY2FzZVxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1Jc0hUTUxEREEtaW50ZXJuYWwtc2xvdC1hZWNcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCA9PT0gbnVsbCB8fCBpdCA9PT0gdW5kZWZpbmVkO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBpc0NhbGxhYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWNhbGxhYmxlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiB0eXBlb2YgaXQgPT0gJ29iamVjdCcgPyBpdCAhPT0gbnVsbCA6IGlzQ2FsbGFibGUoaXQpO1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZmFsc2U7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2V0QnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nZXQtYnVpbHQtaW4nKTtcbnZhciBpc0NhbGxhYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWNhbGxhYmxlJyk7XG52YXIgaXNQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtaXMtcHJvdG90eXBlLW9mJyk7XG52YXIgVVNFX1NZTUJPTF9BU19VSUQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdXNlLXN5bWJvbC1hcy11aWQnKTtcblxudmFyICRPYmplY3QgPSBPYmplY3Q7XG5cbm1vZHVsZS5leHBvcnRzID0gVVNFX1NZTUJPTF9BU19VSUQgPyBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJztcbn0gOiBmdW5jdGlvbiAoaXQpIHtcbiAgdmFyICRTeW1ib2wgPSBnZXRCdWlsdEluKCdTeW1ib2wnKTtcbiAgcmV0dXJuIGlzQ2FsbGFibGUoJFN5bWJvbCkgJiYgaXNQcm90b3R5cGVPZigkU3ltYm9sLnByb3RvdHlwZSwgJE9iamVjdChpdCkpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciB1bmN1cnJ5VGhpcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi11bmN1cnJ5LXRoaXMnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGlzQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtY2FsbGFibGUnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgQ09ORklHVVJBQkxFX0ZVTkNUSU9OX05BTUUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tbmFtZScpLkNPTkZJR1VSQUJMRTtcbnZhciBpbnNwZWN0U291cmNlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2luc3BlY3Qtc291cmNlJyk7XG52YXIgSW50ZXJuYWxTdGF0ZU1vZHVsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pbnRlcm5hbC1zdGF0ZScpO1xuXG52YXIgZW5mb3JjZUludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLmVuZm9yY2U7XG52YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0O1xudmFyICRTdHJpbmcgPSBTdHJpbmc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHNhZmVcbnZhciBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcbnZhciBzdHJpbmdTbGljZSA9IHVuY3VycnlUaGlzKCcnLnNsaWNlKTtcbnZhciByZXBsYWNlID0gdW5jdXJyeVRoaXMoJycucmVwbGFjZSk7XG52YXIgam9pbiA9IHVuY3VycnlUaGlzKFtdLmpvaW4pO1xuXG52YXIgQ09ORklHVVJBQkxFX0xFTkdUSCA9IERFU0NSSVBUT1JTICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBkZWZpbmVQcm9wZXJ0eShmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH0sICdsZW5ndGgnLCB7IHZhbHVlOiA4IH0pLmxlbmd0aCAhPT0gODtcbn0pO1xuXG52YXIgVEVNUExBVEUgPSBTdHJpbmcoU3RyaW5nKS5zcGxpdCgnU3RyaW5nJyk7XG5cbnZhciBtYWtlQnVpbHRJbiA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lLCBvcHRpb25zKSB7XG4gIGlmIChzdHJpbmdTbGljZSgkU3RyaW5nKG5hbWUpLCAwLCA3KSA9PT0gJ1N5bWJvbCgnKSB7XG4gICAgbmFtZSA9ICdbJyArIHJlcGxhY2UoJFN0cmluZyhuYW1lKSwgL15TeW1ib2xcXCgoW14pXSopXFwpLiokLywgJyQxJykgKyAnXSc7XG4gIH1cbiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5nZXR0ZXIpIG5hbWUgPSAnZ2V0ICcgKyBuYW1lO1xuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnNldHRlcikgbmFtZSA9ICdzZXQgJyArIG5hbWU7XG4gIGlmICghaGFzT3duKHZhbHVlLCAnbmFtZScpIHx8IChDT05GSUdVUkFCTEVfRlVOQ1RJT05fTkFNRSAmJiB2YWx1ZS5uYW1lICE9PSBuYW1lKSkge1xuICAgIGlmIChERVNDUklQVE9SUykgZGVmaW5lUHJvcGVydHkodmFsdWUsICduYW1lJywgeyB2YWx1ZTogbmFtZSwgY29uZmlndXJhYmxlOiB0cnVlIH0pO1xuICAgIGVsc2UgdmFsdWUubmFtZSA9IG5hbWU7XG4gIH1cbiAgaWYgKENPTkZJR1VSQUJMRV9MRU5HVEggJiYgb3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2FyaXR5JykgJiYgdmFsdWUubGVuZ3RoICE9PSBvcHRpb25zLmFyaXR5KSB7XG4gICAgZGVmaW5lUHJvcGVydHkodmFsdWUsICdsZW5ndGgnLCB7IHZhbHVlOiBvcHRpb25zLmFyaXR5IH0pO1xuICB9XG4gIHRyeSB7XG4gICAgaWYgKG9wdGlvbnMgJiYgaGFzT3duKG9wdGlvbnMsICdjb25zdHJ1Y3RvcicpICYmIG9wdGlvbnMuY29uc3RydWN0b3IpIHtcbiAgICAgIGlmIChERVNDUklQVE9SUykgZGVmaW5lUHJvcGVydHkodmFsdWUsICdwcm90b3R5cGUnLCB7IHdyaXRhYmxlOiBmYWxzZSB9KTtcbiAgICAvLyBpbiBWOCB+IENocm9tZSA1MywgcHJvdG90eXBlcyBvZiBzb21lIG1ldGhvZHMsIGxpa2UgYEFycmF5LnByb3RvdHlwZS52YWx1ZXNgLCBhcmUgbm9uLXdyaXRhYmxlXG4gICAgfSBlbHNlIGlmICh2YWx1ZS5wcm90b3R5cGUpIHZhbHVlLnByb3RvdHlwZSA9IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICB2YXIgc3RhdGUgPSBlbmZvcmNlSW50ZXJuYWxTdGF0ZSh2YWx1ZSk7XG4gIGlmICghaGFzT3duKHN0YXRlLCAnc291cmNlJykpIHtcbiAgICBzdGF0ZS5zb3VyY2UgPSBqb2luKFRFTVBMQVRFLCB0eXBlb2YgbmFtZSA9PSAnc3RyaW5nJyA/IG5hbWUgOiAnJyk7XG4gIH0gcmV0dXJuIHZhbHVlO1xufTtcblxuLy8gYWRkIGZha2UgRnVuY3Rpb24jdG9TdHJpbmcgZm9yIGNvcnJlY3Qgd29yayB3cmFwcGVkIG1ldGhvZHMgLyBjb25zdHJ1Y3RvcnMgd2l0aCBtZXRob2RzIGxpa2UgTG9EYXNoIGlzTmF0aXZlXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZXh0ZW5kLW5hdGl2ZSAtLSByZXF1aXJlZFxuRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nID0gbWFrZUJ1aWx0SW4oZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gIHJldHVybiBpc0NhbGxhYmxlKHRoaXMpICYmIGdldEludGVybmFsU3RhdGUodGhpcykuc291cmNlIHx8IGluc3BlY3RTb3VyY2UodGhpcyk7XG59LCAndG9TdHJpbmcnKTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9kZXNjcmlwdG9ycycpO1xudmFyIElFOF9ET01fREVGSU5FID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2llOC1kb20tZGVmaW5lJyk7XG52YXIgVjhfUFJPVE9UWVBFX0RFRklORV9CVUcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdjgtcHJvdG90eXBlLWRlZmluZS1idWcnKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcbnZhciB0b1Byb3BlcnR5S2V5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXByb3BlcnR5LWtleScpO1xuXG52YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZVxudmFyICRkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmVcbnZhciAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcbnZhciBFTlVNRVJBQkxFID0gJ2VudW1lcmFibGUnO1xudmFyIENPTkZJR1VSQUJMRSA9ICdjb25maWd1cmFibGUnO1xudmFyIFdSSVRBQkxFID0gJ3dyaXRhYmxlJztcblxuLy8gYE9iamVjdC5kZWZpbmVQcm9wZXJ0eWAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5kZWZpbmVwcm9wZXJ0eVxuZXhwb3J0cy5mID0gREVTQ1JJUFRPUlMgPyBWOF9QUk9UT1RZUEVfREVGSU5FX0JVRyA/IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1Byb3BlcnR5S2V5KFApO1xuICBhbk9iamVjdChBdHRyaWJ1dGVzKTtcbiAgaWYgKHR5cGVvZiBPID09PSAnZnVuY3Rpb24nICYmIFAgPT09ICdwcm90b3R5cGUnICYmICd2YWx1ZScgaW4gQXR0cmlidXRlcyAmJiBXUklUQUJMRSBpbiBBdHRyaWJ1dGVzICYmICFBdHRyaWJ1dGVzW1dSSVRBQkxFXSkge1xuICAgIHZhciBjdXJyZW50ID0gJGdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKTtcbiAgICBpZiAoY3VycmVudCAmJiBjdXJyZW50W1dSSVRBQkxFXSkge1xuICAgICAgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gICAgICBBdHRyaWJ1dGVzID0ge1xuICAgICAgICBjb25maWd1cmFibGU6IENPTkZJR1VSQUJMRSBpbiBBdHRyaWJ1dGVzID8gQXR0cmlidXRlc1tDT05GSUdVUkFCTEVdIDogY3VycmVudFtDT05GSUdVUkFCTEVdLFxuICAgICAgICBlbnVtZXJhYmxlOiBFTlVNRVJBQkxFIGluIEF0dHJpYnV0ZXMgPyBBdHRyaWJ1dGVzW0VOVU1FUkFCTEVdIDogY3VycmVudFtFTlVNRVJBQkxFXSxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlXG4gICAgICB9O1xuICAgIH1cbiAgfSByZXR1cm4gJGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpO1xufSA6ICRkZWZpbmVQcm9wZXJ0eSA6IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1Byb3BlcnR5S2V5KFApO1xuICBhbk9iamVjdChBdHRyaWJ1dGVzKTtcbiAgaWYgKElFOF9ET01fREVGSU5FKSB0cnkge1xuICAgIHJldHVybiAkZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJ0FjY2Vzc29ycyBub3Qgc3VwcG9ydGVkJyk7XG4gIGlmICgndmFsdWUnIGluIEF0dHJpYnV0ZXMpIE9bUF0gPSBBdHRyaWJ1dGVzLnZhbHVlO1xuICByZXR1cm4gTztcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gdW5jdXJyeVRoaXMoe30uaXNQcm90b3R5cGVPZik7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydCcpO1xudmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZicpO1xuXG4vLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kIGltcGxlbWVudGF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmdcbm1vZHVsZS5leHBvcnRzID0gVE9fU1RSSU5HX1RBR19TVVBQT1JUID8ge30udG9TdHJpbmcgOiBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgcmV0dXJuICdbb2JqZWN0ICcgKyBjbGFzc29mKHRoaXMpICsgJ10nO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjYWxsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLWNhbGwnKTtcbnZhciBpc0NhbGxhYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWNhbGxhYmxlJyk7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtb2JqZWN0Jyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xuXG4vLyBgT3JkaW5hcnlUb1ByaW1pdGl2ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9yZGluYXJ5dG9wcmltaXRpdmVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGlucHV0LCBwcmVmKSB7XG4gIHZhciBmbiwgdmFsO1xuICBpZiAocHJlZiA9PT0gJ3N0cmluZycgJiYgaXNDYWxsYWJsZShmbiA9IGlucHV0LnRvU3RyaW5nKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKGlzQ2FsbGFibGUoZm4gPSBpbnB1dC52YWx1ZU9mKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKHByZWYgIT09ICdzdHJpbmcnICYmIGlzQ2FsbGFibGUoZm4gPSBpbnB1dC50b1N0cmluZykgJiYgIWlzT2JqZWN0KHZhbCA9IGNhbGwoZm4sIGlucHV0KSkpIHJldHVybiB2YWw7XG4gIHRocm93IG5ldyAkVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcblxuLy8gYFJlZ0V4cC5wcm90b3R5cGUuZmxhZ3NgIGdldHRlciBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXQtcmVnZXhwLnByb3RvdHlwZS5mbGFnc1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciB0aGF0ID0gYW5PYmplY3QodGhpcyk7XG4gIHZhciByZXN1bHQgPSAnJztcbiAgaWYgKHRoYXQuaGFzSW5kaWNlcykgcmVzdWx0ICs9ICdkJztcbiAgaWYgKHRoYXQuZ2xvYmFsKSByZXN1bHQgKz0gJ2cnO1xuICBpZiAodGhhdC5pZ25vcmVDYXNlKSByZXN1bHQgKz0gJ2knO1xuICBpZiAodGhhdC5tdWx0aWxpbmUpIHJlc3VsdCArPSAnbSc7XG4gIGlmICh0aGF0LmRvdEFsbCkgcmVzdWx0ICs9ICdzJztcbiAgaWYgKHRoYXQudW5pY29kZSkgcmVzdWx0ICs9ICd1JztcbiAgaWYgKHRoYXQudW5pY29kZVNldHMpIHJlc3VsdCArPSAndic7XG4gIGlmICh0aGF0LnN0aWNreSkgcmVzdWx0ICs9ICd5JztcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgY2FsbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi1jYWxsJyk7XG52YXIgaGFzT3duID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2hhcy1vd24tcHJvcGVydHknKTtcbnZhciBpc1Byb3RvdHlwZU9mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL29iamVjdC1pcy1wcm90b3R5cGUtb2YnKTtcbnZhciByZWdFeHBGbGFncyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWdleHAtZmxhZ3MnKTtcblxudmFyIFJlZ0V4cFByb3RvdHlwZSA9IFJlZ0V4cC5wcm90b3R5cGU7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFIpIHtcbiAgdmFyIGZsYWdzID0gUi5mbGFncztcbiAgcmV0dXJuIGZsYWdzID09PSB1bmRlZmluZWQgJiYgISgnZmxhZ3MnIGluIFJlZ0V4cFByb3RvdHlwZSkgJiYgIWhhc093bihSLCAnZmxhZ3MnKSAmJiBpc1Byb3RvdHlwZU9mKFJlZ0V4cFByb3RvdHlwZSwgUilcbiAgICA/IGNhbGwocmVnRXhwRmxhZ3MsIFIpIDogZmxhZ3M7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW51bGwtb3ItdW5kZWZpbmVkJyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xuXG4vLyBgUmVxdWlyZU9iamVjdENvZXJjaWJsZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlcXVpcmVvYmplY3Rjb2VyY2libGVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIGlmIChpc051bGxPclVuZGVmaW5lZChpdCkpIHRocm93IG5ldyAkVHlwZUVycm9yKFwiQ2FuJ3QgY2FsbCBtZXRob2Qgb24gXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgc2hhcmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NoYXJlZCcpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91aWQnKTtcblxudmFyIGtleXMgPSBzaGFyZWQoJ2tleXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiBrZXlzW2tleV0gfHwgKGtleXNba2V5XSA9IHVpZChrZXkpKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgSVNfUFVSRSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1wdXJlJyk7XG52YXIgZ2xvYmFsVGhpcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciBkZWZpbmVHbG9iYWxQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9kZWZpbmUtZ2xvYmFsLXByb3BlcnR5Jyk7XG5cbnZhciBTSEFSRUQgPSAnX19jb3JlLWpzX3NoYXJlZF9fJztcbnZhciBzdG9yZSA9IG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsVGhpc1tTSEFSRURdIHx8IGRlZmluZUdsb2JhbFByb3BlcnR5KFNIQVJFRCwge30pO1xuXG4oc3RvcmUudmVyc2lvbnMgfHwgKHN0b3JlLnZlcnNpb25zID0gW10pKS5wdXNoKHtcbiAgdmVyc2lvbjogJzMuMzcuMScsXG4gIG1vZGU6IElTX1BVUkUgPyAncHVyZScgOiAnZ2xvYmFsJyxcbiAgY29weXJpZ2h0OiAnwqkgMjAxNC0yMDI0IERlbmlzIFB1c2hrYXJldiAoemxvaXJvY2sucnUpJyxcbiAgbGljZW5zZTogJ2h0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2Jsb2IvdjMuMzcuMS9MSUNFTlNFJyxcbiAgc291cmNlOiAnaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMnXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBzdG9yZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQtc3RvcmUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICByZXR1cm4gc3RvcmVba2V5XSB8fCAoc3RvcmVba2V5XSA9IHZhbHVlIHx8IHt9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vKiBlc2xpbnQtZGlzYWJsZSBlcy9uby1zeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbnZhciBWOF9WRVJTSU9OID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2VuZ2luZS12OC12ZXJzaW9uJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG5cbnZhciAkU3RyaW5nID0gZ2xvYmFsLlN0cmluZztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eXN5bWJvbHMgLS0gcmVxdWlyZWQgZm9yIHRlc3Rpbmdcbm1vZHVsZS5leHBvcnRzID0gISFPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHZhciBzeW1ib2wgPSBTeW1ib2woJ3N5bWJvbCBkZXRlY3Rpb24nKTtcbiAgLy8gQ2hyb21lIDM4IFN5bWJvbCBoYXMgaW5jb3JyZWN0IHRvU3RyaW5nIGNvbnZlcnNpb25cbiAgLy8gYGdldC1vd24tcHJvcGVydHktc3ltYm9sc2AgcG9seWZpbGwgc3ltYm9scyBjb252ZXJ0ZWQgdG8gb2JqZWN0IGFyZSBub3QgU3ltYm9sIGluc3RhbmNlc1xuICAvLyBuYjogRG8gbm90IGNhbGwgYFN0cmluZ2AgZGlyZWN0bHkgdG8gYXZvaWQgdGhpcyBiZWluZyBvcHRpbWl6ZWQgb3V0IHRvIGBzeW1ib2wrJydgIHdoaWNoIHdpbGwsXG4gIC8vIG9mIGNvdXJzZSwgZmFpbC5cbiAgcmV0dXJuICEkU3RyaW5nKHN5bWJvbCkgfHwgIShPYmplY3Qoc3ltYm9sKSBpbnN0YW5jZW9mIFN5bWJvbCkgfHxcbiAgICAvLyBDaHJvbWUgMzgtNDAgc3ltYm9scyBhcmUgbm90IGluaGVyaXRlZCBmcm9tIERPTSBjb2xsZWN0aW9ucyBwcm90b3R5cGVzIHRvIGluc3RhbmNlc1xuICAgICFTeW1ib2wuc2hhbSAmJiBWOF9WRVJTSU9OICYmIFY4X1ZFUlNJT04gPCA0MTtcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHJlcXVpcmVPYmplY3RDb2VyY2libGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVxdWlyZS1vYmplY3QtY29lcmNpYmxlJyk7XG5cbnZhciAkT2JqZWN0ID0gT2JqZWN0O1xuXG4vLyBgVG9PYmplY3RgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b29iamVjdFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgcmV0dXJuICRPYmplY3QocmVxdWlyZU9iamVjdENvZXJjaWJsZShhcmd1bWVudCkpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjYWxsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLWNhbGwnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1vYmplY3QnKTtcbnZhciBpc1N5bWJvbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1zeW1ib2wnKTtcbnZhciBnZXRNZXRob2QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2V0LW1ldGhvZCcpO1xudmFyIG9yZGluYXJ5VG9QcmltaXRpdmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb3JkaW5hcnktdG8tcHJpbWl0aXZlJyk7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xudmFyIFRPX1BSSU1JVElWRSA9IHdlbGxLbm93blN5bWJvbCgndG9QcmltaXRpdmUnKTtcblxuLy8gYFRvUHJpbWl0aXZlYCBhYnN0cmFjdCBvcGVyYXRpb25cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9wcmltaXRpdmVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGlucHV0LCBwcmVmKSB7XG4gIGlmICghaXNPYmplY3QoaW5wdXQpIHx8IGlzU3ltYm9sKGlucHV0KSkgcmV0dXJuIGlucHV0O1xuICB2YXIgZXhvdGljVG9QcmltID0gZ2V0TWV0aG9kKGlucHV0LCBUT19QUklNSVRJVkUpO1xuICB2YXIgcmVzdWx0O1xuICBpZiAoZXhvdGljVG9QcmltKSB7XG4gICAgaWYgKHByZWYgPT09IHVuZGVmaW5lZCkgcHJlZiA9ICdkZWZhdWx0JztcbiAgICByZXN1bHQgPSBjYWxsKGV4b3RpY1RvUHJpbSwgaW5wdXQsIHByZWYpO1xuICAgIGlmICghaXNPYmplY3QocmVzdWx0KSB8fCBpc1N5bWJvbChyZXN1bHQpKSByZXR1cm4gcmVzdWx0O1xuICAgIHRocm93IG5ldyAkVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xuICB9XG4gIGlmIChwcmVmID09PSB1bmRlZmluZWQpIHByZWYgPSAnbnVtYmVyJztcbiAgcmV0dXJuIG9yZGluYXJ5VG9QcmltaXRpdmUoaW5wdXQsIHByZWYpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciB0b1ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1wcmltaXRpdmUnKTtcbnZhciBpc1N5bWJvbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1zeW1ib2wnKTtcblxuLy8gYFRvUHJvcGVydHlLZXlgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b3Byb3BlcnR5a2V5XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICB2YXIga2V5ID0gdG9QcmltaXRpdmUoYXJndW1lbnQsICdzdHJpbmcnKTtcbiAgcmV0dXJuIGlzU3ltYm9sKGtleSkgPyBrZXkgOiBrZXkgKyAnJztcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG5cbnZhciBUT19TVFJJTkdfVEFHID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpO1xudmFyIHRlc3QgPSB7fTtcblxudGVzdFtUT19TVFJJTkdfVEFHXSA9ICd6JztcblxubW9kdWxlLmV4cG9ydHMgPSBTdHJpbmcodGVzdCkgPT09ICdbb2JqZWN0IHpdJztcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjbGFzc29mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NsYXNzb2YnKTtcblxudmFyICRTdHJpbmcgPSBTdHJpbmc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gIGlmIChjbGFzc29mKGFyZ3VtZW50KSA9PT0gJ1N5bWJvbCcpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IGEgU3ltYm9sIHZhbHVlIHRvIGEgc3RyaW5nJyk7XG4gIHJldHVybiAkU3RyaW5nKGFyZ3VtZW50KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJFN0cmluZyA9IFN0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gJFN0cmluZyhhcmd1bWVudCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuICdPYmplY3QnO1xuICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHVuY3VycnlUaGlzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLXVuY3VycnktdGhpcycpO1xuXG52YXIgaWQgPSAwO1xudmFyIHBvc3RmaXggPSBNYXRoLnJhbmRvbSgpO1xudmFyIHRvU3RyaW5nID0gdW5jdXJyeVRoaXMoMS4wLnRvU3RyaW5nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiAnU3ltYm9sKCcgKyAoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSkgKyAnKV8nICsgdG9TdHJpbmcoKytpZCArIHBvc3RmaXgsIDM2KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vKiBlc2xpbnQtZGlzYWJsZSBlcy9uby1zeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbnZhciBOQVRJVkVfU1lNQk9MID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N5bWJvbC1jb25zdHJ1Y3Rvci1kZXRlY3Rpb24nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfU1lNQk9MXG4gICYmICFTeW1ib2wuc2hhbVxuICAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxuLy8gVjggfiBDaHJvbWUgMzYtXG4vLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0zMzM0XG5tb2R1bGUuZXhwb3J0cyA9IERFU0NSSVBUT1JTICYmIGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfSwgJ3Byb3RvdHlwZScsIHtcbiAgICB2YWx1ZTogNDIsXG4gICAgd3JpdGFibGU6IGZhbHNlXG4gIH0pLnByb3RvdHlwZSAhPT0gNDI7XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xuXG52YXIgV2Vha01hcCA9IGdsb2JhbC5XZWFrTWFwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzQ2FsbGFibGUoV2Vha01hcCkgJiYgL25hdGl2ZSBjb2RlLy50ZXN0KFN0cmluZyhXZWFrTWFwKSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91aWQnKTtcbnZhciBOQVRJVkVfU1lNQk9MID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N5bWJvbC1jb25zdHJ1Y3Rvci1kZXRlY3Rpb24nKTtcbnZhciBVU0VfU1lNQk9MX0FTX1VJRCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91c2Utc3ltYm9sLWFzLXVpZCcpO1xuXG52YXIgU3ltYm9sID0gZ2xvYmFsLlN5bWJvbDtcbnZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpO1xudmFyIGNyZWF0ZVdlbGxLbm93blN5bWJvbCA9IFVTRV9TWU1CT0xfQVNfVUlEID8gU3ltYm9sWydmb3InXSB8fCBTeW1ib2wgOiBTeW1ib2wgJiYgU3ltYm9sLndpdGhvdXRTZXR0ZXIgfHwgdWlkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gIGlmICghaGFzT3duKFdlbGxLbm93blN5bWJvbHNTdG9yZSwgbmFtZSkpIHtcbiAgICBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPSBOQVRJVkVfU1lNQk9MICYmIGhhc093bihTeW1ib2wsIG5hbWUpXG4gICAgICA/IFN5bWJvbFtuYW1lXVxuICAgICAgOiBjcmVhdGVXZWxsS25vd25TeW1ib2woJ1N5bWJvbC4nICsgbmFtZSk7XG4gIH0gcmV0dXJuIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vLyBUT0RPOiBSZW1vdmUgZnJvbSBgY29yZS1qc0A0YFxudmFyIHVuY3VycnlUaGlzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLXVuY3VycnktdGhpcycpO1xudmFyIGRlZmluZUJ1aWx0SW4gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVmaW5lLWJ1aWx0LWluJyk7XG5cbnZhciBEYXRlUHJvdG90eXBlID0gRGF0ZS5wcm90b3R5cGU7XG52YXIgSU5WQUxJRF9EQVRFID0gJ0ludmFsaWQgRGF0ZSc7XG52YXIgVE9fU1RSSU5HID0gJ3RvU3RyaW5nJztcbnZhciBuYXRpdmVEYXRlVG9TdHJpbmcgPSB1bmN1cnJ5VGhpcyhEYXRlUHJvdG90eXBlW1RPX1NUUklOR10pO1xudmFyIHRoaXNUaW1lVmFsdWUgPSB1bmN1cnJ5VGhpcyhEYXRlUHJvdG90eXBlLmdldFRpbWUpO1xuXG4vLyBgRGF0ZS5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1kYXRlLnByb3RvdHlwZS50b3N0cmluZ1xuaWYgKFN0cmluZyhuZXcgRGF0ZShOYU4pKSAhPT0gSU5WQUxJRF9EQVRFKSB7XG4gIGRlZmluZUJ1aWx0SW4oRGF0ZVByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICB2YXIgdmFsdWUgPSB0aGlzVGltZVZhbHVlKHRoaXMpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWNvbXBhcmUgLS0gTmFOIGNoZWNrXG4gICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSA/IG5hdGl2ZURhdGVUb1N0cmluZyh0aGlzKSA6IElOVkFMSURfREFURTtcbiAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG52YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydCcpO1xudmFyIGRlZmluZUJ1aWx0SW4gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVmaW5lLWJ1aWx0LWluJyk7XG52YXIgdG9TdHJpbmcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LXRvLXN0cmluZycpO1xuXG4vLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmdcbmlmICghVE9fU1RSSU5HX1RBR19TVVBQT1JUKSB7XG4gIGRlZmluZUJ1aWx0SW4oT2JqZWN0LnByb3RvdHlwZSwgJ3RvU3RyaW5nJywgdG9TdHJpbmcsIHsgdW5zYWZlOiB0cnVlIH0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIFBST1BFUl9GVU5DVElPTl9OQU1FID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLW5hbWUnKS5QUk9QRVI7XG52YXIgZGVmaW5lQnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9kZWZpbmUtYnVpbHQtaW4nKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcbnZhciAkdG9TdHJpbmcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tc3RyaW5nJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBnZXRSZWdFeHBGbGFncyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWdleHAtZ2V0LWZsYWdzJyk7XG5cbnZhciBUT19TVFJJTkcgPSAndG9TdHJpbmcnO1xudmFyIFJlZ0V4cFByb3RvdHlwZSA9IFJlZ0V4cC5wcm90b3R5cGU7XG52YXIgbmF0aXZlVG9TdHJpbmcgPSBSZWdFeHBQcm90b3R5cGVbVE9fU1RSSU5HXTtcblxudmFyIE5PVF9HRU5FUklDID0gZmFpbHMoZnVuY3Rpb24gKCkgeyByZXR1cm4gbmF0aXZlVG9TdHJpbmcuY2FsbCh7IHNvdXJjZTogJ2EnLCBmbGFnczogJ2InIH0pICE9PSAnL2EvYic7IH0pO1xuLy8gRkY0NC0gUmVnRXhwI3RvU3RyaW5nIGhhcyBhIHdyb25nIG5hbWVcbnZhciBJTkNPUlJFQ1RfTkFNRSA9IFBST1BFUl9GVU5DVElPTl9OQU1FICYmIG5hdGl2ZVRvU3RyaW5nLm5hbWUgIT09IFRPX1NUUklORztcblxuLy8gYFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG5pZiAoTk9UX0dFTkVSSUMgfHwgSU5DT1JSRUNUX05BTUUpIHtcbiAgZGVmaW5lQnVpbHRJbihSZWdFeHBQcm90b3R5cGUsIFRPX1NUUklORywgZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgdmFyIFIgPSBhbk9iamVjdCh0aGlzKTtcbiAgICB2YXIgcGF0dGVybiA9ICR0b1N0cmluZyhSLnNvdXJjZSk7XG4gICAgdmFyIGZsYWdzID0gJHRvU3RyaW5nKGdldFJlZ0V4cEZsYWdzKFIpKTtcbiAgICByZXR1cm4gJy8nICsgcGF0dGVybiArICcvJyArIGZsYWdzO1xuICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbn1cbiIsInZhciBnO1xuXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxuZyA9IChmdW5jdGlvbigpIHtcblx0cmV0dXJuIHRoaXM7XG59KSgpO1xuXG50cnkge1xuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcblx0ZyA9IGcgfHwgbmV3IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKTtcbn0gY2F0Y2ggKGUpIHtcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcblx0aWYgKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpIGcgPSB3aW5kb3c7XG59XG5cbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XG5cbm1vZHVsZS5leHBvcnRzID0gZztcbiJdLCJzb3VyY2VSb290IjoiIn0=