ninesurvey/src/ninesurvey-1.0/public/build/vendors~fullcalendar.js

13475 lines
1.3 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/an-object.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/an-object.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
module.exports = function (it) {
if (!isObject(it)) {
throw TypeError(String(it) + ' is not an object');
} return it;
};
/***/ }),
/***/ "./node_modules/core-js/internals/classof-raw.js":
/*!*******************************************************!*\
!*** ./node_modules/core-js/internals/classof-raw.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
var toString = {}.toString;
module.exports = function (it) {
return toString.call(it).slice(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__) {
var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.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');
// 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' && typeof O.callee == 'function' ? '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__) {
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) {
module.exports = function (bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value: value
};
};
/***/ }),
/***/ "./node_modules/core-js/internals/descriptors.js":
/*!*******************************************************!*\
!*** ./node_modules/core-js/internals/descriptors.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
// Thank's IE8 for his funny defineProperty
module.exports = !fails(function () {
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__) {
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/fails.js":
/*!*************************************************!*\
!*** ./node_modules/core-js/internals/fails.js ***!
\*************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = function (exec) {
try {
return !!exec();
} catch (error) {
return true;
}
};
/***/ }),
/***/ "./node_modules/core-js/internals/global.js":
/*!**************************************************!*\
!*** ./node_modules/core-js/internals/global.js ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
/* 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 no-undef
check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
check(typeof self == 'object' && self) ||
check(typeof global == 'object' && global) ||
// eslint-disable-next-line no-new-func
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.js":
/*!***********************************************!*\
!*** ./node_modules/core-js/internals/has.js ***!
\***********************************************/
/*! no static exports found */
/***/ (function(module, exports) {
var hasOwnProperty = {}.hasOwnProperty;
module.exports = function (it, key) {
return hasOwnProperty.call(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) {
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__) {
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");
// Thank's IE8 for his funny defineProperty
module.exports = !DESCRIPTORS && !fails(function () {
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__) {
var store = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js");
var functionToString = Function.toString;
// this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper
if (typeof store.inspectSource != 'function') {
store.inspectSource = function (it) {
return functionToString.call(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__) {
var NATIVE_WEAK_MAP = __webpack_require__(/*! ../internals/native-weak-map */ "./node_modules/core-js/internals/native-weak-map.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 objectHas = __webpack_require__(/*! ../internals/has */ "./node_modules/core-js/internals/has.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 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 TypeError('Incompatible receiver, ' + TYPE + ' required');
} return state;
};
};
if (NATIVE_WEAK_MAP) {
var store = new WeakMap();
var wmget = store.get;
var wmhas = store.has;
var wmset = store.set;
set = function (it, metadata) {
wmset.call(store, it, metadata);
return metadata;
};
get = function (it) {
return wmget.call(store, it) || {};
};
has = function (it) {
return wmhas.call(store, it);
};
} else {
var STATE = sharedKey('state');
hiddenKeys[STATE] = true;
set = function (it, metadata) {
createNonEnumerableProperty(it, STATE, metadata);
return metadata;
};
get = function (it) {
return objectHas(it, STATE) ? it[STATE] : {};
};
has = function (it) {
return objectHas(it, STATE);
};
}
module.exports = {
set: set,
get: get,
has: has,
enforce: enforce,
getterFor: getterFor
};
/***/ }),
/***/ "./node_modules/core-js/internals/is-object.js":
/*!*****************************************************!*\
!*** ./node_modules/core-js/internals/is-object.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = function (it) {
return typeof it === 'object' ? it !== null : typeof it === 'function';
};
/***/ }),
/***/ "./node_modules/core-js/internals/is-pure.js":
/*!***************************************************!*\
!*** ./node_modules/core-js/internals/is-pure.js ***!
\***************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = false;
/***/ }),
/***/ "./node_modules/core-js/internals/native-symbol.js":
/*!*********************************************************!*\
!*** ./node_modules/core-js/internals/native-symbol.js ***!
\*********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
module.exports = !!Object.getOwnPropertySymbols && !fails(function () {
// Chrome 38 Symbol has incorrect toString conversion
// eslint-disable-next-line no-undef
return !String(Symbol());
});
/***/ }),
/***/ "./node_modules/core-js/internals/native-weak-map.js":
/*!***********************************************************!*\
!*** ./node_modules/core-js/internals/native-weak-map.js ***!
\***********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var inspectSource = __webpack_require__(/*! ../internals/inspect-source */ "./node_modules/core-js/internals/inspect-source.js");
var WeakMap = global.WeakMap;
module.exports = typeof WeakMap === 'function' && /native code/.test(inspectSource(WeakMap));
/***/ }),
/***/ "./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__) {
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 anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js");
var toPrimitive = __webpack_require__(/*! ../internals/to-primitive */ "./node_modules/core-js/internals/to-primitive.js");
var nativeDefineProperty = Object.defineProperty;
// `Object.defineProperty` method
// https://tc39.github.io/ecma262/#sec-object.defineproperty
exports.f = DESCRIPTORS ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
anObject(O);
P = toPrimitive(P, true);
anObject(Attributes);
if (IE8_DOM_DEFINE) try {
return nativeDefineProperty(O, P, Attributes);
} catch (error) { /* empty */ }
if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
if ('value' in Attributes) O[P] = Attributes.value;
return O;
};
/***/ }),
/***/ "./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.github.io/ecma262/#sec-object.prototype.tostring
module.exports = TO_STRING_TAG_SUPPORT ? {}.toString : function toString() {
return '[object ' + classof(this) + ']';
};
/***/ }),
/***/ "./node_modules/core-js/internals/redefine.js":
/*!****************************************************!*\
!*** ./node_modules/core-js/internals/redefine.js ***!
\****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var createNonEnumerableProperty = __webpack_require__(/*! ../internals/create-non-enumerable-property */ "./node_modules/core-js/internals/create-non-enumerable-property.js");
var has = __webpack_require__(/*! ../internals/has */ "./node_modules/core-js/internals/has.js");
var setGlobal = __webpack_require__(/*! ../internals/set-global */ "./node_modules/core-js/internals/set-global.js");
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 getInternalState = InternalStateModule.get;
var enforceInternalState = InternalStateModule.enforce;
var TEMPLATE = String(String).split('String');
(module.exports = function (O, key, value, options) {
var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false;
if (typeof value == 'function') {
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key);
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
if (O === global) {
if (simple) O[key] = value;
else setGlobal(key, value);
return;
} else if (!unsafe) {
delete O[key];
} else if (!noTargetGet && O[key]) {
simple = true;
}
if (simple) O[key] = value;
else createNonEnumerableProperty(O, key, value);
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
})(Function.prototype, 'toString', function toString() {
return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
});
/***/ }),
/***/ "./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.github.io/ecma262/#sec-get-regexp.prototype.flags
module.exports = function () {
var that = anObject(this);
var result = '';
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.sticky) result += 'y';
return result;
};
/***/ }),
/***/ "./node_modules/core-js/internals/set-global.js":
/*!******************************************************!*\
!*** ./node_modules/core-js/internals/set-global.js ***!
\******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var createNonEnumerableProperty = __webpack_require__(/*! ../internals/create-non-enumerable-property */ "./node_modules/core-js/internals/create-non-enumerable-property.js");
module.exports = function (key, value) {
try {
createNonEnumerableProperty(global, key, value);
} catch (error) {
global[key] = value;
} return value;
};
/***/ }),
/***/ "./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__) {
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__) {
var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js");
var setGlobal = __webpack_require__(/*! ../internals/set-global */ "./node_modules/core-js/internals/set-global.js");
var SHARED = '__core-js_shared__';
var store = global[SHARED] || setGlobal(SHARED, {});
module.exports = store;
/***/ }),
/***/ "./node_modules/core-js/internals/shared.js":
/*!**************************************************!*\
!*** ./node_modules/core-js/internals/shared.js ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var IS_PURE = __webpack_require__(/*! ../internals/is-pure */ "./node_modules/core-js/internals/is-pure.js");
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 !== undefined ? value : {});
})('versions', []).push({
version: '3.6.5',
mode: IS_PURE ? 'pure' : 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
});
/***/ }),
/***/ "./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__) {
var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js");
// `ToPrimitive` abstract operation
// https://tc39.github.io/ecma262/#sec-toprimitive
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
module.exports = function (input, PREFERRED_STRING) {
if (!isObject(input)) return input;
var fn, val;
if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
throw TypeError("Can't convert object to primitive value");
};
/***/ }),
/***/ "./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__) {
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/uid.js":
/*!***********************************************!*\
!*** ./node_modules/core-js/internals/uid.js ***!
\***********************************************/
/*! no static exports found */
/***/ (function(module, exports) {
var id = 0;
var postfix = Math.random();
module.exports = function (key) {
return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(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__) {
var NATIVE_SYMBOL = __webpack_require__(/*! ../internals/native-symbol */ "./node_modules/core-js/internals/native-symbol.js");
module.exports = NATIVE_SYMBOL
// eslint-disable-next-line no-undef
&& !Symbol.sham
// eslint-disable-next-line no-undef
&& typeof Symbol.iterator == 'symbol';
/***/ }),
/***/ "./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__) {
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 has = __webpack_require__(/*! ../internals/has */ "./node_modules/core-js/internals/has.js");
var uid = __webpack_require__(/*! ../internals/uid */ "./node_modules/core-js/internals/uid.js");
var NATIVE_SYMBOL = __webpack_require__(/*! ../internals/native-symbol */ "./node_modules/core-js/internals/native-symbol.js");
var USE_SYMBOL_AS_UID = __webpack_require__(/*! ../internals/use-symbol-as-uid */ "./node_modules/core-js/internals/use-symbol-as-uid.js");
var WellKnownSymbolsStore = shared('wks');
var Symbol = global.Symbol;
var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol : Symbol && Symbol.withoutSetter || uid;
module.exports = function (name) {
if (!has(WellKnownSymbolsStore, name)) {
if (NATIVE_SYMBOL && has(Symbol, name)) WellKnownSymbolsStore[name] = Symbol[name];
else WellKnownSymbolsStore[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__) {
var redefine = __webpack_require__(/*! ../internals/redefine */ "./node_modules/core-js/internals/redefine.js");
var DatePrototype = Date.prototype;
var INVALID_DATE = 'Invalid Date';
var TO_STRING = 'toString';
var nativeDateToString = DatePrototype[TO_STRING];
var getTime = DatePrototype.getTime;
// `Date.prototype.toString` method
// https://tc39.github.io/ecma262/#sec-date.prototype.tostring
if (new Date(NaN) + '' != INVALID_DATE) {
redefine(DatePrototype, TO_STRING, function toString() {
var value = getTime.call(this);
// eslint-disable-next-line no-self-compare
return value === value ? nativeDateToString.call(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__) {
var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js");
var redefine = __webpack_require__(/*! ../internals/redefine */ "./node_modules/core-js/internals/redefine.js");
var toString = __webpack_require__(/*! ../internals/object-to-string */ "./node_modules/core-js/internals/object-to-string.js");
// `Object.prototype.toString` method
// https://tc39.github.io/ecma262/#sec-object.prototype.tostring
if (!TO_STRING_TAG_SUPPORT) {
redefine(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 redefine = __webpack_require__(/*! ../internals/redefine */ "./node_modules/core-js/internals/redefine.js");
var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js");
var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js");
var flags = __webpack_require__(/*! ../internals/regexp-flags */ "./node_modules/core-js/internals/regexp-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 = nativeToString.name != TO_STRING;
// `RegExp.prototype.toString` method
// https://tc39.github.io/ecma262/#sec-regexp.prototype.tostring
if (NOT_GENERIC || INCORRECT_NAME) {
redefine(RegExp.prototype, TO_STRING, function toString() {
var R = anObject(this);
var p = String(R.source);
var rf = R.flags;
var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? flags.call(R) : rf);
return '/' + p + '/' + f;
}, { 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL2xvY2FsZXMvZnIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvY29yZS9tYWluLmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL21haW4uZXNtLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2RheWdyaWQvbWFpbi5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvZGF5Z3JpZC9tYWluLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9pbnRlcmFjdGlvbi9tYWluLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvYW4tb2JqZWN0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9jbGFzc29mLXJhdy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvY2xhc3NvZi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvY3JlYXRlLW5vbi1lbnVtZXJhYmxlLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9jcmVhdGUtcHJvcGVydHktZGVzY3JpcHRvci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZGVzY3JpcHRvcnMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2RvY3VtZW50LWNyZWF0ZS1lbGVtZW50LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mYWlscy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9oYXMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2hpZGRlbi1rZXlzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9pZTgtZG9tLWRlZmluZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvaW5zcGVjdC1zb3VyY2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2ludGVybmFsLXN0YXRlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9pcy1vYmplY3QuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLXB1cmUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL25hdGl2ZS1zeW1ib2wuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL25hdGl2ZS13ZWFrLW1hcC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LWRlZmluZS1wcm9wZXJ0eS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LXRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvcmVkZWZpbmUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3JlZ2V4cC1mbGFncy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2V0LWdsb2JhbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2hhcmVkLWtleS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2hhcmVkLXN0b3JlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9zaGFyZWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RvLXByaW1pdGl2ZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvdG8tc3RyaW5nLXRhZy1zdXBwb3J0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy91aWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3VzZS1zeW1ib2wtYXMtdWlkLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy93ZWxsLWtub3duLXN5bWJvbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmRhdGUudG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMub2JqZWN0LnRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnJlZ2V4cC50by1zdHJpbmcuanMiLCJ3ZWJwYWNrOi8vLyh3ZWJwYWNrKS9idWlsZGluL2dsb2JhbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBLElBQUksS0FBNEQ7QUFDaEUsSUFBSSxTQUNxSTtBQUN6SSxDQUFDLG9CQUFvQjs7QUFFckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDOzs7Ozs7Ozs7Ozs7QUM5QkQsdUM7Ozs7Ozs7Ozs7OztBQ0FBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQix1QkFBdUI7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QyxtQkFBbUIsbUJBQW1CO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixtQkFBbUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLHVCQUF1QjtBQUMxQztBQUNBLHVCQUF1QixvQkFBb0I7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsb0JBQW9CO0FBQ3ZDLDZDQUE2QztBQUM3Qyx1QkFBdUIsdUJBQXVCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0NBQWdDLG9CQUFvQjtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUVBQXlFO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMseUJBQXlCO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxxREFBcUQ7QUFDckQsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Q7QUFDbEQ7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsaUJBQWlCO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLFVBQVUsNENBQTRDO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hELG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQsb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHVCQUF1QjtBQUMvQztBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsZ0JBQWdCO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxnQkFBZ0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2Qiw2Q0FBNkM7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUVBQXVFO0FBQ3ZFLHlDQUF5QztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxnQkFBZ0I7QUFDOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0NBQW9DLGFBQWE7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLHdCQUF3QjtBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBLHNCQUFzQixFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsUUFBUSxFQUFFO0FBQzlHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLFVBQVU7QUFDekMsOG5CQUE4bkI7QUFDOW5CLCtEQUErRCxnQkFBZ0I7QUFDL0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUMvTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBLGdCQUFnQixrQ0FBa0M7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBLDREQUE0RDtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQSx1QkFBdUIsaUJBQWlCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLGdCQUFnQjtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0FBcUMsNkJBQTZCLDBCQUEwQixZQUFZLEVBQUU7QUFDMUc7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHLEdBQUcsZUFBZTtBQUNyQjs7Ozs7Ozs7Ozs7O0FDeEJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1QyIsImZpbGUiOiJ2ZW5kb3JzfmZ1bGxjYWxlbmRhci5qcyIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuICAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gICAgKGdsb2JhbCA9IGdsb2JhbCB8fCBzZWxmLCAoZ2xvYmFsLkZ1bGxDYWxlbmRhckxvY2FsZXMgPSBnbG9iYWwuRnVsbENhbGVuZGFyTG9jYWxlcyB8fCB7fSwgZ2xvYmFsLkZ1bGxDYWxlbmRhckxvY2FsZXMuZnIgPSBmYWN0b3J5KCkpKTtcbn0odGhpcywgZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbiAgICB2YXIgZnIgPSB7XG4gICAgICAgIGNvZGU6IFwiZnJcIixcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLFxuICAgICAgICAgICAgZG95OiA0IC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICAgICAgYnV0dG9uVGV4dDoge1xuICAgICAgICAgICAgcHJldjogXCJQcsOpY8OpZGVudFwiLFxuICAgICAgICAgICAgbmV4dDogXCJTdWl2YW50XCIsXG4gICAgICAgICAgICB0b2RheTogXCJBdWpvdXJkJ2h1aVwiLFxuICAgICAgICAgICAgeWVhcjogXCJBbm7DqWVcIixcbiAgICAgICAgICAgIG1vbnRoOiBcIk1vaXNcIixcbiAgICAgICAgICAgIHdlZWs6IFwiU2VtYWluZVwiLFxuICAgICAgICAgICAgZGF5OiBcIkpvdXJcIixcbiAgICAgICAgICAgIGxpc3Q6IFwiUGxhbm5pbmdcIlxuICAgICAgICB9LFxuICAgICAgICB3ZWVrTGFiZWw6IFwiU2VtLlwiLFxuICAgICAgICBhbGxEYXlIdG1sOiBcIlRvdXRlIGxhPGJyLz5qb3VybsOpZVwiLFxuICAgICAgICBldmVudExpbWl0VGV4dDogXCJlbiBwbHVzXCIsXG4gICAgICAgIG5vRXZlbnRzTWVzc2FnZTogXCJBdWN1biDDqXbDqW5lbWVudCDDoCBhZmZpY2hlclwiXG4gICAgfTtcblxuICAgIHJldHVybiBmcjtcblxufSkpO1xuIiwiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luIiwiLyohXG5GdWxsQ2FsZW5kYXIgQ29yZSBQYWNrYWdlIHY0LjQuMlxuRG9jcyAmIExpY2Vuc2U6IGh0dHBzOi8vZnVsbGNhbGVuZGFyLmlvL1xuKGMpIDIwMTkgQWRhbSBTaGF3XG4qL1xuXG4vLyBDcmVhdGluZ1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxudmFyIGVsZW1lbnRQcm9wSGFzaCA9IHtcbiAgICBjbGFzc05hbWU6IHRydWUsXG4gICAgY29sU3BhbjogdHJ1ZSxcbiAgICByb3dTcGFuOiB0cnVlXG59O1xudmFyIGNvbnRhaW5lclRhZ0hhc2ggPSB7XG4gICAgJzx0cic6ICd0Ym9keScsXG4gICAgJzx0ZCc6ICd0cidcbn07XG5mdW5jdGlvbiBjcmVhdGVFbGVtZW50KHRhZ05hbWUsIGF0dHJzLCBjb250ZW50KSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbiAgICBpZiAoYXR0cnMpIHtcbiAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gYXR0cnMpIHtcbiAgICAgICAgICAgIGlmIChhdHRyTmFtZSA9PT0gJ3N0eWxlJykge1xuICAgICAgICAgICAgICAgIGFwcGx5U3R5bGUoZWwsIGF0dHJzW2F0dHJOYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChlbGVtZW50UHJvcEhhc2hbYXR0ck5hbWVdKSB7XG4gICAgICAgICAgICAgICAgZWxbYXR0ck5hbWVdID0gYXR0cnNbYXR0ck5hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyc1thdHRyTmFtZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0eXBlb2YgY29udGVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZWwuaW5uZXJIVE1MID0gY29udGVudDsgLy8gc2hvcnRjdXQuIG5vIG5lZWQgdG8gcHJvY2VzcyBIVE1MIGluIGFueSB3YXlcbiAgICB9XG4gICAgZWxzZSBpZiAoY29udGVudCAhPSBudWxsKSB7XG4gICAgICAgIGFwcGVuZFRvRWxlbWVudChlbCwgY29udGVudCk7XG4gICAgfVxuICAgIHJldHVybiBlbDtcbn1cbmZ1bmN0aW9uIGh0bWxUb0VsZW1lbnQoaHRtbCkge1xuICAgIGh0bWwgPSBodG1sLnRyaW0oKTtcbiAgICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChjb21wdXRlQ29udGFpbmVyVGFnKGh0bWwpKTtcbiAgICBjb250YWluZXIuaW5uZXJIVE1MID0gaHRtbDtcbiAgICByZXR1cm4gY29udGFpbmVyLmZpcnN0Q2hpbGQ7XG59XG5mdW5jdGlvbiBodG1sVG9FbGVtZW50cyhodG1sKSB7XG4gICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGh0bWxUb05vZGVMaXN0KGh0bWwpKTtcbn1cbmZ1bmN0aW9uIGh0bWxUb05vZGVMaXN0KGh0bWwpIHtcbiAgICBodG1sID0gaHRtbC50cmltKCk7XG4gICAgdmFyIGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoY29tcHV0ZUNvbnRhaW5lclRhZyhodG1sKSk7XG4gICAgY29udGFpbmVyLmlubmVySFRNTCA9IGh0bWw7XG4gICAgcmV0dXJuIGNvbnRhaW5lci5jaGlsZE5vZGVzO1xufVxuLy8gYXNzdW1lcyBodG1sIGFscmVhZHkgdHJpbW1lZCBhbmQgdGFnIG5hbWVzIGFyZSBsb3dlcmNhc2VcbmZ1bmN0aW9uIGNvbXB1dGVDb250YWluZXJUYWcoaHRtbCkge1xuICAgIHJldHVybiBjb250YWluZXJUYWdIYXNoW2h0bWwuc3Vic3RyKDAsIDMpIC8vIGZhc3RlciB0aGFuIHVzaW5nIHJlZ2V4XG4gICAgXSB8fCAnZGl2Jztcbn1cbmZ1bmN0aW9uIGFwcGVuZFRvRWxlbWVudChlbCwgY29udGVudCkge1xuICAgIHZhciBjaGlsZE5vZGVzID0gbm9ybWFsaXplQ29udGVudChjb250ZW50KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZWwuYXBwZW5kQ2hpbGQoY2hpbGROb2Rlc1tpXSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcHJlcGVuZFRvRWxlbWVudChwYXJlbnQsIGNvbnRlbnQpIHtcbiAgICB2YXIgbmV3RWxzID0gbm9ybWFsaXplQ29udGVudChjb250ZW50KTtcbiAgICB2YXIgYWZ0ZXJFbCA9IHBhcmVudC5maXJzdENoaWxkIHx8IG51bGw7IC8vIGlmIG5vIGZpcnN0Q2hpbGQsIHdpbGwgYXBwZW5kIHRvIGVuZCwgYnV0IHRoYXQncyBva2F5LCBiL2MgdGhlcmUgd2VyZSBubyBjaGlsZHJlblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmV3RWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHBhcmVudC5pbnNlcnRCZWZvcmUobmV3RWxzW2ldLCBhZnRlckVsKTtcbiAgICB9XG59XG5mdW5jdGlvbiBpbnNlcnRBZnRlckVsZW1lbnQocmVmRWwsIGNvbnRlbnQpIHtcbiAgICB2YXIgbmV3RWxzID0gbm9ybWFsaXplQ29udGVudChjb250ZW50KTtcbiAgICB2YXIgYWZ0ZXJFbCA9IHJlZkVsLm5leHRTaWJsaW5nIHx8IG51bGw7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuZXdFbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVmRWwucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobmV3RWxzW2ldLCBhZnRlckVsKTtcbiAgICB9XG59XG5mdW5jdGlvbiBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpIHtcbiAgICB2YXIgZWxzO1xuICAgIGlmICh0eXBlb2YgY29udGVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZWxzID0gaHRtbFRvRWxlbWVudHMoY29udGVudCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGNvbnRlbnQgaW5zdGFuY2VvZiBOb2RlKSB7XG4gICAgICAgIGVscyA9IFtjb250ZW50XTtcbiAgICB9XG4gICAgZWxzZSB7IC8vIE5vZGVbXSBvciBOb2RlTGlzdFxuICAgICAgICBlbHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChjb250ZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGVscztcbn1cbmZ1bmN0aW9uIHJlbW92ZUVsZW1lbnQoZWwpIHtcbiAgICBpZiAoZWwucGFyZW50Tm9kZSkge1xuICAgICAgICBlbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsKTtcbiAgICB9XG59XG4vLyBRdWVyeWluZ1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gZnJvbSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRWxlbWVudC9jbG9zZXN0XG52YXIgbWF0Y2hlc01ldGhvZCA9IEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXMgfHxcbiAgICBFbGVtZW50LnByb3RvdHlwZS5tYXRjaGVzU2VsZWN0b3IgfHxcbiAgICBFbGVtZW50LnByb3RvdHlwZS5tc01hdGNoZXNTZWxlY3RvcjtcbnZhciBjbG9zZXN0TWV0aG9kID0gRWxlbWVudC5wcm90b3R5cGUuY2xvc2VzdCB8fCBmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICAvLyBwb2x5ZmlsbFxuICAgIHZhciBlbCA9IHRoaXM7XG4gICAgaWYgKCFkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY29udGFpbnMoZWwpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBkbyB7XG4gICAgICAgIGlmIChlbGVtZW50TWF0Y2hlcyhlbCwgc2VsZWN0b3IpKSB7XG4gICAgICAgICAgICByZXR1cm4gZWw7XG4gICAgICAgIH1cbiAgICAgICAgZWwgPSBlbC5wYXJlbnRFbGVtZW50IHx8IGVsLnBhcmVudE5vZGU7XG4gICAgfSB3aGlsZSAoZWwgIT09IG51bGwgJiYgZWwubm9kZVR5cGUgPT09IDEpO1xuICAgIHJldHVybiBudWxsO1xufTtcbmZ1bmN0aW9uIGVsZW1lbnRDbG9zZXN0KGVsLCBzZWxlY3Rvcikge1xuICAgIHJldHVybiBjbG9zZXN0TWV0aG9kLmNhbGwoZWwsIHNlbGVjdG9yKTtcbn1cbmZ1bmN0aW9uIGVsZW1lbnRNYXRjaGVzKGVsLCBzZWxlY3Rvcikge1xuICAgIHJldHVybiBtYXRjaGVzTWV0aG9kLmNhbGwoZWwsIHNlbGVjdG9yKTtcbn1cbi8vIGFjY2VwdHMgbXVsdGlwbGUgc3ViamVjdCBlbHNcbi8vIHJldHVybnMgYSByZWFsIGFycmF5LiBnb29kIGZvciBtZXRob2RzIGxpa2UgZm9yRWFjaFxuZnVuY3Rpb24gZmluZEVsZW1lbnRzKGNvbnRhaW5lciwgc2VsZWN0b3IpIHtcbiAgICB2YXIgY29udGFpbmVycyA9IGNvbnRhaW5lciBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ID8gW2NvbnRhaW5lcl0gOiBjb250YWluZXI7XG4gICAgdmFyIGFsbE1hdGNoZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbnRhaW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG1hdGNoZXMgPSBjb250YWluZXJzW2ldLnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hdGNoZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGFsbE1hdGNoZXMucHVzaChtYXRjaGVzW2pdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYWxsTWF0Y2hlcztcbn1cbi8vIGFjY2VwdHMgbXVsdGlwbGUgc3ViamVjdCBlbHNcbi8vIG9ubHkgcXVlcmllcyBkaXJlY3QgY2hpbGQgZWxlbWVudHNcbmZ1bmN0aW9uIGZpbmRDaGlsZHJlbihwYXJlbnQsIHNlbGVjdG9yKSB7XG4gICAgdmFyIHBhcmVudHMgPSBwYXJlbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCA/IFtwYXJlbnRdIDogcGFyZW50O1xuICAgIHZhciBhbGxNYXRjaGVzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjaGlsZE5vZGVzID0gcGFyZW50c1tpXS5jaGlsZHJlbjsgLy8gb25seSBldmVyIGVsZW1lbnRzXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNoaWxkTm9kZXNbal07XG4gICAgICAgICAgICBpZiAoIXNlbGVjdG9yIHx8IGVsZW1lbnRNYXRjaGVzKGNoaWxkTm9kZSwgc2VsZWN0b3IpKSB7XG4gICAgICAgICAgICAgICAgYWxsTWF0Y2hlcy5wdXNoKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFsbE1hdGNoZXM7XG59XG4vLyBBdHRyaWJ1dGVzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBmb3JjZUNsYXNzTmFtZShlbCwgY2xhc3NOYW1lLCBib29sKSB7XG4gICAgaWYgKGJvb2wpIHtcbiAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZWwuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgIH1cbn1cbi8vIFN0eWxlXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG52YXIgUElYRUxfUFJPUF9SRSA9IC8odG9wfGxlZnR8cmlnaHR8Ym90dG9tfHdpZHRofGhlaWdodCkkL2k7XG5mdW5jdGlvbiBhcHBseVN0eWxlKGVsLCBwcm9wcykge1xuICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgIGFwcGx5U3R5bGVQcm9wKGVsLCBwcm9wTmFtZSwgcHJvcHNbcHJvcE5hbWVdKTtcbiAgICB9XG59XG5mdW5jdGlvbiBhcHBseVN0eWxlUHJvcChlbCwgbmFtZSwgdmFsKSB7XG4gICAgaWYgKHZhbCA9PSBudWxsKSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gJyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInICYmIFBJWEVMX1BST1BfUkUudGVzdChuYW1lKSkge1xuICAgICAgICBlbC5zdHlsZVtuYW1lXSA9IHZhbCArICdweCc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBlbC5zdHlsZVtuYW1lXSA9IHZhbDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHBvaW50SW5zaWRlUmVjdChwb2ludCwgcmVjdCkge1xuICAgIHJldHVybiBwb2ludC5sZWZ0ID49IHJlY3QubGVmdCAmJlxuICAgICAgICBwb2ludC5sZWZ0IDwgcmVjdC5yaWdodCAmJlxuICAgICAgICBwb2ludC50b3AgPj0gcmVjdC50b3AgJiZcbiAgICAgICAgcG9pbnQudG9wIDwgcmVjdC5ib3R0b207XG59XG4vLyBSZXR1cm5zIGEgbmV3IHJlY3RhbmdsZSB0aGF0IGlzIHRoZSBpbnRlcnNlY3Rpb24gb2YgdGhlIHR3byByZWN0YW5nbGVzLiBJZiB0aGV5IGRvbid0IGludGVyc2VjdCwgcmV0dXJucyBmYWxzZVxuZnVuY3Rpb24gaW50ZXJzZWN0UmVjdHMocmVjdDEsIHJlY3QyKSB7XG4gICAgdmFyIHJlcyA9IHtcbiAgICAgICAgbGVmdDogTWF0aC5tYXgocmVjdDEubGVmdCwgcmVjdDIubGVmdCksXG4gICAgICAgIHJpZ2h0OiBNYXRoLm1pbihyZWN0MS5yaWdodCwgcmVjdDIucmlnaHQpLFxuICAgICAgICB0b3A6IE1hdGgubWF4KHJlY3QxLnRvcCwgcmVjdDIudG9wKSxcbiAgICAgICAgYm90dG9tOiBNYXRoLm1pbihyZWN0MS5ib3R0b20sIHJlY3QyLmJvdHRvbSlcbiAgICB9O1xuICAgIGlmIChyZXMubGVmdCA8IHJlcy5yaWdodCAmJiByZXMudG9wIDwgcmVzLmJvdHRvbSkge1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiB0cmFuc2xhdGVSZWN0KHJlY3QsIGRlbHRhWCwgZGVsdGFZKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogcmVjdC5sZWZ0ICsgZGVsdGFYLFxuICAgICAgICByaWdodDogcmVjdC5yaWdodCArIGRlbHRhWCxcbiAgICAgICAgdG9wOiByZWN0LnRvcCArIGRlbHRhWSxcbiAgICAgICAgYm90dG9tOiByZWN0LmJvdHRvbSArIGRlbHRhWVxuICAgIH07XG59XG4vLyBSZXR1cm5zIGEgbmV3IHBvaW50IHRoYXQgd2lsbCBoYXZlIGJlZW4gbW92ZWQgdG8gcmVzaWRlIHdpdGhpbiB0aGUgZ2l2ZW4gcmVjdGFuZ2xlXG5mdW5jdGlvbiBjb25zdHJhaW5Qb2ludChwb2ludCwgcmVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IE1hdGgubWluKE1hdGgubWF4KHBvaW50LmxlZnQsIHJlY3QubGVmdCksIHJlY3QucmlnaHQpLFxuICAgICAgICB0b3A6IE1hdGgubWluKE1hdGgubWF4KHBvaW50LnRvcCwgcmVjdC50b3ApLCByZWN0LmJvdHRvbSlcbiAgICB9O1xufVxuLy8gUmV0dXJucyBhIHBvaW50IHRoYXQgaXMgdGhlIGNlbnRlciBvZiB0aGUgZ2l2ZW4gcmVjdGFuZ2xlXG5mdW5jdGlvbiBnZXRSZWN0Q2VudGVyKHJlY3QpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiAocmVjdC5sZWZ0ICsgcmVjdC5yaWdodCkgLyAyLFxuICAgICAgICB0b3A6IChyZWN0LnRvcCArIHJlY3QuYm90dG9tKSAvIDJcbiAgICB9O1xufVxuLy8gU3VidHJhY3RzIHBvaW50MidzIGNvb3JkaW5hdGVzIGZyb20gcG9pbnQxJ3MgY29vcmRpbmF0ZXMsIHJldHVybmluZyBhIGRlbHRhXG5mdW5jdGlvbiBkaWZmUG9pbnRzKHBvaW50MSwgcG9pbnQyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogcG9pbnQxLmxlZnQgLSBwb2ludDIubGVmdCxcbiAgICAgICAgdG9wOiBwb2ludDEudG9wIC0gcG9pbnQyLnRvcFxuICAgIH07XG59XG5cbi8vIExvZ2ljIGZvciBkZXRlcm1pbmluZyBpZiwgd2hlbiB0aGUgZWxlbWVudCBpcyByaWdodC10by1sZWZ0LCB0aGUgc2Nyb2xsYmFyIGFwcGVhcnMgb24gdGhlIGxlZnQgc2lkZVxudmFyIGlzUnRsU2Nyb2xsYmFyT25MZWZ0ID0gbnVsbDtcbmZ1bmN0aW9uIGdldElzUnRsU2Nyb2xsYmFyT25MZWZ0KCkge1xuICAgIGlmIChpc1J0bFNjcm9sbGJhck9uTGVmdCA9PT0gbnVsbCkge1xuICAgICAgICBpc1J0bFNjcm9sbGJhck9uTGVmdCA9IGNvbXB1dGVJc1J0bFNjcm9sbGJhck9uTGVmdCgpO1xuICAgIH1cbiAgICByZXR1cm4gaXNSdGxTY3JvbGxiYXJPbkxlZnQ7XG59XG5mdW5jdGlvbiBjb21wdXRlSXNSdGxTY3JvbGxiYXJPbkxlZnQoKSB7XG4gICAgdmFyIG91dGVyRWwgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCB7XG4gICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgICAgIHRvcDogLTEwMDAsXG4gICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgYm9yZGVyOiAwLFxuICAgICAgICAgICAgcGFkZGluZzogMCxcbiAgICAgICAgICAgIG92ZXJmbG93OiAnc2Nyb2xsJyxcbiAgICAgICAgICAgIGRpcmVjdGlvbjogJ3J0bCdcbiAgICAgICAgfVxuICAgIH0sICc8ZGl2PjwvZGl2PicpO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQob3V0ZXJFbCk7XG4gICAgdmFyIGlubmVyRWwgPSBvdXRlckVsLmZpcnN0Q2hpbGQ7XG4gICAgdmFyIHJlcyA9IGlubmVyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCA+IG91dGVyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdDtcbiAgICByZW1vdmVFbGVtZW50KG91dGVyRWwpO1xuICAgIHJldHVybiByZXM7XG59XG4vLyBUaGUgc2Nyb2xsYmFyIHdpZHRoIGNvbXB1dGF0aW9ucyBpbiBjb21wdXRlRWRnZXMgYXJlIHNvbWV0aW1lcyBmbGF3ZWQgd2hlbiBpdCBjb21lcyB0b1xuLy8gcmV0aW5hIGRpc3BsYXlzLCByb3VuZGluZywgYW5kIElFMTEuIE1hc3NhZ2UgdGhlbSBpbnRvIGEgdXNhYmxlIHZhbHVlLlxuZnVuY3Rpb24gc2FuaXRpemVTY3JvbGxiYXJXaWR0aCh3aWR0aCkge1xuICAgIHdpZHRoID0gTWF0aC5tYXgoMCwgd2lkdGgpOyAvLyBubyBuZWdhdGl2ZXNcbiAgICB3aWR0aCA9IE1hdGgucm91bmQod2lkdGgpO1xuICAgIHJldHVybiB3aWR0aDtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUVkZ2VzKGVsLCBnZXRQYWRkaW5nKSB7XG4gICAgaWYgKGdldFBhZGRpbmcgPT09IHZvaWQgMCkgeyBnZXRQYWRkaW5nID0gZmFsc2U7IH1cbiAgICB2YXIgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsKTtcbiAgICB2YXIgYm9yZGVyTGVmdCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUuYm9yZGVyTGVmdFdpZHRoLCAxMCkgfHwgMDtcbiAgICB2YXIgYm9yZGVyUmlnaHQgPSBwYXJzZUludChjb21wdXRlZFN0eWxlLmJvcmRlclJpZ2h0V2lkdGgsIDEwKSB8fCAwO1xuICAgIHZhciBib3JkZXJUb3AgPSBwYXJzZUludChjb21wdXRlZFN0eWxlLmJvcmRlclRvcFdpZHRoLCAxMCkgfHwgMDtcbiAgICB2YXIgYm9yZGVyQm90dG9tID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5ib3JkZXJCb3R0b21XaWR0aCwgMTApIHx8IDA7XG4gICAgLy8gbXVzdCB1c2Ugb2Zmc2V0KFdpZHRofEhlaWdodCkgYmVjYXVzZSBjb21wYXRpYmxlIHdpdGggY2xpZW50KFdpZHRofEhlaWdodClcbiAgICB2YXIgc2Nyb2xsYmFyTGVmdFJpZ2h0ID0gc2FuaXRpemVTY3JvbGxiYXJXaWR0aChlbC5vZmZzZXRXaWR0aCAtIGVsLmNsaWVudFdpZHRoIC0gYm9yZGVyTGVmdCAtIGJvcmRlclJpZ2h0KTtcbiAgICB2YXIgc2Nyb2xsYmFyQm90dG9tID0gc2FuaXRpemVTY3JvbGxiYXJXaWR0aChlbC5vZmZzZXRIZWlnaHQgLSBlbC5jbGllbnRIZWlnaHQgLSBib3JkZXJUb3AgLSBib3JkZXJCb3R0b20pO1xuICAgIHZhciByZXMgPSB7XG4gICAgICAgIGJvcmRlckxlZnQ6IGJvcmRlckxlZnQsXG4gICAgICAgIGJvcmRlclJpZ2h0OiBib3JkZXJSaWdodCxcbiAgICAgICAgYm9yZGVyVG9wOiBib3JkZXJUb3AsXG4gICAgICAgIGJvcmRlckJvdHRvbTogYm9yZGVyQm90dG9tLFxuICAgICAgICBzY3JvbGxiYXJCb3R0b206IHNjcm9sbGJhckJvdHRvbSxcbiAgICAgICAgc2Nyb2xsYmFyTGVmdDogMCxcbiAgICAgICAgc2Nyb2xsYmFyUmlnaHQ6IDBcbiAgICB9O1xuICAgIGlmIChnZXRJc1J0bFNjcm9sbGJhck9uTGVmdCgpICYmIGNvbXB1dGVkU3R5bGUuZGlyZWN0aW9uID09PSAncnRsJykgeyAvLyBpcyB0aGUgc2Nyb2xsYmFyIG9uIHRoZSBsZWZ0IHNpZGU/XG4gICAgICAgIHJlcy5zY3JvbGxiYXJMZWZ0ID0gc2Nyb2xsYmFyTGVmdFJpZ2h0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmVzLnNjcm9sbGJhclJpZ2h0ID0gc2Nyb2xsYmFyTGVmdFJpZ2h0O1xuICAgIH1cbiAgICBpZiAoZ2V0UGFkZGluZykge1xuICAgICAgICByZXMucGFkZGluZ0xlZnQgPSBwYXJzZUludChjb21wdXRlZFN0eWxlLnBhZGRpbmdMZWZ0LCAxMCkgfHwgMDtcbiAgICAgICAgcmVzLnBhZGRpbmdSaWdodCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUucGFkZGluZ1JpZ2h0LCAxMCkgfHwgMDtcbiAgICAgICAgcmVzLnBhZGRpbmdUb3AgPSBwYXJzZUludChjb21wdXRlZFN0eWxlLnBhZGRpbmdUb3AsIDEwKSB8fCAwO1xuICAgICAgICByZXMucGFkZGluZ0JvdHRvbSA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUucGFkZGluZ0JvdHRvbSwgMTApIHx8IDA7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBjb21wdXRlSW5uZXJSZWN0KGVsLCBnb1dpdGhpblBhZGRpbmcpIHtcbiAgICBpZiAoZ29XaXRoaW5QYWRkaW5nID09PSB2b2lkIDApIHsgZ29XaXRoaW5QYWRkaW5nID0gZmFsc2U7IH1cbiAgICB2YXIgb3V0ZXJSZWN0ID0gY29tcHV0ZVJlY3QoZWwpO1xuICAgIHZhciBlZGdlcyA9IGNvbXB1dGVFZGdlcyhlbCwgZ29XaXRoaW5QYWRkaW5nKTtcbiAgICB2YXIgcmVzID0ge1xuICAgICAgICBsZWZ0OiBvdXRlclJlY3QubGVmdCArIGVkZ2VzLmJvcmRlckxlZnQgKyBlZGdlcy5zY3JvbGxiYXJMZWZ0LFxuICAgICAgICByaWdodDogb3V0ZXJSZWN0LnJpZ2h0IC0gZWRnZXMuYm9yZGVyUmlnaHQgLSBlZGdlcy5zY3JvbGxiYXJSaWdodCxcbiAgICAgICAgdG9wOiBvdXRlclJlY3QudG9wICsgZWRnZXMuYm9yZGVyVG9wLFxuICAgICAgICBib3R0b206IG91dGVyUmVjdC5ib3R0b20gLSBlZGdlcy5ib3JkZXJCb3R0b20gLSBlZGdlcy5zY3JvbGxiYXJCb3R0b21cbiAgICB9O1xuICAgIGlmIChnb1dpdGhpblBhZGRpbmcpIHtcbiAgICAgICAgcmVzLmxlZnQgKz0gZWRnZXMucGFkZGluZ0xlZnQ7XG4gICAgICAgIHJlcy5yaWdodCAtPSBlZGdlcy5wYWRkaW5nUmlnaHQ7XG4gICAgICAgIHJlcy50b3AgKz0gZWRnZXMucGFkZGluZ1RvcDtcbiAgICAgICAgcmVzLmJvdHRvbSAtPSBlZGdlcy5wYWRkaW5nQm90dG9tO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gY29tcHV0ZVJlY3QoZWwpIHtcbiAgICB2YXIgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IHJlY3QubGVmdCArIHdpbmRvdy5wYWdlWE9mZnNldCxcbiAgICAgICAgdG9wOiByZWN0LnRvcCArIHdpbmRvdy5wYWdlWU9mZnNldCxcbiAgICAgICAgcmlnaHQ6IHJlY3QucmlnaHQgKyB3aW5kb3cucGFnZVhPZmZzZXQsXG4gICAgICAgIGJvdHRvbTogcmVjdC5ib3R0b20gKyB3aW5kb3cucGFnZVlPZmZzZXRcbiAgICB9O1xufVxuZnVuY3Rpb24gY29tcHV0ZVZpZXdwb3J0UmVjdCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiB3aW5kb3cucGFnZVhPZmZzZXQsXG4gICAgICAgIHJpZ2h0OiB3aW5kb3cucGFnZVhPZmZzZXQgKyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgsXG4gICAgICAgIHRvcDogd2luZG93LnBhZ2VZT2Zmc2V0LFxuICAgICAgICBib3R0b206IHdpbmRvdy5wYWdlWU9mZnNldCArIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHRcbiAgICB9O1xufVxuZnVuY3Rpb24gY29tcHV0ZUhlaWdodEFuZE1hcmdpbnMoZWwpIHtcbiAgICByZXR1cm4gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0ICsgY29tcHV0ZVZNYXJnaW5zKGVsKTtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVWTWFyZ2lucyhlbCkge1xuICAgIHZhciBjb21wdXRlZCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsKTtcbiAgICByZXR1cm4gcGFyc2VJbnQoY29tcHV0ZWQubWFyZ2luVG9wLCAxMCkgK1xuICAgICAgICBwYXJzZUludChjb21wdXRlZC5tYXJnaW5Cb3R0b20sIDEwKTtcbn1cbi8vIGRvZXMgbm90IHJldHVybiB3aW5kb3dcbmZ1bmN0aW9uIGdldENsaXBwaW5nUGFyZW50cyhlbCkge1xuICAgIHZhciBwYXJlbnRzID0gW107XG4gICAgd2hpbGUgKGVsIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHsgLy8gd2lsbCBzdG9wIHdoZW4gZ2V0cyB0byBkb2N1bWVudCBvciBudWxsXG4gICAgICAgIHZhciBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgICAgICBpZiAoY29tcHV0ZWRTdHlsZS5wb3NpdGlvbiA9PT0gJ2ZpeGVkJykge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCgvKGF1dG98c2Nyb2xsKS8pLnRlc3QoY29tcHV0ZWRTdHlsZS5vdmVyZmxvdyArIGNvbXB1dGVkU3R5bGUub3ZlcmZsb3dZICsgY29tcHV0ZWRTdHlsZS5vdmVyZmxvd1gpKSB7XG4gICAgICAgICAgICBwYXJlbnRzLnB1c2goZWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsID0gZWwucGFyZW50Tm9kZTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcmVudHM7XG59XG5mdW5jdGlvbiBjb21wdXRlQ2xpcHBpbmdSZWN0KGVsKSB7XG4gICAgcmV0dXJuIGdldENsaXBwaW5nUGFyZW50cyhlbClcbiAgICAgICAgLm1hcChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgcmV0dXJuIGNvbXB1dGVJbm5lclJlY3QoZWwpO1xuICAgIH0pXG4gICAgICAgIC5jb25jYXQoY29tcHV0ZVZpZXdwb3J0UmVjdCgpKVxuICAgICAgICAucmVkdWNlKGZ1bmN0aW9uIChyZWN0MCwgcmVjdDEpIHtcbiAgICAgICAgcmV0dXJuIGludGVyc2VjdFJlY3RzKHJlY3QwLCByZWN0MSkgfHwgcmVjdDE7IC8vIHNob3VsZCBhbHdheXMgaW50ZXJzZWN0XG4gICAgfSk7XG59XG5cbi8vIFN0b3BzIGEgbW91c2UvdG91Y2ggZXZlbnQgZnJvbSBkb2luZyBpdCdzIG5hdGl2ZSBicm93c2VyIGFjdGlvblxuZnVuY3Rpb24gcHJldmVudERlZmF1bHQoZXYpIHtcbiAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xufVxuLy8gRXZlbnQgRGVsZWdhdGlvblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gbGlzdGVuQnlTZWxlY3Rvcihjb250YWluZXIsIGV2ZW50VHlwZSwgc2VsZWN0b3IsIGhhbmRsZXIpIHtcbiAgICBmdW5jdGlvbiByZWFsSGFuZGxlcihldikge1xuICAgICAgICB2YXIgbWF0Y2hlZENoaWxkID0gZWxlbWVudENsb3Nlc3QoZXYudGFyZ2V0LCBzZWxlY3Rvcik7XG4gICAgICAgIGlmIChtYXRjaGVkQ2hpbGQpIHtcbiAgICAgICAgICAgIGhhbmRsZXIuY2FsbChtYXRjaGVkQ2hpbGQsIGV2LCBtYXRjaGVkQ2hpbGQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgcmVhbEhhbmRsZXIpO1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgcmVhbEhhbmRsZXIpO1xuICAgIH07XG59XG5mdW5jdGlvbiBsaXN0ZW5Ub0hvdmVyQnlTZWxlY3Rvcihjb250YWluZXIsIHNlbGVjdG9yLCBvbk1vdXNlRW50ZXIsIG9uTW91c2VMZWF2ZSkge1xuICAgIHZhciBjdXJyZW50TWF0Y2hlZENoaWxkO1xuICAgIHJldHVybiBsaXN0ZW5CeVNlbGVjdG9yKGNvbnRhaW5lciwgJ21vdXNlb3ZlcicsIHNlbGVjdG9yLCBmdW5jdGlvbiAoZXYsIG1hdGNoZWRDaGlsZCkge1xuICAgICAgICBpZiAobWF0Y2hlZENoaWxkICE9PSBjdXJyZW50TWF0Y2hlZENoaWxkKSB7XG4gICAgICAgICAgICBjdXJyZW50TWF0Y2hlZENoaWxkID0gbWF0Y2hlZENoaWxkO1xuICAgICAgICAgICAgb25Nb3VzZUVudGVyKGV2LCBtYXRjaGVkQ2hpbGQpO1xuICAgICAgICAgICAgdmFyIHJlYWxPbk1vdXNlTGVhdmVfMSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRNYXRjaGVkQ2hpbGQgPSBudWxsO1xuICAgICAgICAgICAgICAgIG9uTW91c2VMZWF2ZShldiwgbWF0Y2hlZENoaWxkKTtcbiAgICAgICAgICAgICAgICBtYXRjaGVkQ2hpbGQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIHJlYWxPbk1vdXNlTGVhdmVfMSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gbGlzdGVuIHRvIHRoZSBuZXh0IG1vdXNlbGVhdmUsIGFuZCB0aGVuIHVuYXR0YWNoXG4gICAgICAgICAgICBtYXRjaGVkQ2hpbGQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIHJlYWxPbk1vdXNlTGVhdmVfMSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cbi8vIEFuaW1hdGlvblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxudmFyIHRyYW5zaXRpb25FdmVudE5hbWVzID0gW1xuICAgICd3ZWJraXRUcmFuc2l0aW9uRW5kJyxcbiAgICAnb3RyYW5zaXRpb25lbmQnLFxuICAgICdvVHJhbnNpdGlvbkVuZCcsXG4gICAgJ21zVHJhbnNpdGlvbkVuZCcsXG4gICAgJ3RyYW5zaXRpb25lbmQnXG5dO1xuLy8gdHJpZ2dlcmVkIG9ubHkgd2hlbiB0aGUgbmV4dCBzaW5nbGUgc3Vic2VxdWVudCB0cmFuc2l0aW9uIGZpbmlzaGVzXG5mdW5jdGlvbiB3aGVuVHJhbnNpdGlvbkRvbmUoZWwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHJlYWxDYWxsYmFjayA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICBjYWxsYmFjayhldik7XG4gICAgICAgIHRyYW5zaXRpb25FdmVudE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIHJlYWxDYWxsYmFjayk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgdHJhbnNpdGlvbkV2ZW50TmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnROYW1lKSB7XG4gICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCByZWFsQ2FsbGJhY2spOyAvLyBjcm9zcy1icm93c2VyIHdheSB0byBkZXRlcm1pbmUgd2hlbiB0aGUgdHJhbnNpdGlvbiBmaW5pc2hlc1xuICAgIH0pO1xufVxuXG52YXIgREFZX0lEUyA9IFsnc3VuJywgJ21vbicsICd0dWUnLCAnd2VkJywgJ3RodScsICdmcmknLCAnc2F0J107XG4vLyBBZGRpbmdcbmZ1bmN0aW9uIGFkZFdlZWtzKG0sIG4pIHtcbiAgICB2YXIgYSA9IGRhdGVUb1V0Y0FycmF5KG0pO1xuICAgIGFbMl0gKz0gbiAqIDc7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGEpO1xufVxuZnVuY3Rpb24gYWRkRGF5cyhtLCBuKSB7XG4gICAgdmFyIGEgPSBkYXRlVG9VdGNBcnJheShtKTtcbiAgICBhWzJdICs9IG47XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGEpO1xufVxuZnVuY3Rpb24gYWRkTXMobSwgbikge1xuICAgIHZhciBhID0gZGF0ZVRvVXRjQXJyYXkobSk7XG4gICAgYVs2XSArPSBuO1xuICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShhKTtcbn1cbi8vIERpZmZpbmcgKGFsbCByZXR1cm4gZmxvYXRzKVxuZnVuY3Rpb24gZGlmZldlZWtzKG0wLCBtMSkge1xuICAgIHJldHVybiBkaWZmRGF5cyhtMCwgbTEpIC8gNztcbn1cbmZ1bmN0aW9uIGRpZmZEYXlzKG0wLCBtMSkge1xuICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvICgxMDAwICogNjAgKiA2MCAqIDI0KTtcbn1cbmZ1bmN0aW9uIGRpZmZIb3VycyhtMCwgbTEpIHtcbiAgICByZXR1cm4gKG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSkgLyAoMTAwMCAqIDYwICogNjApO1xufVxuZnVuY3Rpb24gZGlmZk1pbnV0ZXMobTAsIG0xKSB7XG4gICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gKDEwMDAgKiA2MCk7XG59XG5mdW5jdGlvbiBkaWZmU2Vjb25kcyhtMCwgbTEpIHtcbiAgICByZXR1cm4gKG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSkgLyAxMDAwO1xufVxuZnVuY3Rpb24gZGlmZkRheUFuZFRpbWUobTAsIG0xKSB7XG4gICAgdmFyIG0wZGF5ID0gc3RhcnRPZkRheShtMCk7XG4gICAgdmFyIG0xZGF5ID0gc3RhcnRPZkRheShtMSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IDAsXG4gICAgICAgIG1vbnRoczogMCxcbiAgICAgICAgZGF5czogTWF0aC5yb3VuZChkaWZmRGF5cyhtMGRheSwgbTFkYXkpKSxcbiAgICAgICAgbWlsbGlzZWNvbmRzOiAobTEudmFsdWVPZigpIC0gbTFkYXkudmFsdWVPZigpKSAtIChtMC52YWx1ZU9mKCkgLSBtMGRheS52YWx1ZU9mKCkpXG4gICAgfTtcbn1cbi8vIERpZmZpbmcgV2hvbGUgVW5pdHNcbmZ1bmN0aW9uIGRpZmZXaG9sZVdlZWtzKG0wLCBtMSkge1xuICAgIHZhciBkID0gZGlmZldob2xlRGF5cyhtMCwgbTEpO1xuICAgIGlmIChkICE9PSBudWxsICYmIGQgJSA3ID09PSAwKSB7XG4gICAgICAgIHJldHVybiBkIC8gNztcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBkaWZmV2hvbGVEYXlzKG0wLCBtMSkge1xuICAgIGlmICh0aW1lQXNNcyhtMCkgPT09IHRpbWVBc01zKG0xKSkge1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChkaWZmRGF5cyhtMCwgbTEpKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG4vLyBTdGFydC1PZlxuZnVuY3Rpb24gc3RhcnRPZkRheShtKSB7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKFtcbiAgICAgICAgbS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBtLmdldFVUQ01vbnRoKCksXG4gICAgICAgIG0uZ2V0VVRDRGF0ZSgpXG4gICAgXSk7XG59XG5mdW5jdGlvbiBzdGFydE9mSG91cihtKSB7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKFtcbiAgICAgICAgbS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBtLmdldFVUQ01vbnRoKCksXG4gICAgICAgIG0uZ2V0VVRDRGF0ZSgpLFxuICAgICAgICBtLmdldFVUQ0hvdXJzKClcbiAgICBdKTtcbn1cbmZ1bmN0aW9uIHN0YXJ0T2ZNaW51dGUobSkge1xuICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShbXG4gICAgICAgIG0uZ2V0VVRDRnVsbFllYXIoKSxcbiAgICAgICAgbS5nZXRVVENNb250aCgpLFxuICAgICAgICBtLmdldFVUQ0RhdGUoKSxcbiAgICAgICAgbS5nZXRVVENIb3VycygpLFxuICAgICAgICBtLmdldFVUQ01pbnV0ZXMoKVxuICAgIF0pO1xufVxuZnVuY3Rpb24gc3RhcnRPZlNlY29uZChtKSB7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKFtcbiAgICAgICAgbS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBtLmdldFVUQ01vbnRoKCksXG4gICAgICAgIG0uZ2V0VVRDRGF0ZSgpLFxuICAgICAgICBtLmdldFVUQ0hvdXJzKCksXG4gICAgICAgIG0uZ2V0VVRDTWludXRlcygpLFxuICAgICAgICBtLmdldFVUQ1NlY29uZHMoKVxuICAgIF0pO1xufVxuLy8gV2VlayBDb21wdXRhdGlvblxuZnVuY3Rpb24gd2Vla09mWWVhcihtYXJrZXIsIGRvdywgZG95KSB7XG4gICAgdmFyIHkgPSBtYXJrZXIuZ2V0VVRDRnVsbFllYXIoKTtcbiAgICB2YXIgdyA9IHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHksIGRvdywgZG95KTtcbiAgICBpZiAodyA8IDEpIHtcbiAgICAgICAgcmV0dXJuIHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHkgLSAxLCBkb3csIGRveSk7XG4gICAgfVxuICAgIHZhciBuZXh0VyA9IHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHkgKyAxLCBkb3csIGRveSk7XG4gICAgaWYgKG5leHRXID49IDEpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKHcsIG5leHRXKTtcbiAgICB9XG4gICAgcmV0dXJuIHc7XG59XG5mdW5jdGlvbiB3ZWVrT2ZHaXZlblllYXIobWFya2VyLCB5ZWFyLCBkb3csIGRveSkge1xuICAgIHZhciBmaXJzdFdlZWtTdGFydCA9IGFycmF5VG9VdGNEYXRlKFt5ZWFyLCAwLCAxICsgZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KV0pO1xuICAgIHZhciBkYXlTdGFydCA9IHN0YXJ0T2ZEYXkobWFya2VyKTtcbiAgICB2YXIgZGF5cyA9IE1hdGgucm91bmQoZGlmZkRheXMoZmlyc3RXZWVrU3RhcnQsIGRheVN0YXJ0KSk7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoZGF5cyAvIDcpICsgMTsgLy8gemVyby1pbmRleGVkXG59XG4vLyBzdGFydC1vZi1maXJzdC13ZWVrIC0gc3RhcnQtb2YteWVhclxuZnVuY3Rpb24gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSB7XG4gICAgLy8gZmlyc3Qtd2VlayBkYXkgLS0gd2hpY2ggamFudWFyeSBpcyBhbHdheXMgaW4gdGhlIGZpcnN0IHdlZWsgKDQgZm9yIGlzbywgMSBmb3Igb3RoZXIpXG4gICAgdmFyIGZ3ZCA9IDcgKyBkb3cgLSBkb3k7XG4gICAgLy8gZmlyc3Qtd2VlayBkYXkgbG9jYWwgd2Vla2RheSAtLSB3aGljaCBsb2NhbCB3ZWVrZGF5IGlzIGZ3ZFxuICAgIHZhciBmd2RsdyA9ICg3ICsgYXJyYXlUb1V0Y0RhdGUoW3llYXIsIDAsIGZ3ZF0pLmdldFVUQ0RheSgpIC0gZG93KSAlIDc7XG4gICAgcmV0dXJuIC1md2RsdyArIGZ3ZCAtIDE7XG59XG4vLyBBcnJheSBDb252ZXJzaW9uXG5mdW5jdGlvbiBkYXRlVG9Mb2NhbEFycmF5KGRhdGUpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgICAgIGRhdGUuZ2V0TW9udGgoKSxcbiAgICAgICAgZGF0ZS5nZXREYXRlKCksXG4gICAgICAgIGRhdGUuZ2V0SG91cnMoKSxcbiAgICAgICAgZGF0ZS5nZXRNaW51dGVzKCksXG4gICAgICAgIGRhdGUuZ2V0U2Vjb25kcygpLFxuICAgICAgICBkYXRlLmdldE1pbGxpc2Vjb25kcygpXG4gICAgXTtcbn1cbmZ1bmN0aW9uIGFycmF5VG9Mb2NhbERhdGUoYSkge1xuICAgIHJldHVybiBuZXcgRGF0ZShhWzBdLCBhWzFdIHx8IDAsIGFbMl0gPT0gbnVsbCA/IDEgOiBhWzJdLCAvLyBkYXkgb2YgbW9udGhcbiAgICBhWzNdIHx8IDAsIGFbNF0gfHwgMCwgYVs1XSB8fCAwKTtcbn1cbmZ1bmN0aW9uIGRhdGVUb1V0Y0FycmF5KGRhdGUpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBkYXRlLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENEYXRlKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDSG91cnMoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENNaW51dGVzKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDU2Vjb25kcygpLFxuICAgICAgICBkYXRlLmdldFVUQ01pbGxpc2Vjb25kcygpXG4gICAgXTtcbn1cbmZ1bmN0aW9uIGFycmF5VG9VdGNEYXRlKGEpIHtcbiAgICAvLyBhY2NvcmRpbmcgdG8gd2ViIHN0YW5kYXJkcyAoYW5kIFNhZmFyaSksIGEgbW9udGggaW5kZXggaXMgcmVxdWlyZWQuXG4gICAgLy8gbWFzc2FnZSBpZiBvbmx5IGdpdmVuIGEgeWVhci5cbiAgICBpZiAoYS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgYSA9IGEuY29uY2F0KFswXSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQy5hcHBseShEYXRlLCBhKSk7XG59XG4vLyBPdGhlciBVdGlsc1xuZnVuY3Rpb24gaXNWYWxpZERhdGUobSkge1xuICAgIHJldHVybiAhaXNOYU4obS52YWx1ZU9mKCkpO1xufVxuZnVuY3Rpb24gdGltZUFzTXMobSkge1xuICAgIHJldHVybiBtLmdldFVUQ0hvdXJzKCkgKiAxMDAwICogNjAgKiA2MCArXG4gICAgICAgIG0uZ2V0VVRDTWludXRlcygpICogMTAwMCAqIDYwICtcbiAgICAgICAgbS5nZXRVVENTZWNvbmRzKCkgKiAxMDAwICtcbiAgICAgICAgbS5nZXRVVENNaWxsaXNlY29uZHMoKTtcbn1cblxudmFyIElOVEVSTkFMX1VOSVRTID0gWyd5ZWFycycsICdtb250aHMnLCAnZGF5cycsICdtaWxsaXNlY29uZHMnXTtcbnZhciBQQVJTRV9SRSA9IC9eKC0/KSg/OihcXGQrKVxcLik/KFxcZCspOihcXGRcXGQpKD86OihcXGRcXGQpKD86XFwuKFxcZFxcZFxcZCkpPyk/Lztcbi8vIFBhcnNpbmcgYW5kIENyZWF0aW9uXG5mdW5jdGlvbiBjcmVhdGVEdXJhdGlvbihpbnB1dCwgdW5pdCkge1xuICAgIHZhciBfYTtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gcGFyc2VTdHJpbmcoaW5wdXQpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gbm9ybWFsaXplT2JqZWN0KGlucHV0KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gbm9ybWFsaXplT2JqZWN0KChfYSA9IHt9LCBfYVt1bml0IHx8ICdtaWxsaXNlY29uZHMnXSA9IGlucHV0LCBfYSkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufVxuZnVuY3Rpb24gcGFyc2VTdHJpbmcocykge1xuICAgIHZhciBtID0gUEFSU0VfUkUuZXhlYyhzKTtcbiAgICBpZiAobSkge1xuICAgICAgICB2YXIgc2lnbiA9IG1bMV0gPyAtMSA6IDE7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB5ZWFyczogMCxcbiAgICAgICAgICAgIG1vbnRoczogMCxcbiAgICAgICAgICAgIGRheXM6IHNpZ24gKiAobVsyXSA/IHBhcnNlSW50KG1bMl0sIDEwKSA6IDApLFxuICAgICAgICAgICAgbWlsbGlzZWNvbmRzOiBzaWduICogKChtWzNdID8gcGFyc2VJbnQobVszXSwgMTApIDogMCkgKiA2MCAqIDYwICogMTAwMCArIC8vIGhvdXJzXG4gICAgICAgICAgICAgICAgKG1bNF0gPyBwYXJzZUludChtWzRdLCAxMCkgOiAwKSAqIDYwICogMTAwMCArIC8vIG1pbnV0ZXNcbiAgICAgICAgICAgICAgICAobVs1XSA/IHBhcnNlSW50KG1bNV0sIDEwKSA6IDApICogMTAwMCArIC8vIHNlY29uZHNcbiAgICAgICAgICAgICAgICAobVs2XSA/IHBhcnNlSW50KG1bNl0sIDEwKSA6IDApIC8vIG1zXG4gICAgICAgICAgICApXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gbm9ybWFsaXplT2JqZWN0KG9iaikge1xuICAgIHJldHVybiB7XG4gICAgICAgIHllYXJzOiBvYmoueWVhcnMgfHwgb2JqLnllYXIgfHwgMCxcbiAgICAgICAgbW9udGhzOiBvYmoubW9udGhzIHx8IG9iai5tb250aCB8fCAwLFxuICAgICAgICBkYXlzOiAob2JqLmRheXMgfHwgb2JqLmRheSB8fCAwKSArXG4gICAgICAgICAgICBnZXRXZWVrc0Zyb21JbnB1dChvYmopICogNyxcbiAgICAgICAgbWlsbGlzZWNvbmRzOiAob2JqLmhvdXJzIHx8IG9iai5ob3VyIHx8IDApICogNjAgKiA2MCAqIDEwMDAgKyAvLyBob3Vyc1xuICAgICAgICAgICAgKG9iai5taW51dGVzIHx8IG9iai5taW51dGUgfHwgMCkgKiA2MCAqIDEwMDAgKyAvLyBtaW51dGVzXG4gICAgICAgICAgICAob2JqLnNlY29uZHMgfHwgb2JqLnNlY29uZCB8fCAwKSAqIDEwMDAgKyAvLyBzZWNvbmRzXG4gICAgICAgICAgICAob2JqLm1pbGxpc2Vjb25kcyB8fCBvYmoubWlsbGlzZWNvbmQgfHwgb2JqLm1zIHx8IDApIC8vIG1zXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldFdlZWtzRnJvbUlucHV0KG9iaikge1xuICAgIHJldHVybiBvYmoud2Vla3MgfHwgb2JqLndlZWsgfHwgMDtcbn1cbi8vIEVxdWFsaXR5XG5mdW5jdGlvbiBkdXJhdGlvbnNFcXVhbChkMCwgZDEpIHtcbiAgICByZXR1cm4gZDAueWVhcnMgPT09IGQxLnllYXJzICYmXG4gICAgICAgIGQwLm1vbnRocyA9PT0gZDEubW9udGhzICYmXG4gICAgICAgIGQwLmRheXMgPT09IGQxLmRheXMgJiZcbiAgICAgICAgZDAubWlsbGlzZWNvbmRzID09PSBkMS5taWxsaXNlY29uZHM7XG59XG5mdW5jdGlvbiBpc1NpbmdsZURheShkdXIpIHtcbiAgICByZXR1cm4gZHVyLnllYXJzID09PSAwICYmIGR1ci5tb250aHMgPT09IDAgJiYgZHVyLmRheXMgPT09IDEgJiYgZHVyLm1pbGxpc2Vjb25kcyA9PT0gMDtcbn1cbi8vIFNpbXBsZSBNYXRoXG5mdW5jdGlvbiBhZGREdXJhdGlvbnMoZDAsIGQxKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IGQwLnllYXJzICsgZDEueWVhcnMsXG4gICAgICAgIG1vbnRoczogZDAubW9udGhzICsgZDEubW9udGhzLFxuICAgICAgICBkYXlzOiBkMC5kYXlzICsgZDEuZGF5cyxcbiAgICAgICAgbWlsbGlzZWNvbmRzOiBkMC5taWxsaXNlY29uZHMgKyBkMS5taWxsaXNlY29uZHNcbiAgICB9O1xufVxuZnVuY3Rpb24gc3VidHJhY3REdXJhdGlvbnMoZDEsIGQwKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IGQxLnllYXJzIC0gZDAueWVhcnMsXG4gICAgICAgIG1vbnRoczogZDEubW9udGhzIC0gZDAubW9udGhzLFxuICAgICAgICBkYXlzOiBkMS5kYXlzIC0gZDAuZGF5cyxcbiAgICAgICAgbWlsbGlzZWNvbmRzOiBkMS5taWxsaXNlY29uZHMgLSBkMC5taWxsaXNlY29uZHNcbiAgICB9O1xufVxuZnVuY3Rpb24gbXVsdGlwbHlEdXJhdGlvbihkLCBuKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IGQueWVhcnMgKiBuLFxuICAgICAgICBtb250aHM6IGQubW9udGhzICogbixcbiAgICAgICAgZGF5czogZC5kYXlzICogbixcbiAgICAgICAgbWlsbGlzZWNvbmRzOiBkLm1pbGxpc2Vjb25kcyAqIG5cbiAgICB9O1xufVxuLy8gQ29udmVyc2lvbnNcbi8vIFwiUm91Z2hcIiBiZWNhdXNlIHRoZXkgYXJlIGJhc2VkIG9uIGF2ZXJhZ2UtY2FzZSBHcmVnb3JpYW4gbW9udGhzL3llYXJzXG5mdW5jdGlvbiBhc1JvdWdoWWVhcnMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hEYXlzKGR1cikgLyAzNjU7XG59XG5mdW5jdGlvbiBhc1JvdWdoTW9udGhzKGR1cikge1xuICAgIHJldHVybiBhc1JvdWdoRGF5cyhkdXIpIC8gMzA7XG59XG5mdW5jdGlvbiBhc1JvdWdoRGF5cyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaE1zKGR1cikgLyA4NjRlNTtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hNaW51dGVzKGR1cikge1xuICAgIHJldHVybiBhc1JvdWdoTXMoZHVyKSAvICgxMDAwICogNjApO1xufVxuZnVuY3Rpb24gYXNSb3VnaFNlY29uZHMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hNcyhkdXIpIC8gMTAwMDtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hNcyhkdXIpIHtcbiAgICByZXR1cm4gZHVyLnllYXJzICogKDM2NSAqIDg2NGU1KSArXG4gICAgICAgIGR1ci5tb250aHMgKiAoMzAgKiA4NjRlNSkgK1xuICAgICAgICBkdXIuZGF5cyAqIDg2NGU1ICtcbiAgICAgICAgZHVyLm1pbGxpc2Vjb25kcztcbn1cbi8vIEFkdmFuY2VkIE1hdGhcbmZ1bmN0aW9uIHdob2xlRGl2aWRlRHVyYXRpb25zKG51bWVyYXRvciwgZGVub21pbmF0b3IpIHtcbiAgICB2YXIgcmVzID0gbnVsbDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IElOVEVSTkFMX1VOSVRTLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1bml0ID0gSU5URVJOQUxfVU5JVFNbaV07XG4gICAgICAgIGlmIChkZW5vbWluYXRvclt1bml0XSkge1xuICAgICAgICAgICAgdmFyIGxvY2FsUmVzID0gbnVtZXJhdG9yW3VuaXRdIC8gZGVub21pbmF0b3JbdW5pdF07XG4gICAgICAgICAgICBpZiAoIWlzSW50KGxvY2FsUmVzKSB8fCAocmVzICE9PSBudWxsICYmIHJlcyAhPT0gbG9jYWxSZXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMgPSBsb2NhbFJlcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChudW1lcmF0b3JbdW5pdF0pIHtcbiAgICAgICAgICAgIC8vIG5lZWRzIHRvIGRpdmlkZSBieSBzb21ldGhpbmcgYnV0IGNhbid0IVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGdyZWF0ZXN0RHVyYXRpb25EZW5vbWluYXRvcihkdXIsIGRvbnRSZXR1cm5XZWVrcykge1xuICAgIHZhciBtcyA9IGR1ci5taWxsaXNlY29uZHM7XG4gICAgaWYgKG1zKSB7XG4gICAgICAgIGlmIChtcyAlIDEwMDAgIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdtaWxsaXNlY29uZCcsIHZhbHVlOiBtcyB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChtcyAlICgxMDAwICogNjApICE9PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnc2Vjb25kJywgdmFsdWU6IG1zIC8gMTAwMCB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChtcyAlICgxMDAwICogNjAgKiA2MCkgIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdtaW51dGUnLCB2YWx1ZTogbXMgLyAoMTAwMCAqIDYwKSB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChtcykge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ2hvdXInLCB2YWx1ZTogbXMgLyAoMTAwMCAqIDYwICogNjApIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGR1ci5kYXlzKSB7XG4gICAgICAgIGlmICghZG9udFJldHVybldlZWtzICYmIGR1ci5kYXlzICUgNyA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3dlZWsnLCB2YWx1ZTogZHVyLmRheXMgLyA3IH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ2RheScsIHZhbHVlOiBkdXIuZGF5cyB9O1xuICAgIH1cbiAgICBpZiAoZHVyLm1vbnRocykge1xuICAgICAgICByZXR1cm4geyB1bml0OiAnbW9udGgnLCB2YWx1ZTogZHVyLm1vbnRocyB9O1xuICAgIH1cbiAgICBpZiAoZHVyLnllYXJzKSB7XG4gICAgICAgIHJldHVybiB7IHVuaXQ6ICd5ZWFyJywgdmFsdWU6IGR1ci55ZWFycyB9O1xuICAgIH1cbiAgICByZXR1cm4geyB1bml0OiAnbWlsbGlzZWNvbmQnLCB2YWx1ZTogMCB9O1xufVxuXG4vKiBGdWxsQ2FsZW5kYXItc3BlY2lmaWMgRE9NIFV0aWxpdGllc1xuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4vLyBHaXZlbiB0aGUgc2Nyb2xsYmFyIHdpZHRocyBvZiBzb21lIG90aGVyIGNvbnRhaW5lciwgY3JlYXRlIGJvcmRlcnMvbWFyZ2lucyBvbiByb3dFbHMgaW4gb3JkZXIgdG8gbWF0Y2ggdGhlIGxlZnRcbi8vIGFuZCByaWdodCBzcGFjZSB0aGF0IHdhcyBvZmZzZXQgYnkgdGhlIHNjcm9sbGJhcnMuIEEgMS1waXhlbCBib3JkZXIgZmlyc3QsIHRoZW4gbWFyZ2luIGJleW9uZCB0aGF0LlxuZnVuY3Rpb24gY29tcGVuc2F0ZVNjcm9sbChyb3dFbCwgc2Nyb2xsYmFyV2lkdGhzKSB7XG4gICAgaWYgKHNjcm9sbGJhcldpZHRocy5sZWZ0KSB7XG4gICAgICAgIGFwcGx5U3R5bGUocm93RWwsIHtcbiAgICAgICAgICAgIGJvcmRlckxlZnRXaWR0aDogMSxcbiAgICAgICAgICAgIG1hcmdpbkxlZnQ6IHNjcm9sbGJhcldpZHRocy5sZWZ0IC0gMVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHNjcm9sbGJhcldpZHRocy5yaWdodCkge1xuICAgICAgICBhcHBseVN0eWxlKHJvd0VsLCB7XG4gICAgICAgICAgICBib3JkZXJSaWdodFdpZHRoOiAxLFxuICAgICAgICAgICAgbWFyZ2luUmlnaHQ6IHNjcm9sbGJhcldpZHRocy5yaWdodCAtIDFcbiAgICAgICAgfSk7XG4gICAgfVxufVxuLy8gVW5kb2VzIGNvbXBlbnNhdGVTY3JvbGwgYW5kIHJlc3RvcmVzIGFsbCBib3JkZXJzL21hcmdpbnNcbmZ1bmN0aW9uIHVuY29tcGVuc2F0ZVNjcm9sbChyb3dFbCkge1xuICAgIGFwcGx5U3R5bGUocm93RWwsIHtcbiAgICAgICAgbWFyZ2luTGVmdDogJycsXG4gICAgICAgIG1hcmdpblJpZ2h0OiAnJyxcbiAgICAgICAgYm9yZGVyTGVmdFdpZHRoOiAnJyxcbiAgICAgICAgYm9yZGVyUmlnaHRXaWR0aDogJydcbiAgICB9KTtcbn1cbi8vIE1ha2UgdGhlIG1vdXNlIGN1cnNvciBleHByZXNzIHRoYXQgYW4gZXZlbnQgaXMgbm90IGFsbG93ZWQgaW4gdGhlIGN1cnJlbnQgYXJlYVxuZnVuY3Rpb24gZGlzYWJsZUN1cnNvcigpIHtcbiAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ2ZjLW5vdC1hbGxvd2VkJyk7XG59XG4vLyBSZXR1cm5zIHRoZSBtb3VzZSBjdXJzb3IgdG8gaXRzIG9yaWdpbmFsIGxvb2tcbmZ1bmN0aW9uIGVuYWJsZUN1cnNvcigpIHtcbiAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ2ZjLW5vdC1hbGxvd2VkJyk7XG59XG4vLyBHaXZlbiBhIHRvdGFsIGF2YWlsYWJsZSBoZWlnaHQgdG8gZmlsbCwgaGF2ZSBgZWxzYCAoZXNzZW50aWFsbHkgY2hpbGQgcm93cykgZXhwYW5kIHRvIGFjY29tb2RhdGUuXG4vLyBCeSBkZWZhdWx0LCBhbGwgZWxlbWVudHMgdGhhdCBhcmUgc2hvcnRlciB0aGFuIHRoZSByZWNvbW1lbmRlZCBoZWlnaHQgYXJlIGV4cGFuZGVkIHVuaWZvcm1seSwgbm90IGNvbnNpZGVyaW5nXG4vLyBhbnkgb3RoZXIgZWxzIHRoYXQgYXJlIGFscmVhZHkgdG9vIHRhbGwuIGlmIGBzaG91bGRSZWRpc3RyaWJ1dGVgIGlzIG9uLCBpdCBjb25zaWRlcnMgdGhlc2UgdGFsbCByb3dzIGFuZFxuLy8gcmVkdWNlcyB0aGUgYXZhaWxhYmxlIGhlaWdodC5cbmZ1bmN0aW9uIGRpc3RyaWJ1dGVIZWlnaHQoZWxzLCBhdmFpbGFibGVIZWlnaHQsIHNob3VsZFJlZGlzdHJpYnV0ZSkge1xuICAgIC8vICpGTE9PUklORyBOT1RFKjogd2UgZmxvb3IgaW4gY2VydGFpbiBwbGFjZXMgYmVjYXVzZSB6b29tIGNhbiBnaXZlIGluYWNjdXJhdGUgZmxvYXRpbmctcG9pbnQgZGltZW5zaW9ucyxcbiAgICAvLyBhbmQgaXQgaXMgYmV0dGVyIHRvIGJlIHNob3J0ZXIgdGhhbiB0YWxsZXIsIHRvIGF2b2lkIGNyZWF0aW5nIHVubmVjZXNzYXJ5IHNjcm9sbGJhcnMuXG4gICAgdmFyIG1pbk9mZnNldDEgPSBNYXRoLmZsb29yKGF2YWlsYWJsZUhlaWdodCAvIGVscy5sZW5ndGgpOyAvLyBmb3Igbm9uLWxhc3QgZWxlbWVudFxuICAgIHZhciBtaW5PZmZzZXQyID0gTWF0aC5mbG9vcihhdmFpbGFibGVIZWlnaHQgLSBtaW5PZmZzZXQxICogKGVscy5sZW5ndGggLSAxKSk7IC8vIGZvciBsYXN0IGVsZW1lbnQgKkZMT09SSU5HIE5PVEUqXG4gICAgdmFyIGZsZXhFbHMgPSBbXTsgLy8gZWxlbWVudHMgdGhhdCBhcmUgYWxsb3dlZCB0byBleHBhbmQuIGFycmF5IG9mIERPTSBub2Rlc1xuICAgIHZhciBmbGV4T2Zmc2V0cyA9IFtdOyAvLyBhbW91bnQgb2YgdmVydGljYWwgc3BhY2UgaXQgdGFrZXMgdXBcbiAgICB2YXIgZmxleEhlaWdodHMgPSBbXTsgLy8gYWN0dWFsIGNzcyBoZWlnaHRcbiAgICB2YXIgdXNlZEhlaWdodCA9IDA7XG4gICAgdW5kaXN0cmlidXRlSGVpZ2h0KGVscyk7IC8vIGdpdmUgYWxsIGVsZW1lbnRzIHRoZWlyIG5hdHVyYWwgaGVpZ2h0XG4gICAgLy8gZmluZCBlbGVtZW50cyB0aGF0IGFyZSBiZWxvdyB0aGUgcmVjb21tZW5kZWQgaGVpZ2h0IChleHBhbmRhYmxlKS5cbiAgICAvLyBpbXBvcnRhbnQgdG8gcXVlcnkgZm9yIGhlaWdodHMgaW4gYSBzaW5nbGUgZmlyc3QgcGFzcyAodG8gYXZvaWQgcmVmbG93IG9zY2lsbGF0aW9uKS5cbiAgICBlbHMuZm9yRWFjaChmdW5jdGlvbiAoZWwsIGkpIHtcbiAgICAgICAgdmFyIG1pbk9mZnNldCA9IGkgPT09IGVscy5sZW5ndGggLSAxID8gbWluT2Zmc2V0MiA6IG1pbk9mZnNldDE7XG4gICAgICAgIHZhciBuYXR1cmFsSGVpZ2h0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xuICAgICAgICB2YXIgbmF0dXJhbE9mZnNldCA9IG5hdHVyYWxIZWlnaHQgKyBjb21wdXRlVk1hcmdpbnMoZWwpO1xuICAgICAgICBpZiAobmF0dXJhbE9mZnNldCA8IG1pbk9mZnNldCkge1xuICAgICAgICAgICAgZmxleEVscy5wdXNoKGVsKTtcbiAgICAgICAgICAgIGZsZXhPZmZzZXRzLnB1c2gobmF0dXJhbE9mZnNldCk7XG4gICAgICAgICAgICBmbGV4SGVpZ2h0cy5wdXNoKG5hdHVyYWxIZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gdGhpcyBlbGVtZW50IHN0cmV0Y2hlcyBwYXN0IHJlY29tbWVuZGVkIGhlaWdodCAobm9uLWV4cGFuZGFibGUpLiBtYXJrIHRoZSBzcGFjZSBhcyBvY2N1cGllZC5cbiAgICAgICAgICAgIHVzZWRIZWlnaHQgKz0gbmF0dXJhbE9mZnNldDtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIC8vIHJlYWRqdXN0IHRoZSByZWNvbW1lbmRlZCBoZWlnaHQgdG8gb25seSBjb25zaWRlciB0aGUgaGVpZ2h0IGF2YWlsYWJsZSB0byBub24tbWF4ZWQtb3V0IHJvd3MuXG4gICAgaWYgKHNob3VsZFJlZGlzdHJpYnV0ZSkge1xuICAgICAgICBhdmFpbGFibGVIZWlnaHQgLT0gdXNlZEhlaWdodDtcbiAgICAgICAgbWluT2Zmc2V0MSA9IE1hdGguZmxvb3IoYXZhaWxhYmxlSGVpZ2h0IC8gZmxleEVscy5sZW5ndGgpO1xuICAgICAgICBtaW5PZmZzZXQyID0gTWF0aC5mbG9vcihhdmFpbGFibGVIZWlnaHQgLSBtaW5PZmZzZXQxICogKGZsZXhFbHMubGVuZ3RoIC0gMSkpOyAvLyAqRkxPT1JJTkcgTk9URSpcbiAgICB9XG4gICAgLy8gYXNzaWduIGhlaWdodHMgdG8gYWxsIGV4cGFuZGFibGUgZWxlbWVudHNcbiAgICBmbGV4RWxzLmZvckVhY2goZnVuY3Rpb24gKGVsLCBpKSB7XG4gICAgICAgIHZhciBtaW5PZmZzZXQgPSBpID09PSBmbGV4RWxzLmxlbmd0aCAtIDEgPyBtaW5PZmZzZXQyIDogbWluT2Zmc2V0MTtcbiAgICAgICAgdmFyIG5hdHVyYWxPZmZzZXQgPSBmbGV4T2Zmc2V0c1tpXTtcbiAgICAgICAgdmFyIG5hdHVyYWxIZWlnaHQgPSBmbGV4SGVpZ2h0c1tpXTtcbiAgICAgICAgdmFyIG5ld0hlaWdodCA9IG1pbk9mZnNldCAtIChuYXR1cmFsT2Zmc2V0IC0gbmF0dXJhbEhlaWdodCk7IC8vIHN1YnRyYWN0IHRoZSBtYXJnaW4vcGFkZGluZ1xuICAgICAgICBpZiAobmF0dXJhbE9mZnNldCA8IG1pbk9mZnNldCkgeyAvLyB3ZSBjaGVjayB0aGlzIGFnYWluIGJlY2F1c2UgcmVkaXN0cmlidXRpb24gbWlnaHQgaGF2ZSBjaGFuZ2VkIHRoaW5nc1xuICAgICAgICAgICAgZWwuc3R5bGUuaGVpZ2h0ID0gbmV3SGVpZ2h0ICsgJ3B4JztcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLy8gVW5kb2VzIGRpc3RydWJ1dGVIZWlnaHQsIHJlc3RvcmluZyBhbGwgZWxzIHRvIHRoZWlyIG5hdHVyYWwgaGVpZ2h0XG5mdW5jdGlvbiB1bmRpc3RyaWJ1dGVIZWlnaHQoZWxzKSB7XG4gICAgZWxzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIGVsLnN0eWxlLmhlaWdodCA9ICcnO1xuICAgIH0pO1xufVxuLy8gR2l2ZW4gYGVsc2AsIGEgc2V0IG9mIDx0ZD4gY2VsbHMsIGZpbmQgdGhlIGNlbGwgd2l0aCB0aGUgbGFyZ2VzdCBuYXR1cmFsIHdpZHRoIGFuZCBzZXQgdGhlIHdpZHRocyBvZiBhbGwgdGhlXG4vLyBjZWxscyB0byBiZSB0aGF0IHdpZHRoLlxuLy8gUFJFUkVRVUlTSVRFOiBpZiB5b3Ugd2FudCBhIGNlbGwgdG8gdGFrZSB1cCB3aWR0aCwgaXQgbmVlZHMgdG8gaGF2ZSBhIHNpbmdsZSBpbm5lciBlbGVtZW50IHcvIGRpc3BsYXk6aW5saW5lXG5mdW5jdGlvbiBtYXRjaENlbGxXaWR0aHMoZWxzKSB7XG4gICAgdmFyIG1heElubmVyV2lkdGggPSAwO1xuICAgIGVscy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICB2YXIgaW5uZXJFbCA9IGVsLmZpcnN0Q2hpbGQ7IC8vIGhvcGVmdWxseSBhbiBlbGVtZW50XG4gICAgICAgIGlmIChpbm5lckVsIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHZhciBpbm5lcldpZHRoXzEgPSBpbm5lckVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoO1xuICAgICAgICAgICAgaWYgKGlubmVyV2lkdGhfMSA+IG1heElubmVyV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBtYXhJbm5lcldpZHRoID0gaW5uZXJXaWR0aF8xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG4gICAgbWF4SW5uZXJXaWR0aCsrOyAvLyBzb21ldGltZXMgbm90IGFjY3VyYXRlIG9mIHdpZHRoIHRoZSB0ZXh0IG5lZWRzIHRvIHN0YXkgb24gb25lIGxpbmUuIGluc3VyYW5jZVxuICAgIGVscy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICBlbC5zdHlsZS53aWR0aCA9IG1heElubmVyV2lkdGggKyAncHgnO1xuICAgIH0pO1xuICAgIHJldHVybiBtYXhJbm5lcldpZHRoO1xufVxuLy8gR2l2ZW4gb25lIGVsZW1lbnQgdGhhdCByZXNpZGVzIGluc2lkZSBhbm90aGVyLFxuLy8gU3VidHJhY3RzIHRoZSBoZWlnaHQgb2YgdGhlIGlubmVyIGVsZW1lbnQgZnJvbSB0aGUgb3V0ZXIgZWxlbWVudC5cbmZ1bmN0aW9uIHN1YnRyYWN0SW5uZXJFbEhlaWdodChvdXRlckVsLCBpbm5lckVsKSB7XG4gICAgLy8gZWZmaW4nIElFOC85LzEwLzExIHNvbWV0aW1lcyByZXR1cm5zIDAgZm9yIGRpbWVuc2lvbnMuIHRoaXMgd2VpcmQgaGFjayB3YXMgdGhlIG9ubHkgdGhpbmcgdGhhdCB3b3JrZWRcbiAgICB2YXIgcmVmbG93U3R5bGVQcm9wcyA9IHtcbiAgICAgICAgcG9zaXRpb246ICdyZWxhdGl2ZScsXG4gICAgICAgIGxlZnQ6IC0xIC8vIGVuc3VyZSByZWZsb3cgaW4gY2FzZSB0aGUgZWwgd2FzIGFscmVhZHkgcmVsYXRpdmUuIG5lZ2F0aXZlIGlzIGxlc3MgbGlrZWx5IHRvIGNhdXNlIG5ldyBzY3JvbGxcbiAgICB9O1xuICAgIGFwcGx5U3R5bGUob3V0ZXJFbCwgcmVmbG93U3R5bGVQcm9wcyk7XG4gICAgYXBwbHlTdHlsZShpbm5lckVsLCByZWZsb3dTdHlsZVByb3BzKTtcbiAgICB2YXIgZGlmZiA9IC8vIGdyYWIgdGhlIGRpbWVuc2lvbnNcbiAgICAgb3V0ZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgLVxuICAgICAgICBpbm5lckVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodDtcbiAgICAvLyB1bmRvIGhhY2tcbiAgICB2YXIgcmVzZXRTdHlsZVByb3BzID0geyBwb3NpdGlvbjogJycsIGxlZnQ6ICcnIH07XG4gICAgYXBwbHlTdHlsZShvdXRlckVsLCByZXNldFN0eWxlUHJvcHMpO1xuICAgIGFwcGx5U3R5bGUoaW5uZXJFbCwgcmVzZXRTdHlsZVByb3BzKTtcbiAgICByZXR1cm4gZGlmZjtcbn1cbi8qIFNlbGVjdGlvblxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5mdW5jdGlvbiBwcmV2ZW50U2VsZWN0aW9uKGVsKSB7XG4gICAgZWwuY2xhc3NMaXN0LmFkZCgnZmMtdW5zZWxlY3RhYmxlJyk7XG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG5mdW5jdGlvbiBhbGxvd1NlbGVjdGlvbihlbCkge1xuICAgIGVsLmNsYXNzTGlzdC5yZW1vdmUoJ2ZjLXVuc2VsZWN0YWJsZScpO1xuICAgIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xufVxuLyogQ29udGV4dCBNZW51XG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIHByZXZlbnRDb250ZXh0TWVudShlbCkge1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgcHJldmVudERlZmF1bHQpO1xufVxuZnVuY3Rpb24gYWxsb3dDb250ZXh0TWVudShlbCkge1xuICAgIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgcHJldmVudERlZmF1bHQpO1xufVxuLyogT2JqZWN0IE9yZGVyaW5nIGJ5IEZpZWxkXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIHBhcnNlRmllbGRTcGVjcyhpbnB1dCkge1xuICAgIHZhciBzcGVjcyA9IFtdO1xuICAgIHZhciB0b2tlbnMgPSBbXTtcbiAgICB2YXIgaTtcbiAgICB2YXIgdG9rZW47XG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdG9rZW5zID0gaW5wdXQuc3BsaXQoL1xccyosXFxzKi8pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdG9rZW5zID0gW2lucHV0XTtcbiAgICB9XG4gICAgZWxzZSBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgdG9rZW5zID0gaW5wdXQ7XG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdG9rZW4gPSB0b2tlbnNbaV07XG4gICAgICAgIGlmICh0eXBlb2YgdG9rZW4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBzcGVjcy5wdXNoKHRva2VuLmNoYXJBdCgwKSA9PT0gJy0nID9cbiAgICAgICAgICAgICAgICB7IGZpZWxkOiB0b2tlbi5zdWJzdHJpbmcoMSksIG9yZGVyOiAtMSB9IDpcbiAgICAgICAgICAgICAgICB7IGZpZWxkOiB0b2tlbiwgb3JkZXI6IDEgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHRva2VuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBzcGVjcy5wdXNoKHsgZnVuYzogdG9rZW4gfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNwZWNzO1xufVxuZnVuY3Rpb24gY29tcGFyZUJ5RmllbGRTcGVjcyhvYmowLCBvYmoxLCBmaWVsZFNwZWNzKSB7XG4gICAgdmFyIGk7XG4gICAgdmFyIGNtcDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgZmllbGRTcGVjcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjbXAgPSBjb21wYXJlQnlGaWVsZFNwZWMob2JqMCwgb2JqMSwgZmllbGRTcGVjc1tpXSk7XG4gICAgICAgIGlmIChjbXApIHtcbiAgICAgICAgICAgIHJldHVybiBjbXA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5mdW5jdGlvbiBjb21wYXJlQnlGaWVsZFNwZWMob2JqMCwgb2JqMSwgZmllbGRTcGVjKSB7XG4gICAgaWYgKGZpZWxkU3BlYy5mdW5jKSB7XG4gICAgICAgIHJldHVybiBmaWVsZFNwZWMuZnVuYyhvYmowLCBvYmoxKTtcbiAgICB9XG4gICAgcmV0dXJuIGZsZXhpYmxlQ29tcGFyZShvYmowW2ZpZWxkU3BlYy5maWVsZF0sIG9iajFbZmllbGRTcGVjLmZpZWxkXSlcbiAgICAgICAgKiAoZmllbGRTcGVjLm9yZGVyIHx8IDEpO1xufVxuZnVuY3Rpb24gZmxleGlibGVDb21wYXJlKGEsIGIpIHtcbiAgICBpZiAoIWEgJiYgIWIpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmIChiID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgICBpZiAoYSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGEgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBiID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gU3RyaW5nKGEpLmxvY2FsZUNvbXBhcmUoU3RyaW5nKGIpKTtcbiAgICB9XG4gICAgcmV0dXJuIGEgLSBiO1xufVxuLyogU3RyaW5nIFV0aWxpdGllc1xuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5mdW5jdGlvbiBjYXBpdGFsaXNlRmlyc3RMZXR0ZXIoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0ci5zbGljZSgxKTtcbn1cbmZ1bmN0aW9uIHBhZFN0YXJ0KHZhbCwgbGVuKSB7XG4gICAgdmFyIHMgPSBTdHJpbmcodmFsKTtcbiAgICByZXR1cm4gJzAwMCcuc3Vic3RyKDAsIGxlbiAtIHMubGVuZ3RoKSArIHM7XG59XG4vKiBOdW1iZXIgVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIGNvbXBhcmVOdW1iZXJzKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG59XG5mdW5jdGlvbiBpc0ludChuKSB7XG4gICAgcmV0dXJuIG4gJSAxID09PSAwO1xufVxuLyogV2VpcmQgVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIGFwcGx5QWxsKGZ1bmN0aW9ucywgdGhpc09iaiwgYXJncykge1xuICAgIGlmICh0eXBlb2YgZnVuY3Rpb25zID09PSAnZnVuY3Rpb24nKSB7IC8vIHN1cHBsaWVkIGEgc2luZ2xlIGZ1bmN0aW9uXG4gICAgICAgIGZ1bmN0aW9ucyA9IFtmdW5jdGlvbnNdO1xuICAgIH1cbiAgICBpZiAoZnVuY3Rpb25zKSB7XG4gICAgICAgIHZhciBpID0gdm9pZCAwO1xuICAgICAgICB2YXIgcmV0ID0gdm9pZCAwO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZnVuY3Rpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICByZXQgPSBmdW5jdGlvbnNbaV0uYXBwbHkodGhpc09iaiwgYXJncykgfHwgcmV0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfVxufVxuZnVuY3Rpb24gZmlyc3REZWZpbmVkKCkge1xuICAgIHZhciBhcmdzID0gW107XG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgYXJnc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGFyZ3NbaV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3NbaV07XG4gICAgICAgIH1cbiAgICB9XG59XG4vLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90XG4vLyBiZSB0cmlnZ2VyZWQuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciBpdCBzdG9wcyBiZWluZyBjYWxsZWQgZm9yXG4vLyBOIG1pbGxpc2Vjb25kcy4gSWYgYGltbWVkaWF0ZWAgaXMgcGFzc2VkLCB0cmlnZ2VyIHRoZSBmdW5jdGlvbiBvbiB0aGVcbi8vIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuXG4vLyBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvYmxvYi8xLjYuMC91bmRlcnNjb3JlLmpzI0w3MTRcbmZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQpIHtcbiAgICB2YXIgdGltZW91dDtcbiAgICB2YXIgYXJncztcbiAgICB2YXIgY29udGV4dDtcbiAgICB2YXIgdGltZXN0YW1wO1xuICAgIHZhciByZXN1bHQ7XG4gICAgdmFyIGxhdGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGFzdCA9IG5ldyBEYXRlKCkudmFsdWVPZigpIC0gdGltZXN0YW1wO1xuICAgICAgICBpZiAobGFzdCA8IHdhaXQpIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0IC0gbGFzdCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICB0aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLnZhbHVlT2YoKTtcbiAgICAgICAgaWYgKCF0aW1lb3V0KSB7XG4gICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xufVxuLy8gTnVtYmVyIGFuZCBCb29sZWFuIGFyZSBvbmx5IHR5cGVzIHRoYXQgZGVmYXVsdHMgb3Igbm90IGNvbXB1dGVkIGZvclxuLy8gVE9ETzogd3JpdGUgbW9yZSBjb21tZW50c1xuZnVuY3Rpb24gcmVmaW5lUHJvcHMocmF3UHJvcHMsIHByb2Nlc3NvcnMsIGRlZmF1bHRzLCBsZWZ0b3ZlclByb3BzKSB7XG4gICAgaWYgKGRlZmF1bHRzID09PSB2b2lkIDApIHsgZGVmYXVsdHMgPSB7fTsgfVxuICAgIHZhciByZWZpbmVkID0ge307XG4gICAgZm9yICh2YXIga2V5IGluIHByb2Nlc3NvcnMpIHtcbiAgICAgICAgdmFyIHByb2Nlc3NvciA9IHByb2Nlc3NvcnNba2V5XTtcbiAgICAgICAgaWYgKHJhd1Byb3BzW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gZm91bmRcbiAgICAgICAgICAgIGlmIChwcm9jZXNzb3IgPT09IEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gdHlwZW9mIHJhd1Byb3BzW2tleV0gPT09ICdmdW5jdGlvbicgPyByYXdQcm9wc1trZXldIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHByb2Nlc3NvcikgeyAvLyBhIHJlZmluaW5nIGZ1bmN0aW9uP1xuICAgICAgICAgICAgICAgIHJlZmluZWRba2V5XSA9IHByb2Nlc3NvcihyYXdQcm9wc1trZXldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlZmluZWRba2V5XSA9IHJhd1Byb3BzW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZGVmYXVsdHNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyB0aGVyZSdzIGFuIGV4cGxpY2l0IGRlZmF1bHRcbiAgICAgICAgICAgIHJlZmluZWRba2V5XSA9IGRlZmF1bHRzW2tleV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBtdXN0IGNvbXB1dGUgYSBkZWZhdWx0XG4gICAgICAgICAgICBpZiAocHJvY2Vzc29yID09PSBTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICByZWZpbmVkW2tleV0gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIGlzIGRlZmF1bHQgZm9yIFN0cmluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoIXByb2Nlc3NvciB8fCBwcm9jZXNzb3IgPT09IE51bWJlciB8fCBwcm9jZXNzb3IgPT09IEJvb2xlYW4gfHwgcHJvY2Vzc29yID09PSBGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgIHJlZmluZWRba2V5XSA9IG51bGw7IC8vIGFzc2lnbiBudWxsIGZvciBvdGhlciBub24tY3VzdG9tIHByb2Nlc3NvciBmdW5jc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gcHJvY2Vzc29yKG51bGwpOyAvLyBydW4gdGhlIGN1c3RvbSBwcm9jZXNzb3IgZnVuY1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChsZWZ0b3ZlclByb3BzKSB7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiByYXdQcm9wcykge1xuICAgICAgICAgICAgaWYgKHByb2Nlc3NvcnNba2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbGVmdG92ZXJQcm9wc1trZXldID0gcmF3UHJvcHNba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVmaW5lZDtcbn1cbi8qIERhdGUgc3R1ZmYgdGhhdCBkb2Vzbid0IGJlbG9uZyBpbiBkYXRlbGliIGNvcmVcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLy8gZ2l2ZW4gYSB0aW1lZCByYW5nZSwgY29tcHV0ZXMgYW4gYWxsLWRheSByYW5nZSB0aGF0IGhhcyB0aGUgc2FtZSBleGFjdCBkdXJhdGlvbixcbi8vIGJ1dCB3aG9zZSBzdGFydCB0aW1lIGlzIGFsaWduZWQgd2l0aCB0aGUgc3RhcnQgb2YgdGhlIGRheS5cbmZ1bmN0aW9uIGNvbXB1dGVBbGlnbmVkRGF5UmFuZ2UodGltZWRSYW5nZSkge1xuICAgIHZhciBkYXlDbnQgPSBNYXRoLmZsb29yKGRpZmZEYXlzKHRpbWVkUmFuZ2Uuc3RhcnQsIHRpbWVkUmFuZ2UuZW5kKSkgfHwgMTtcbiAgICB2YXIgc3RhcnQgPSBzdGFydE9mRGF5KHRpbWVkUmFuZ2Uuc3RhcnQpO1xuICAgIHZhciBlbmQgPSBhZGREYXlzKHN0YXJ0LCBkYXlDbnQpO1xuICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfTtcbn1cbi8vIGdpdmVuIGEgdGltZWQgcmFuZ2UsIGNvbXB1dGVzIGFuIGFsbC1kYXkgcmFuZ2UgYmFzZWQgb24gaG93IGZvciB0aGUgZW5kIGRhdGUgYmxlZWRzIGludG8gdGhlIG5leHQgZGF5XG4vLyBUT0RPOiBnaXZlIG5leHREYXlUaHJlc2hvbGQgYSBkZWZhdWx0IGFyZ1xuZnVuY3Rpb24gY29tcHV0ZVZpc2libGVEYXlSYW5nZSh0aW1lZFJhbmdlLCBuZXh0RGF5VGhyZXNob2xkKSB7XG4gICAgaWYgKG5leHREYXlUaHJlc2hvbGQgPT09IHZvaWQgMCkgeyBuZXh0RGF5VGhyZXNob2xkID0gY3JlYXRlRHVyYXRpb24oMCk7IH1cbiAgICB2YXIgc3RhcnREYXkgPSBudWxsO1xuICAgIHZhciBlbmREYXkgPSBudWxsO1xuICAgIGlmICh0aW1lZFJhbmdlLmVuZCkge1xuICAgICAgICBlbmREYXkgPSBzdGFydE9mRGF5KHRpbWVkUmFuZ2UuZW5kKTtcbiAgICAgICAgdmFyIGVuZFRpbWVNUyA9IHRpbWVkUmFuZ2UuZW5kLnZhbHVlT2YoKSAtIGVuZERheS52YWx1ZU9mKCk7IC8vICMgb2YgbWlsbGlzZWNvbmRzIGludG8gYGVuZERheWBcbiAgICAgICAgLy8gSWYgdGhlIGVuZCB0aW1lIGlzIGFjdHVhbGx5IGluY2x1c2l2ZWx5IHBhcnQgb2YgdGhlIG5leHQgZGF5IGFuZCBpcyBlcXVhbCB0byBvclxuICAgICAgICAvLyBiZXlvbmQgdGhlIG5leHQgZGF5IHRocmVzaG9sZCwgYWRqdXN0IHRoZSBlbmQgdG8gYmUgdGhlIGV4Y2x1c2l2ZSBlbmQgb2YgYGVuZERheWAuXG4gICAgICAgIC8vIE90aGVyd2lzZSwgbGVhdmluZyBpdCBhcyBpbmNsdXNpdmUgd2lsbCBjYXVzZSBpdCB0byBleGNsdWRlIGBlbmREYXlgLlxuICAgICAgICBpZiAoZW5kVGltZU1TICYmIGVuZFRpbWVNUyA+PSBhc1JvdWdoTXMobmV4dERheVRocmVzaG9sZCkpIHtcbiAgICAgICAgICAgIGVuZERheSA9IGFkZERheXMoZW5kRGF5LCAxKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAodGltZWRSYW5nZS5zdGFydCkge1xuICAgICAgICBzdGFydERheSA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5zdGFydCk7IC8vIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGRheSB0aGUgcmFuZ2Ugc3RhcnRzXG4gICAgICAgIC8vIElmIGVuZCBpcyB3aXRoaW4gYHN0YXJ0RGF5YCBidXQgbm90IHBhc3QgbmV4dERheVRocmVzaG9sZCwgYXNzaWduIHRoZSBkZWZhdWx0IGR1cmF0aW9uIG9mIG9uZSBkYXkuXG4gICAgICAgIGlmIChlbmREYXkgJiYgZW5kRGF5IDw9IHN0YXJ0RGF5KSB7XG4gICAgICAgICAgICBlbmREYXkgPSBhZGREYXlzKHN0YXJ0RGF5LCAxKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBzdGFydDogc3RhcnREYXksIGVuZDogZW5kRGF5IH07XG59XG4vLyBzcGFucyBmcm9tIG9uZSBkYXkgaW50byBhbm90aGVyP1xuZnVuY3Rpb24gaXNNdWx0aURheVJhbmdlKHJhbmdlKSB7XG4gICAgdmFyIHZpc2libGVSYW5nZSA9IGNvbXB1dGVWaXNpYmxlRGF5UmFuZ2UocmFuZ2UpO1xuICAgIHJldHVybiBkaWZmRGF5cyh2aXNpYmxlUmFuZ2Uuc3RhcnQsIHZpc2libGVSYW5nZS5lbmQpID4gMTtcbn1cbmZ1bmN0aW9uIGRpZmZEYXRlcyhkYXRlMCwgZGF0ZTEsIGRhdGVFbnYsIGxhcmdlVW5pdCkge1xuICAgIGlmIChsYXJnZVVuaXQgPT09ICd5ZWFyJykge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oZGF0ZUVudi5kaWZmV2hvbGVZZWFycyhkYXRlMCwgZGF0ZTEpLCAneWVhcicpO1xuICAgIH1cbiAgICBlbHNlIGlmIChsYXJnZVVuaXQgPT09ICdtb250aCcpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKGRhdGVFbnYuZGlmZldob2xlTW9udGhzKGRhdGUwLCBkYXRlMSksICdtb250aCcpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRpZmZEYXlBbmRUaW1lKGRhdGUwLCBkYXRlMSk7IC8vIHJldHVybnMgYSBkdXJhdGlvblxuICAgIH1cbn1cblxuLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxudmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH07XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufTtcblxuZnVuY3Rpb24gcGFyc2VSZWN1cnJpbmcoZXZlbnRJbnB1dCwgYWxsRGF5RGVmYXVsdCwgZGF0ZUVudiwgcmVjdXJyaW5nVHlwZXMsIGxlZnRvdmVycykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVjdXJyaW5nVHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGxvY2FsTGVmdG92ZXJzID0ge307XG4gICAgICAgIHZhciBwYXJzZWQgPSByZWN1cnJpbmdUeXBlc1tpXS5wYXJzZShldmVudElucHV0LCBsb2NhbExlZnRvdmVycywgZGF0ZUVudik7XG4gICAgICAgIGlmIChwYXJzZWQpIHtcbiAgICAgICAgICAgIHZhciBhbGxEYXkgPSBsb2NhbExlZnRvdmVycy5hbGxEYXk7XG4gICAgICAgICAgICBkZWxldGUgbG9jYWxMZWZ0b3ZlcnMuYWxsRGF5OyAvLyByZW1vdmUgZnJvbSBsZWZ0b3ZlcnNcbiAgICAgICAgICAgIGlmIChhbGxEYXkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGFsbERheSA9IGFsbERheURlZmF1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsbERheSA9IHBhcnNlZC5hbGxEYXlHdWVzcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGxEYXkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF9fYXNzaWduKGxlZnRvdmVycywgbG9jYWxMZWZ0b3ZlcnMpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhbGxEYXk6IGFsbERheSxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogcGFyc2VkLmR1cmF0aW9uLFxuICAgICAgICAgICAgICAgIHR5cGVEYXRhOiBwYXJzZWQudHlwZURhdGEsXG4gICAgICAgICAgICAgICAgdHlwZUlkOiBpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuLypcbkV2ZW50IE1VU1QgaGF2ZSBhIHJlY3VycmluZ0RlZlxuKi9cbmZ1bmN0aW9uIGV4cGFuZFJlY3VycmluZ1JhbmdlcyhldmVudERlZiwgZHVyYXRpb24sIGZyYW1pbmdSYW5nZSwgZGF0ZUVudiwgcmVjdXJyaW5nVHlwZXMpIHtcbiAgICB2YXIgdHlwZURlZiA9IHJlY3VycmluZ1R5cGVzW2V2ZW50RGVmLnJlY3VycmluZ0RlZi50eXBlSWRdO1xuICAgIHZhciBtYXJrZXJzID0gdHlwZURlZi5leHBhbmQoZXZlbnREZWYucmVjdXJyaW5nRGVmLnR5cGVEYXRhLCB7XG4gICAgICAgIHN0YXJ0OiBkYXRlRW52LnN1YnRyYWN0KGZyYW1pbmdSYW5nZS5zdGFydCwgZHVyYXRpb24pLFxuICAgICAgICBlbmQ6IGZyYW1pbmdSYW5nZS5lbmRcbiAgICB9LCBkYXRlRW52KTtcbiAgICAvLyB0aGUgcmVjdXJyZW5jZSBwbHVnaW5zIGRvbid0IGd1YXJhbnRlZSB0aGF0IGFsbC1kYXkgZXZlbnRzIGFyZSBzdGFydC1vZi1kYXksIHNvIHdlIGhhdmUgdG9cbiAgICBpZiAoZXZlbnREZWYuYWxsRGF5KSB7XG4gICAgICAgIG1hcmtlcnMgPSBtYXJrZXJzLm1hcChzdGFydE9mRGF5KTtcbiAgICB9XG4gICAgcmV0dXJuIG1hcmtlcnM7XG59XG5cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG4vLyBNZXJnZXMgYW4gYXJyYXkgb2Ygb2JqZWN0cyBpbnRvIGEgc2luZ2xlIG9iamVjdC5cbi8vIFRoZSBzZWNvbmQgYXJndW1lbnQgYWxsb3dzIGZvciBhbiBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyB3aG8ncyBvYmplY3QgdmFsdWVzIHdpbGwgYmUgbWVyZ2VkIHRvZ2V0aGVyLlxuZnVuY3Rpb24gbWVyZ2VQcm9wcyhwcm9wT2JqcywgY29tcGxleFByb3BzKSB7XG4gICAgdmFyIGRlc3QgPSB7fTtcbiAgICB2YXIgaTtcbiAgICB2YXIgbmFtZTtcbiAgICB2YXIgY29tcGxleE9ianM7XG4gICAgdmFyIGo7XG4gICAgdmFyIHZhbDtcbiAgICB2YXIgcHJvcHM7XG4gICAgaWYgKGNvbXBsZXhQcm9wcykge1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcGxleFByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBuYW1lID0gY29tcGxleFByb3BzW2ldO1xuICAgICAgICAgICAgY29tcGxleE9ianMgPSBbXTtcbiAgICAgICAgICAgIC8vIGNvbGxlY3QgdGhlIHRyYWlsaW5nIG9iamVjdCB2YWx1ZXMsIHN0b3BwaW5nIHdoZW4gYSBub24tb2JqZWN0IGlzIGRpc2NvdmVyZWRcbiAgICAgICAgICAgIGZvciAoaiA9IHByb3BPYmpzLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gcHJvcE9ianNbal1bbmFtZV07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbCkgeyAvLyBub24tbnVsbCBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgY29tcGxleE9ianMudW5zaGlmdCh2YWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBkZXN0W25hbWVdID0gdmFsOyAvLyBpZiB0aGVyZSB3ZXJlIG5vIG9iamVjdHMsIHRoaXMgdmFsdWUgd2lsbCBiZSB1c2VkXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHRoZSB0cmFpbGluZyB2YWx1ZXMgd2VyZSBvYmplY3RzLCB1c2UgdGhlIG1lcmdlZCB2YWx1ZVxuICAgICAgICAgICAgaWYgKGNvbXBsZXhPYmpzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGRlc3RbbmFtZV0gPSBtZXJnZVByb3BzKGNvbXBsZXhPYmpzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBjb3B5IHZhbHVlcyBpbnRvIHRoZSBkZXN0aW5hdGlvbiwgZ29pbmcgZnJvbSBsYXN0IHRvIGZpcnN0XG4gICAgZm9yIChpID0gcHJvcE9ianMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgcHJvcHMgPSBwcm9wT2Jqc1tpXTtcbiAgICAgICAgZm9yIChuYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICBpZiAoIShuYW1lIGluIGRlc3QpKSB7IC8vIGlmIGFscmVhZHkgYXNzaWduZWQgYnkgcHJldmlvdXMgcHJvcHMgb3IgY29tcGxleCBwcm9wcywgZG9uJ3QgcmVhc3NpZ25cbiAgICAgICAgICAgICAgICBkZXN0W25hbWVdID0gcHJvcHNbbmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRlc3Q7XG59XG5mdW5jdGlvbiBmaWx0ZXJIYXNoKGhhc2gsIGZ1bmMpIHtcbiAgICB2YXIgZmlsdGVyZWQgPSB7fTtcbiAgICBmb3IgKHZhciBrZXkgaW4gaGFzaCkge1xuICAgICAgICBpZiAoZnVuYyhoYXNoW2tleV0sIGtleSkpIHtcbiAgICAgICAgICAgIGZpbHRlcmVkW2tleV0gPSBoYXNoW2tleV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZpbHRlcmVkO1xufVxuZnVuY3Rpb24gbWFwSGFzaChoYXNoLCBmdW5jKSB7XG4gICAgdmFyIG5ld0hhc2ggPSB7fTtcbiAgICBmb3IgKHZhciBrZXkgaW4gaGFzaCkge1xuICAgICAgICBuZXdIYXNoW2tleV0gPSBmdW5jKGhhc2hba2V5XSwga2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld0hhc2g7XG59XG5mdW5jdGlvbiBhcnJheVRvSGFzaChhKSB7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIGFfMSA9IGE7IF9pIDwgYV8xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgaXRlbSA9IGFfMVtfaV07XG4gICAgICAgIGhhc2hbaXRlbV0gPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gaGFzaDtcbn1cbmZ1bmN0aW9uIGhhc2hWYWx1ZXNUb0FycmF5KG9iaikge1xuICAgIHZhciBhID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICBhLnB1c2gob2JqW2tleV0pO1xuICAgIH1cbiAgICByZXR1cm4gYTtcbn1cbmZ1bmN0aW9uIGlzUHJvcHNFcXVhbChvYmowLCBvYmoxKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iajApIHtcbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqMCwga2V5KSkge1xuICAgICAgICAgICAgaWYgKCEoa2V5IGluIG9iajEpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAodmFyIGtleSBpbiBvYmoxKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iajEsIGtleSkpIHtcbiAgICAgICAgICAgIGlmIChvYmowW2tleV0gIT09IG9iajFba2V5XSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gcGFyc2VFdmVudHMocmF3RXZlbnRzLCBzb3VyY2VJZCwgY2FsZW5kYXIsIGFsbG93T3BlblJhbmdlKSB7XG4gICAgdmFyIGV2ZW50U3RvcmUgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHJhd0V2ZW50c18xID0gcmF3RXZlbnRzOyBfaSA8IHJhd0V2ZW50c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgcmF3RXZlbnQgPSByYXdFdmVudHNfMVtfaV07XG4gICAgICAgIHZhciB0dXBsZSA9IHBhcnNlRXZlbnQocmF3RXZlbnQsIHNvdXJjZUlkLCBjYWxlbmRhciwgYWxsb3dPcGVuUmFuZ2UpO1xuICAgICAgICBpZiAodHVwbGUpIHtcbiAgICAgICAgICAgIGV2ZW50VHVwbGVUb1N0b3JlKHR1cGxlLCBldmVudFN0b3JlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXZlbnRTdG9yZTtcbn1cbmZ1bmN0aW9uIGV2ZW50VHVwbGVUb1N0b3JlKHR1cGxlLCBldmVudFN0b3JlKSB7XG4gICAgaWYgKGV2ZW50U3RvcmUgPT09IHZvaWQgMCkgeyBldmVudFN0b3JlID0gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7IH1cbiAgICBldmVudFN0b3JlLmRlZnNbdHVwbGUuZGVmLmRlZklkXSA9IHR1cGxlLmRlZjtcbiAgICBpZiAodHVwbGUuaW5zdGFuY2UpIHtcbiAgICAgICAgZXZlbnRTdG9yZS5pbnN0YW5jZXNbdHVwbGUuaW5zdGFuY2UuaW5zdGFuY2VJZF0gPSB0dXBsZS5pbnN0YW5jZTtcbiAgICB9XG4gICAgcmV0dXJuIGV2ZW50U3RvcmU7XG59XG5mdW5jdGlvbiBleHBhbmRSZWN1cnJpbmcoZXZlbnRTdG9yZSwgZnJhbWluZ1JhbmdlLCBjYWxlbmRhcikge1xuICAgIHZhciBkYXRlRW52ID0gY2FsZW5kYXIuZGF0ZUVudjtcbiAgICB2YXIgZGVmcyA9IGV2ZW50U3RvcmUuZGVmcywgaW5zdGFuY2VzID0gZXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgLy8gcmVtb3ZlIGV4aXN0aW5nIHJlY3VycmluZyBpbnN0YW5jZXNcbiAgICBpbnN0YW5jZXMgPSBmaWx0ZXJIYXNoKGluc3RhbmNlcywgZnVuY3Rpb24gKGluc3RhbmNlKSB7XG4gICAgICAgIHJldHVybiAhZGVmc1tpbnN0YW5jZS5kZWZJZF0ucmVjdXJyaW5nRGVmO1xuICAgIH0pO1xuICAgIGZvciAodmFyIGRlZklkIGluIGRlZnMpIHtcbiAgICAgICAgdmFyIGRlZiA9IGRlZnNbZGVmSWRdO1xuICAgICAgICBpZiAoZGVmLnJlY3VycmluZ0RlZikge1xuICAgICAgICAgICAgdmFyIGR1cmF0aW9uID0gZGVmLnJlY3VycmluZ0RlZi5kdXJhdGlvbjtcbiAgICAgICAgICAgIGlmICghZHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IGRlZi5hbGxEYXkgP1xuICAgICAgICAgICAgICAgICAgICBjYWxlbmRhci5kZWZhdWx0QWxsRGF5RXZlbnREdXJhdGlvbiA6XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgc3RhcnRzID0gZXhwYW5kUmVjdXJyaW5nUmFuZ2VzKGRlZiwgZHVyYXRpb24sIGZyYW1pbmdSYW5nZSwgY2FsZW5kYXIuZGF0ZUVudiwgY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLnJlY3VycmluZ1R5cGVzKTtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgc3RhcnRzXzEgPSBzdGFydHM7IF9pIDwgc3RhcnRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN0YXJ0ID0gc3RhcnRzXzFbX2ldO1xuICAgICAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGNyZWF0ZUV2ZW50SW5zdGFuY2UoZGVmSWQsIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IGRhdGVFbnYuYWRkKHN0YXJ0LCBkdXJhdGlvbilcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpbnN0YW5jZXNbaW5zdGFuY2UuaW5zdGFuY2VJZF0gPSBpbnN0YW5jZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBkZWZzOiBkZWZzLCBpbnN0YW5jZXM6IGluc3RhbmNlcyB9O1xufVxuLy8gcmV0cmlldmVzIGV2ZW50cyB0aGF0IGhhdmUgdGhlIHNhbWUgZ3JvdXBJZCBhcyB0aGUgaW5zdGFuY2Ugc3BlY2lmaWVkIGJ5IGBpbnN0YW5jZUlkYFxuLy8gb3IgdGhleSBhcmUgdGhlIHNhbWUgYXMgdGhlIGluc3RhbmNlLlxuLy8gd2h5IG1pZ2h0IGluc3RhbmNlSWQgbm90IGJlIGluIHRoZSBzdG9yZT8gYW4gZXZlbnQgZnJvbSBhbm90aGVyIGNhbGVuZGFyP1xuZnVuY3Rpb24gZ2V0UmVsZXZhbnRFdmVudHMoZXZlbnRTdG9yZSwgaW5zdGFuY2VJZCkge1xuICAgIHZhciBpbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlSWRdO1xuICAgIGlmIChpbnN0YW5jZSkge1xuICAgICAgICB2YXIgZGVmXzEgPSBldmVudFN0b3JlLmRlZnNbaW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICAvLyBnZXQgZXZlbnRzL2luc3RhbmNlcyB3aXRoIHNhbWUgZ3JvdXBcbiAgICAgICAgdmFyIG5ld1N0b3JlID0gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZnVuY3Rpb24gKGxvb2tEZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0V2ZW50RGVmc0dyb3VwZWQoZGVmXzEsIGxvb2tEZWYpO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gYWRkIHRoZSBvcmlnaW5hbFxuICAgICAgICAvLyBUT0RPOiB3aXNoIHdlIGNvdWxkIHVzZSBldmVudFR1cGxlVG9TdG9yZSBvciBzb21ldGhpbmcgbGlrZSBpdFxuICAgICAgICBuZXdTdG9yZS5kZWZzW2RlZl8xLmRlZklkXSA9IGRlZl8xO1xuICAgICAgICBuZXdTdG9yZS5pbnN0YW5jZXNbaW5zdGFuY2UuaW5zdGFuY2VJZF0gPSBpbnN0YW5jZTtcbiAgICAgICAgcmV0dXJuIG5ld1N0b3JlO1xuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7XG59XG5mdW5jdGlvbiBpc0V2ZW50RGVmc0dyb3VwZWQoZGVmMCwgZGVmMSkge1xuICAgIHJldHVybiBCb29sZWFuKGRlZjAuZ3JvdXBJZCAmJiBkZWYwLmdyb3VwSWQgPT09IGRlZjEuZ3JvdXBJZCk7XG59XG5mdW5jdGlvbiB0cmFuc2Zvcm1SYXdFdmVudHMocmF3RXZlbnRzLCBldmVudFNvdXJjZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgY2FsRWFjaFRyYW5zZm9ybSA9IGNhbGVuZGFyLm9wdCgnZXZlbnREYXRhVHJhbnNmb3JtJyk7XG4gICAgdmFyIHNvdXJjZUVhY2hUcmFuc2Zvcm0gPSBldmVudFNvdXJjZSA/IGV2ZW50U291cmNlLmV2ZW50RGF0YVRyYW5zZm9ybSA6IG51bGw7XG4gICAgaWYgKHNvdXJjZUVhY2hUcmFuc2Zvcm0pIHtcbiAgICAgICAgcmF3RXZlbnRzID0gdHJhbnNmb3JtRWFjaFJhd0V2ZW50KHJhd0V2ZW50cywgc291cmNlRWFjaFRyYW5zZm9ybSk7XG4gICAgfVxuICAgIGlmIChjYWxFYWNoVHJhbnNmb3JtKSB7XG4gICAgICAgIHJhd0V2ZW50cyA9IHRyYW5zZm9ybUVhY2hSYXdFdmVudChyYXdFdmVudHMsIGNhbEVhY2hUcmFuc2Zvcm0pO1xuICAgIH1cbiAgICByZXR1cm4gcmF3RXZlbnRzO1xufVxuZnVuY3Rpb24gdHJhbnNmb3JtRWFjaFJhd0V2ZW50KHJhd0V2ZW50cywgZnVuYykge1xuICAgIHZhciByZWZpbmVkRXZlbnRzO1xuICAgIGlmICghZnVuYykge1xuICAgICAgICByZWZpbmVkRXZlbnRzID0gcmF3RXZlbnRzO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmVmaW5lZEV2ZW50cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHJhd0V2ZW50c18yID0gcmF3RXZlbnRzOyBfaSA8IHJhd0V2ZW50c18yLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHJhd0V2ZW50ID0gcmF3RXZlbnRzXzJbX2ldO1xuICAgICAgICAgICAgdmFyIHJlZmluZWRFdmVudCA9IGZ1bmMocmF3RXZlbnQpO1xuICAgICAgICAgICAgaWYgKHJlZmluZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHJlZmluZWRFdmVudHMucHVzaChyZWZpbmVkRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocmVmaW5lZEV2ZW50ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZWZpbmVkRXZlbnRzLnB1c2gocmF3RXZlbnQpO1xuICAgICAgICAgICAgfSAvLyBpZiBhIGRpZmZlcmVudCBmYWxzeSB2YWx1ZSwgZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWZpbmVkRXZlbnRzO1xufVxuZnVuY3Rpb24gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCkge1xuICAgIHJldHVybiB7IGRlZnM6IHt9LCBpbnN0YW5jZXM6IHt9IH07XG59XG5mdW5jdGlvbiBtZXJnZUV2ZW50U3RvcmVzKHN0b3JlMCwgc3RvcmUxKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGVmczogX19hc3NpZ24oe30sIHN0b3JlMC5kZWZzLCBzdG9yZTEuZGVmcyksXG4gICAgICAgIGluc3RhbmNlczogX19hc3NpZ24oe30sIHN0b3JlMC5pbnN0YW5jZXMsIHN0b3JlMS5pbnN0YW5jZXMpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGZpbHRlckV2ZW50U3RvcmVEZWZzKGV2ZW50U3RvcmUsIGZpbHRlckZ1bmMpIHtcbiAgICB2YXIgZGVmcyA9IGZpbHRlckhhc2goZXZlbnRTdG9yZS5kZWZzLCBmaWx0ZXJGdW5jKTtcbiAgICB2YXIgaW5zdGFuY2VzID0gZmlsdGVySGFzaChldmVudFN0b3JlLmluc3RhbmNlcywgZnVuY3Rpb24gKGluc3RhbmNlKSB7XG4gICAgICAgIHJldHVybiBkZWZzW2luc3RhbmNlLmRlZklkXTsgLy8gc3RpbGwgZXhpc3RzP1xuICAgIH0pO1xuICAgIHJldHVybiB7IGRlZnM6IGRlZnMsIGluc3RhbmNlczogaW5zdGFuY2VzIH07XG59XG5cbmZ1bmN0aW9uIHBhcnNlUmFuZ2UoaW5wdXQsIGRhdGVFbnYpIHtcbiAgICB2YXIgc3RhcnQgPSBudWxsO1xuICAgIHZhciBlbmQgPSBudWxsO1xuICAgIGlmIChpbnB1dC5zdGFydCkge1xuICAgICAgICBzdGFydCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKGlucHV0LnN0YXJ0KTtcbiAgICB9XG4gICAgaWYgKGlucHV0LmVuZCkge1xuICAgICAgICBlbmQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihpbnB1dC5lbmQpO1xuICAgIH1cbiAgICBpZiAoIXN0YXJ0ICYmICFlbmQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChzdGFydCAmJiBlbmQgJiYgZW5kIDwgc3RhcnQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfTtcbn1cbi8vIFNJREUtRUZGRUNUOiB3aWxsIG11dGF0ZSByYW5nZXMuXG4vLyBXaWxsIHJldHVybiBhIG5ldyBhcnJheSByZXN1bHQuXG5mdW5jdGlvbiBpbnZlcnRSYW5nZXMocmFuZ2VzLCBjb25zdHJhaW50UmFuZ2UpIHtcbiAgICB2YXIgaW52ZXJ0ZWRSYW5nZXMgPSBbXTtcbiAgICB2YXIgc3RhcnQgPSBjb25zdHJhaW50UmFuZ2Uuc3RhcnQ7IC8vIHRoZSBlbmQgb2YgdGhlIHByZXZpb3VzIHJhbmdlLiB0aGUgc3RhcnQgb2YgdGhlIG5ldyByYW5nZVxuICAgIHZhciBpO1xuICAgIHZhciBkYXRlUmFuZ2U7XG4gICAgLy8gcmFuZ2VzIG5lZWQgdG8gYmUgaW4gb3JkZXIuIHJlcXVpcmVkIGZvciBvdXIgZGF0ZS13YWxraW5nIGFsZ29yaXRobVxuICAgIHJhbmdlcy5zb3J0KGNvbXBhcmVSYW5nZXMpO1xuICAgIGZvciAoaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGF0ZVJhbmdlID0gcmFuZ2VzW2ldO1xuICAgICAgICAvLyBhZGQgdGhlIHNwYW4gb2YgdGltZSBiZWZvcmUgdGhlIGV2ZW50IChpZiB0aGVyZSBpcyBhbnkpXG4gICAgICAgIGlmIChkYXRlUmFuZ2Uuc3RhcnQgPiBzdGFydCkgeyAvLyBjb21wYXJlIG1pbGxpc2Vjb25kIHRpbWUgKHNraXAgYW55IGFtYmlnIGxvZ2ljKVxuICAgICAgICAgICAgaW52ZXJ0ZWRSYW5nZXMucHVzaCh7IHN0YXJ0OiBzdGFydCwgZW5kOiBkYXRlUmFuZ2Uuc3RhcnQgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGVSYW5nZS5lbmQgPiBzdGFydCkge1xuICAgICAgICAgICAgc3RhcnQgPSBkYXRlUmFuZ2UuZW5kO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGFkZCB0aGUgc3BhbiBvZiB0aW1lIGFmdGVyIHRoZSBsYXN0IGV2ZW50IChpZiB0aGVyZSBpcyBhbnkpXG4gICAgaWYgKHN0YXJ0IDwgY29uc3RyYWludFJhbmdlLmVuZCkgeyAvLyBjb21wYXJlIG1pbGxpc2Vjb25kIHRpbWUgKHNraXAgYW55IGFtYmlnIGxvZ2ljKVxuICAgICAgICBpbnZlcnRlZFJhbmdlcy5wdXNoKHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGNvbnN0cmFpbnRSYW5nZS5lbmQgfSk7XG4gICAgfVxuICAgIHJldHVybiBpbnZlcnRlZFJhbmdlcztcbn1cbmZ1bmN0aW9uIGNvbXBhcmVSYW5nZXMocmFuZ2UwLCByYW5nZTEpIHtcbiAgICByZXR1cm4gcmFuZ2UwLnN0YXJ0LnZhbHVlT2YoKSAtIHJhbmdlMS5zdGFydC52YWx1ZU9mKCk7IC8vIGVhcmxpZXIgcmFuZ2VzIGdvIGZpcnN0XG59XG5mdW5jdGlvbiBpbnRlcnNlY3RSYW5nZXMocmFuZ2UwLCByYW5nZTEpIHtcbiAgICB2YXIgc3RhcnQgPSByYW5nZTAuc3RhcnQ7XG4gICAgdmFyIGVuZCA9IHJhbmdlMC5lbmQ7XG4gICAgdmFyIG5ld1JhbmdlID0gbnVsbDtcbiAgICBpZiAocmFuZ2UxLnN0YXJ0ICE9PSBudWxsKSB7XG4gICAgICAgIGlmIChzdGFydCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgc3RhcnQgPSByYW5nZTEuc3RhcnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzdGFydCA9IG5ldyBEYXRlKE1hdGgubWF4KHN0YXJ0LnZhbHVlT2YoKSwgcmFuZ2UxLnN0YXJ0LnZhbHVlT2YoKSkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChyYW5nZTEuZW5kICE9IG51bGwpIHtcbiAgICAgICAgaWYgKGVuZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZW5kID0gcmFuZ2UxLmVuZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGVuZCA9IG5ldyBEYXRlKE1hdGgubWluKGVuZC52YWx1ZU9mKCksIHJhbmdlMS5lbmQudmFsdWVPZigpKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHN0YXJ0ID09PSBudWxsIHx8IGVuZCA9PT0gbnVsbCB8fCBzdGFydCA8IGVuZCkge1xuICAgICAgICBuZXdSYW5nZSA9IHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgIH1cbiAgICByZXR1cm4gbmV3UmFuZ2U7XG59XG5mdW5jdGlvbiByYW5nZXNFcXVhbChyYW5nZTAsIHJhbmdlMSkge1xuICAgIHJldHVybiAocmFuZ2UwLnN0YXJ0ID09PSBudWxsID8gbnVsbCA6IHJhbmdlMC5zdGFydC52YWx1ZU9mKCkpID09PSAocmFuZ2UxLnN0YXJ0ID09PSBudWxsID8gbnVsbCA6IHJhbmdlMS5zdGFydC52YWx1ZU9mKCkpICYmXG4gICAgICAgIChyYW5nZTAuZW5kID09PSBudWxsID8gbnVsbCA6IHJhbmdlMC5lbmQudmFsdWVPZigpKSA9PT0gKHJhbmdlMS5lbmQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UxLmVuZC52YWx1ZU9mKCkpO1xufVxuZnVuY3Rpb24gcmFuZ2VzSW50ZXJzZWN0KHJhbmdlMCwgcmFuZ2UxKSB7XG4gICAgcmV0dXJuIChyYW5nZTAuZW5kID09PSBudWxsIHx8IHJhbmdlMS5zdGFydCA9PT0gbnVsbCB8fCByYW5nZTAuZW5kID4gcmFuZ2UxLnN0YXJ0KSAmJlxuICAgICAgICAocmFuZ2UwLnN0YXJ0ID09PSBudWxsIHx8IHJhbmdlMS5lbmQgPT09IG51bGwgfHwgcmFuZ2UwLnN0YXJ0IDwgcmFuZ2UxLmVuZCk7XG59XG5mdW5jdGlvbiByYW5nZUNvbnRhaW5zUmFuZ2Uob3V0ZXJSYW5nZSwgaW5uZXJSYW5nZSkge1xuICAgIHJldHVybiAob3V0ZXJSYW5nZS5zdGFydCA9PT0gbnVsbCB8fCAoaW5uZXJSYW5nZS5zdGFydCAhPT0gbnVsbCAmJiBpbm5lclJhbmdlLnN0YXJ0ID49IG91dGVyUmFuZ2Uuc3RhcnQpKSAmJlxuICAgICAgICAob3V0ZXJSYW5nZS5lbmQgPT09IG51bGwgfHwgKGlubmVyUmFuZ2UuZW5kICE9PSBudWxsICYmIGlubmVyUmFuZ2UuZW5kIDw9IG91dGVyUmFuZ2UuZW5kKSk7XG59XG5mdW5jdGlvbiByYW5nZUNvbnRhaW5zTWFya2VyKHJhbmdlLCBkYXRlKSB7XG4gICAgcmV0dXJuIChyYW5nZS5zdGFydCA9PT0gbnVsbCB8fCBkYXRlID49IHJhbmdlLnN0YXJ0KSAmJlxuICAgICAgICAocmFuZ2UuZW5kID09PSBudWxsIHx8IGRhdGUgPCByYW5nZS5lbmQpO1xufVxuLy8gSWYgdGhlIGdpdmVuIGRhdGUgaXMgbm90IHdpdGhpbiB0aGUgZ2l2ZW4gcmFuZ2UsIG1vdmUgaXQgaW5zaWRlLlxuLy8gKElmIGl0J3MgcGFzdCB0aGUgZW5kLCBtYWtlIGl0IG9uZSBtaWxsaXNlY29uZCBiZWZvcmUgdGhlIGVuZCkuXG5mdW5jdGlvbiBjb25zdHJhaW5NYXJrZXJUb1JhbmdlKGRhdGUsIHJhbmdlKSB7XG4gICAgaWYgKHJhbmdlLnN0YXJ0ICE9IG51bGwgJiYgZGF0ZSA8IHJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIHJldHVybiByYW5nZS5zdGFydDtcbiAgICB9XG4gICAgaWYgKHJhbmdlLmVuZCAhPSBudWxsICYmIGRhdGUgPj0gcmFuZ2UuZW5kKSB7XG4gICAgICAgIHJldHVybiBuZXcgRGF0ZShyYW5nZS5lbmQudmFsdWVPZigpIC0gMSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlO1xufVxuXG5mdW5jdGlvbiByZW1vdmVFeGFjdChhcnJheSwgZXhhY3RWYWwpIHtcbiAgICB2YXIgcmVtb3ZlQ250ID0gMDtcbiAgICB2YXIgaSA9IDA7XG4gICAgd2hpbGUgKGkgPCBhcnJheS5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGFycmF5W2ldID09PSBleGFjdFZhbCkge1xuICAgICAgICAgICAgYXJyYXkuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgcmVtb3ZlQ250Kys7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpKys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlbW92ZUNudDtcbn1cbmZ1bmN0aW9uIGlzQXJyYXlzRXF1YWwoYTAsIGExKSB7XG4gICAgdmFyIGxlbiA9IGEwLmxlbmd0aDtcbiAgICB2YXIgaTtcbiAgICBpZiAobGVuICE9PSBhMS5sZW5ndGgpIHsgLy8gbm90IGFycmF5PyBvciBub3Qgc2FtZSBsZW5ndGg/XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmIChhMFtpXSAhPT0gYTFbaV0pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gbWVtb2l6ZSh3b3JrZXJGdW5jKSB7XG4gICAgdmFyIGFyZ3M7XG4gICAgdmFyIHJlcztcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWFyZ3MgfHwgIWlzQXJyYXlzRXF1YWwoYXJncywgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgIHJlcyA9IHdvcmtlckZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG59XG4vKlxuYWx3YXlzIGV4ZWN1dGVzIHRoZSB3b3JrZXJGdW5jLCBidXQgaWYgdGhlIHJlc3VsdCBpcyBlcXVhbCB0byB0aGUgcHJldmlvdXMgcmVzdWx0LFxucmV0dXJuIHRoZSBwcmV2aW91cyByZXN1bHQgaW5zdGVhZC5cbiovXG5mdW5jdGlvbiBtZW1vaXplT3V0cHV0KHdvcmtlckZ1bmMsIGVxdWFsaXR5RnVuYykge1xuICAgIHZhciBjYWNoZWRSZXMgPSBudWxsO1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBuZXdSZXMgPSB3b3JrZXJGdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIGlmIChjYWNoZWRSZXMgPT09IG51bGwgfHwgIShjYWNoZWRSZXMgPT09IG5ld1JlcyB8fCBlcXVhbGl0eUZ1bmMoY2FjaGVkUmVzLCBuZXdSZXMpKSkge1xuICAgICAgICAgICAgY2FjaGVkUmVzID0gbmV3UmVzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjYWNoZWRSZXM7XG4gICAgfTtcbn1cblxudmFyIEVYVEVOREVEX1NFVFRJTkdTX0FORF9TRVZFUklUSUVTID0ge1xuICAgIHdlZWs6IDMsXG4gICAgc2VwYXJhdG9yOiAwLFxuICAgIG9taXRaZXJvTWludXRlOiAwLFxuICAgIG1lcmlkaWVtOiAwLFxuICAgIG9taXRDb21tYXM6IDBcbn07XG52YXIgU1RBTkRBUkRfREFURV9QUk9QX1NFVkVSSVRJRVMgPSB7XG4gICAgdGltZVpvbmVOYW1lOiA3LFxuICAgIGVyYTogNixcbiAgICB5ZWFyOiA1LFxuICAgIG1vbnRoOiA0LFxuICAgIGRheTogMixcbiAgICB3ZWVrZGF5OiAyLFxuICAgIGhvdXI6IDEsXG4gICAgbWludXRlOiAxLFxuICAgIHNlY29uZDogMVxufTtcbnZhciBNRVJJRElFTV9SRSA9IC9cXHMqKFthcF0pXFwuP21cXC4/L2k7IC8vIGVhdHMgdXAgbGVhZGluZyBzcGFjZXMgdG9vXG52YXIgQ09NTUFfUkUgPSAvLC9nOyAvLyB3ZSBuZWVkIHJlIGZvciBnbG9iYWxuZXNzXG52YXIgTVVMVElfU1BBQ0VfUkUgPSAvXFxzKy9nO1xudmFyIExUUl9SRSA9IC9cXHUyMDBlL2c7IC8vIGNvbnRyb2wgY2hhcmFjdGVyXG52YXIgVVRDX1JFID0gL1VUQ3xHTVQvO1xudmFyIE5hdGl2ZUZvcm1hdHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBOYXRpdmVGb3JtYXR0ZXIoZm9ybWF0U2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIHN0YW5kYXJkRGF0ZVByb3BzID0ge307XG4gICAgICAgIHZhciBleHRlbmRlZFNldHRpbmdzID0ge307XG4gICAgICAgIHZhciBzZXZlcml0eSA9IDA7XG4gICAgICAgIGZvciAodmFyIG5hbWVfMSBpbiBmb3JtYXRTZXR0aW5ncykge1xuICAgICAgICAgICAgaWYgKG5hbWVfMSBpbiBFWFRFTkRFRF9TRVRUSU5HU19BTkRfU0VWRVJJVElFUykge1xuICAgICAgICAgICAgICAgIGV4dGVuZGVkU2V0dGluZ3NbbmFtZV8xXSA9IGZvcm1hdFNldHRpbmdzW25hbWVfMV07XG4gICAgICAgICAgICAgICAgc2V2ZXJpdHkgPSBNYXRoLm1heChFWFRFTkRFRF9TRVRUSU5HU19BTkRfU0VWRVJJVElFU1tuYW1lXzFdLCBzZXZlcml0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wc1tuYW1lXzFdID0gZm9ybWF0U2V0dGluZ3NbbmFtZV8xXTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZV8xIGluIFNUQU5EQVJEX0RBVEVfUFJPUF9TRVZFUklUSUVTKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldmVyaXR5ID0gTWF0aC5tYXgoU1RBTkRBUkRfREFURV9QUk9QX1NFVkVSSVRJRVNbbmFtZV8xXSwgc2V2ZXJpdHkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YW5kYXJkRGF0ZVByb3BzID0gc3RhbmRhcmREYXRlUHJvcHM7XG4gICAgICAgIHRoaXMuZXh0ZW5kZWRTZXR0aW5ncyA9IGV4dGVuZGVkU2V0dGluZ3M7XG4gICAgICAgIHRoaXMuc2V2ZXJpdHkgPSBzZXZlcml0eTtcbiAgICAgICAgdGhpcy5idWlsZEZvcm1hdHRpbmdGdW5jID0gbWVtb2l6ZShidWlsZEZvcm1hdHRpbmdGdW5jKTtcbiAgICB9XG4gICAgTmF0aXZlRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAoZGF0ZSwgY29udGV4dCkge1xuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEZvcm1hdHRpbmdGdW5jKHRoaXMuc3RhbmRhcmREYXRlUHJvcHMsIHRoaXMuZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCkoZGF0ZSk7XG4gICAgfTtcbiAgICBOYXRpdmVGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgc3RhbmRhcmREYXRlUHJvcHMgPSBfYS5zdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncyA9IF9hLmV4dGVuZGVkU2V0dGluZ3M7XG4gICAgICAgIHZhciBkaWZmU2V2ZXJpdHkgPSBjb21wdXRlTWFya2VyRGlmZlNldmVyaXR5KHN0YXJ0Lm1hcmtlciwgZW5kLm1hcmtlciwgY29udGV4dC5jYWxlbmRhclN5c3RlbSk7XG4gICAgICAgIGlmICghZGlmZlNldmVyaXR5KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXQoc3RhcnQsIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBiaWdnZXN0VW5pdEZvclBhcnRpYWwgPSBkaWZmU2V2ZXJpdHk7XG4gICAgICAgIGlmIChiaWdnZXN0VW5pdEZvclBhcnRpYWwgPiAxICYmIC8vIHRoZSB0d28gZGF0ZXMgYXJlIGRpZmZlcmVudCBpbiBhIHdheSB0aGF0J3MgbGFyZ2VyIHNjYWxlIHRoYW4gdGltZVxuICAgICAgICAgICAgKHN0YW5kYXJkRGF0ZVByb3BzLnllYXIgPT09ICdudW1lcmljJyB8fCBzdGFuZGFyZERhdGVQcm9wcy55ZWFyID09PSAnMi1kaWdpdCcpICYmXG4gICAgICAgICAgICAoc3RhbmRhcmREYXRlUHJvcHMubW9udGggPT09ICdudW1lcmljJyB8fCBzdGFuZGFyZERhdGVQcm9wcy5tb250aCA9PT0gJzItZGlnaXQnKSAmJlxuICAgICAgICAgICAgKHN0YW5kYXJkRGF0ZVByb3BzLmRheSA9PT0gJ251bWVyaWMnIHx8IHN0YW5kYXJkRGF0ZVByb3BzLmRheSA9PT0gJzItZGlnaXQnKSkge1xuICAgICAgICAgICAgYmlnZ2VzdFVuaXRGb3JQYXJ0aWFsID0gMTsgLy8gbWFrZSBpdCBsb29rIGxpa2UgdGhlIGRhdGVzIGFyZSBvbmx5IGRpZmZlcmVudCBpbiB0ZXJtcyBvZiB0aW1lXG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZ1bGwwID0gdGhpcy5mb3JtYXQoc3RhcnQsIGNvbnRleHQpO1xuICAgICAgICB2YXIgZnVsbDEgPSB0aGlzLmZvcm1hdChlbmQsIGNvbnRleHQpO1xuICAgICAgICBpZiAoZnVsbDAgPT09IGZ1bGwxKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVsbDA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcnRpYWxEYXRlUHJvcHMgPSBjb21wdXRlUGFydGlhbEZvcm1hdHRpbmdPcHRpb25zKHN0YW5kYXJkRGF0ZVByb3BzLCBiaWdnZXN0VW5pdEZvclBhcnRpYWwpO1xuICAgICAgICB2YXIgcGFydGlhbEZvcm1hdHRpbmdGdW5jID0gYnVpbGRGb3JtYXR0aW5nRnVuYyhwYXJ0aWFsRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KTtcbiAgICAgICAgdmFyIHBhcnRpYWwwID0gcGFydGlhbEZvcm1hdHRpbmdGdW5jKHN0YXJ0KTtcbiAgICAgICAgdmFyIHBhcnRpYWwxID0gcGFydGlhbEZvcm1hdHRpbmdGdW5jKGVuZCk7XG4gICAgICAgIHZhciBpbnNlcnRpb24gPSBmaW5kQ29tbW9uSW5zZXJ0aW9uKGZ1bGwwLCBwYXJ0aWFsMCwgZnVsbDEsIHBhcnRpYWwxKTtcbiAgICAgICAgdmFyIHNlcGFyYXRvciA9IGV4dGVuZGVkU2V0dGluZ3Muc2VwYXJhdG9yIHx8ICcnO1xuICAgICAgICBpZiAoaW5zZXJ0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5zZXJ0aW9uLmJlZm9yZSArIHBhcnRpYWwwICsgc2VwYXJhdG9yICsgcGFydGlhbDEgKyBpbnNlcnRpb24uYWZ0ZXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bGwwICsgc2VwYXJhdG9yICsgZnVsbDE7XG4gICAgfTtcbiAgICBOYXRpdmVGb3JtYXR0ZXIucHJvdG90eXBlLmdldExhcmdlc3RVbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBzd2l0Y2ggKHRoaXMuc2V2ZXJpdHkpIHtcbiAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3llYXInO1xuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIHJldHVybiAnbW9udGgnO1xuICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIHJldHVybiAnd2Vlayc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiAnZGF5JztcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIE5hdGl2ZUZvcm1hdHRlcjtcbn0oKSk7XG5mdW5jdGlvbiBidWlsZEZvcm1hdHRpbmdGdW5jKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgdmFyIHN0YW5kYXJkRGF0ZVByb3BDbnQgPSBPYmplY3Qua2V5cyhzdGFuZGFyZERhdGVQcm9wcykubGVuZ3RoO1xuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wQ250ID09PSAxICYmIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9PT0gJ3Nob3J0Jykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRUaW1lWm9uZU9mZnNldChkYXRlLnRpbWVab25lT2Zmc2V0KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BDbnQgPT09IDAgJiYgZXh0ZW5kZWRTZXR0aW5ncy53ZWVrKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdFdlZWtOdW1iZXIoY29udGV4dC5jb21wdXRlV2Vla051bWJlcihkYXRlLm1hcmtlciksIGNvbnRleHQud2Vla0xhYmVsLCBjb250ZXh0LmxvY2FsZSwgZXh0ZW5kZWRTZXR0aW5ncy53ZWVrKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1aWxkTmF0aXZlRm9ybWF0dGluZ0Z1bmMoc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpO1xufVxuZnVuY3Rpb24gYnVpbGROYXRpdmVGb3JtYXR0aW5nRnVuYyhzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCkge1xuICAgIHN0YW5kYXJkRGF0ZVByb3BzID0gX19hc3NpZ24oe30sIHN0YW5kYXJkRGF0ZVByb3BzKTsgLy8gY29weVxuICAgIGV4dGVuZGVkU2V0dGluZ3MgPSBfX2Fzc2lnbih7fSwgZXh0ZW5kZWRTZXR0aW5ncyk7IC8vIGNvcHlcbiAgICBzYW5pdGl6ZVNldHRpbmdzKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzKTtcbiAgICBzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZSA9ICdVVEMnOyAvLyB3ZSBsZXZlcmFnZSB0aGUgb25seSBndWFyYW50ZWVkIHRpbWVab25lIGZvciBvdXIgVVRDIG1hcmtlcnNcbiAgICB2YXIgbm9ybWFsRm9ybWF0ID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoY29udGV4dC5sb2NhbGUuY29kZXMsIHN0YW5kYXJkRGF0ZVByb3BzKTtcbiAgICB2YXIgemVyb0Zvcm1hdDsgLy8gbmVlZGVkP1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlKSB7XG4gICAgICAgIHZhciB6ZXJvUHJvcHMgPSBfX2Fzc2lnbih7fSwgc3RhbmRhcmREYXRlUHJvcHMpO1xuICAgICAgICBkZWxldGUgemVyb1Byb3BzLm1pbnV0ZTsgLy8gc2Vjb25kcyBhbmQgbXMgd2VyZSBhbHJlYWR5IGNvbnNpZGVyZWQgaW4gc2FuaXRpemVTZXR0aW5nc1xuICAgICAgICB6ZXJvRm9ybWF0ID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoY29udGV4dC5sb2NhbGUuY29kZXMsIHplcm9Qcm9wcyk7XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB2YXIgbWFya2VyID0gZGF0ZS5tYXJrZXI7XG4gICAgICAgIHZhciBmb3JtYXQ7XG4gICAgICAgIGlmICh6ZXJvRm9ybWF0ICYmICFtYXJrZXIuZ2V0VVRDTWludXRlcygpKSB7XG4gICAgICAgICAgICBmb3JtYXQgPSB6ZXJvRm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm9ybWF0ID0gbm9ybWFsRm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIHZhciBzID0gZm9ybWF0LmZvcm1hdChtYXJrZXIpO1xuICAgICAgICByZXR1cm4gcG9zdFByb2Nlc3MocywgZGF0ZSwgc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpO1xuICAgIH07XG59XG5mdW5jdGlvbiBzYW5pdGl6ZVNldHRpbmdzKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzKSB7XG4gICAgLy8gZGVhbCB3aXRoIGEgYnJvd3NlciBpbmNvbnNpc3RlbmN5IHdoZXJlIGZvcm1hdHRpbmcgdGhlIHRpbWV6b25lXG4gICAgLy8gcmVxdWlyZXMgdGhhdCB0aGUgaG91ci9taW51dGUgYmUgcHJlc2VudC5cbiAgICBpZiAoc3RhbmRhcmREYXRlUHJvcHMudGltZVpvbmVOYW1lKSB7XG4gICAgICAgIGlmICghc3RhbmRhcmREYXRlUHJvcHMuaG91cikge1xuICAgICAgICAgICAgc3RhbmRhcmREYXRlUHJvcHMuaG91ciA9ICcyLWRpZ2l0JztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0YW5kYXJkRGF0ZVByb3BzLm1pbnV0ZSkge1xuICAgICAgICAgICAgc3RhbmRhcmREYXRlUHJvcHMubWludXRlID0gJzItZGlnaXQnO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIG9ubHkgc3VwcG9ydCBzaG9ydCB0aW1lem9uZSBuYW1lc1xuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZU5hbWUgPT09ICdsb25nJykge1xuICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZU5hbWUgPSAnc2hvcnQnO1xuICAgIH1cbiAgICAvLyBpZiByZXF1ZXN0aW5nIHRvIGRpc3BsYXkgc2Vjb25kcywgTVVTVCBkaXNwbGF5IG1pbnV0ZXNcbiAgICBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5vbWl0WmVyb01pbnV0ZSAmJiAoc3RhbmRhcmREYXRlUHJvcHMuc2Vjb25kIHx8IHN0YW5kYXJkRGF0ZVByb3BzLm1pbGxpc2Vjb25kKSkge1xuICAgICAgICBkZWxldGUgZXh0ZW5kZWRTZXR0aW5ncy5vbWl0WmVyb01pbnV0ZTtcbiAgICB9XG59XG5mdW5jdGlvbiBwb3N0UHJvY2VzcyhzLCBkYXRlLCBzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCkge1xuICAgIHMgPSBzLnJlcGxhY2UoTFRSX1JFLCAnJyk7IC8vIHJlbW92ZSBsZWZ0LXRvLXJpZ2h0IGNvbnRyb2wgY2hhcnMuIGRvIGZpcnN0LiBnb29kIGZvciBvdGhlciByZWdleGVzXG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9PT0gJ3Nob3J0Jykge1xuICAgICAgICBzID0gaW5qZWN0VHpvU3RyKHMsIChjb250ZXh0LnRpbWVab25lID09PSAnVVRDJyB8fCBkYXRlLnRpbWVab25lT2Zmc2V0ID09IG51bGwpID9cbiAgICAgICAgICAgICdVVEMnIDogLy8gaW1wb3J0YW50IHRvIG5vcm1hbGl6ZSBmb3IgSUUsIHdoaWNoIGRvZXMgXCJHTVRcIlxuICAgICAgICAgICAgZm9ybWF0VGltZVpvbmVPZmZzZXQoZGF0ZS50aW1lWm9uZU9mZnNldCkpO1xuICAgIH1cbiAgICBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5vbWl0Q29tbWFzKSB7XG4gICAgICAgIHMgPSBzLnJlcGxhY2UoQ09NTUFfUkUsICcnKS50cmltKCk7XG4gICAgfVxuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlKSB7XG4gICAgICAgIHMgPSBzLnJlcGxhY2UoJzowMCcsICcnKTsgLy8gemVyb0Zvcm1hdCBkb2Vzbid0IGFsd2F5cyBhY2hpZXZlIHRoaXNcbiAgICB9XG4gICAgLy8gXiBkbyBhbnl0aGluZyB0aGF0IG1pZ2h0IGNyZWF0ZSBhZGphY2VudCBzcGFjZXMgYmVmb3JlIHRoaXMgcG9pbnQsXG4gICAgLy8gYmVjYXVzZSBNRVJJRElFTV9SRSBsaWtlcyB0byBlYXQgdXAgbG9hZGluZyBzcGFjZXNcbiAgICBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5tZXJpZGllbSA9PT0gZmFsc2UpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgJycpLnRyaW0oKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5tZXJpZGllbSA9PT0gJ25hcnJvdycpIHsgLy8gYS9wXG4gICAgICAgIHMgPSBzLnJlcGxhY2UoTUVSSURJRU1fUkUsIGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgICAgIHJldHVybiBtMS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5tZXJpZGllbSA9PT0gJ3Nob3J0JykgeyAvLyBhbS9wbVxuICAgICAgICBzID0gcy5yZXBsYWNlKE1FUklESUVNX1JFLCBmdW5jdGlvbiAobTAsIG0xKSB7XG4gICAgICAgICAgICByZXR1cm4gbTEudG9Mb2NhbGVMb3dlckNhc2UoKSArICdtJztcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGV4dGVuZGVkU2V0dGluZ3MubWVyaWRpZW0gPT09ICdsb3dlcmNhc2UnKSB7IC8vIG90aGVyIG1lcmlkaWVtIHRyYW5zZm9ybWVycyBhbHJlYWR5IGNvbnZlcnRlZCB0byBsb3dlcmNhc2VcbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgZnVuY3Rpb24gKG0wKSB7XG4gICAgICAgICAgICByZXR1cm4gbTAudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHMgPSBzLnJlcGxhY2UoTVVMVElfU1BBQ0VfUkUsICcgJyk7XG4gICAgcyA9IHMudHJpbSgpO1xuICAgIHJldHVybiBzO1xufVxuZnVuY3Rpb24gaW5qZWN0VHpvU3RyKHMsIHR6b1N0cikge1xuICAgIHZhciByZXBsYWNlZCA9IGZhbHNlO1xuICAgIHMgPSBzLnJlcGxhY2UoVVRDX1JFLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHR6b1N0cjtcbiAgICB9KTtcbiAgICAvLyBJRTExIGRvZXNuJ3QgaW5jbHVkZSBVVEMvR01UIGluIHRoZSBvcmlnaW5hbCBzdHJpbmcsIHNvIGFwcGVuZCB0byBlbmRcbiAgICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgICAgIHMgKz0gJyAnICsgdHpvU3RyO1xuICAgIH1cbiAgICByZXR1cm4gcztcbn1cbmZ1bmN0aW9uIGZvcm1hdFdlZWtOdW1iZXIobnVtLCB3ZWVrTGFiZWwsIGxvY2FsZSwgZGlzcGxheSkge1xuICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgIGlmIChkaXNwbGF5ID09PSAnbmFycm93Jykge1xuICAgICAgICBwYXJ0cy5wdXNoKHdlZWtMYWJlbCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGRpc3BsYXkgPT09ICdzaG9ydCcpIHtcbiAgICAgICAgcGFydHMucHVzaCh3ZWVrTGFiZWwsICcgJyk7XG4gICAgfVxuICAgIC8vIG90aGVyd2lzZSwgY29uc2lkZXJlZCAnbnVtZXJpYydcbiAgICBwYXJ0cy5wdXNoKGxvY2FsZS5zaW1wbGVOdW1iZXJGb3JtYXQuZm9ybWF0KG51bSkpO1xuICAgIGlmIChsb2NhbGUub3B0aW9ucy5pc1J0bCkgeyAvLyBUT0RPOiB1c2UgY29udHJvbCBjaGFyYWN0ZXJzIGluc3RlYWQ/XG4gICAgICAgIHBhcnRzLnJldmVyc2UoKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnRzLmpvaW4oJycpO1xufVxuLy8gUmFuZ2UgRm9ybWF0dGluZyBVdGlsc1xuLy8gMCA9IGV4YWN0bHkgdGhlIHNhbWVcbi8vIDEgPSBkaWZmZXJlbnQgYnkgdGltZVxuLy8gYW5kIGJpZ2dlclxuZnVuY3Rpb24gY29tcHV0ZU1hcmtlckRpZmZTZXZlcml0eShkMCwgZDEsIGNhKSB7XG4gICAgaWYgKGNhLmdldE1hcmtlclllYXIoZDApICE9PSBjYS5nZXRNYXJrZXJZZWFyKGQxKSkge1xuICAgICAgICByZXR1cm4gNTtcbiAgICB9XG4gICAgaWYgKGNhLmdldE1hcmtlck1vbnRoKGQwKSAhPT0gY2EuZ2V0TWFya2VyTW9udGgoZDEpKSB7XG4gICAgICAgIHJldHVybiA0O1xuICAgIH1cbiAgICBpZiAoY2EuZ2V0TWFya2VyRGF5KGQwKSAhPT0gY2EuZ2V0TWFya2VyRGF5KGQxKSkge1xuICAgICAgICByZXR1cm4gMjtcbiAgICB9XG4gICAgaWYgKHRpbWVBc01zKGQwKSAhPT0gdGltZUFzTXMoZDEpKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVQYXJ0aWFsRm9ybWF0dGluZ09wdGlvbnMob3B0aW9ucywgYmlnZ2VzdFVuaXQpIHtcbiAgICB2YXIgcGFydGlhbE9wdGlvbnMgPSB7fTtcbiAgICBmb3IgKHZhciBuYW1lXzIgaW4gb3B0aW9ucykge1xuICAgICAgICBpZiAoIShuYW1lXzIgaW4gU1RBTkRBUkRfREFURV9QUk9QX1NFVkVSSVRJRVMpIHx8IC8vIG5vdCBhIGRhdGUgcGFydCBwcm9wIChsaWtlIHRpbWVab25lKVxuICAgICAgICAgICAgU1RBTkRBUkRfREFURV9QUk9QX1NFVkVSSVRJRVNbbmFtZV8yXSA8PSBiaWdnZXN0VW5pdCkge1xuICAgICAgICAgICAgcGFydGlhbE9wdGlvbnNbbmFtZV8yXSA9IG9wdGlvbnNbbmFtZV8yXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFydGlhbE9wdGlvbnM7XG59XG5mdW5jdGlvbiBmaW5kQ29tbW9uSW5zZXJ0aW9uKGZ1bGwwLCBwYXJ0aWFsMCwgZnVsbDEsIHBhcnRpYWwxKSB7XG4gICAgdmFyIGkwID0gMDtcbiAgICB3aGlsZSAoaTAgPCBmdWxsMC5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGZvdW5kMCA9IGZ1bGwwLmluZGV4T2YocGFydGlhbDAsIGkwKTtcbiAgICAgICAgaWYgKGZvdW5kMCA9PT0gLTEpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHZhciBiZWZvcmUwID0gZnVsbDAuc3Vic3RyKDAsIGZvdW5kMCk7XG4gICAgICAgIGkwID0gZm91bmQwICsgcGFydGlhbDAubGVuZ3RoO1xuICAgICAgICB2YXIgYWZ0ZXIwID0gZnVsbDAuc3Vic3RyKGkwKTtcbiAgICAgICAgdmFyIGkxID0gMDtcbiAgICAgICAgd2hpbGUgKGkxIDwgZnVsbDEubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgZm91bmQxID0gZnVsbDEuaW5kZXhPZihwYXJ0aWFsMSwgaTEpO1xuICAgICAgICAgICAgaWYgKGZvdW5kMSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBiZWZvcmUxID0gZnVsbDEuc3Vic3RyKDAsIGZvdW5kMSk7XG4gICAgICAgICAgICBpMSA9IGZvdW5kMSArIHBhcnRpYWwxLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBhZnRlcjEgPSBmdWxsMS5zdWJzdHIoaTEpO1xuICAgICAgICAgICAgaWYgKGJlZm9yZTAgPT09IGJlZm9yZTEgJiYgYWZ0ZXIwID09PSBhZnRlcjEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBiZWZvcmU6IGJlZm9yZTAsXG4gICAgICAgICAgICAgICAgICAgIGFmdGVyOiBhZnRlcjBcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG4vKlxuVE9ETzogZml4IHRoZSB0ZXJtaW5vbG9neSBvZiBcImZvcm1hdHRlclwiIHZzIFwiZm9ybWF0dGluZyBmdW5jXCJcbiovXG4vKlxuQXQgdGhlIHRpbWUgb2YgaW5zdGFudGlhdGlvbiwgdGhpcyBvYmplY3QgZG9lcyBub3Qga25vdyB3aGljaCBjbWQtZm9ybWF0dGluZyBzeXN0ZW0gaXQgd2lsbCB1c2UuXG5JdCByZWNlaXZlcyB0aGlzIGF0IHRoZSB0aW1lIG9mIGZvcm1hdHRpbmcsIGFzIGEgc2V0dGluZy5cbiovXG52YXIgQ21kRm9ybWF0dGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENtZEZvcm1hdHRlcihjbWRTdHIsIHNlcGFyYXRvcikge1xuICAgICAgICB0aGlzLmNtZFN0ciA9IGNtZFN0cjtcbiAgICAgICAgdGhpcy5zZXBhcmF0b3IgPSBzZXBhcmF0b3I7XG4gICAgfVxuICAgIENtZEZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24gKGRhdGUsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIGNvbnRleHQuY21kRm9ybWF0dGVyKHRoaXMuY21kU3RyLCBjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhkYXRlLCBudWxsLCBjb250ZXh0LCB0aGlzLnNlcGFyYXRvcikpO1xuICAgIH07XG4gICAgQ21kRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXRSYW5nZSA9IGZ1bmN0aW9uIChzdGFydCwgZW5kLCBjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiBjb250ZXh0LmNtZEZvcm1hdHRlcih0aGlzLmNtZFN0ciwgY3JlYXRlVmVyYm9zZUZvcm1hdHRpbmdBcmcoc3RhcnQsIGVuZCwgY29udGV4dCwgdGhpcy5zZXBhcmF0b3IpKTtcbiAgICB9O1xuICAgIHJldHVybiBDbWRGb3JtYXR0ZXI7XG59KCkpO1xuXG52YXIgRnVuY0Zvcm1hdHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGdW5jRm9ybWF0dGVyKGZ1bmMpIHtcbiAgICAgICAgdGhpcy5mdW5jID0gZnVuYztcbiAgICB9XG4gICAgRnVuY0Zvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24gKGRhdGUsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuYyhjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhkYXRlLCBudWxsLCBjb250ZXh0KSk7XG4gICAgfTtcbiAgICBGdW5jRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXRSYW5nZSA9IGZ1bmN0aW9uIChzdGFydCwgZW5kLCBjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZ1bmMoY3JlYXRlVmVyYm9zZUZvcm1hdHRpbmdBcmcoc3RhcnQsIGVuZCwgY29udGV4dCkpO1xuICAgIH07XG4gICAgcmV0dXJuIEZ1bmNGb3JtYXR0ZXI7XG59KCkpO1xuXG4vLyBGb3JtYXR0ZXIgT2JqZWN0IENyZWF0aW9uXG5mdW5jdGlvbiBjcmVhdGVGb3JtYXR0ZXIoaW5wdXQsIGRlZmF1bHRTZXBhcmF0b3IpIHtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnb2JqZWN0JyAmJiBpbnB1dCkgeyAvLyBub24tbnVsbCBvYmplY3RcbiAgICAgICAgaWYgKHR5cGVvZiBkZWZhdWx0U2VwYXJhdG9yID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaW5wdXQgPSBfX2Fzc2lnbih7IHNlcGFyYXRvcjogZGVmYXVsdFNlcGFyYXRvciB9LCBpbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVGb3JtYXR0ZXIoaW5wdXQpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ21kRm9ybWF0dGVyKGlucHV0LCBkZWZhdWx0U2VwYXJhdG9yKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGlucHV0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgRnVuY0Zvcm1hdHRlcihpbnB1dCk7XG4gICAgfVxufVxuLy8gU3RyaW5nIFV0aWxzXG4vLyB0aW1lWm9uZU9mZnNldCBpcyBpbiBtaW51dGVzXG5mdW5jdGlvbiBidWlsZElzb1N0cmluZyhtYXJrZXIsIHRpbWVab25lT2Zmc2V0LCBzdHJpcFplcm9UaW1lKSB7XG4gICAgaWYgKHN0cmlwWmVyb1RpbWUgPT09IHZvaWQgMCkgeyBzdHJpcFplcm9UaW1lID0gZmFsc2U7IH1cbiAgICB2YXIgcyA9IG1hcmtlci50b0lTT1N0cmluZygpO1xuICAgIHMgPSBzLnJlcGxhY2UoJy4wMDAnLCAnJyk7XG4gICAgaWYgKHN0cmlwWmVyb1RpbWUpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZSgnVDAwOjAwOjAwWicsICcnKTtcbiAgICB9XG4gICAgaWYgKHMubGVuZ3RoID4gMTApIHsgLy8gdGltZSBwYXJ0IHdhc24ndCBzdHJpcHBlZCwgY2FuIGFkZCB0aW1lem9uZSBpbmZvXG4gICAgICAgIGlmICh0aW1lWm9uZU9mZnNldCA9PSBudWxsKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCdaJywgJycpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRpbWVab25lT2Zmc2V0ICE9PSAwKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCdaJywgZm9ybWF0VGltZVpvbmVPZmZzZXQodGltZVpvbmVPZmZzZXQsIHRydWUpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UsIGl0cyBVVEMtMCBhbmQgd2Ugd2FudCB0byBrZWVwIHRoZSBaXG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuZnVuY3Rpb24gZm9ybWF0SXNvVGltZVN0cmluZyhtYXJrZXIpIHtcbiAgICByZXR1cm4gcGFkU3RhcnQobWFya2VyLmdldFVUQ0hvdXJzKCksIDIpICsgJzonICtcbiAgICAgICAgcGFkU3RhcnQobWFya2VyLmdldFVUQ01pbnV0ZXMoKSwgMikgKyAnOicgK1xuICAgICAgICBwYWRTdGFydChtYXJrZXIuZ2V0VVRDU2Vjb25kcygpLCAyKTtcbn1cbmZ1bmN0aW9uIGZvcm1hdFRpbWVab25lT2Zmc2V0KG1pbnV0ZXMsIGRvSXNvKSB7XG4gICAgaWYgKGRvSXNvID09PSB2b2lkIDApIHsgZG9Jc28gPSBmYWxzZTsgfVxuICAgIHZhciBzaWduID0gbWludXRlcyA8IDAgPyAnLScgOiAnKyc7XG4gICAgdmFyIGFicyA9IE1hdGguYWJzKG1pbnV0ZXMpO1xuICAgIHZhciBob3VycyA9IE1hdGguZmxvb3IoYWJzIC8gNjApO1xuICAgIHZhciBtaW5zID0gTWF0aC5yb3VuZChhYnMgJSA2MCk7XG4gICAgaWYgKGRvSXNvKSB7XG4gICAgICAgIHJldHVybiBzaWduICsgcGFkU3RhcnQoaG91cnMsIDIpICsgJzonICsgcGFkU3RhcnQobWlucywgMik7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gJ0dNVCcgKyBzaWduICsgaG91cnMgKyAobWlucyA/ICc6JyArIHBhZFN0YXJ0KG1pbnMsIDIpIDogJycpO1xuICAgIH1cbn1cbi8vIEFyZyBVdGlsc1xuZnVuY3Rpb24gY3JlYXRlVmVyYm9zZUZvcm1hdHRpbmdBcmcoc3RhcnQsIGVuZCwgY29udGV4dCwgc2VwYXJhdG9yKSB7XG4gICAgdmFyIHN0YXJ0SW5mbyA9IGV4cGFuZFpvbmVkTWFya2VyKHN0YXJ0LCBjb250ZXh0LmNhbGVuZGFyU3lzdGVtKTtcbiAgICB2YXIgZW5kSW5mbyA9IGVuZCA/IGV4cGFuZFpvbmVkTWFya2VyKGVuZCwgY29udGV4dC5jYWxlbmRhclN5c3RlbSkgOiBudWxsO1xuICAgIHJldHVybiB7XG4gICAgICAgIGRhdGU6IHN0YXJ0SW5mbyxcbiAgICAgICAgc3RhcnQ6IHN0YXJ0SW5mbyxcbiAgICAgICAgZW5kOiBlbmRJbmZvLFxuICAgICAgICB0aW1lWm9uZTogY29udGV4dC50aW1lWm9uZSxcbiAgICAgICAgbG9jYWxlQ29kZXM6IGNvbnRleHQubG9jYWxlLmNvZGVzLFxuICAgICAgICBzZXBhcmF0b3I6IHNlcGFyYXRvclxuICAgIH07XG59XG5mdW5jdGlvbiBleHBhbmRab25lZE1hcmtlcihkYXRlSW5mbywgY2FsZW5kYXJTeXN0ZW0pIHtcbiAgICB2YXIgYSA9IGNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkoZGF0ZUluZm8ubWFya2VyKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBtYXJrZXI6IGRhdGVJbmZvLm1hcmtlcixcbiAgICAgICAgdGltZVpvbmVPZmZzZXQ6IGRhdGVJbmZvLnRpbWVab25lT2Zmc2V0LFxuICAgICAgICBhcnJheTogYSxcbiAgICAgICAgeWVhcjogYVswXSxcbiAgICAgICAgbW9udGg6IGFbMV0sXG4gICAgICAgIGRheTogYVsyXSxcbiAgICAgICAgaG91cjogYVszXSxcbiAgICAgICAgbWludXRlOiBhWzRdLFxuICAgICAgICBzZWNvbmQ6IGFbNV0sXG4gICAgICAgIG1pbGxpc2Vjb25kOiBhWzZdXG4gICAgfTtcbn1cblxudmFyIEV2ZW50U291cmNlQXBpID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEV2ZW50U291cmNlQXBpKGNhbGVuZGFyLCBpbnRlcm5hbEV2ZW50U291cmNlKSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICAgICAgdGhpcy5pbnRlcm5hbEV2ZW50U291cmNlID0gaW50ZXJuYWxFdmVudFNvdXJjZTtcbiAgICB9XG4gICAgRXZlbnRTb3VyY2VBcGkucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVNT1ZFX0VWRU5UX1NPVVJDRScsXG4gICAgICAgICAgICBzb3VyY2VJZDogdGhpcy5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRXZlbnRTb3VyY2VBcGkucHJvdG90eXBlLnJlZmV0Y2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ0ZFVENIX0VWRU5UX1NPVVJDRVMnLFxuICAgICAgICAgICAgc291cmNlSWRzOiBbdGhpcy5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkXVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudFNvdXJjZUFwaS5wcm90b3R5cGUsIFwiaWRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmludGVybmFsRXZlbnRTb3VyY2UucHVibGljSWQ7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudFNvdXJjZUFwaS5wcm90b3R5cGUsIFwidXJsXCIsIHtcbiAgICAgICAgLy8gb25seSByZWxldmFudCB0byBqc29uLWZlZWQgZXZlbnQgc291cmNlc1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmludGVybmFsRXZlbnRTb3VyY2UubWV0YS51cmw7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIHJldHVybiBFdmVudFNvdXJjZUFwaTtcbn0oKSk7XG5cbnZhciBFdmVudEFwaSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFdmVudEFwaShjYWxlbmRhciwgZGVmLCBpbnN0YW5jZSkge1xuICAgICAgICB0aGlzLl9jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLl9kZWYgPSBkZWY7XG4gICAgICAgIHRoaXMuX2luc3RhbmNlID0gaW5zdGFuY2UgfHwgbnVsbDtcbiAgICB9XG4gICAgLypcbiAgICBUT0RPOiBtYWtlIGV2ZW50IHN0cnVjdCBtb3JlIHJlc3BvbnNpYmxlIGZvciB0aGlzXG4gICAgKi9cbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0UHJvcCA9IGZ1bmN0aW9uIChuYW1lLCB2YWwpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgaWYgKG5hbWUgaW4gREFURV9QUk9QUykgO1xuICAgICAgICBlbHNlIGlmIChuYW1lIGluIE5PTl9EQVRFX1BST1BTKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIE5PTl9EQVRFX1BST1BTW25hbWVdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gTk9OX0RBVEVfUFJPUFNbbmFtZV0odmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFByb3BzOiAoX2EgPSB7fSwgX2FbbmFtZV0gPSB2YWwsIF9hKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobmFtZSBpbiBVTlNDT1BFRF9FVkVOVF9VSV9QUk9QUykge1xuICAgICAgICAgICAgdmFyIHVpID0gdm9pZCAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBVTlNDT1BFRF9FVkVOVF9VSV9QUk9QU1tuYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHZhbCA9IFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTW25hbWVdKHZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobmFtZSA9PT0gJ2NvbG9yJykge1xuICAgICAgICAgICAgICAgIHVpID0geyBiYWNrZ3JvdW5kQ29sb3I6IHZhbCwgYm9yZGVyQ29sb3I6IHZhbCB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobmFtZSA9PT0gJ2VkaXRhYmxlJykge1xuICAgICAgICAgICAgICAgIHVpID0geyBzdGFydEVkaXRhYmxlOiB2YWwsIGR1cmF0aW9uRWRpdGFibGU6IHZhbCB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdWkgPSAoX2IgPSB7fSwgX2JbbmFtZV0gPSB2YWwsIF9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFByb3BzOiB7IHVpOiB1aSB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLnNldEV4dGVuZGVkUHJvcCA9IGZ1bmN0aW9uIChuYW1lLCB2YWwpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB0aGlzLm11dGF0ZSh7XG4gICAgICAgICAgICBleHRlbmRlZFByb3BzOiAoX2EgPSB7fSwgX2FbbmFtZV0gPSB2YWwsIF9hKVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRTdGFydCA9IGZ1bmN0aW9uIChzdGFydElucHV0LCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5fY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdmFyIHN0YXJ0ID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoc3RhcnRJbnB1dCk7XG4gICAgICAgIGlmIChzdGFydCAmJiB0aGlzLl9pbnN0YW5jZSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZVJhbmdlID0gdGhpcy5faW5zdGFuY2UucmFuZ2U7XG4gICAgICAgICAgICB2YXIgc3RhcnREZWx0YSA9IGRpZmZEYXRlcyhpbnN0YW5jZVJhbmdlLnN0YXJ0LCBzdGFydCwgZGF0ZUVudiwgb3B0aW9ucy5ncmFudWxhcml0eSk7IC8vIHdoYXQgaWYgcGFyc2VkIGJhZCE/XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tYWludGFpbkR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBkYXRlc0RlbHRhOiBzdGFydERlbHRhIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFydERlbHRhOiBzdGFydERlbHRhIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0RW5kID0gZnVuY3Rpb24gKGVuZElucHV0LCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5fY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgaWYgKGVuZElucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGVuZCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKGVuZElucHV0KTtcbiAgICAgICAgICAgIGlmICghZW5kKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5faW5zdGFuY2UpIHtcbiAgICAgICAgICAgIGlmIChlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZW5kRGVsdGEgPSBkaWZmRGF0ZXModGhpcy5faW5zdGFuY2UucmFuZ2UuZW5kLCBlbmQsIGRhdGVFbnYsIG9wdGlvbnMuZ3JhbnVsYXJpdHkpO1xuICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZW5kRGVsdGE6IGVuZERlbHRhIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFuZGFyZFByb3BzOiB7IGhhc0VuZDogZmFsc2UgfSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLnNldERhdGVzID0gZnVuY3Rpb24gKHN0YXJ0SW5wdXQsIGVuZElucHV0LCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5fY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdmFyIHN0YW5kYXJkUHJvcHMgPSB7IGFsbERheTogb3B0aW9ucy5hbGxEYXkgfTtcbiAgICAgICAgdmFyIHN0YXJ0ID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoc3RhcnRJbnB1dCk7XG4gICAgICAgIHZhciBlbmQ7XG4gICAgICAgIGlmICghc3RhcnQpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVuZElucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGVuZCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKGVuZElucHV0KTtcbiAgICAgICAgICAgIGlmICghZW5kKSB7IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5faW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZVJhbmdlID0gdGhpcy5faW5zdGFuY2UucmFuZ2U7XG4gICAgICAgICAgICAvLyB3aGVuIGNvbXB1dGluZyB0aGUgZGlmZiBmb3IgYW4gZXZlbnQgYmVpbmcgY29udmVydGVkIHRvIGFsbC1kYXksXG4gICAgICAgICAgICAvLyBjb21wdXRlIGRpZmYgb2ZmIG9mIHRoZSBhbGwtZGF5IHZhbHVlcyB0aGUgd2F5IGV2ZW50LW11dGF0aW9uIGRvZXMuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5hbGxEYXkgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBpbnN0YW5jZVJhbmdlID0gY29tcHV0ZUFsaWduZWREYXlSYW5nZShpbnN0YW5jZVJhbmdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdGFydERlbHRhID0gZGlmZkRhdGVzKGluc3RhbmNlUmFuZ2Uuc3RhcnQsIHN0YXJ0LCBkYXRlRW52LCBvcHRpb25zLmdyYW51bGFyaXR5KTtcbiAgICAgICAgICAgIGlmIChlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZW5kRGVsdGEgPSBkaWZmRGF0ZXMoaW5zdGFuY2VSYW5nZS5lbmQsIGVuZCwgZGF0ZUVudiwgb3B0aW9ucy5ncmFudWxhcml0eSk7XG4gICAgICAgICAgICAgICAgaWYgKGR1cmF0aW9uc0VxdWFsKHN0YXJ0RGVsdGEsIGVuZERlbHRhKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGRhdGVzRGVsdGE6IHN0YXJ0RGVsdGEsIHN0YW5kYXJkUHJvcHM6IHN0YW5kYXJkUHJvcHMgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YXJ0RGVsdGE6IHN0YXJ0RGVsdGEsIGVuZERlbHRhOiBlbmREZWx0YSwgc3RhbmRhcmRQcm9wczogc3RhbmRhcmRQcm9wcyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8gbWVhbnMgXCJjbGVhciB0aGUgZW5kXCJcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFByb3BzLmhhc0VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZGF0ZXNEZWx0YTogc3RhcnREZWx0YSwgc3RhbmRhcmRQcm9wczogc3RhbmRhcmRQcm9wcyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLm1vdmVTdGFydCA9IGZ1bmN0aW9uIChkZWx0YUlucHV0KSB7XG4gICAgICAgIHZhciBkZWx0YSA9IGNyZWF0ZUR1cmF0aW9uKGRlbHRhSW5wdXQpO1xuICAgICAgICBpZiAoZGVsdGEpIHsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YXJ0RGVsdGE6IGRlbHRhIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUubW92ZUVuZCA9IGZ1bmN0aW9uIChkZWx0YUlucHV0KSB7XG4gICAgICAgIHZhciBkZWx0YSA9IGNyZWF0ZUR1cmF0aW9uKGRlbHRhSW5wdXQpO1xuICAgICAgICBpZiAoZGVsdGEpIHsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGVuZERlbHRhOiBkZWx0YSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLm1vdmVEYXRlcyA9IGZ1bmN0aW9uIChkZWx0YUlucHV0KSB7XG4gICAgICAgIHZhciBkZWx0YSA9IGNyZWF0ZUR1cmF0aW9uKGRlbHRhSW5wdXQpO1xuICAgICAgICBpZiAoZGVsdGEpIHsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGRhdGVzRGVsdGE6IGRlbHRhIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0QWxsRGF5ID0gZnVuY3Rpb24gKGFsbERheSwgb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgICAgICB2YXIgc3RhbmRhcmRQcm9wcyA9IHsgYWxsRGF5OiBhbGxEYXkgfTtcbiAgICAgICAgdmFyIG1haW50YWluRHVyYXRpb24gPSBvcHRpb25zLm1haW50YWluRHVyYXRpb247XG4gICAgICAgIGlmIChtYWludGFpbkR1cmF0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgIG1haW50YWluRHVyYXRpb24gPSB0aGlzLl9jYWxlbmRhci5vcHQoJ2FsbERheU1haW50YWluRHVyYXRpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fZGVmLmFsbERheSAhPT0gYWxsRGF5KSB7XG4gICAgICAgICAgICBzdGFuZGFyZFByb3BzLmhhc0VuZCA9IG1haW50YWluRHVyYXRpb247XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tdXRhdGUoeyBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzIH0pO1xuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKGZvcm1hdElucHV0KSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5fY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5faW5zdGFuY2U7XG4gICAgICAgIHZhciBmb3JtYXR0ZXIgPSBjcmVhdGVGb3JtYXR0ZXIoZm9ybWF0SW5wdXQsIHRoaXMuX2NhbGVuZGFyLm9wdCgnZGVmYXVsdFJhbmdlU2VwYXJhdG9yJykpO1xuICAgICAgICBpZiAodGhpcy5fZGVmLmhhc0VuZCkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2UoaW5zdGFuY2UucmFuZ2Uuc3RhcnQsIGluc3RhbmNlLnJhbmdlLmVuZCwgZm9ybWF0dGVyLCB7XG4gICAgICAgICAgICAgICAgZm9yY2VkU3RhcnRUem86IGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvLFxuICAgICAgICAgICAgICAgIGZvcmNlZEVuZFR6bzogaW5zdGFuY2UuZm9yY2VkRW5kVHpvXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdChpbnN0YW5jZS5yYW5nZS5zdGFydCwgZm9ybWF0dGVyLCB7XG4gICAgICAgICAgICAgICAgZm9yY2VkVHpvOiBpbnN0YW5jZS5mb3JjZWRTdGFydFR6b1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5tdXRhdGUgPSBmdW5jdGlvbiAobXV0YXRpb24pIHtcbiAgICAgICAgdmFyIGRlZiA9IHRoaXMuX2RlZjtcbiAgICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5faW5zdGFuY2U7XG4gICAgICAgIGlmIChpbnN0YW5jZSkge1xuICAgICAgICAgICAgdGhpcy5fY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdNVVRBVEVfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZUlkOiBpbnN0YW5jZS5pbnN0YW5jZUlkLFxuICAgICAgICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvbixcbiAgICAgICAgICAgICAgICBmcm9tQXBpOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBldmVudFN0b3JlID0gdGhpcy5fY2FsZW5kYXIuc3RhdGUuZXZlbnRTdG9yZTtcbiAgICAgICAgICAgIHRoaXMuX2RlZiA9IGV2ZW50U3RvcmUuZGVmc1tkZWYuZGVmSWRdO1xuICAgICAgICAgICAgdGhpcy5faW5zdGFuY2UgPSBldmVudFN0b3JlLmluc3RhbmNlc1tpbnN0YW5jZS5pbnN0YW5jZUlkXTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1JFTU9WRV9FVkVOVF9ERUYnLFxuICAgICAgICAgICAgZGVmSWQ6IHRoaXMuX2RlZi5kZWZJZFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwic291cmNlXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlSWQgPSB0aGlzLl9kZWYuc291cmNlSWQ7XG4gICAgICAgICAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlQXBpKHRoaXMuX2NhbGVuZGFyLCB0aGlzLl9jYWxlbmRhci5zdGF0ZS5ldmVudFNvdXJjZXNbc291cmNlSWRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcInN0YXJ0XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faW5zdGFuY2UgP1xuICAgICAgICAgICAgICAgIHRoaXMuX2NhbGVuZGFyLmRhdGVFbnYudG9EYXRlKHRoaXMuX2luc3RhbmNlLnJhbmdlLnN0YXJ0KSA6XG4gICAgICAgICAgICAgICAgbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJlbmRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5faW5zdGFuY2UgJiYgdGhpcy5fZGVmLmhhc0VuZCkgP1xuICAgICAgICAgICAgICAgIHRoaXMuX2NhbGVuZGFyLmRhdGVFbnYudG9EYXRlKHRoaXMuX2luc3RhbmNlLnJhbmdlLmVuZCkgOlxuICAgICAgICAgICAgICAgIG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwiaWRcIiwge1xuICAgICAgICAvLyBjb21wdXRhYmxlIHByb3BzIHRoYXQgYWxsIGFjY2VzcyB0aGUgZGVmXG4gICAgICAgIC8vIFRPRE86IGZpbmQgYSBUeXBlU2NyaXB0LWNvbXBhdGlibGUgd2F5IHRvIGRvIHRoaXMgYXQgc2NhbGVcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYucHVibGljSWQ7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwiZ3JvdXBJZFwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGVmLmdyb3VwSWQ7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwiYWxsRGF5XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYuYWxsRGF5OyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcInRpdGxlXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudGl0bGU7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwidXJsXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudXJsOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcInJlbmRlcmluZ1wiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGVmLnJlbmRlcmluZzsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJzdGFydEVkaXRhYmxlXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuc3RhcnRFZGl0YWJsZTsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJkdXJhdGlvbkVkaXRhYmxlXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuZHVyYXRpb25FZGl0YWJsZTsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJjb25zdHJhaW50XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuY29uc3RyYWludHNbMF0gfHwgbnVsbDsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJvdmVybGFwXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkub3ZlcmxhcDsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJhbGxvd1wiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLmFsbG93c1swXSB8fCBudWxsOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImJhY2tncm91bmRDb2xvclwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLmJhY2tncm91bmRDb2xvcjsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJib3JkZXJDb2xvclwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLmJvcmRlckNvbG9yOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcInRleHRDb2xvclwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGVmLnVpLnRleHRDb2xvcjsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJjbGFzc05hbWVzXCIsIHtcbiAgICAgICAgLy8gTk9URTogdXNlciBjYW4ndCBtb2RpZnkgdGhlc2UgYmVjYXVzZSBPYmplY3QuZnJlZXplIHdhcyBjYWxsZWQgaW4gZXZlbnQtZGVmIHBhcnNpbmdcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuY2xhc3NOYW1lczsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJleHRlbmRlZFByb3BzXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYuZXh0ZW5kZWRQcm9wczsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIEV2ZW50QXBpO1xufSgpKTtcblxuLypcblNwZWNpZnlpbmcgbmV4dERheVRocmVzaG9sZCBzaWduYWxzIHRoYXQgYWxsLWRheSByYW5nZXMgc2hvdWxkIGJlIHNsaWNlZC5cbiovXG5mdW5jdGlvbiBzbGljZUV2ZW50U3RvcmUoZXZlbnRTdG9yZSwgZXZlbnRVaUJhc2VzLCBmcmFtaW5nUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQpIHtcbiAgICB2YXIgaW52ZXJzZUJnQnlHcm91cElkID0ge307XG4gICAgdmFyIGludmVyc2VCZ0J5RGVmSWQgPSB7fTtcbiAgICB2YXIgZGVmQnlHcm91cElkID0ge307XG4gICAgdmFyIGJnUmFuZ2VzID0gW107XG4gICAgdmFyIGZnUmFuZ2VzID0gW107XG4gICAgdmFyIGV2ZW50VWlzID0gY29tcGlsZUV2ZW50VWlzKGV2ZW50U3RvcmUuZGVmcywgZXZlbnRVaUJhc2VzKTtcbiAgICBmb3IgKHZhciBkZWZJZCBpbiBldmVudFN0b3JlLmRlZnMpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF07XG4gICAgICAgIGlmIChkZWYucmVuZGVyaW5nID09PSAnaW52ZXJzZS1iYWNrZ3JvdW5kJykge1xuICAgICAgICAgICAgaWYgKGRlZi5ncm91cElkKSB7XG4gICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlHcm91cElkW2RlZi5ncm91cElkXSA9IFtdO1xuICAgICAgICAgICAgICAgIGlmICghZGVmQnlHcm91cElkW2RlZi5ncm91cElkXSkge1xuICAgICAgICAgICAgICAgICAgICBkZWZCeUdyb3VwSWRbZGVmLmdyb3VwSWRdID0gZGVmO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGludmVyc2VCZ0J5RGVmSWRbZGVmSWRdID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIgaW5zdGFuY2VJZCBpbiBldmVudFN0b3JlLmluc3RhbmNlcykge1xuICAgICAgICB2YXIgaW5zdGFuY2UgPSBldmVudFN0b3JlLmluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50U3RvcmUuZGVmc1tpbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIHZhciB1aSA9IGV2ZW50VWlzW2RlZi5kZWZJZF07XG4gICAgICAgIHZhciBvcmlnUmFuZ2UgPSBpbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgdmFyIG5vcm1hbFJhbmdlID0gKCFkZWYuYWxsRGF5ICYmIG5leHREYXlUaHJlc2hvbGQpID9cbiAgICAgICAgICAgIGNvbXB1dGVWaXNpYmxlRGF5UmFuZ2Uob3JpZ1JhbmdlLCBuZXh0RGF5VGhyZXNob2xkKSA6XG4gICAgICAgICAgICBvcmlnUmFuZ2U7XG4gICAgICAgIHZhciBzbGljZWRSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhub3JtYWxSYW5nZSwgZnJhbWluZ1JhbmdlKTtcbiAgICAgICAgaWYgKHNsaWNlZFJhbmdlKSB7XG4gICAgICAgICAgICBpZiAoZGVmLnJlbmRlcmluZyA9PT0gJ2ludmVyc2UtYmFja2dyb3VuZCcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVmLmdyb3VwSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlHcm91cElkW2RlZi5ncm91cElkXS5wdXNoKHNsaWNlZFJhbmdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGludmVyc2VCZ0J5RGVmSWRbaW5zdGFuY2UuZGVmSWRdLnB1c2goc2xpY2VkUmFuZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIChkZWYucmVuZGVyaW5nID09PSAnYmFja2dyb3VuZCcgPyBiZ1JhbmdlcyA6IGZnUmFuZ2VzKS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgZGVmOiBkZWYsXG4gICAgICAgICAgICAgICAgICAgIHVpOiB1aSxcbiAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2U6IGluc3RhbmNlLFxuICAgICAgICAgICAgICAgICAgICByYW5nZTogc2xpY2VkUmFuZ2UsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IG5vcm1hbFJhbmdlLnN0YXJ0ICYmIG5vcm1hbFJhbmdlLnN0YXJ0LnZhbHVlT2YoKSA9PT0gc2xpY2VkUmFuZ2Uuc3RhcnQudmFsdWVPZigpLFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogbm9ybWFsUmFuZ2UuZW5kICYmIG5vcm1hbFJhbmdlLmVuZC52YWx1ZU9mKCkgPT09IHNsaWNlZFJhbmdlLmVuZC52YWx1ZU9mKClcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBncm91cElkIGluIGludmVyc2VCZ0J5R3JvdXBJZCkgeyAvLyBCWSBHUk9VUFxuICAgICAgICB2YXIgcmFuZ2VzID0gaW52ZXJzZUJnQnlHcm91cElkW2dyb3VwSWRdO1xuICAgICAgICB2YXIgaW52ZXJ0ZWRSYW5nZXMgPSBpbnZlcnRSYW5nZXMocmFuZ2VzLCBmcmFtaW5nUmFuZ2UpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIGludmVydGVkUmFuZ2VzXzEgPSBpbnZlcnRlZFJhbmdlczsgX2kgPCBpbnZlcnRlZFJhbmdlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGludmVydGVkUmFuZ2UgPSBpbnZlcnRlZFJhbmdlc18xW19pXTtcbiAgICAgICAgICAgIHZhciBkZWYgPSBkZWZCeUdyb3VwSWRbZ3JvdXBJZF07XG4gICAgICAgICAgICB2YXIgdWkgPSBldmVudFVpc1tkZWYuZGVmSWRdO1xuICAgICAgICAgICAgYmdSYW5nZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZGVmOiBkZWYsXG4gICAgICAgICAgICAgICAgdWk6IHVpLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlOiBudWxsLFxuICAgICAgICAgICAgICAgIHJhbmdlOiBpbnZlcnRlZFJhbmdlLFxuICAgICAgICAgICAgICAgIGlzU3RhcnQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGlzRW5kOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIgZGVmSWQgaW4gaW52ZXJzZUJnQnlEZWZJZCkge1xuICAgICAgICB2YXIgcmFuZ2VzID0gaW52ZXJzZUJnQnlEZWZJZFtkZWZJZF07XG4gICAgICAgIHZhciBpbnZlcnRlZFJhbmdlcyA9IGludmVydFJhbmdlcyhyYW5nZXMsIGZyYW1pbmdSYW5nZSk7XG4gICAgICAgIGZvciAodmFyIF9hID0gMCwgaW52ZXJ0ZWRSYW5nZXNfMiA9IGludmVydGVkUmFuZ2VzOyBfYSA8IGludmVydGVkUmFuZ2VzXzIubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgICAgICB2YXIgaW52ZXJ0ZWRSYW5nZSA9IGludmVydGVkUmFuZ2VzXzJbX2FdO1xuICAgICAgICAgICAgYmdSYW5nZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgZGVmOiBldmVudFN0b3JlLmRlZnNbZGVmSWRdLFxuICAgICAgICAgICAgICAgIHVpOiBldmVudFVpc1tkZWZJZF0sXG4gICAgICAgICAgICAgICAgaW5zdGFuY2U6IG51bGwsXG4gICAgICAgICAgICAgICAgcmFuZ2U6IGludmVydGVkUmFuZ2UsXG4gICAgICAgICAgICAgICAgaXNTdGFydDogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNFbmQ6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBiZzogYmdSYW5nZXMsIGZnOiBmZ1JhbmdlcyB9O1xufVxuZnVuY3Rpb24gaGFzQmdSZW5kZXJpbmcoZGVmKSB7XG4gICAgcmV0dXJuIGRlZi5yZW5kZXJpbmcgPT09ICdiYWNrZ3JvdW5kJyB8fCBkZWYucmVuZGVyaW5nID09PSAnaW52ZXJzZS1iYWNrZ3JvdW5kJztcbn1cbmZ1bmN0aW9uIGZpbHRlclNlZ3NWaWFFbHMoY29udGV4dCwgc2VncywgaXNNaXJyb3IpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBjb250ZXh0LmNhbGVuZGFyLCB2aWV3ID0gY29udGV4dC52aWV3O1xuICAgIGlmIChjYWxlbmRhci5oYXNQdWJsaWNIYW5kbGVycygnZXZlbnRSZW5kZXInKSkge1xuICAgICAgICBzZWdzID0gc2Vncy5maWx0ZXIoZnVuY3Rpb24gKHNlZykge1xuICAgICAgICAgICAgdmFyIGN1c3RvbSA9IGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZW5kZXInLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgaXNNaXJyb3I6IGlzTWlycm9yLFxuICAgICAgICAgICAgICAgICAgICBpc1N0YXJ0OiBzZWcuaXNTdGFydCxcbiAgICAgICAgICAgICAgICAgICAgaXNFbmQ6IHNlZy5pc0VuZCxcbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogaW5jbHVkZSBzZWcucmFuZ2Ugb25jZSBhbGwgY29tcG9uZW50cyBjb25zaXN0ZW50bHkgZ2VuZXJhdGUgaXRcbiAgICAgICAgICAgICAgICAgICAgZWw6IHNlZy5lbCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgaWYgKGN1c3RvbSA9PT0gZmFsc2UpIHsgLy8gbWVhbnMgZG9uJ3QgcmVuZGVyIGF0IGFsbFxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGN1c3RvbSAmJiBjdXN0b20gIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBzZWcuZWwgPSBjdXN0b207XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18xID0gc2VnczsgX2kgPCBzZWdzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBzZWcgPSBzZWdzXzFbX2ldO1xuICAgICAgICBzZXRFbFNlZyhzZWcuZWwsIHNlZyk7XG4gICAgfVxuICAgIHJldHVybiBzZWdzO1xufVxuZnVuY3Rpb24gc2V0RWxTZWcoZWwsIHNlZykge1xuICAgIGVsLmZjU2VnID0gc2VnO1xufVxuZnVuY3Rpb24gZ2V0RWxTZWcoZWwpIHtcbiAgICByZXR1cm4gZWwuZmNTZWcgfHwgbnVsbDtcbn1cbi8vIGV2ZW50IHVpIGNvbXB1dGF0aW9uXG5mdW5jdGlvbiBjb21waWxlRXZlbnRVaXMoZXZlbnREZWZzLCBldmVudFVpQmFzZXMpIHtcbiAgICByZXR1cm4gbWFwSGFzaChldmVudERlZnMsIGZ1bmN0aW9uIChldmVudERlZikge1xuICAgICAgICByZXR1cm4gY29tcGlsZUV2ZW50VWkoZXZlbnREZWYsIGV2ZW50VWlCYXNlcyk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBjb21waWxlRXZlbnRVaShldmVudERlZiwgZXZlbnRVaUJhc2VzKSB7XG4gICAgdmFyIHVpcyA9IFtdO1xuICAgIGlmIChldmVudFVpQmFzZXNbJyddKSB7XG4gICAgICAgIHVpcy5wdXNoKGV2ZW50VWlCYXNlc1snJ10pO1xuICAgIH1cbiAgICBpZiAoZXZlbnRVaUJhc2VzW2V2ZW50RGVmLmRlZklkXSkge1xuICAgICAgICB1aXMucHVzaChldmVudFVpQmFzZXNbZXZlbnREZWYuZGVmSWRdKTtcbiAgICB9XG4gICAgdWlzLnB1c2goZXZlbnREZWYudWkpO1xuICAgIHJldHVybiBjb21iaW5lRXZlbnRVaXModWlzKTtcbn1cbi8vIHRyaWdnZXJzXG5mdW5jdGlvbiB0cmlnZ2VyUmVuZGVyZWRTZWdzKGNvbnRleHQsIHNlZ3MsIGlzTWlycm9ycykge1xuICAgIHZhciBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXIsIHZpZXcgPSBjb250ZXh0LnZpZXc7XG4gICAgaWYgKGNhbGVuZGFyLmhhc1B1YmxpY0hhbmRsZXJzKCdldmVudFBvc2l0aW9uZWQnKSkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHNlZ3NfMiA9IHNlZ3M7IF9pIDwgc2Vnc18yLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMltfaV07XG4gICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXJBZnRlclNpemluZygnZXZlbnRQb3NpdGlvbmVkJywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IG5ldyBFdmVudEFwaShjYWxlbmRhciwgc2VnLmV2ZW50UmFuZ2UuZGVmLCBzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICAgICAgICAgIGlzTWlycm9yOiBpc01pcnJvcnMsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IHNlZy5pc1N0YXJ0LFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogc2VnLmlzRW5kLFxuICAgICAgICAgICAgICAgICAgICBlbDogc2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFjYWxlbmRhci5zdGF0ZS5ldmVudFNvdXJjZUxvYWRpbmdMZXZlbCkgeyAvLyBhdm9pZCBpbml0aWFsIGVtcHR5IHN0YXRlIHdoaWxlIHBlbmRpbmdcbiAgICAgICAgY2FsZW5kYXIuYWZ0ZXJTaXppbmdUcmlnZ2Vycy5fZXZlbnRzUG9zaXRpb25lZCA9IFtudWxsXTsgLy8gZmlyZSBvbmNlXG4gICAgfVxufVxuZnVuY3Rpb24gdHJpZ2dlcldpbGxSZW1vdmVTZWdzKGNvbnRleHQsIHNlZ3MsIGlzTWlycm9ycykge1xuICAgIHZhciBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXIsIHZpZXcgPSBjb250ZXh0LnZpZXc7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBzZWdzXzMgPSBzZWdzOyBfaSA8IHNlZ3NfMy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHNlZyA9IHNlZ3NfM1tfaV07XG4gICAgICAgIGNhbGVuZGFyLnRyaWdnZXIoJ2V2ZW50RWxSZW1vdmUnLCBzZWcuZWwpO1xuICAgIH1cbiAgICBpZiAoY2FsZW5kYXIuaGFzUHVibGljSGFuZGxlcnMoJ2V2ZW50RGVzdHJveScpKSB7XG4gICAgICAgIGZvciAodmFyIF9hID0gMCwgc2Vnc180ID0gc2VnczsgX2EgPCBzZWdzXzQubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc180W19hXTtcbiAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnREZXN0cm95JywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IG5ldyBFdmVudEFwaShjYWxlbmRhciwgc2VnLmV2ZW50UmFuZ2UuZGVmLCBzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICAgICAgICAgIGlzTWlycm9yOiBpc01pcnJvcnMsXG4gICAgICAgICAgICAgICAgICAgIGVsOiBzZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8vIGlzLWludGVyYWN0YWJsZVxuZnVuY3Rpb24gY29tcHV0ZUV2ZW50RHJhZ2dhYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKSB7XG4gICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhciwgdmlldyA9IGNvbnRleHQudmlldztcbiAgICB2YXIgdHJhbnNmb3JtZXJzID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzO1xuICAgIHZhciB2YWwgPSBldmVudFVpLnN0YXJ0RWRpdGFibGU7XG4gICAgZm9yICh2YXIgX2kgPSAwLCB0cmFuc2Zvcm1lcnNfMSA9IHRyYW5zZm9ybWVyczsgX2kgPCB0cmFuc2Zvcm1lcnNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHRyYW5zZm9ybWVyID0gdHJhbnNmb3JtZXJzXzFbX2ldO1xuICAgICAgICB2YWwgPSB0cmFuc2Zvcm1lcih2YWwsIGV2ZW50RGVmLCBldmVudFVpLCB2aWV3KTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVFdmVudFN0YXJ0UmVzaXphYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKSB7XG4gICAgcmV0dXJuIGV2ZW50VWkuZHVyYXRpb25FZGl0YWJsZSAmJiBjb250ZXh0Lm9wdGlvbnMuZXZlbnRSZXNpemFibGVGcm9tU3RhcnQ7XG59XG5mdW5jdGlvbiBjb21wdXRlRXZlbnRFbmRSZXNpemFibGUoY29udGV4dCwgZXZlbnREZWYsIGV2ZW50VWkpIHtcbiAgICByZXR1cm4gZXZlbnRVaS5kdXJhdGlvbkVkaXRhYmxlO1xufVxuXG4vLyBhcHBsaWVzIHRoZSBtdXRhdGlvbiB0byBBTEwgZGVmcy9pbnN0YW5jZXMgd2l0aGluIHRoZSBldmVudCBzdG9yZVxuZnVuY3Rpb24gYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudENvbmZpZ0Jhc2UsIG11dGF0aW9uLCBjYWxlbmRhcikge1xuICAgIHZhciBldmVudENvbmZpZ3MgPSBjb21waWxlRXZlbnRVaXMoZXZlbnRTdG9yZS5kZWZzLCBldmVudENvbmZpZ0Jhc2UpO1xuICAgIHZhciBkZXN0ID0gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7XG4gICAgZm9yICh2YXIgZGVmSWQgaW4gZXZlbnRTdG9yZS5kZWZzKSB7XG4gICAgICAgIHZhciBkZWYgPSBldmVudFN0b3JlLmRlZnNbZGVmSWRdO1xuICAgICAgICBkZXN0LmRlZnNbZGVmSWRdID0gYXBwbHlNdXRhdGlvblRvRXZlbnREZWYoZGVmLCBldmVudENvbmZpZ3NbZGVmSWRdLCBtdXRhdGlvbiwgY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycywgY2FsZW5kYXIpO1xuICAgIH1cbiAgICBmb3IgKHZhciBpbnN0YW5jZUlkIGluIGV2ZW50U3RvcmUuaW5zdGFuY2VzKSB7XG4gICAgICAgIHZhciBpbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlSWRdO1xuICAgICAgICB2YXIgZGVmID0gZGVzdC5kZWZzW2luc3RhbmNlLmRlZklkXTsgLy8gaW1wb3J0YW50IHRvIGdyYWIgdGhlIG5ld2x5IG1vZGlmaWVkIGRlZlxuICAgICAgICBkZXN0Lmluc3RhbmNlc1tpbnN0YW5jZUlkXSA9IGFwcGx5TXV0YXRpb25Ub0V2ZW50SW5zdGFuY2UoaW5zdGFuY2UsIGRlZiwgZXZlbnRDb25maWdzW2luc3RhbmNlLmRlZklkXSwgbXV0YXRpb24sIGNhbGVuZGFyKTtcbiAgICB9XG4gICAgcmV0dXJuIGRlc3Q7XG59XG5mdW5jdGlvbiBhcHBseU11dGF0aW9uVG9FdmVudERlZihldmVudERlZiwgZXZlbnRDb25maWcsIG11dGF0aW9uLCBhcHBsaWVycywgY2FsZW5kYXIpIHtcbiAgICB2YXIgc3RhbmRhcmRQcm9wcyA9IG11dGF0aW9uLnN0YW5kYXJkUHJvcHMgfHwge307XG4gICAgLy8gaWYgaGFzRW5kIGhhcyBub3QgYmVlbiBzcGVjaWZpZWQsIGd1ZXNzIGEgZ29vZCB2YWx1ZSBiYXNlZCBvbiBkZWx0YXMuXG4gICAgLy8gaWYgZHVyYXRpb24gd2lsbCBjaGFuZ2UsIHRoZXJlJ3Mgbm8gd2F5IHRoZSBkZWZhdWx0IGR1cmF0aW9uIHdpbGwgcGVyc2lzdCxcbiAgICAvLyBhbmQgdGh1cywgd2UgbmVlZCB0byBtYXJrIHRoZSBldmVudCBhcyBoYXZpbmcgYSByZWFsIGVuZFxuICAgIGlmIChzdGFuZGFyZFByb3BzLmhhc0VuZCA9PSBudWxsICYmXG4gICAgICAgIGV2ZW50Q29uZmlnLmR1cmF0aW9uRWRpdGFibGUgJiZcbiAgICAgICAgKG11dGF0aW9uLnN0YXJ0RGVsdGEgfHwgbXV0YXRpb24uZW5kRGVsdGEpKSB7XG4gICAgICAgIHN0YW5kYXJkUHJvcHMuaGFzRW5kID0gdHJ1ZTsgLy8gVE9ETzogaXMgdGhpcyBtdXRhdGlvbiBva2F5P1xuICAgIH1cbiAgICB2YXIgY29weSA9IF9fYXNzaWduKHt9LCBldmVudERlZiwgc3RhbmRhcmRQcm9wcywgeyB1aTogX19hc3NpZ24oe30sIGV2ZW50RGVmLnVpLCBzdGFuZGFyZFByb3BzLnVpKSB9KTtcbiAgICBpZiAobXV0YXRpb24uZXh0ZW5kZWRQcm9wcykge1xuICAgICAgICBjb3B5LmV4dGVuZGVkUHJvcHMgPSBfX2Fzc2lnbih7fSwgY29weS5leHRlbmRlZFByb3BzLCBtdXRhdGlvbi5leHRlbmRlZFByb3BzKTtcbiAgICB9XG4gICAgZm9yICh2YXIgX2kgPSAwLCBhcHBsaWVyc18xID0gYXBwbGllcnM7IF9pIDwgYXBwbGllcnNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIGFwcGxpZXIgPSBhcHBsaWVyc18xW19pXTtcbiAgICAgICAgYXBwbGllcihjb3B5LCBtdXRhdGlvbiwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICBpZiAoIWNvcHkuaGFzRW5kICYmIGNhbGVuZGFyLm9wdCgnZm9yY2VFdmVudER1cmF0aW9uJykpIHtcbiAgICAgICAgY29weS5oYXNFbmQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbn1cbmZ1bmN0aW9uIGFwcGx5TXV0YXRpb25Ub0V2ZW50SW5zdGFuY2UoZXZlbnRJbnN0YW5jZSwgZXZlbnREZWYsIC8vIG11c3QgZmlyc3QgYmUgbW9kaWZpZWQgYnkgYXBwbHlNdXRhdGlvblRvRXZlbnREZWZcbmV2ZW50Q29uZmlnLCBtdXRhdGlvbiwgY2FsZW5kYXIpIHtcbiAgICB2YXIgZGF0ZUVudiA9IGNhbGVuZGFyLmRhdGVFbnY7XG4gICAgdmFyIGZvcmNlQWxsRGF5ID0gbXV0YXRpb24uc3RhbmRhcmRQcm9wcyAmJiBtdXRhdGlvbi5zdGFuZGFyZFByb3BzLmFsbERheSA9PT0gdHJ1ZTtcbiAgICB2YXIgY2xlYXJFbmQgPSBtdXRhdGlvbi5zdGFuZGFyZFByb3BzICYmIG11dGF0aW9uLnN0YW5kYXJkUHJvcHMuaGFzRW5kID09PSBmYWxzZTtcbiAgICB2YXIgY29weSA9IF9fYXNzaWduKHt9LCBldmVudEluc3RhbmNlKTtcbiAgICBpZiAoZm9yY2VBbGxEYXkpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IGNvbXB1dGVBbGlnbmVkRGF5UmFuZ2UoY29weS5yYW5nZSk7XG4gICAgfVxuICAgIGlmIChtdXRhdGlvbi5kYXRlc0RlbHRhICYmIGV2ZW50Q29uZmlnLnN0YXJ0RWRpdGFibGUpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBkYXRlRW52LmFkZChjb3B5LnJhbmdlLnN0YXJ0LCBtdXRhdGlvbi5kYXRlc0RlbHRhKSxcbiAgICAgICAgICAgIGVuZDogZGF0ZUVudi5hZGQoY29weS5yYW5nZS5lbmQsIG11dGF0aW9uLmRhdGVzRGVsdGEpXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChtdXRhdGlvbi5zdGFydERlbHRhICYmIGV2ZW50Q29uZmlnLmR1cmF0aW9uRWRpdGFibGUpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBkYXRlRW52LmFkZChjb3B5LnJhbmdlLnN0YXJ0LCBtdXRhdGlvbi5zdGFydERlbHRhKSxcbiAgICAgICAgICAgIGVuZDogY29weS5yYW5nZS5lbmRcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLmVuZERlbHRhICYmIGV2ZW50Q29uZmlnLmR1cmF0aW9uRWRpdGFibGUpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBjb3B5LnJhbmdlLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBkYXRlRW52LmFkZChjb3B5LnJhbmdlLmVuZCwgbXV0YXRpb24uZW5kRGVsdGEpXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChjbGVhckVuZCkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGNvcHkucmFuZ2Uuc3RhcnQsXG4gICAgICAgICAgICBlbmQ6IGNhbGVuZGFyLmdldERlZmF1bHRFdmVudEVuZChldmVudERlZi5hbGxEYXksIGNvcHkucmFuZ2Uuc3RhcnQpXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8vIGluIGNhc2UgZXZlbnQgd2FzIGFsbC1kYXkgYnV0IHRoZSBzdXBwbGllZCBkZWx0YXMgd2VyZSBub3RcbiAgICAvLyBiZXR0ZXIgdXRpbCBmb3IgdGhpcz9cbiAgICBpZiAoZXZlbnREZWYuYWxsRGF5KSB7XG4gICAgICAgIGNvcHkucmFuZ2UgPSB7XG4gICAgICAgICAgICBzdGFydDogc3RhcnRPZkRheShjb3B5LnJhbmdlLnN0YXJ0KSxcbiAgICAgICAgICAgIGVuZDogc3RhcnRPZkRheShjb3B5LnJhbmdlLmVuZClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gaGFuZGxlIGludmFsaWQgZHVyYXRpb25zXG4gICAgaWYgKGNvcHkucmFuZ2UuZW5kIDwgY29weS5yYW5nZS5zdGFydCkge1xuICAgICAgICBjb3B5LnJhbmdlLmVuZCA9IGNhbGVuZGFyLmdldERlZmF1bHRFdmVudEVuZChldmVudERlZi5hbGxEYXksIGNvcHkucmFuZ2Uuc3RhcnQpO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gcmVkdWNlRXZlbnRTdG9yZSAoZXZlbnRTdG9yZSwgYWN0aW9uLCBldmVudFNvdXJjZXMsIGRhdGVQcm9maWxlLCBjYWxlbmRhcikge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnUkVDRUlWRV9FVkVOVFMnOiAvLyByYXdcbiAgICAgICAgICAgIHJldHVybiByZWNlaXZlUmF3RXZlbnRzKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlc1thY3Rpb24uc291cmNlSWRdLCBhY3Rpb24uZmV0Y2hJZCwgYWN0aW9uLmZldGNoUmFuZ2UsIGFjdGlvbi5yYXdFdmVudHMsIGNhbGVuZGFyKTtcbiAgICAgICAgY2FzZSAnQUREX0VWRU5UUyc6IC8vIGFscmVhZHkgcGFyc2VkLCBidXQgbm90IGV4cGFuZGVkXG4gICAgICAgICAgICByZXR1cm4gYWRkRXZlbnQoZXZlbnRTdG9yZSwgYWN0aW9uLmV2ZW50U3RvcmUsIC8vIG5ldyBvbmVzXG4gICAgICAgICAgICBkYXRlUHJvZmlsZSA/IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIDogbnVsbCwgY2FsZW5kYXIpO1xuICAgICAgICBjYXNlICdNRVJHRV9FVkVOVFMnOiAvLyBhbHJlYWR5IHBhcnNlZCBhbmQgZXhwYW5kZWRcbiAgICAgICAgICAgIHJldHVybiBtZXJnZUV2ZW50U3RvcmVzKGV2ZW50U3RvcmUsIGFjdGlvbi5ldmVudFN0b3JlKTtcbiAgICAgICAgY2FzZSAnUFJFVic6IC8vIFRPRE86IGhvdyBkbyB3ZSB0cmFjayBhbGwgYWN0aW9ucyB0aGF0IGFmZmVjdCBkYXRlUHJvZmlsZSA6KFxuICAgICAgICBjYXNlICdORVhUJzpcbiAgICAgICAgY2FzZSAnU0VUX0RBVEUnOlxuICAgICAgICBjYXNlICdTRVRfVklFV19UWVBFJzpcbiAgICAgICAgICAgIGlmIChkYXRlUHJvZmlsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBleHBhbmRSZWN1cnJpbmcoZXZlbnRTdG9yZSwgZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBldmVudFN0b3JlO1xuICAgICAgICAgICAgfVxuICAgICAgICBjYXNlICdDSEFOR0VfVElNRVpPTkUnOlxuICAgICAgICAgICAgcmV0dXJuIHJlem9uZURhdGVzKGV2ZW50U3RvcmUsIGFjdGlvbi5vbGREYXRlRW52LCBjYWxlbmRhci5kYXRlRW52KTtcbiAgICAgICAgY2FzZSAnTVVUQVRFX0VWRU5UUyc6XG4gICAgICAgICAgICByZXR1cm4gYXBwbHlNdXRhdGlvblRvUmVsYXRlZChldmVudFN0b3JlLCBhY3Rpb24uaW5zdGFuY2VJZCwgYWN0aW9uLm11dGF0aW9uLCBhY3Rpb24uZnJvbUFwaSwgY2FsZW5kYXIpO1xuICAgICAgICBjYXNlICdSRU1PVkVfRVZFTlRfSU5TVEFOQ0VTJzpcbiAgICAgICAgICAgIHJldHVybiBleGNsdWRlSW5zdGFuY2VzKGV2ZW50U3RvcmUsIGFjdGlvbi5pbnN0YW5jZXMpO1xuICAgICAgICBjYXNlICdSRU1PVkVfRVZFTlRfREVGJzpcbiAgICAgICAgICAgIHJldHVybiBmaWx0ZXJFdmVudFN0b3JlRGVmcyhldmVudFN0b3JlLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnREZWYuZGVmSWQgIT09IGFjdGlvbi5kZWZJZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlICdSRU1PVkVfRVZFTlRfU09VUkNFJzpcbiAgICAgICAgICAgIHJldHVybiBleGNsdWRlRXZlbnRzQnlTb3VyY2VJZChldmVudFN0b3JlLCBhY3Rpb24uc291cmNlSWQpO1xuICAgICAgICBjYXNlICdSRU1PVkVfQUxMX0VWRU5UX1NPVVJDRVMnOlxuICAgICAgICAgICAgcmV0dXJuIGZpbHRlckV2ZW50U3RvcmVEZWZzKGV2ZW50U3RvcmUsIGZ1bmN0aW9uIChldmVudERlZikge1xuICAgICAgICAgICAgICAgIHJldHVybiAhZXZlbnREZWYuc291cmNlSWQ7IC8vIG9ubHkga2VlcCBldmVudHMgd2l0aCBubyBzb3VyY2UgaWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlICdSRU1PVkVfQUxMX0VWRU5UUyc6XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7XG4gICAgICAgIGNhc2UgJ1JFU0VUX0VWRU5UUyc6XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGRlZnM6IGV2ZW50U3RvcmUuZGVmcyxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZXM6IGV2ZW50U3RvcmUuaW5zdGFuY2VzXG4gICAgICAgICAgICB9O1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmU7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVjZWl2ZVJhd0V2ZW50cyhldmVudFN0b3JlLCBldmVudFNvdXJjZSwgZmV0Y2hJZCwgZmV0Y2hSYW5nZSwgcmF3RXZlbnRzLCBjYWxlbmRhcikge1xuICAgIGlmIChldmVudFNvdXJjZSAmJiAvLyBub3QgYWxyZWFkeSByZW1vdmVkXG4gICAgICAgIGZldGNoSWQgPT09IGV2ZW50U291cmNlLmxhdGVzdEZldGNoSWQgLy8gVE9ETzogd2lzaCB0aGlzIGxvZ2ljIHdhcyBhbHdheXMgaW4gZXZlbnQtc291cmNlc1xuICAgICkge1xuICAgICAgICB2YXIgc3Vic2V0ID0gcGFyc2VFdmVudHModHJhbnNmb3JtUmF3RXZlbnRzKHJhd0V2ZW50cywgZXZlbnRTb3VyY2UsIGNhbGVuZGFyKSwgZXZlbnRTb3VyY2Uuc291cmNlSWQsIGNhbGVuZGFyKTtcbiAgICAgICAgaWYgKGZldGNoUmFuZ2UpIHtcbiAgICAgICAgICAgIHN1YnNldCA9IGV4cGFuZFJlY3VycmluZyhzdWJzZXQsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWVyZ2VFdmVudFN0b3JlcyhleGNsdWRlRXZlbnRzQnlTb3VyY2VJZChldmVudFN0b3JlLCBldmVudFNvdXJjZS5zb3VyY2VJZCksIHN1YnNldCk7XG4gICAgfVxuICAgIHJldHVybiBldmVudFN0b3JlO1xufVxuZnVuY3Rpb24gYWRkRXZlbnQoZXZlbnRTdG9yZSwgc3Vic2V0LCBleHBhbmRSYW5nZSwgY2FsZW5kYXIpIHtcbiAgICBpZiAoZXhwYW5kUmFuZ2UpIHtcbiAgICAgICAgc3Vic2V0ID0gZXhwYW5kUmVjdXJyaW5nKHN1YnNldCwgZXhwYW5kUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICB9XG4gICAgcmV0dXJuIG1lcmdlRXZlbnRTdG9yZXMoZXZlbnRTdG9yZSwgc3Vic2V0KTtcbn1cbmZ1bmN0aW9uIHJlem9uZURhdGVzKGV2ZW50U3RvcmUsIG9sZERhdGVFbnYsIG5ld0RhdGVFbnYpIHtcbiAgICB2YXIgZGVmcyA9IGV2ZW50U3RvcmUuZGVmcztcbiAgICB2YXIgaW5zdGFuY2VzID0gbWFwSGFzaChldmVudFN0b3JlLmluc3RhbmNlcywgZnVuY3Rpb24gKGluc3RhbmNlKSB7XG4gICAgICAgIHZhciBkZWYgPSBkZWZzW2luc3RhbmNlLmRlZklkXTtcbiAgICAgICAgaWYgKGRlZi5hbGxEYXkgfHwgZGVmLnJlY3VycmluZ0RlZikge1xuICAgICAgICAgICAgcmV0dXJuIGluc3RhbmNlOyAvLyBpc24ndCBkZXBlbmRlbnQgb24gdGltZXpvbmVcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBfX2Fzc2lnbih7fSwgaW5zdGFuY2UsIHsgcmFuZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IG5ld0RhdGVFbnYuY3JlYXRlTWFya2VyKG9sZERhdGVFbnYudG9EYXRlKGluc3RhbmNlLnJhbmdlLnN0YXJ0LCBpbnN0YW5jZS5mb3JjZWRTdGFydFR6bykpLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IG5ld0RhdGVFbnYuY3JlYXRlTWFya2VyKG9sZERhdGVFbnYudG9EYXRlKGluc3RhbmNlLnJhbmdlLmVuZCwgaW5zdGFuY2UuZm9yY2VkRW5kVHpvKSlcbiAgICAgICAgICAgICAgICB9LCBmb3JjZWRTdGFydFR6bzogbmV3RGF0ZUVudi5jYW5Db21wdXRlT2Zmc2V0ID8gbnVsbCA6IGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvLCBmb3JjZWRFbmRUem86IG5ld0RhdGVFbnYuY2FuQ29tcHV0ZU9mZnNldCA/IG51bGwgOiBpbnN0YW5jZS5mb3JjZWRFbmRUem8gfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4geyBkZWZzOiBkZWZzLCBpbnN0YW5jZXM6IGluc3RhbmNlcyB9O1xufVxuZnVuY3Rpb24gYXBwbHlNdXRhdGlvblRvUmVsYXRlZChldmVudFN0b3JlLCBpbnN0YW5jZUlkLCBtdXRhdGlvbiwgZnJvbUFwaSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgcmVsZXZhbnQgPSBnZXRSZWxldmFudEV2ZW50cyhldmVudFN0b3JlLCBpbnN0YW5jZUlkKTtcbiAgICB2YXIgZXZlbnRDb25maWdCYXNlID0gZnJvbUFwaSA/XG4gICAgICAgIHsgJyc6IHtcbiAgICAgICAgICAgICAgICBzdGFydEVkaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uRWRpdGFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgY29uc3RyYWludHM6IFtdLFxuICAgICAgICAgICAgICAgIG92ZXJsYXA6IG51bGwsXG4gICAgICAgICAgICAgICAgYWxsb3dzOiBbXSxcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6ICcnLFxuICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiAnJyxcbiAgICAgICAgICAgICAgICB0ZXh0Q29sb3I6ICcnLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZXM6IFtdXG4gICAgICAgICAgICB9IH0gOlxuICAgICAgICBjYWxlbmRhci5ldmVudFVpQmFzZXM7XG4gICAgcmVsZXZhbnQgPSBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlKHJlbGV2YW50LCBldmVudENvbmZpZ0Jhc2UsIG11dGF0aW9uLCBjYWxlbmRhcik7XG4gICAgcmV0dXJuIG1lcmdlRXZlbnRTdG9yZXMoZXZlbnRTdG9yZSwgcmVsZXZhbnQpO1xufVxuZnVuY3Rpb24gZXhjbHVkZUV2ZW50c0J5U291cmNlSWQoZXZlbnRTdG9yZSwgc291cmNlSWQpIHtcbiAgICByZXR1cm4gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgIHJldHVybiBldmVudERlZi5zb3VyY2VJZCAhPT0gc291cmNlSWQ7XG4gICAgfSk7XG59XG4vLyBRVUVTVElPTjogd2h5IG5vdCBqdXN0IHJldHVybiBpbnN0YW5jZXM/IGRvIGEgZ2VuZXJhbCBvYmplY3QtcHJvcGVydHktZXhjbHVzaW9uIHV0aWxcbmZ1bmN0aW9uIGV4Y2x1ZGVJbnN0YW5jZXMoZXZlbnRTdG9yZSwgcmVtb3ZhbHMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkZWZzOiBldmVudFN0b3JlLmRlZnMsXG4gICAgICAgIGluc3RhbmNlczogZmlsdGVySGFzaChldmVudFN0b3JlLmluc3RhbmNlcywgZnVuY3Rpb24gKGluc3RhbmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gIXJlbW92YWxzW2luc3RhbmNlLmluc3RhbmNlSWRdO1xuICAgICAgICB9KVxuICAgIH07XG59XG5cbi8vIGhpZ2gtbGV2ZWwgc2VnbWVudGluZy1hd2FyZSB0ZXN0ZXIgZnVuY3Rpb25zXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbiwgY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gaXNOZXdQcm9wc1ZhbGlkKHsgZXZlbnREcmFnOiBpbnRlcmFjdGlvbiB9LCBjYWxlbmRhcik7IC8vIEhBQ0s6IHRoZSBldmVudERyYWcgcHJvcHMgaXMgdXNlZCBmb3IgQUxMIGludGVyYWN0aW9uc1xufVxuZnVuY3Rpb24gaXNEYXRlU2VsZWN0aW9uVmFsaWQoZGF0ZVNlbGVjdGlvbiwgY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gaXNOZXdQcm9wc1ZhbGlkKHsgZGF0ZVNlbGVjdGlvbjogZGF0ZVNlbGVjdGlvbiB9LCBjYWxlbmRhcik7XG59XG5mdW5jdGlvbiBpc05ld1Byb3BzVmFsaWQobmV3UHJvcHMsIGNhbGVuZGFyKSB7XG4gICAgdmFyIHZpZXcgPSBjYWxlbmRhci52aWV3O1xuICAgIHZhciBwcm9wcyA9IF9fYXNzaWduKHsgYnVzaW5lc3NIb3VyczogdmlldyA/IHZpZXcucHJvcHMuYnVzaW5lc3NIb3VycyA6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLCBkYXRlU2VsZWN0aW9uOiAnJywgZXZlbnRTdG9yZTogY2FsZW5kYXIuc3RhdGUuZXZlbnRTdG9yZSwgZXZlbnRVaUJhc2VzOiBjYWxlbmRhci5ldmVudFVpQmFzZXMsIGV2ZW50U2VsZWN0aW9uOiAnJywgZXZlbnREcmFnOiBudWxsLCBldmVudFJlc2l6ZTogbnVsbCB9LCBuZXdQcm9wcyk7XG4gICAgcmV0dXJuIChjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuaXNQcm9wc1ZhbGlkIHx8IGlzUHJvcHNWYWxpZCkocHJvcHMsIGNhbGVuZGFyKTtcbn1cbmZ1bmN0aW9uIGlzUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgaWYgKGRhdGVTcGFuTWV0YSA9PT0gdm9pZCAwKSB7IGRhdGVTcGFuTWV0YSA9IHt9OyB9XG4gICAgaWYgKHN0YXRlLmV2ZW50RHJhZyAmJiAhaXNJbnRlcmFjdGlvblByb3BzVmFsaWQoc3RhdGUsIGNhbGVuZGFyLCBkYXRlU3Bhbk1ldGEsIGZpbHRlckNvbmZpZykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoc3RhdGUuZGF0ZVNlbGVjdGlvbiAmJiAhaXNEYXRlU2VsZWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuLy8gTW92aW5nIEV2ZW50IFZhbGlkYXRpb25cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gaXNJbnRlcmFjdGlvblByb3BzVmFsaWQoc3RhdGUsIGNhbGVuZGFyLCBkYXRlU3Bhbk1ldGEsIGZpbHRlckNvbmZpZykge1xuICAgIHZhciBpbnRlcmFjdGlvbiA9IHN0YXRlLmV2ZW50RHJhZzsgLy8gSEFDSzogdGhlIGV2ZW50RHJhZyBwcm9wcyBpcyB1c2VkIGZvciBBTEwgaW50ZXJhY3Rpb25zXG4gICAgdmFyIHN1YmplY3RFdmVudFN0b3JlID0gaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cztcbiAgICB2YXIgc3ViamVjdERlZnMgPSBzdWJqZWN0RXZlbnRTdG9yZS5kZWZzO1xuICAgIHZhciBzdWJqZWN0SW5zdGFuY2VzID0gc3ViamVjdEV2ZW50U3RvcmUuaW5zdGFuY2VzO1xuICAgIHZhciBzdWJqZWN0Q29uZmlncyA9IGNvbXBpbGVFdmVudFVpcyhzdWJqZWN0RGVmcywgaW50ZXJhY3Rpb24uaXNFdmVudCA/XG4gICAgICAgIHN0YXRlLmV2ZW50VWlCYXNlcyA6XG4gICAgICAgIHsgJyc6IGNhbGVuZGFyLnNlbGVjdGlvbkNvbmZpZyB9IC8vIGlmIG5vdCBhIHJlYWwgZXZlbnQsIHZhbGlkYXRlIGFzIGEgc2VsZWN0aW9uXG4gICAgKTtcbiAgICBpZiAoZmlsdGVyQ29uZmlnKSB7XG4gICAgICAgIHN1YmplY3RDb25maWdzID0gbWFwSGFzaChzdWJqZWN0Q29uZmlncywgZmlsdGVyQ29uZmlnKTtcbiAgICB9XG4gICAgdmFyIG90aGVyRXZlbnRTdG9yZSA9IGV4Y2x1ZGVJbnN0YW5jZXMoc3RhdGUuZXZlbnRTdG9yZSwgaW50ZXJhY3Rpb24uYWZmZWN0ZWRFdmVudHMuaW5zdGFuY2VzKTsgLy8gZXhjbHVkZSB0aGUgc3ViamVjdCBldmVudHMuIFRPRE86IGV4Y2x1ZGUgZGVmcyB0b28/XG4gICAgdmFyIG90aGVyRGVmcyA9IG90aGVyRXZlbnRTdG9yZS5kZWZzO1xuICAgIHZhciBvdGhlckluc3RhbmNlcyA9IG90aGVyRXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIG90aGVyQ29uZmlncyA9IGNvbXBpbGVFdmVudFVpcyhvdGhlckRlZnMsIHN0YXRlLmV2ZW50VWlCYXNlcyk7XG4gICAgZm9yICh2YXIgc3ViamVjdEluc3RhbmNlSWQgaW4gc3ViamVjdEluc3RhbmNlcykge1xuICAgICAgICB2YXIgc3ViamVjdEluc3RhbmNlID0gc3ViamVjdEluc3RhbmNlc1tzdWJqZWN0SW5zdGFuY2VJZF07XG4gICAgICAgIHZhciBzdWJqZWN0UmFuZ2UgPSBzdWJqZWN0SW5zdGFuY2UucmFuZ2U7XG4gICAgICAgIHZhciBzdWJqZWN0Q29uZmlnID0gc3ViamVjdENvbmZpZ3Nbc3ViamVjdEluc3RhbmNlLmRlZklkXTtcbiAgICAgICAgdmFyIHN1YmplY3REZWYgPSBzdWJqZWN0RGVmc1tzdWJqZWN0SW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICAvLyBjb25zdHJhaW50XG4gICAgICAgIGlmICghYWxsQ29uc3RyYWludHNQYXNzKHN1YmplY3RDb25maWcuY29uc3RyYWludHMsIHN1YmplY3RSYW5nZSwgb3RoZXJFdmVudFN0b3JlLCBzdGF0ZS5idXNpbmVzc0hvdXJzLCBjYWxlbmRhcikpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdmVybGFwXG4gICAgICAgIHZhciBvdmVybGFwRnVuYyA9IGNhbGVuZGFyLm9wdCgnZXZlbnRPdmVybGFwJyk7XG4gICAgICAgIGlmICh0eXBlb2Ygb3ZlcmxhcEZ1bmMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG92ZXJsYXBGdW5jID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBvdGhlckluc3RhbmNlSWQgaW4gb3RoZXJJbnN0YW5jZXMpIHtcbiAgICAgICAgICAgIHZhciBvdGhlckluc3RhbmNlID0gb3RoZXJJbnN0YW5jZXNbb3RoZXJJbnN0YW5jZUlkXTtcbiAgICAgICAgICAgIC8vIGludGVyc2VjdCEgZXZhbHVhdGVcbiAgICAgICAgICAgIGlmIChyYW5nZXNJbnRlcnNlY3Qoc3ViamVjdFJhbmdlLCBvdGhlckluc3RhbmNlLnJhbmdlKSkge1xuICAgICAgICAgICAgICAgIHZhciBvdGhlck92ZXJsYXAgPSBvdGhlckNvbmZpZ3Nbb3RoZXJJbnN0YW5jZS5kZWZJZF0ub3ZlcmxhcDtcbiAgICAgICAgICAgICAgICAvLyBjb25zaWRlciB0aGUgb3RoZXIgZXZlbnQncyBvdmVybGFwLiBvbmx5IGRvIHRoaXMgaWYgdGhlIHN1YmplY3QgZXZlbnQgaXMgYSBcInJlYWxcIiBldmVudFxuICAgICAgICAgICAgICAgIGlmIChvdGhlck92ZXJsYXAgPT09IGZhbHNlICYmIGludGVyYWN0aW9uLmlzRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc3ViamVjdENvbmZpZy5vdmVybGFwID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvdmVybGFwRnVuYyAmJiAhb3ZlcmxhcEZ1bmMobmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBvdGhlckRlZnNbb3RoZXJJbnN0YW5jZS5kZWZJZF0sIG90aGVySW5zdGFuY2UpLCAvLyBzdGlsbCBldmVudFxuICAgICAgICAgICAgICAgIG5ldyBFdmVudEFwaShjYWxlbmRhciwgc3ViamVjdERlZiwgc3ViamVjdEluc3RhbmNlKSAvLyBtb3ZpbmcgZXZlbnRcbiAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWxsb3cgKGEgZnVuY3Rpb24pXG4gICAgICAgIHZhciBjYWxlbmRhckV2ZW50U3RvcmUgPSBjYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlOyAvLyBuZWVkIGdsb2JhbC10by1jYWxlbmRhciwgbm90IGxvY2FsIHRvIGNvbXBvbmVudCAoc3BsaXR0YWJsZSlzdGF0ZVxuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gc3ViamVjdENvbmZpZy5hbGxvd3M7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc3ViamVjdEFsbG93ID0gX2FbX2ldO1xuICAgICAgICAgICAgdmFyIHN1YmplY3REYXRlU3BhbiA9IF9fYXNzaWduKHt9LCBkYXRlU3Bhbk1ldGEsIHsgcmFuZ2U6IHN1YmplY3RJbnN0YW5jZS5yYW5nZSwgYWxsRGF5OiBzdWJqZWN0RGVmLmFsbERheSB9KTtcbiAgICAgICAgICAgIHZhciBvcmlnRGVmID0gY2FsZW5kYXJFdmVudFN0b3JlLmRlZnNbc3ViamVjdERlZi5kZWZJZF07XG4gICAgICAgICAgICB2YXIgb3JpZ0luc3RhbmNlID0gY2FsZW5kYXJFdmVudFN0b3JlLmluc3RhbmNlc1tzdWJqZWN0SW5zdGFuY2VJZF07XG4gICAgICAgICAgICB2YXIgZXZlbnRBcGkgPSB2b2lkIDA7XG4gICAgICAgICAgICBpZiAob3JpZ0RlZikgeyAvLyB3YXMgcHJldmlvdXNseSBpbiB0aGUgY2FsZW5kYXJcbiAgICAgICAgICAgICAgICBldmVudEFwaSA9IG5ldyBFdmVudEFwaShjYWxlbmRhciwgb3JpZ0RlZiwgb3JpZ0luc3RhbmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgeyAvLyB3YXMgYW4gZXh0ZXJuYWwgZXZlbnRcbiAgICAgICAgICAgICAgICBldmVudEFwaSA9IG5ldyBFdmVudEFwaShjYWxlbmRhciwgc3ViamVjdERlZik7IC8vIG5vIGluc3RhbmNlLCBiZWNhdXNlIGhhZCBubyBkYXRlc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzdWJqZWN0QWxsb3coY2FsZW5kYXIuYnVpbGREYXRlU3BhbkFwaShzdWJqZWN0RGF0ZVNwYW4pLCBldmVudEFwaSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG4vLyBEYXRlIFNlbGVjdGlvbiBWYWxpZGF0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGlzRGF0ZVNlbGVjdGlvblByb3BzVmFsaWQoc3RhdGUsIGNhbGVuZGFyLCBkYXRlU3Bhbk1ldGEsIGZpbHRlckNvbmZpZykge1xuICAgIHZhciByZWxldmFudEV2ZW50U3RvcmUgPSBzdGF0ZS5ldmVudFN0b3JlO1xuICAgIHZhciByZWxldmFudERlZnMgPSByZWxldmFudEV2ZW50U3RvcmUuZGVmcztcbiAgICB2YXIgcmVsZXZhbnRJbnN0YW5jZXMgPSByZWxldmFudEV2ZW50U3RvcmUuaW5zdGFuY2VzO1xuICAgIHZhciBzZWxlY3Rpb24gPSBzdGF0ZS5kYXRlU2VsZWN0aW9uO1xuICAgIHZhciBzZWxlY3Rpb25SYW5nZSA9IHNlbGVjdGlvbi5yYW5nZTtcbiAgICB2YXIgc2VsZWN0aW9uQ29uZmlnID0gY2FsZW5kYXIuc2VsZWN0aW9uQ29uZmlnO1xuICAgIGlmIChmaWx0ZXJDb25maWcpIHtcbiAgICAgICAgc2VsZWN0aW9uQ29uZmlnID0gZmlsdGVyQ29uZmlnKHNlbGVjdGlvbkNvbmZpZyk7XG4gICAgfVxuICAgIC8vIGNvbnN0cmFpbnRcbiAgICBpZiAoIWFsbENvbnN0cmFpbnRzUGFzcyhzZWxlY3Rpb25Db25maWcuY29uc3RyYWludHMsIHNlbGVjdGlvblJhbmdlLCByZWxldmFudEV2ZW50U3RvcmUsIHN0YXRlLmJ1c2luZXNzSG91cnMsIGNhbGVuZGFyKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIG92ZXJsYXBcbiAgICB2YXIgb3ZlcmxhcEZ1bmMgPSBjYWxlbmRhci5vcHQoJ3NlbGVjdE92ZXJsYXAnKTtcbiAgICBpZiAodHlwZW9mIG92ZXJsYXBGdW5jICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIG92ZXJsYXBGdW5jID0gbnVsbDtcbiAgICB9XG4gICAgZm9yICh2YXIgcmVsZXZhbnRJbnN0YW5jZUlkIGluIHJlbGV2YW50SW5zdGFuY2VzKSB7XG4gICAgICAgIHZhciByZWxldmFudEluc3RhbmNlID0gcmVsZXZhbnRJbnN0YW5jZXNbcmVsZXZhbnRJbnN0YW5jZUlkXTtcbiAgICAgICAgLy8gaW50ZXJzZWN0ISBldmFsdWF0ZVxuICAgICAgICBpZiAocmFuZ2VzSW50ZXJzZWN0KHNlbGVjdGlvblJhbmdlLCByZWxldmFudEluc3RhbmNlLnJhbmdlKSkge1xuICAgICAgICAgICAgaWYgKHNlbGVjdGlvbkNvbmZpZy5vdmVybGFwID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdmVybGFwRnVuYyAmJiAhb3ZlcmxhcEZ1bmMobmV3IEV2ZW50QXBpKGNhbGVuZGFyLCByZWxldmFudERlZnNbcmVsZXZhbnRJbnN0YW5jZS5kZWZJZF0sIHJlbGV2YW50SW5zdGFuY2UpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBhbGxvdyAoYSBmdW5jdGlvbilcbiAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gc2VsZWN0aW9uQ29uZmlnLmFsbG93czsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHNlbGVjdGlvbkFsbG93ID0gX2FbX2ldO1xuICAgICAgICB2YXIgZnVsbERhdGVTcGFuID0gX19hc3NpZ24oe30sIGRhdGVTcGFuTWV0YSwgc2VsZWN0aW9uKTtcbiAgICAgICAgaWYgKCFzZWxlY3Rpb25BbGxvdyhjYWxlbmRhci5idWlsZERhdGVTcGFuQXBpKGZ1bGxEYXRlU3BhbiksIG51bGwpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG4vLyBDb25zdHJhaW50IFV0aWxzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGFsbENvbnN0cmFpbnRzUGFzcyhjb25zdHJhaW50cywgc3ViamVjdFJhbmdlLCBvdGhlckV2ZW50U3RvcmUsIGJ1c2luZXNzSG91cnNVbmV4cGFuZGVkLCBjYWxlbmRhcikge1xuICAgIGZvciAodmFyIF9pID0gMCwgY29uc3RyYWludHNfMSA9IGNvbnN0cmFpbnRzOyBfaSA8IGNvbnN0cmFpbnRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBjb25zdHJhaW50ID0gY29uc3RyYWludHNfMVtfaV07XG4gICAgICAgIGlmICghYW55UmFuZ2VzQ29udGFpblJhbmdlKGNvbnN0cmFpbnRUb1Jhbmdlcyhjb25zdHJhaW50LCBzdWJqZWN0UmFuZ2UsIG90aGVyRXZlbnRTdG9yZSwgYnVzaW5lc3NIb3Vyc1VuZXhwYW5kZWQsIGNhbGVuZGFyKSwgc3ViamVjdFJhbmdlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gY29uc3RyYWludFRvUmFuZ2VzKGNvbnN0cmFpbnQsIHN1YmplY3RSYW5nZSwgLy8gZm9yIGV4cGFuZGluZyBhIHJlY3VycmluZyBjb25zdHJhaW50LCBvciBleHBhbmRpbmcgYnVzaW5lc3MgaG91cnNcbm90aGVyRXZlbnRTdG9yZSwgLy8gZm9yIGlmIGNvbnN0cmFpbnQgaXMgYW4gZXZlbiBncm91cCBJRFxuYnVzaW5lc3NIb3Vyc1VuZXhwYW5kZWQsIC8vIGZvciBpZiBjb25zdHJhaW50IGlzICdidXNpbmVzc0hvdXJzJ1xuY2FsZW5kYXIgLy8gZm9yIGV4cGFuZGluZyBidXNpbmVzc2hvdXJzXG4pIHtcbiAgICBpZiAoY29uc3RyYWludCA9PT0gJ2J1c2luZXNzSG91cnMnKSB7XG4gICAgICAgIHJldHVybiBldmVudFN0b3JlVG9SYW5nZXMoZXhwYW5kUmVjdXJyaW5nKGJ1c2luZXNzSG91cnNVbmV4cGFuZGVkLCBzdWJqZWN0UmFuZ2UsIGNhbGVuZGFyKSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBjb25zdHJhaW50ID09PSAnc3RyaW5nJykgeyAvLyBhbiBncm91cCBJRFxuICAgICAgICByZXR1cm4gZXZlbnRTdG9yZVRvUmFuZ2VzKGZpbHRlckV2ZW50U3RvcmVEZWZzKG90aGVyRXZlbnRTdG9yZSwgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gZXZlbnREZWYuZ3JvdXBJZCA9PT0gY29uc3RyYWludDtcbiAgICAgICAgfSkpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgY29uc3RyYWludCA9PT0gJ29iamVjdCcgJiYgY29uc3RyYWludCkgeyAvLyBub24tbnVsbCBvYmplY3RcbiAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmVUb1JhbmdlcyhleHBhbmRSZWN1cnJpbmcoY29uc3RyYWludCwgc3ViamVjdFJhbmdlLCBjYWxlbmRhcikpO1xuICAgIH1cbiAgICByZXR1cm4gW107IC8vIGlmIGl0J3MgZmFsc2Vcbn1cbi8vIFRPRE86IG1vdmUgdG8gZXZlbnQtc3RvcmUgZmlsZT9cbmZ1bmN0aW9uIGV2ZW50U3RvcmVUb1JhbmdlcyhldmVudFN0b3JlKSB7XG4gICAgdmFyIGluc3RhbmNlcyA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzO1xuICAgIHZhciByYW5nZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpbnN0YW5jZUlkIGluIGluc3RhbmNlcykge1xuICAgICAgICByYW5nZXMucHVzaChpbnN0YW5jZXNbaW5zdGFuY2VJZF0ucmFuZ2UpO1xuICAgIH1cbiAgICByZXR1cm4gcmFuZ2VzO1xufVxuLy8gVE9ETzogbW92ZSB0byBnZW9tIGZpbGU/XG5mdW5jdGlvbiBhbnlSYW5nZXNDb250YWluUmFuZ2Uob3V0ZXJSYW5nZXMsIGlubmVyUmFuZ2UpIHtcbiAgICBmb3IgKHZhciBfaSA9IDAsIG91dGVyUmFuZ2VzXzEgPSBvdXRlclJhbmdlczsgX2kgPCBvdXRlclJhbmdlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgb3V0ZXJSYW5nZSA9IG91dGVyUmFuZ2VzXzFbX2ldO1xuICAgICAgICBpZiAocmFuZ2VDb250YWluc1JhbmdlKG91dGVyUmFuZ2UsIGlubmVyUmFuZ2UpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG4vLyBQYXJzaW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIG5vcm1hbGl6ZUNvbnN0cmFpbnQoaW5wdXQsIGNhbGVuZGFyKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUV2ZW50cyhpbnB1dCwgJycsIGNhbGVuZGFyLCB0cnVlKTsgLy8gYWxsb3dPcGVuUmFuZ2U9dHJ1ZVxuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gcGFyc2VFdmVudHMoW2lucHV0XSwgJycsIGNhbGVuZGFyLCB0cnVlKTsgLy8gYWxsb3dPcGVuUmFuZ2U9dHJ1ZVxuICAgIH1cbiAgICBlbHNlIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoaW5wdXQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBodG1sRXNjYXBlKHMpIHtcbiAgICByZXR1cm4gKHMgKyAnJykucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpXG4gICAgICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgICAgICAgLnJlcGxhY2UoLycvZywgJyYjMDM5OycpXG4gICAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAgICAgLnJlcGxhY2UoL1xcbi9nLCAnPGJyIC8+Jyk7XG59XG4vLyBHaXZlbiBhIGhhc2ggb2YgQ1NTIHByb3BlcnRpZXMsIHJldHVybnMgYSBzdHJpbmcgb2YgQ1NTLlxuLy8gVXNlcyBwcm9wZXJ0eSBuYW1lcyBhcy1pcyAobm8gY2FtZWwtY2FzZSBjb252ZXJzaW9uKS4gV2lsbCBub3QgbWFrZSBzdGF0ZW1lbnRzIGZvciBudWxsL3VuZGVmaW5lZCB2YWx1ZXMuXG5mdW5jdGlvbiBjc3NUb1N0cihjc3NQcm9wcykge1xuICAgIHZhciBzdGF0ZW1lbnRzID0gW107XG4gICAgZm9yICh2YXIgbmFtZV8xIGluIGNzc1Byb3BzKSB7XG4gICAgICAgIHZhciB2YWwgPSBjc3NQcm9wc1tuYW1lXzFdO1xuICAgICAgICBpZiAodmFsICE9IG51bGwgJiYgdmFsICE9PSAnJykge1xuICAgICAgICAgICAgc3RhdGVtZW50cy5wdXNoKG5hbWVfMSArICc6JyArIHZhbCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0YXRlbWVudHMuam9pbignOycpO1xufVxuLy8gR2l2ZW4gYW4gb2JqZWN0IGhhc2ggb2YgSFRNTCBhdHRyaWJ1dGUgbmFtZXMgdG8gdmFsdWVzLFxuLy8gZ2VuZXJhdGVzIGEgc3RyaW5nIHRoYXQgY2FuIGJlIGluamVjdGVkIGJldHdlZW4gPCA+IGluIEhUTUxcbmZ1bmN0aW9uIGF0dHJzVG9TdHIoYXR0cnMpIHtcbiAgICB2YXIgcGFydHMgPSBbXTtcbiAgICBmb3IgKHZhciBuYW1lXzIgaW4gYXR0cnMpIHtcbiAgICAgICAgdmFyIHZhbCA9IGF0dHJzW25hbWVfMl07XG4gICAgICAgIGlmICh2YWwgIT0gbnVsbCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChuYW1lXzIgKyAnPVwiJyArIGh0bWxFc2NhcGUodmFsKSArICdcIicpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJ0cy5qb2luKCcgJyk7XG59XG5mdW5jdGlvbiBwYXJzZUNsYXNzTmFtZShyYXcpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShyYXcpKSB7XG4gICAgICAgIHJldHVybiByYXc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiByYXcuc3BsaXQoL1xccysvKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG59XG5cbnZhciBVTlNDT1BFRF9FVkVOVF9VSV9QUk9QUyA9IHtcbiAgICBlZGl0YWJsZTogQm9vbGVhbixcbiAgICBzdGFydEVkaXRhYmxlOiBCb29sZWFuLFxuICAgIGR1cmF0aW9uRWRpdGFibGU6IEJvb2xlYW4sXG4gICAgY29uc3RyYWludDogbnVsbCxcbiAgICBvdmVybGFwOiBudWxsLFxuICAgIGFsbG93OiBudWxsLFxuICAgIGNsYXNzTmFtZTogcGFyc2VDbGFzc05hbWUsXG4gICAgY2xhc3NOYW1lczogcGFyc2VDbGFzc05hbWUsXG4gICAgY29sb3I6IFN0cmluZyxcbiAgICBiYWNrZ3JvdW5kQ29sb3I6IFN0cmluZyxcbiAgICBib3JkZXJDb2xvcjogU3RyaW5nLFxuICAgIHRleHRDb2xvcjogU3RyaW5nXG59O1xuZnVuY3Rpb24gcHJvY2Vzc1Vuc2NvcGVkVWlQcm9wcyhyYXdQcm9wcywgY2FsZW5kYXIsIGxlZnRvdmVycykge1xuICAgIHZhciBwcm9wcyA9IHJlZmluZVByb3BzKHJhd1Byb3BzLCBVTlNDT1BFRF9FVkVOVF9VSV9QUk9QUywge30sIGxlZnRvdmVycyk7XG4gICAgdmFyIGNvbnN0cmFpbnQgPSBub3JtYWxpemVDb25zdHJhaW50KHByb3BzLmNvbnN0cmFpbnQsIGNhbGVuZGFyKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydEVkaXRhYmxlOiBwcm9wcy5zdGFydEVkaXRhYmxlICE9IG51bGwgPyBwcm9wcy5zdGFydEVkaXRhYmxlIDogcHJvcHMuZWRpdGFibGUsXG4gICAgICAgIGR1cmF0aW9uRWRpdGFibGU6IHByb3BzLmR1cmF0aW9uRWRpdGFibGUgIT0gbnVsbCA/IHByb3BzLmR1cmF0aW9uRWRpdGFibGUgOiBwcm9wcy5lZGl0YWJsZSxcbiAgICAgICAgY29uc3RyYWludHM6IGNvbnN0cmFpbnQgIT0gbnVsbCA/IFtjb25zdHJhaW50XSA6IFtdLFxuICAgICAgICBvdmVybGFwOiBwcm9wcy5vdmVybGFwLFxuICAgICAgICBhbGxvd3M6IHByb3BzLmFsbG93ICE9IG51bGwgPyBbcHJvcHMuYWxsb3ddIDogW10sXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogcHJvcHMuYmFja2dyb3VuZENvbG9yIHx8IHByb3BzLmNvbG9yLFxuICAgICAgICBib3JkZXJDb2xvcjogcHJvcHMuYm9yZGVyQ29sb3IgfHwgcHJvcHMuY29sb3IsXG4gICAgICAgIHRleHRDb2xvcjogcHJvcHMudGV4dENvbG9yLFxuICAgICAgICBjbGFzc05hbWVzOiBwcm9wcy5jbGFzc05hbWVzLmNvbmNhdChwcm9wcy5jbGFzc05hbWUpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHByb2Nlc3NTY29wZWRVaVByb3BzKHByZWZpeCwgcmF3U2NvcGVkLCBjYWxlbmRhciwgbGVmdG92ZXJzKSB7XG4gICAgdmFyIHJhd1Vuc2NvcGVkID0ge307XG4gICAgdmFyIHdhc0ZvdW5kID0ge307XG4gICAgZm9yICh2YXIga2V5IGluIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTKSB7XG4gICAgICAgIHZhciBzY29wZWRLZXkgPSBwcmVmaXggKyBjYXBpdGFsaXNlRmlyc3RMZXR0ZXIoa2V5KTtcbiAgICAgICAgcmF3VW5zY29wZWRba2V5XSA9IHJhd1Njb3BlZFtzY29wZWRLZXldO1xuICAgICAgICB3YXNGb3VuZFtzY29wZWRLZXldID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHByZWZpeCA9PT0gJ2V2ZW50Jykge1xuICAgICAgICByYXdVbnNjb3BlZC5lZGl0YWJsZSA9IHJhd1Njb3BlZC5lZGl0YWJsZTsgLy8gc3BlY2lhbCBjYXNlLiB0aGVyZSBpcyBubyAnZXZlbnRFZGl0YWJsZScsIGp1c3QgJ2VkaXRhYmxlJ1xuICAgIH1cbiAgICBpZiAobGVmdG92ZXJzKSB7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiByYXdTY29wZWQpIHtcbiAgICAgICAgICAgIGlmICghd2FzRm91bmRba2V5XSkge1xuICAgICAgICAgICAgICAgIGxlZnRvdmVyc1trZXldID0gcmF3U2NvcGVkW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHByb2Nlc3NVbnNjb3BlZFVpUHJvcHMocmF3VW5zY29wZWQsIGNhbGVuZGFyKTtcbn1cbnZhciBFTVBUWV9FVkVOVF9VSSA9IHtcbiAgICBzdGFydEVkaXRhYmxlOiBudWxsLFxuICAgIGR1cmF0aW9uRWRpdGFibGU6IG51bGwsXG4gICAgY29uc3RyYWludHM6IFtdLFxuICAgIG92ZXJsYXA6IG51bGwsXG4gICAgYWxsb3dzOiBbXSxcbiAgICBiYWNrZ3JvdW5kQ29sb3I6ICcnLFxuICAgIGJvcmRlckNvbG9yOiAnJyxcbiAgICB0ZXh0Q29sb3I6ICcnLFxuICAgIGNsYXNzTmFtZXM6IFtdXG59O1xuLy8gcHJldmVudCBhZ2FpbnN0IHByb2JsZW1zIHdpdGggPDIgYXJncyFcbmZ1bmN0aW9uIGNvbWJpbmVFdmVudFVpcyh1aXMpIHtcbiAgICByZXR1cm4gdWlzLnJlZHVjZShjb21iaW5lVHdvRXZlbnRVaXMsIEVNUFRZX0VWRU5UX1VJKTtcbn1cbmZ1bmN0aW9uIGNvbWJpbmVUd29FdmVudFVpcyhpdGVtMCwgaXRlbTEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydEVkaXRhYmxlOiBpdGVtMS5zdGFydEVkaXRhYmxlICE9IG51bGwgPyBpdGVtMS5zdGFydEVkaXRhYmxlIDogaXRlbTAuc3RhcnRFZGl0YWJsZSxcbiAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogaXRlbTEuZHVyYXRpb25FZGl0YWJsZSAhPSBudWxsID8gaXRlbTEuZHVyYXRpb25FZGl0YWJsZSA6IGl0ZW0wLmR1cmF0aW9uRWRpdGFibGUsXG4gICAgICAgIGNvbnN0cmFpbnRzOiBpdGVtMC5jb25zdHJhaW50cy5jb25jYXQoaXRlbTEuY29uc3RyYWludHMpLFxuICAgICAgICBvdmVybGFwOiB0eXBlb2YgaXRlbTEub3ZlcmxhcCA9PT0gJ2Jvb2xlYW4nID8gaXRlbTEub3ZlcmxhcCA6IGl0ZW0wLm92ZXJsYXAsXG4gICAgICAgIGFsbG93czogaXRlbTAuYWxsb3dzLmNvbmNhdChpdGVtMS5hbGxvd3MpLFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IGl0ZW0xLmJhY2tncm91bmRDb2xvciB8fCBpdGVtMC5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgIGJvcmRlckNvbG9yOiBpdGVtMS5ib3JkZXJDb2xvciB8fCBpdGVtMC5ib3JkZXJDb2xvcixcbiAgICAgICAgdGV4dENvbG9yOiBpdGVtMS50ZXh0Q29sb3IgfHwgaXRlbTAudGV4dENvbG9yLFxuICAgICAgICBjbGFzc05hbWVzOiBpdGVtMC5jbGFzc05hbWVzLmNvbmNhdChpdGVtMS5jbGFzc05hbWVzKVxuICAgIH07XG59XG5cbnZhciBOT05fREFURV9QUk9QUyA9IHtcbiAgICBpZDogU3RyaW5nLFxuICAgIGdyb3VwSWQ6IFN0cmluZyxcbiAgICB0aXRsZTogU3RyaW5nLFxuICAgIHVybDogU3RyaW5nLFxuICAgIHJlbmRlcmluZzogU3RyaW5nLFxuICAgIGV4dGVuZGVkUHJvcHM6IG51bGxcbn07XG52YXIgREFURV9QUk9QUyA9IHtcbiAgICBzdGFydDogbnVsbCxcbiAgICBkYXRlOiBudWxsLFxuICAgIGVuZDogbnVsbCxcbiAgICBhbGxEYXk6IG51bGxcbn07XG52YXIgdWlkID0gMDtcbmZ1bmN0aW9uIHBhcnNlRXZlbnQocmF3LCBzb3VyY2VJZCwgY2FsZW5kYXIsIGFsbG93T3BlblJhbmdlKSB7XG4gICAgdmFyIGFsbERheURlZmF1bHQgPSBjb21wdXRlSXNBbGxEYXlEZWZhdWx0KHNvdXJjZUlkLCBjYWxlbmRhcik7XG4gICAgdmFyIGxlZnRvdmVyczAgPSB7fTtcbiAgICB2YXIgcmVjdXJyaW5nUmVzID0gcGFyc2VSZWN1cnJpbmcocmF3LCAvLyByYXcsIGJ1dCB3aXRoIHNpbmdsZS1ldmVudCBzdHVmZiBzdHJpcHBlZCBvdXRcbiAgICBhbGxEYXlEZWZhdWx0LCBjYWxlbmRhci5kYXRlRW52LCBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MucmVjdXJyaW5nVHlwZXMsIGxlZnRvdmVyczAgLy8gd2lsbCBwb3B1bGF0ZSB3aXRoIG5vbi1yZWN1cnJpbmcgcHJvcHNcbiAgICApO1xuICAgIGlmIChyZWN1cnJpbmdSZXMpIHtcbiAgICAgICAgdmFyIGRlZiA9IHBhcnNlRXZlbnREZWYobGVmdG92ZXJzMCwgc291cmNlSWQsIHJlY3VycmluZ1Jlcy5hbGxEYXksIEJvb2xlYW4ocmVjdXJyaW5nUmVzLmR1cmF0aW9uKSwgY2FsZW5kYXIpO1xuICAgICAgICBkZWYucmVjdXJyaW5nRGVmID0ge1xuICAgICAgICAgICAgdHlwZUlkOiByZWN1cnJpbmdSZXMudHlwZUlkLFxuICAgICAgICAgICAgdHlwZURhdGE6IHJlY3VycmluZ1Jlcy50eXBlRGF0YSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiByZWN1cnJpbmdSZXMuZHVyYXRpb25cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHsgZGVmOiBkZWYsIGluc3RhbmNlOiBudWxsIH07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgbGVmdG92ZXJzMSA9IHt9O1xuICAgICAgICB2YXIgc2luZ2xlUmVzID0gcGFyc2VTaW5nbGUocmF3LCBhbGxEYXlEZWZhdWx0LCBjYWxlbmRhciwgbGVmdG92ZXJzMSwgYWxsb3dPcGVuUmFuZ2UpO1xuICAgICAgICBpZiAoc2luZ2xlUmVzKSB7XG4gICAgICAgICAgICB2YXIgZGVmID0gcGFyc2VFdmVudERlZihsZWZ0b3ZlcnMxLCBzb3VyY2VJZCwgc2luZ2xlUmVzLmFsbERheSwgc2luZ2xlUmVzLmhhc0VuZCwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIHNpbmdsZVJlcy5yYW5nZSwgc2luZ2xlUmVzLmZvcmNlZFN0YXJ0VHpvLCBzaW5nbGVSZXMuZm9yY2VkRW5kVHpvKTtcbiAgICAgICAgICAgIHJldHVybiB7IGRlZjogZGVmLCBpbnN0YW5jZTogaW5zdGFuY2UgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbi8qXG5XaWxsIE5PVCBwb3B1bGF0ZSBleHRlbmRlZFByb3BzIHdpdGggdGhlIGxlZnRvdmVyIHByb3BlcnRpZXMuXG5XaWxsIE5PVCBwb3B1bGF0ZSBkYXRlLXJlbGF0ZWQgcHJvcHMuXG5UaGUgRXZlbnROb25EYXRlSW5wdXQgaGFzIGJlZW4gbm9ybWFsaXplZCAoaWQgPT4gcHVibGljSWQsIGV0YykuXG4qL1xuZnVuY3Rpb24gcGFyc2VFdmVudERlZihyYXcsIHNvdXJjZUlkLCBhbGxEYXksIGhhc0VuZCwgY2FsZW5kYXIpIHtcbiAgICB2YXIgbGVmdG92ZXJzID0ge307XG4gICAgdmFyIGRlZiA9IHBsdWNrTm9uRGF0ZVByb3BzKHJhdywgY2FsZW5kYXIsIGxlZnRvdmVycyk7XG4gICAgZGVmLmRlZklkID0gU3RyaW5nKHVpZCsrKTtcbiAgICBkZWYuc291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICBkZWYuYWxsRGF5ID0gYWxsRGF5O1xuICAgIGRlZi5oYXNFbmQgPSBoYXNFbmQ7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudERlZlBhcnNlcnM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBldmVudERlZlBhcnNlciA9IF9hW19pXTtcbiAgICAgICAgdmFyIG5ld0xlZnRvdmVycyA9IHt9O1xuICAgICAgICBldmVudERlZlBhcnNlcihkZWYsIGxlZnRvdmVycywgbmV3TGVmdG92ZXJzKTtcbiAgICAgICAgbGVmdG92ZXJzID0gbmV3TGVmdG92ZXJzO1xuICAgIH1cbiAgICBkZWYuZXh0ZW5kZWRQcm9wcyA9IF9fYXNzaWduKGxlZnRvdmVycywgZGVmLmV4dGVuZGVkUHJvcHMgfHwge30pO1xuICAgIC8vIGhlbHAgb3V0IEV2ZW50QXBpIGZyb20gaGF2aW5nIHVzZXIgbW9kaWZ5IHByb3BzXG4gICAgT2JqZWN0LmZyZWV6ZShkZWYudWkuY2xhc3NOYW1lcyk7XG4gICAgT2JqZWN0LmZyZWV6ZShkZWYuZXh0ZW5kZWRQcm9wcyk7XG4gICAgcmV0dXJuIGRlZjtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUV2ZW50SW5zdGFuY2UoZGVmSWQsIHJhbmdlLCBmb3JjZWRTdGFydFR6bywgZm9yY2VkRW5kVHpvKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgaW5zdGFuY2VJZDogU3RyaW5nKHVpZCsrKSxcbiAgICAgICAgZGVmSWQ6IGRlZklkLFxuICAgICAgICByYW5nZTogcmFuZ2UsXG4gICAgICAgIGZvcmNlZFN0YXJ0VHpvOiBmb3JjZWRTdGFydFR6byA9PSBudWxsID8gbnVsbCA6IGZvcmNlZFN0YXJ0VHpvLFxuICAgICAgICBmb3JjZWRFbmRUem86IGZvcmNlZEVuZFR6byA9PSBudWxsID8gbnVsbCA6IGZvcmNlZEVuZFR6b1xuICAgIH07XG59XG5mdW5jdGlvbiBwYXJzZVNpbmdsZShyYXcsIGFsbERheURlZmF1bHQsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMsIGFsbG93T3BlblJhbmdlKSB7XG4gICAgdmFyIHByb3BzID0gcGx1Y2tEYXRlUHJvcHMocmF3LCBsZWZ0b3ZlcnMpO1xuICAgIHZhciBhbGxEYXkgPSBwcm9wcy5hbGxEYXk7XG4gICAgdmFyIHN0YXJ0TWV0YTtcbiAgICB2YXIgc3RhcnRNYXJrZXIgPSBudWxsO1xuICAgIHZhciBoYXNFbmQgPSBmYWxzZTtcbiAgICB2YXIgZW5kTWV0YTtcbiAgICB2YXIgZW5kTWFya2VyID0gbnVsbDtcbiAgICBzdGFydE1ldGEgPSBjYWxlbmRhci5kYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEocHJvcHMuc3RhcnQpO1xuICAgIGlmIChzdGFydE1ldGEpIHtcbiAgICAgICAgc3RhcnRNYXJrZXIgPSBzdGFydE1ldGEubWFya2VyO1xuICAgIH1cbiAgICBlbHNlIGlmICghYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChwcm9wcy5lbmQgIT0gbnVsbCkge1xuICAgICAgICBlbmRNZXRhID0gY2FsZW5kYXIuZGF0ZUVudi5jcmVhdGVNYXJrZXJNZXRhKHByb3BzLmVuZCk7XG4gICAgfVxuICAgIGlmIChhbGxEYXkgPT0gbnVsbCkge1xuICAgICAgICBpZiAoYWxsRGF5RGVmYXVsdCAhPSBudWxsKSB7XG4gICAgICAgICAgICBhbGxEYXkgPSBhbGxEYXlEZWZhdWx0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gZmFsbCBiYWNrIHRvIHRoZSBkYXRlIHByb3BzIExBU1RcbiAgICAgICAgICAgIGFsbERheSA9ICghc3RhcnRNZXRhIHx8IHN0YXJ0TWV0YS5pc1RpbWVVbnNwZWNpZmllZCkgJiZcbiAgICAgICAgICAgICAgICAoIWVuZE1ldGEgfHwgZW5kTWV0YS5pc1RpbWVVbnNwZWNpZmllZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGFsbERheSAmJiBzdGFydE1hcmtlcikge1xuICAgICAgICBzdGFydE1hcmtlciA9IHN0YXJ0T2ZEYXkoc3RhcnRNYXJrZXIpO1xuICAgIH1cbiAgICBpZiAoZW5kTWV0YSkge1xuICAgICAgICBlbmRNYXJrZXIgPSBlbmRNZXRhLm1hcmtlcjtcbiAgICAgICAgaWYgKGFsbERheSkge1xuICAgICAgICAgICAgZW5kTWFya2VyID0gc3RhcnRPZkRheShlbmRNYXJrZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGFydE1hcmtlciAmJiBlbmRNYXJrZXIgPD0gc3RhcnRNYXJrZXIpIHtcbiAgICAgICAgICAgIGVuZE1hcmtlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGVuZE1hcmtlcikge1xuICAgICAgICBoYXNFbmQgPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIGlmICghYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICAgICAgaGFzRW5kID0gY2FsZW5kYXIub3B0KCdmb3JjZUV2ZW50RHVyYXRpb24nKSB8fCBmYWxzZTtcbiAgICAgICAgZW5kTWFya2VyID0gY2FsZW5kYXIuZGF0ZUVudi5hZGQoc3RhcnRNYXJrZXIsIGFsbERheSA/XG4gICAgICAgICAgICBjYWxlbmRhci5kZWZhdWx0QWxsRGF5RXZlbnREdXJhdGlvbiA6XG4gICAgICAgICAgICBjYWxlbmRhci5kZWZhdWx0VGltZWRFdmVudER1cmF0aW9uKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWxsRGF5OiBhbGxEYXksXG4gICAgICAgIGhhc0VuZDogaGFzRW5kLFxuICAgICAgICByYW5nZTogeyBzdGFydDogc3RhcnRNYXJrZXIsIGVuZDogZW5kTWFya2VyIH0sXG4gICAgICAgIGZvcmNlZFN0YXJ0VHpvOiBzdGFydE1ldGEgPyBzdGFydE1ldGEuZm9yY2VkVHpvIDogbnVsbCxcbiAgICAgICAgZm9yY2VkRW5kVHpvOiBlbmRNZXRhID8gZW5kTWV0YS5mb3JjZWRUem8gOiBudWxsXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHBsdWNrRGF0ZVByb3BzKHJhdywgbGVmdG92ZXJzKSB7XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3LCBEQVRFX1BST1BTLCB7fSwgbGVmdG92ZXJzKTtcbiAgICBwcm9wcy5zdGFydCA9IChwcm9wcy5zdGFydCAhPT0gbnVsbCkgPyBwcm9wcy5zdGFydCA6IHByb3BzLmRhdGU7XG4gICAgZGVsZXRlIHByb3BzLmRhdGU7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuZnVuY3Rpb24gcGx1Y2tOb25EYXRlUHJvcHMocmF3LCBjYWxlbmRhciwgbGVmdG92ZXJzKSB7XG4gICAgdmFyIHByZUxlZnRvdmVycyA9IHt9O1xuICAgIHZhciBwcm9wcyA9IHJlZmluZVByb3BzKHJhdywgTk9OX0RBVEVfUFJPUFMsIHt9LCBwcmVMZWZ0b3ZlcnMpO1xuICAgIHZhciB1aSA9IHByb2Nlc3NVbnNjb3BlZFVpUHJvcHMocHJlTGVmdG92ZXJzLCBjYWxlbmRhciwgbGVmdG92ZXJzKTtcbiAgICBwcm9wcy5wdWJsaWNJZCA9IHByb3BzLmlkO1xuICAgIGRlbGV0ZSBwcm9wcy5pZDtcbiAgICBwcm9wcy51aSA9IHVpO1xuICAgIHJldHVybiBwcm9wcztcbn1cbmZ1bmN0aW9uIGNvbXB1dGVJc0FsbERheURlZmF1bHQoc291cmNlSWQsIGNhbGVuZGFyKSB7XG4gICAgdmFyIHJlcyA9IG51bGw7XG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBjYWxlbmRhci5zdGF0ZS5ldmVudFNvdXJjZXNbc291cmNlSWRdO1xuICAgICAgICByZXMgPSBzb3VyY2UuYWxsRGF5RGVmYXVsdDtcbiAgICB9XG4gICAgaWYgKHJlcyA9PSBudWxsKSB7XG4gICAgICAgIHJlcyA9IGNhbGVuZGFyLm9wdCgnYWxsRGF5RGVmYXVsdCcpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG52YXIgREVGX0RFRkFVTFRTID0ge1xuICAgIHN0YXJ0VGltZTogJzA5OjAwJyxcbiAgICBlbmRUaW1lOiAnMTc6MDAnLFxuICAgIGRheXNPZldlZWs6IFsxLCAyLCAzLCA0LCA1XSxcbiAgICByZW5kZXJpbmc6ICdpbnZlcnNlLWJhY2tncm91bmQnLFxuICAgIGNsYXNzTmFtZXM6ICdmYy1ub25idXNpbmVzcycsXG4gICAgZ3JvdXBJZDogJ19idXNpbmVzc0hvdXJzJyAvLyBzbyBtdWx0aXBsZSBkZWZzIGdldCBncm91cGVkXG59O1xuLypcblRPRE86IHBhc3MgYXJvdW5kIGFzIEV2ZW50RGVmSGFzaCEhIVxuKi9cbmZ1bmN0aW9uIHBhcnNlQnVzaW5lc3NIb3VycyhpbnB1dCwgY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gcGFyc2VFdmVudHMocmVmaW5lSW5wdXRzKGlucHV0KSwgJycsIGNhbGVuZGFyKTtcbn1cbmZ1bmN0aW9uIHJlZmluZUlucHV0cyhpbnB1dCkge1xuICAgIHZhciByYXdEZWZzO1xuICAgIGlmIChpbnB1dCA9PT0gdHJ1ZSkge1xuICAgICAgICByYXdEZWZzID0gW3t9XTsgLy8gd2lsbCBnZXQgREVGX0RFRkFVTFRTIHZlcmJhdGltXG4gICAgfVxuICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgIC8vIGlmIHNwZWNpZnlpbmcgYW4gYXJyYXksIGV2ZXJ5IHN1Yi1kZWZpbml0aW9uIE5FRURTIGEgZGF5LW9mLXdlZWtcbiAgICAgICAgcmF3RGVmcyA9IGlucHV0LmZpbHRlcihmdW5jdGlvbiAocmF3RGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gcmF3RGVmLmRheXNPZldlZWs7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByYXdEZWZzID0gW2lucHV0XTtcbiAgICB9XG4gICAgZWxzZSB7IC8vIGlzIHByb2JhYmx5IGZhbHNlXG4gICAgICAgIHJhd0RlZnMgPSBbXTtcbiAgICB9XG4gICAgcmF3RGVmcyA9IHJhd0RlZnMubWFwKGZ1bmN0aW9uIChyYXdEZWYpIHtcbiAgICAgICAgcmV0dXJuIF9fYXNzaWduKHt9LCBERUZfREVGQVVMVFMsIHJhd0RlZik7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJhd0RlZnM7XG59XG5cbmZ1bmN0aW9uIG1lbW9pemVSZW5kZXJpbmcocmVuZGVyRnVuYywgdW5yZW5kZXJGdW5jLCBkZXBlbmRlbmNpZXMpIHtcbiAgICBpZiAoZGVwZW5kZW5jaWVzID09PSB2b2lkIDApIHsgZGVwZW5kZW5jaWVzID0gW107IH1cbiAgICB2YXIgZGVwZW5kZW50cyA9IFtdO1xuICAgIHZhciB0aGlzQ29udGV4dDtcbiAgICB2YXIgcHJldkFyZ3M7XG4gICAgZnVuY3Rpb24gdW5yZW5kZXIoKSB7XG4gICAgICAgIGlmIChwcmV2QXJncykge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBkZXBlbmRlbnRzXzEgPSBkZXBlbmRlbnRzOyBfaSA8IGRlcGVuZGVudHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVwZW5kZW50ID0gZGVwZW5kZW50c18xW19pXTtcbiAgICAgICAgICAgICAgICBkZXBlbmRlbnQudW5yZW5kZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bnJlbmRlckZ1bmMpIHtcbiAgICAgICAgICAgICAgICB1bnJlbmRlckZ1bmMuYXBwbHkodGhpc0NvbnRleHQsIHByZXZBcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByZXZBcmdzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiByZXMoKSB7XG4gICAgICAgIGlmICghcHJldkFyZ3MgfHwgIWlzQXJyYXlzRXF1YWwocHJldkFyZ3MsIGFyZ3VtZW50cykpIHtcbiAgICAgICAgICAgIHVucmVuZGVyKCk7XG4gICAgICAgICAgICB0aGlzQ29udGV4dCA9IHRoaXM7XG4gICAgICAgICAgICBwcmV2QXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgIHJlbmRlckZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXMuZGVwZW5kZW50cyA9IGRlcGVuZGVudHM7XG4gICAgcmVzLnVucmVuZGVyID0gdW5yZW5kZXI7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBkZXBlbmRlbmNpZXNfMSA9IGRlcGVuZGVuY2llczsgX2kgPCBkZXBlbmRlbmNpZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIGRlcGVuZGVuY3kgPSBkZXBlbmRlbmNpZXNfMVtfaV07XG4gICAgICAgIGRlcGVuZGVuY3kuZGVwZW5kZW50cy5wdXNoKHJlcyk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5cbnZhciBFTVBUWV9FVkVOVF9TVE9SRSA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpOyAvLyBmb3IgcHVyZWNvbXBvbmVudHMuIFRPRE86IGtlZXAgZWxzZXdoZXJlXG52YXIgU3BsaXR0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU3BsaXR0ZXIoKSB7XG4gICAgICAgIHRoaXMuZ2V0S2V5c0ZvckV2ZW50RGVmcyA9IG1lbW9pemUodGhpcy5fZ2V0S2V5c0ZvckV2ZW50RGVmcyk7XG4gICAgICAgIHRoaXMuc3BsaXREYXRlU2VsZWN0aW9uID0gbWVtb2l6ZSh0aGlzLl9zcGxpdERhdGVTcGFuKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50U3RvcmUgPSBtZW1vaXplKHRoaXMuX3NwbGl0RXZlbnRTdG9yZSk7XG4gICAgICAgIHRoaXMuc3BsaXRJbmRpdmlkdWFsVWkgPSBtZW1vaXplKHRoaXMuX3NwbGl0SW5kaXZpZHVhbFVpKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50RHJhZyA9IG1lbW9pemUodGhpcy5fc3BsaXRJbnRlcmFjdGlvbik7XG4gICAgICAgIHRoaXMuc3BsaXRFdmVudFJlc2l6ZSA9IG1lbW9pemUodGhpcy5fc3BsaXRJbnRlcmFjdGlvbik7XG4gICAgICAgIHRoaXMuZXZlbnRVaUJ1aWxkZXJzID0ge307IC8vIFRPRE86IHR5cGVzY3JpcHQgcHJvdGVjdGlvblxuICAgIH1cbiAgICBTcGxpdHRlci5wcm90b3R5cGUuc3BsaXRQcm9wcyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIga2V5SW5mb3MgPSB0aGlzLmdldEtleUluZm8ocHJvcHMpO1xuICAgICAgICB2YXIgZGVmS2V5cyA9IHRoaXMuZ2V0S2V5c0ZvckV2ZW50RGVmcyhwcm9wcy5ldmVudFN0b3JlKTtcbiAgICAgICAgdmFyIGRhdGVTZWxlY3Rpb25zID0gdGhpcy5zcGxpdERhdGVTZWxlY3Rpb24ocHJvcHMuZGF0ZVNlbGVjdGlvbik7XG4gICAgICAgIHZhciBpbmRpdmlkdWFsVWkgPSB0aGlzLnNwbGl0SW5kaXZpZHVhbFVpKHByb3BzLmV2ZW50VWlCYXNlcywgZGVmS2V5cyk7IC8vIHRoZSBpbmRpdmlkdWFsICpiYXNlcypcbiAgICAgICAgdmFyIGV2ZW50U3RvcmVzID0gdGhpcy5zcGxpdEV2ZW50U3RvcmUocHJvcHMuZXZlbnRTdG9yZSwgZGVmS2V5cyk7XG4gICAgICAgIHZhciBldmVudERyYWdzID0gdGhpcy5zcGxpdEV2ZW50RHJhZyhwcm9wcy5ldmVudERyYWcpO1xuICAgICAgICB2YXIgZXZlbnRSZXNpemVzID0gdGhpcy5zcGxpdEV2ZW50UmVzaXplKHByb3BzLmV2ZW50UmVzaXplKTtcbiAgICAgICAgdmFyIHNwbGl0UHJvcHMgPSB7fTtcbiAgICAgICAgdGhpcy5ldmVudFVpQnVpbGRlcnMgPSBtYXBIYXNoKGtleUluZm9zLCBmdW5jdGlvbiAoaW5mbywga2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuZXZlbnRVaUJ1aWxkZXJzW2tleV0gfHwgbWVtb2l6ZShidWlsZEV2ZW50VWlGb3JLZXkpO1xuICAgICAgICB9KTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIGtleUluZm9zKSB7XG4gICAgICAgICAgICB2YXIga2V5SW5mbyA9IGtleUluZm9zW2tleV07XG4gICAgICAgICAgICB2YXIgZXZlbnRTdG9yZSA9IGV2ZW50U3RvcmVzW2tleV0gfHwgRU1QVFlfRVZFTlRfU1RPUkU7XG4gICAgICAgICAgICB2YXIgYnVpbGRFdmVudFVpID0gdGhpcy5ldmVudFVpQnVpbGRlcnNba2V5XTtcbiAgICAgICAgICAgIHNwbGl0UHJvcHNba2V5XSA9IHtcbiAgICAgICAgICAgICAgICBidXNpbmVzc0hvdXJzOiBrZXlJbmZvLmJ1c2luZXNzSG91cnMgfHwgcHJvcHMuYnVzaW5lc3NIb3VycyxcbiAgICAgICAgICAgICAgICBkYXRlU2VsZWN0aW9uOiBkYXRlU2VsZWN0aW9uc1trZXldIHx8IG51bGwsXG4gICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogZXZlbnRTdG9yZSxcbiAgICAgICAgICAgICAgICBldmVudFVpQmFzZXM6IGJ1aWxkRXZlbnRVaShwcm9wcy5ldmVudFVpQmFzZXNbJyddLCBrZXlJbmZvLnVpLCBpbmRpdmlkdWFsVWlba2V5XSksXG4gICAgICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246IGV2ZW50U3RvcmUuaW5zdGFuY2VzW3Byb3BzLmV2ZW50U2VsZWN0aW9uXSA/IHByb3BzLmV2ZW50U2VsZWN0aW9uIDogJycsXG4gICAgICAgICAgICAgICAgZXZlbnREcmFnOiBldmVudERyYWdzW2tleV0gfHwgbnVsbCxcbiAgICAgICAgICAgICAgICBldmVudFJlc2l6ZTogZXZlbnRSZXNpemVzW2tleV0gfHwgbnVsbFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3BsaXRQcm9wcztcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fc3BsaXREYXRlU3BhbiA9IGZ1bmN0aW9uIChkYXRlU3Bhbikge1xuICAgICAgICB2YXIgZGF0ZVNwYW5zID0ge307XG4gICAgICAgIGlmIChkYXRlU3Bhbikge1xuICAgICAgICAgICAgdmFyIGtleXMgPSB0aGlzLmdldEtleXNGb3JEYXRlU3BhbihkYXRlU3Bhbik7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIGtleXNfMSA9IGtleXM7IF9pIDwga2V5c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBrZXlzXzFbX2ldO1xuICAgICAgICAgICAgICAgIGRhdGVTcGFuc1trZXldID0gZGF0ZVNwYW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGVTcGFucztcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fZ2V0S2V5c0ZvckV2ZW50RGVmcyA9IGZ1bmN0aW9uIChldmVudFN0b3JlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBtYXBIYXNoKGV2ZW50U3RvcmUuZGVmcywgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuZ2V0S2V5c0ZvckV2ZW50RGVmKGV2ZW50RGVmKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBTcGxpdHRlci5wcm90b3R5cGUuX3NwbGl0RXZlbnRTdG9yZSA9IGZ1bmN0aW9uIChldmVudFN0b3JlLCBkZWZLZXlzKSB7XG4gICAgICAgIHZhciBkZWZzID0gZXZlbnRTdG9yZS5kZWZzLCBpbnN0YW5jZXMgPSBldmVudFN0b3JlLmluc3RhbmNlcztcbiAgICAgICAgdmFyIHNwbGl0U3RvcmVzID0ge307XG4gICAgICAgIGZvciAodmFyIGRlZklkIGluIGRlZnMpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBkZWZLZXlzW2RlZklkXTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIGlmICghc3BsaXRTdG9yZXNba2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBzcGxpdFN0b3Jlc1trZXldID0gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNwbGl0U3RvcmVzW2tleV0uZGVmc1tkZWZJZF0gPSBkZWZzW2RlZklkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpbnN0YW5jZUlkIGluIGluc3RhbmNlcykge1xuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gaW5zdGFuY2VzW2luc3RhbmNlSWRdO1xuICAgICAgICAgICAgZm9yICh2YXIgX2IgPSAwLCBfYyA9IGRlZktleXNbaW5zdGFuY2UuZGVmSWRdOyBfYiA8IF9jLmxlbmd0aDsgX2IrKykge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBfY1tfYl07XG4gICAgICAgICAgICAgICAgaWYgKHNwbGl0U3RvcmVzW2tleV0pIHsgLy8gbXVzdCBoYXZlIGFscmVhZHkgYmVlbiBjcmVhdGVkXG4gICAgICAgICAgICAgICAgICAgIHNwbGl0U3RvcmVzW2tleV0uaW5zdGFuY2VzW2luc3RhbmNlSWRdID0gaW5zdGFuY2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdFN0b3JlcztcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fc3BsaXRJbmRpdmlkdWFsVWkgPSBmdW5jdGlvbiAoZXZlbnRVaUJhc2VzLCBkZWZLZXlzKSB7XG4gICAgICAgIHZhciBzcGxpdEhhc2hlcyA9IHt9O1xuICAgICAgICBmb3IgKHZhciBkZWZJZCBpbiBldmVudFVpQmFzZXMpIHtcbiAgICAgICAgICAgIGlmIChkZWZJZCkgeyAvLyBub3QgdGhlICcnIGtleVxuICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBkZWZLZXlzW2RlZklkXTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGtleSA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzcGxpdEhhc2hlc1trZXldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcGxpdEhhc2hlc1trZXldID0ge307XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc3BsaXRIYXNoZXNba2V5XVtkZWZJZF0gPSBldmVudFVpQmFzZXNbZGVmSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3BsaXRIYXNoZXM7XG4gICAgfTtcbiAgICBTcGxpdHRlci5wcm90b3R5cGUuX3NwbGl0SW50ZXJhY3Rpb24gPSBmdW5jdGlvbiAoaW50ZXJhY3Rpb24pIHtcbiAgICAgICAgdmFyIHNwbGl0U3RhdGVzID0ge307XG4gICAgICAgIGlmIChpbnRlcmFjdGlvbikge1xuICAgICAgICAgICAgdmFyIGFmZmVjdGVkU3RvcmVzXzEgPSB0aGlzLl9zcGxpdEV2ZW50U3RvcmUoaW50ZXJhY3Rpb24uYWZmZWN0ZWRFdmVudHMsIHRoaXMuX2dldEtleXNGb3JFdmVudERlZnMoaW50ZXJhY3Rpb24uYWZmZWN0ZWRFdmVudHMpIC8vIGNhbid0IHVzZSBjYWNoZWQuIG1pZ2h0IGJlIGV2ZW50cyBmcm9tIG90aGVyIGNhbGVuZGFyXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgLy8gY2FuJ3QgcmVseSBvbiBkZWZLZXlzIGJlY2F1c2UgZXZlbnQgZGF0YSBpcyBtdXRhdGVkXG4gICAgICAgICAgICB2YXIgbXV0YXRlZEtleXNCeURlZklkID0gdGhpcy5fZ2V0S2V5c0ZvckV2ZW50RGVmcyhpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzKTtcbiAgICAgICAgICAgIHZhciBtdXRhdGVkU3RvcmVzXzEgPSB0aGlzLl9zcGxpdEV2ZW50U3RvcmUoaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cywgbXV0YXRlZEtleXNCeURlZklkKTtcbiAgICAgICAgICAgIHZhciBwb3B1bGF0ZSA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXNwbGl0U3RhdGVzW2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgc3BsaXRTdGF0ZXNba2V5XSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFmZmVjdGVkRXZlbnRzOiBhZmZlY3RlZFN0b3Jlc18xW2tleV0gfHwgRU1QVFlfRVZFTlRfU1RPUkUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGVkRXZlbnRzOiBtdXRhdGVkU3RvcmVzXzFba2V5XSB8fCBFTVBUWV9FVkVOVF9TVE9SRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzRXZlbnQ6IGludGVyYWN0aW9uLmlzRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcmlnU2VnOiBpbnRlcmFjdGlvbi5vcmlnU2VnXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBhZmZlY3RlZFN0b3Jlc18xKSB7XG4gICAgICAgICAgICAgICAgcG9wdWxhdGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBtdXRhdGVkU3RvcmVzXzEpIHtcbiAgICAgICAgICAgICAgICBwb3B1bGF0ZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdFN0YXRlcztcbiAgICB9O1xuICAgIHJldHVybiBTcGxpdHRlcjtcbn0oKSk7XG5mdW5jdGlvbiBidWlsZEV2ZW50VWlGb3JLZXkoYWxsVWksIGV2ZW50VWlGb3JLZXksIGluZGl2aWR1YWxVaSkge1xuICAgIHZhciBiYXNlUGFydHMgPSBbXTtcbiAgICBpZiAoYWxsVWkpIHtcbiAgICAgICAgYmFzZVBhcnRzLnB1c2goYWxsVWkpO1xuICAgIH1cbiAgICBpZiAoZXZlbnRVaUZvcktleSkge1xuICAgICAgICBiYXNlUGFydHMucHVzaChldmVudFVpRm9yS2V5KTtcbiAgICB9XG4gICAgdmFyIHN0dWZmID0ge1xuICAgICAgICAnJzogY29tYmluZUV2ZW50VWlzKGJhc2VQYXJ0cylcbiAgICB9O1xuICAgIGlmIChpbmRpdmlkdWFsVWkpIHtcbiAgICAgICAgX19hc3NpZ24oc3R1ZmYsIGluZGl2aWR1YWxVaSk7XG4gICAgfVxuICAgIHJldHVybiBzdHVmZjtcbn1cblxuLy8gR2VuZXJhdGVzIEhUTUwgZm9yIGFuIGFuY2hvciB0byBhbm90aGVyIHZpZXcgaW50byB0aGUgY2FsZW5kYXIuXG4vLyBXaWxsIGVpdGhlciBnZW5lcmF0ZSBhbiA8YT4gdGFnIG9yIGEgbm9uLWNsaWNrYWJsZSA8c3Bhbj4gdGFnLCBkZXBlbmRpbmcgb24gZW5hYmxlZCBzZXR0aW5ncy5cbi8vIGBnb3RvT3B0aW9uc2AgY2FuIGVpdGhlciBiZSBhIERhdGVNYXJrZXIsIG9yIGFuIG9iamVjdCB3aXRoIHRoZSBmb3JtOlxuLy8geyBkYXRlLCB0eXBlLCBmb3JjZU9mZiB9XG4vLyBgdHlwZWAgaXMgYSB2aWV3LXR5cGUgbGlrZSBcImRheVwiIG9yIFwid2Vla1wiLiBkZWZhdWx0IHZhbHVlIGlzIFwiZGF5XCIuXG4vLyBgYXR0cnNgIGFuZCBgaW5uZXJIdG1sYCBhcmUgdXNlIHRvIGdlbmVyYXRlIHRoZSByZXN0IG9mIHRoZSBIVE1MIHRhZy5cbmZ1bmN0aW9uIGJ1aWxkR290b0FuY2hvckh0bWwoYWxsT3B0aW9ucywgZGF0ZUVudiwgZ290b09wdGlvbnMsIGF0dHJzLCBpbm5lckh0bWwpIHtcbiAgICB2YXIgZGF0ZTtcbiAgICB2YXIgdHlwZTtcbiAgICB2YXIgZm9yY2VPZmY7XG4gICAgdmFyIGZpbmFsT3B0aW9ucztcbiAgICBpZiAoZ290b09wdGlvbnMgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIGRhdGUgPSBnb3RvT3B0aW9uczsgLy8gYSBzaW5nbGUgZGF0ZS1saWtlIGlucHV0XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBkYXRlID0gZ290b09wdGlvbnMuZGF0ZTtcbiAgICAgICAgdHlwZSA9IGdvdG9PcHRpb25zLnR5cGU7XG4gICAgICAgIGZvcmNlT2ZmID0gZ290b09wdGlvbnMuZm9yY2VPZmY7XG4gICAgfVxuICAgIGZpbmFsT3B0aW9ucyA9IHtcbiAgICAgICAgZGF0ZTogZGF0ZUVudi5mb3JtYXRJc28oZGF0ZSwgeyBvbWl0VGltZTogdHJ1ZSB9KSxcbiAgICAgICAgdHlwZTogdHlwZSB8fCAnZGF5J1xuICAgIH07XG4gICAgaWYgKHR5cGVvZiBhdHRycyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaW5uZXJIdG1sID0gYXR0cnM7XG4gICAgICAgIGF0dHJzID0gbnVsbDtcbiAgICB9XG4gICAgYXR0cnMgPSBhdHRycyA/ICcgJyArIGF0dHJzVG9TdHIoYXR0cnMpIDogJyc7IC8vIHdpbGwgaGF2ZSBhIGxlYWRpbmcgc3BhY2VcbiAgICBpbm5lckh0bWwgPSBpbm5lckh0bWwgfHwgJyc7XG4gICAgaWYgKCFmb3JjZU9mZiAmJiBhbGxPcHRpb25zLm5hdkxpbmtzKSB7XG4gICAgICAgIHJldHVybiAnPGEnICsgYXR0cnMgK1xuICAgICAgICAgICAgJyBkYXRhLWdvdG89XCInICsgaHRtbEVzY2FwZShKU09OLnN0cmluZ2lmeShmaW5hbE9wdGlvbnMpKSArICdcIj4nICtcbiAgICAgICAgICAgIGlubmVySHRtbCArXG4gICAgICAgICAgICAnPC9hPic7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gJzxzcGFuJyArIGF0dHJzICsgJz4nICtcbiAgICAgICAgICAgIGlubmVySHRtbCArXG4gICAgICAgICAgICAnPC9zcGFuPic7XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0QWxsRGF5SHRtbChhbGxPcHRpb25zKSB7XG4gICAgcmV0dXJuIGFsbE9wdGlvbnMuYWxsRGF5SHRtbCB8fCBodG1sRXNjYXBlKGFsbE9wdGlvbnMuYWxsRGF5VGV4dCk7XG59XG4vLyBDb21wdXRlcyBIVE1MIGNsYXNzTmFtZXMgZm9yIGEgc2luZ2xlLWRheSBlbGVtZW50XG5mdW5jdGlvbiBnZXREYXlDbGFzc2VzKGRhdGUsIGRhdGVQcm9maWxlLCBjb250ZXh0LCBub1RoZW1lSGlnaGxpZ2h0KSB7XG4gICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhciwgb3B0aW9ucyA9IGNvbnRleHQub3B0aW9ucywgdGhlbWUgPSBjb250ZXh0LnRoZW1lLCBkYXRlRW52ID0gY29udGV4dC5kYXRlRW52O1xuICAgIHZhciBjbGFzc2VzID0gW107XG4gICAgdmFyIHRvZGF5U3RhcnQ7XG4gICAgdmFyIHRvZGF5RW5kO1xuICAgIGlmICghcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgZGF0ZSkpIHtcbiAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1kaXNhYmxlZC1kYXknKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNsYXNzZXMucHVzaCgnZmMtJyArIERBWV9JRFNbZGF0ZS5nZXRVVENEYXkoKV0pO1xuICAgICAgICBpZiAob3B0aW9ucy5tb250aE1vZGUgJiZcbiAgICAgICAgICAgIGRhdGVFbnYuZ2V0TW9udGgoZGF0ZSkgIT09IGRhdGVFbnYuZ2V0TW9udGgoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0KSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1vdGhlci1tb250aCcpO1xuICAgICAgICB9XG4gICAgICAgIHRvZGF5U3RhcnQgPSBzdGFydE9mRGF5KGNhbGVuZGFyLmdldE5vdygpKTtcbiAgICAgICAgdG9kYXlFbmQgPSBhZGREYXlzKHRvZGF5U3RhcnQsIDEpO1xuICAgICAgICBpZiAoZGF0ZSA8IHRvZGF5U3RhcnQpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtcGFzdCcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGRhdGUgPj0gdG9kYXlFbmQpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtZnV0dXJlJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLXRvZGF5Jyk7XG4gICAgICAgICAgICBpZiAobm9UaGVtZUhpZ2hsaWdodCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCh0aGVtZS5nZXRDbGFzcygndG9kYXknKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNsYXNzZXM7XG59XG5cbi8vIGdpdmVuIGEgZnVuY3Rpb24gdGhhdCByZXNvbHZlcyBhIHJlc3VsdCBhc3luY2hyb25vdXNseS5cbi8vIHRoZSBmdW5jdGlvbiBjYW4gZWl0aGVyIGNhbGwgcGFzc2VkLWluIHN1Y2Nlc3MgYW5kIGZhaWx1cmUgY2FsbGJhY2tzLFxuLy8gb3IgaXQgY2FuIHJldHVybiBhIHByb21pc2UuXG4vLyBpZiB5b3UgbmVlZCB0byBwYXNzIGFkZGl0aW9uYWwgcGFyYW1zIHRvIGZ1bmMsIGJpbmQgdGhlbSBmaXJzdC5cbmZ1bmN0aW9uIHVucHJvbWlzaWZ5KGZ1bmMsIHN1Y2Nlc3MsIGZhaWx1cmUpIHtcbiAgICAvLyBndWFyZCBhZ2FpbnN0IHN1Y2Nlc3MvZmFpbHVyZSBjYWxsYmFja3MgYmVpbmcgY2FsbGVkIG1vcmUgdGhhbiBvbmNlXG4gICAgLy8gYW5kIGd1YXJkIGFnYWluc3QgYSBwcm9taXNlIEFORCBjYWxsYmFjayBiZWluZyB1c2VkIHRvZ2V0aGVyLlxuICAgIHZhciBpc1Jlc29sdmVkID0gZmFsc2U7XG4gICAgdmFyIHdyYXBwZWRTdWNjZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWlzUmVzb2x2ZWQpIHtcbiAgICAgICAgICAgIGlzUmVzb2x2ZWQgPSB0cnVlO1xuICAgICAgICAgICAgc3VjY2Vzcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICB2YXIgd3JhcHBlZEZhaWx1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghaXNSZXNvbHZlZCkge1xuICAgICAgICAgICAgaXNSZXNvbHZlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoZmFpbHVyZSkge1xuICAgICAgICAgICAgICAgIGZhaWx1cmUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgdmFyIHJlcyA9IGZ1bmMod3JhcHBlZFN1Y2Nlc3MsIHdyYXBwZWRGYWlsdXJlKTtcbiAgICBpZiAocmVzICYmIHR5cGVvZiByZXMudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXMudGhlbih3cmFwcGVkU3VjY2Vzcywgd3JhcHBlZEZhaWx1cmUpO1xuICAgIH1cbn1cblxudmFyIE1peGluID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE1peGluKCkge1xuICAgIH1cbiAgICAvLyBtaXggaW50byBhIENMQVNTXG4gICAgTWl4aW4ubWl4SW50byA9IGZ1bmN0aW9uIChkZXN0Q2xhc3MpIHtcbiAgICAgICAgdGhpcy5taXhJbnRvT2JqKGRlc3RDbGFzcy5wcm90b3R5cGUpO1xuICAgIH07XG4gICAgLy8gbWl4IGludG8gQU5ZIG9iamVjdFxuICAgIE1peGluLm1peEludG9PYmogPSBmdW5jdGlvbiAoZGVzdE9iaikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzLnByb3RvdHlwZSkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgaWYgKCFkZXN0T2JqW25hbWVdKSB7IC8vIGlmIGRlc3RpbmF0aW9uIGRvZXNuJ3QgYWxyZWFkeSBkZWZpbmUgaXRcbiAgICAgICAgICAgICAgICBkZXN0T2JqW25hbWVdID0gX3RoaXMucHJvdG90eXBlW25hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8qXG4gICAgd2lsbCBvdmVycmlkZSBleGlzdGluZyBtZXRob2RzXG4gICAgVE9ETzogcmVtb3ZlISBub3QgdXNlZCBhbnltb3JlXG4gICAgKi9cbiAgICBNaXhpbi5taXhPdmVyID0gZnVuY3Rpb24gKGRlc3RDbGFzcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzLnByb3RvdHlwZSkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgZGVzdENsYXNzLnByb3RvdHlwZVtuYW1lXSA9IF90aGlzLnByb3RvdHlwZVtuYW1lXTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gTWl4aW47XG59KCkpO1xuXG4vKlxuVVNBR0U6XG4gIGltcG9ydCB7IGRlZmF1bHQgYXMgRW1pdHRlck1peGluLCBFbWl0dGVySW50ZXJmYWNlIH0gZnJvbSAnLi9FbWl0dGVyTWl4aW4nXG5pbiBjbGFzczpcbiAgb246IEVtaXR0ZXJJbnRlcmZhY2VbJ29uJ11cbiAgb25lOiBFbWl0dGVySW50ZXJmYWNlWydvbmUnXVxuICBvZmY6IEVtaXR0ZXJJbnRlcmZhY2VbJ29mZiddXG4gIHRyaWdnZXI6IEVtaXR0ZXJJbnRlcmZhY2VbJ3RyaWdnZXInXVxuICB0cmlnZ2VyV2l0aDogRW1pdHRlckludGVyZmFjZVsndHJpZ2dlcldpdGgnXVxuICBoYXNIYW5kbGVyczogRW1pdHRlckludGVyZmFjZVsnaGFzSGFuZGxlcnMnXVxuYWZ0ZXIgY2xhc3M6XG4gIEVtaXR0ZXJNaXhpbi5taXhJbnRvKFRoZUNsYXNzKVxuKi9cbnZhciBFbWl0dGVyTWl4aW4gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEVtaXR0ZXJNaXhpbiwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbWl0dGVyTWl4aW4oKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgRW1pdHRlck1peGluLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uICh0eXBlLCBoYW5kbGVyKSB7XG4gICAgICAgIGFkZFRvSGFzaCh0aGlzLl9oYW5kbGVycyB8fCAodGhpcy5faGFuZGxlcnMgPSB7fSksIHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICByZXR1cm4gdGhpczsgLy8gZm9yIGNoYWluaW5nXG4gICAgfTtcbiAgICAvLyB0b2RvOiBhZGQgY29tbWVudHNcbiAgICBFbWl0dGVyTWl4aW4ucHJvdG90eXBlLm9uZSA9IGZ1bmN0aW9uICh0eXBlLCBoYW5kbGVyKSB7XG4gICAgICAgIGFkZFRvSGFzaCh0aGlzLl9vbmVIYW5kbGVycyB8fCAodGhpcy5fb25lSGFuZGxlcnMgPSB7fSksIHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICByZXR1cm4gdGhpczsgLy8gZm9yIGNoYWluaW5nXG4gICAgfTtcbiAgICBFbWl0dGVyTWl4aW4ucHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uICh0eXBlLCBoYW5kbGVyKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYW5kbGVycykge1xuICAgICAgICAgICAgcmVtb3ZlRnJvbUhhc2godGhpcy5faGFuZGxlcnMsIHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9vbmVIYW5kbGVycykge1xuICAgICAgICAgICAgcmVtb3ZlRnJvbUhhc2godGhpcy5fb25lSGFuZGxlcnMsIHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzOyAvLyBmb3IgY2hhaW5pbmdcbiAgICB9O1xuICAgIEVtaXR0ZXJNaXhpbi5wcm90b3R5cGUudHJpZ2dlciA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBhcmdzW19pIC0gMV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudHJpZ2dlcldpdGgodHlwZSwgdGhpcywgYXJncyk7XG4gICAgICAgIHJldHVybiB0aGlzOyAvLyBmb3IgY2hhaW5pbmdcbiAgICB9O1xuICAgIEVtaXR0ZXJNaXhpbi5wcm90b3R5cGUudHJpZ2dlcldpdGggPSBmdW5jdGlvbiAodHlwZSwgY29udGV4dCwgYXJncykge1xuICAgICAgICBpZiAodGhpcy5faGFuZGxlcnMpIHtcbiAgICAgICAgICAgIGFwcGx5QWxsKHRoaXMuX2hhbmRsZXJzW3R5cGVdLCBjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fb25lSGFuZGxlcnMpIHtcbiAgICAgICAgICAgIGFwcGx5QWxsKHRoaXMuX29uZUhhbmRsZXJzW3R5cGVdLCBjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9vbmVIYW5kbGVyc1t0eXBlXTsgLy8gd2lsbCBuZXZlciBmaXJlIGFnYWluXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGZvciBjaGFpbmluZ1xuICAgIH07XG4gICAgRW1pdHRlck1peGluLnByb3RvdHlwZS5oYXNIYW5kbGVycyA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5faGFuZGxlcnMgJiYgdGhpcy5faGFuZGxlcnNbdHlwZV0gJiYgdGhpcy5faGFuZGxlcnNbdHlwZV0ubGVuZ3RoKSB8fFxuICAgICAgICAgICAgKHRoaXMuX29uZUhhbmRsZXJzICYmIHRoaXMuX29uZUhhbmRsZXJzW3R5cGVdICYmIHRoaXMuX29uZUhhbmRsZXJzW3R5cGVdLmxlbmd0aCk7XG4gICAgfTtcbiAgICByZXR1cm4gRW1pdHRlck1peGluO1xufShNaXhpbikpO1xuZnVuY3Rpb24gYWRkVG9IYXNoKGhhc2gsIHR5cGUsIGhhbmRsZXIpIHtcbiAgICAoaGFzaFt0eXBlXSB8fCAoaGFzaFt0eXBlXSA9IFtdKSlcbiAgICAgICAgLnB1c2goaGFuZGxlcik7XG59XG5mdW5jdGlvbiByZW1vdmVGcm9tSGFzaChoYXNoLCB0eXBlLCBoYW5kbGVyKSB7XG4gICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgaWYgKGhhc2hbdHlwZV0pIHtcbiAgICAgICAgICAgIGhhc2hbdHlwZV0gPSBoYXNoW3R5cGVdLmZpbHRlcihmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jICE9PSBoYW5kbGVyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBoYXNoW3R5cGVdOyAvLyByZW1vdmUgYWxsIGhhbmRsZXIgZnVuY3MgZm9yIHRoaXMgdHlwZVxuICAgIH1cbn1cblxuLypcblJlY29yZHMgb2Zmc2V0IGluZm9ybWF0aW9uIGZvciBhIHNldCBvZiBlbGVtZW50cywgcmVsYXRpdmUgdG8gYW4gb3JpZ2luIGVsZW1lbnQuXG5DYW4gcmVjb3JkIHRoZSBsZWZ0L3JpZ2h0IE9SIHRoZSB0b3AvYm90dG9tIE9SIGJvdGguXG5Qcm92aWRlcyBtZXRob2RzIGZvciBxdWVyeWluZyB0aGUgY2FjaGUgYnkgcG9zaXRpb24uXG4qL1xudmFyIFBvc2l0aW9uQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUG9zaXRpb25DYWNoZShvcmlnaW5FbCwgZWxzLCBpc0hvcml6b250YWwsIGlzVmVydGljYWwpIHtcbiAgICAgICAgdGhpcy5vcmlnaW5FbCA9IG9yaWdpbkVsO1xuICAgICAgICB0aGlzLmVscyA9IGVscztcbiAgICAgICAgdGhpcy5pc0hvcml6b250YWwgPSBpc0hvcml6b250YWw7XG4gICAgICAgIHRoaXMuaXNWZXJ0aWNhbCA9IGlzVmVydGljYWw7XG4gICAgfVxuICAgIC8vIFF1ZXJpZXMgdGhlIGVscyBmb3IgY29vcmRpbmF0ZXMgYW5kIHN0b3JlcyB0aGVtLlxuICAgIC8vIENhbGwgdGhpcyBtZXRob2QgYmVmb3JlIHVzaW5nIGFuZCBvZiB0aGUgZ2V0KiBtZXRob2RzIGJlbG93LlxuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmJ1aWxkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb3JpZ2luRWwgPSB0aGlzLm9yaWdpbkVsO1xuICAgICAgICB2YXIgb3JpZ2luQ2xpZW50UmVjdCA9IHRoaXMub3JpZ2luQ2xpZW50UmVjdCA9XG4gICAgICAgICAgICBvcmlnaW5FbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgLy8gcmVsYXRpdmUgdG8gdmlld3BvcnQgdG9wLWxlZnRcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICB0aGlzLmJ1aWxkRWxIb3Jpem9udGFscyhvcmlnaW5DbGllbnRSZWN0LmxlZnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzVmVydGljYWwpIHtcbiAgICAgICAgICAgIHRoaXMuYnVpbGRFbFZlcnRpY2FscyhvcmlnaW5DbGllbnRSZWN0LnRvcCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFBvcHVsYXRlcyB0aGUgbGVmdC9yaWdodCBpbnRlcm5hbCBjb29yZGluYXRlIGFycmF5c1xuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmJ1aWxkRWxIb3Jpem9udGFscyA9IGZ1bmN0aW9uIChvcmlnaW5DbGllbnRMZWZ0KSB7XG4gICAgICAgIHZhciBsZWZ0cyA9IFtdO1xuICAgICAgICB2YXIgcmlnaHRzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmVsczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBlbCA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBsZWZ0cy5wdXNoKHJlY3QubGVmdCAtIG9yaWdpbkNsaWVudExlZnQpO1xuICAgICAgICAgICAgcmlnaHRzLnB1c2gocmVjdC5yaWdodCAtIG9yaWdpbkNsaWVudExlZnQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubGVmdHMgPSBsZWZ0cztcbiAgICAgICAgdGhpcy5yaWdodHMgPSByaWdodHM7XG4gICAgfTtcbiAgICAvLyBQb3B1bGF0ZXMgdGhlIHRvcC9ib3R0b20gaW50ZXJuYWwgY29vcmRpbmF0ZSBhcnJheXNcbiAgICBQb3NpdGlvbkNhY2hlLnByb3RvdHlwZS5idWlsZEVsVmVydGljYWxzID0gZnVuY3Rpb24gKG9yaWdpbkNsaWVudFRvcCkge1xuICAgICAgICB2YXIgdG9wcyA9IFtdO1xuICAgICAgICB2YXIgYm90dG9tcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5lbHM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgZWwgPSBfYVtfaV07XG4gICAgICAgICAgICB2YXIgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgdG9wcy5wdXNoKHJlY3QudG9wIC0gb3JpZ2luQ2xpZW50VG9wKTtcbiAgICAgICAgICAgIGJvdHRvbXMucHVzaChyZWN0LmJvdHRvbSAtIG9yaWdpbkNsaWVudFRvcCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3BzID0gdG9wcztcbiAgICAgICAgdGhpcy5ib3R0b21zID0gYm90dG9tcztcbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgbGVmdCBvZmZzZXQgKGZyb20gZG9jdW1lbnQgbGVmdCksIHJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBlbCB0aGF0IGl0IGhvcml6b250YWxseSBpbnRlcnNlY3RzLlxuICAgIC8vIElmIG5vIGludGVyc2VjdGlvbiBpcyBtYWRlLCByZXR1cm5zIHVuZGVmaW5lZC5cbiAgICBQb3NpdGlvbkNhY2hlLnByb3RvdHlwZS5sZWZ0VG9JbmRleCA9IGZ1bmN0aW9uIChsZWZ0UG9zaXRpb24pIHtcbiAgICAgICAgdmFyIGxlZnRzID0gdGhpcy5sZWZ0cztcbiAgICAgICAgdmFyIHJpZ2h0cyA9IHRoaXMucmlnaHRzO1xuICAgICAgICB2YXIgbGVuID0gbGVmdHMubGVuZ3RoO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZiAobGVmdFBvc2l0aW9uID49IGxlZnRzW2ldICYmIGxlZnRQb3NpdGlvbiA8IHJpZ2h0c1tpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBHaXZlbiBhIHRvcCBvZmZzZXQgKGZyb20gZG9jdW1lbnQgdG9wKSwgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGVsIHRoYXQgaXQgdmVydGljYWxseSBpbnRlcnNlY3RzLlxuICAgIC8vIElmIG5vIGludGVyc2VjdGlvbiBpcyBtYWRlLCByZXR1cm5zIHVuZGVmaW5lZC5cbiAgICBQb3NpdGlvbkNhY2hlLnByb3RvdHlwZS50b3BUb0luZGV4ID0gZnVuY3Rpb24gKHRvcFBvc2l0aW9uKSB7XG4gICAgICAgIHZhciB0b3BzID0gdGhpcy50b3BzO1xuICAgICAgICB2YXIgYm90dG9tcyA9IHRoaXMuYm90dG9tcztcbiAgICAgICAgdmFyIGxlbiA9IHRvcHMubGVuZ3RoO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodG9wUG9zaXRpb24gPj0gdG9wc1tpXSAmJiB0b3BQb3NpdGlvbiA8IGJvdHRvbXNbaV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gR2V0cyB0aGUgd2lkdGggb2YgdGhlIGVsZW1lbnQgYXQgdGhlIGdpdmVuIGluZGV4XG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuZ2V0V2lkdGggPSBmdW5jdGlvbiAobGVmdEluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJpZ2h0c1tsZWZ0SW5kZXhdIC0gdGhpcy5sZWZ0c1tsZWZ0SW5kZXhdO1xuICAgIH07XG4gICAgLy8gR2V0cyB0aGUgaGVpZ2h0IG9mIHRoZSBlbGVtZW50IGF0IHRoZSBnaXZlbiBpbmRleFxuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmdldEhlaWdodCA9IGZ1bmN0aW9uICh0b3BJbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ib3R0b21zW3RvcEluZGV4XSAtIHRoaXMudG9wc1t0b3BJbmRleF07XG4gICAgfTtcbiAgICByZXR1cm4gUG9zaXRpb25DYWNoZTtcbn0oKSk7XG5cbi8qXG5BbiBvYmplY3QgZm9yIGdldHRpbmcvc2V0dGluZyBzY3JvbGwtcmVsYXRlZCBpbmZvcm1hdGlvbiBmb3IgYW4gZWxlbWVudC5cbkludGVybmFsbHksIHRoaXMgaXMgZG9uZSB2ZXJ5IGRpZmZlcmVudGx5IGZvciB3aW5kb3cgdmVyc3VzIERPTSBlbGVtZW50LFxuc28gdGhpcyBvYmplY3Qgc2VydmVzIGFzIGEgY29tbW9uIGludGVyZmFjZS5cbiovXG52YXIgU2Nyb2xsQ29udHJvbGxlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTY3JvbGxDb250cm9sbGVyKCkge1xuICAgIH1cbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRNYXhTY3JvbGxUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFNjcm9sbEhlaWdodCgpIC0gdGhpcy5nZXRDbGllbnRIZWlnaHQoKTtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldE1heFNjcm9sbExlZnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFNjcm9sbFdpZHRoKCkgLSB0aGlzLmdldENsaWVudFdpZHRoKCk7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxWZXJ0aWNhbGx5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRNYXhTY3JvbGxUb3AoKSA+IDA7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxIb3Jpem9udGFsbHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE1heFNjcm9sbExlZnQoKSA+IDA7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxVcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsVG9wKCkgPiAwO1xuICAgIH07XG4gICAgU2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuY2FuU2Nyb2xsRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsVG9wKCkgPCB0aGlzLmdldE1heFNjcm9sbFRvcCgpO1xuICAgIH07XG4gICAgU2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuY2FuU2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsTGVmdCgpID4gMDtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbFJpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxMZWZ0KCkgPCB0aGlzLmdldE1heFNjcm9sbExlZnQoKTtcbiAgICB9O1xuICAgIHJldHVybiBTY3JvbGxDb250cm9sbGVyO1xufSgpKTtcbnZhciBFbGVtZW50U2Nyb2xsQ29udHJvbGxlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRWxlbWVudFNjcm9sbENvbnRyb2xsZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRWxlbWVudFNjcm9sbENvbnRyb2xsZXIoZWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZWwgPSBlbDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBFbGVtZW50U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsVG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5zY3JvbGxUb3A7XG4gICAgfTtcbiAgICBFbGVtZW50U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuc2Nyb2xsTGVmdDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5zZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAodG9wKSB7XG4gICAgICAgIHRoaXMuZWwuc2Nyb2xsVG9wID0gdG9wO1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLnNldFNjcm9sbExlZnQgPSBmdW5jdGlvbiAobGVmdCkge1xuICAgICAgICB0aGlzLmVsLnNjcm9sbExlZnQgPSBsZWZ0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNjcm9sbFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5zY3JvbGxXaWR0aDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbEhlaWdodDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDbGllbnRIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLmNsaWVudEhlaWdodDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDbGllbnRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuY2xpZW50V2lkdGg7XG4gICAgfTtcbiAgICByZXR1cm4gRWxlbWVudFNjcm9sbENvbnRyb2xsZXI7XG59KFNjcm9sbENvbnRyb2xsZXIpKTtcbnZhciBXaW5kb3dTY3JvbGxDb250cm9sbGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhXaW5kb3dTY3JvbGxDb250cm9sbGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsVG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnBhZ2VZT2Zmc2V0O1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5wYWdlWE9mZnNldDtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLnNldFNjcm9sbFRvcCA9IGZ1bmN0aW9uIChuKSB7XG4gICAgICAgIHdpbmRvdy5zY3JvbGwod2luZG93LnBhZ2VYT2Zmc2V0LCBuKTtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLnNldFNjcm9sbExlZnQgPSBmdW5jdGlvbiAobikge1xuICAgICAgICB3aW5kb3cuc2Nyb2xsKG4sIHdpbmRvdy5wYWdlWU9mZnNldCk7XG4gICAgfTtcbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxXaWR0aDtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQ7XG4gICAgfTtcbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDbGllbnRIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0Q2xpZW50V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgfTtcbiAgICByZXR1cm4gV2luZG93U2Nyb2xsQ29udHJvbGxlcjtcbn0oU2Nyb2xsQ29udHJvbGxlcikpO1xuXG4vKlxuRW1ib2RpZXMgYSBkaXYgdGhhdCBoYXMgcG90ZW50aWFsIHNjcm9sbGJhcnNcbiovXG52YXIgU2Nyb2xsQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTY3JvbGxDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2Nyb2xsQ29tcG9uZW50KG92ZXJmbG93WCwgb3ZlcmZsb3dZKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZTogJ2ZjLXNjcm9sbGVyJ1xuICAgICAgICB9KSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMub3ZlcmZsb3dYID0gb3ZlcmZsb3dYO1xuICAgICAgICBfdGhpcy5vdmVyZmxvd1kgPSBvdmVyZmxvd1k7XG4gICAgICAgIF90aGlzLmFwcGx5T3ZlcmZsb3coKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICAvLyBzZXRzIHRvIG5hdHVyYWwgaGVpZ2h0LCB1bmxvY2tzIG92ZXJmbG93XG4gICAgU2Nyb2xsQ29tcG9uZW50LnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRIZWlnaHQoJ2F1dG8nKTtcbiAgICAgICAgdGhpcy5hcHBseU92ZXJmbG93KCk7XG4gICAgfTtcbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5lbCk7XG4gICAgfTtcbiAgICAvLyBPdmVyZmxvd1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgU2Nyb2xsQ29tcG9uZW50LnByb3RvdHlwZS5hcHBseU92ZXJmbG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBhcHBseVN0eWxlKHRoaXMuZWwsIHtcbiAgICAgICAgICAgIG92ZXJmbG93WDogdGhpcy5vdmVyZmxvd1gsXG4gICAgICAgICAgICBvdmVyZmxvd1k6IHRoaXMub3ZlcmZsb3dZXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gQ2F1c2VzIGFueSAnYXV0bycgb3ZlcmZsb3cgdmFsdWVzIHRvIHJlc29sdmVzIHRvICdzY3JvbGwnIG9yICdoaWRkZW4nLlxuICAgIC8vIFVzZWZ1bCBmb3IgcHJlc2VydmluZyBzY3JvbGxiYXIgd2lkdGhzIHJlZ2FyZGxlc3Mgb2YgZnV0dXJlIHJlc2l6ZXMuXG4gICAgLy8gQ2FuIHBhc3MgaW4gc2Nyb2xsYmFyV2lkdGhzIGZvciBvcHRpbWl6YXRpb24uXG4gICAgU2Nyb2xsQ29tcG9uZW50LnByb3RvdHlwZS5sb2NrT3ZlcmZsb3cgPSBmdW5jdGlvbiAoc2Nyb2xsYmFyV2lkdGhzKSB7XG4gICAgICAgIHZhciBvdmVyZmxvd1ggPSB0aGlzLm92ZXJmbG93WDtcbiAgICAgICAgdmFyIG92ZXJmbG93WSA9IHRoaXMub3ZlcmZsb3dZO1xuICAgICAgICBzY3JvbGxiYXJXaWR0aHMgPSBzY3JvbGxiYXJXaWR0aHMgfHwgdGhpcy5nZXRTY3JvbGxiYXJXaWR0aHMoKTtcbiAgICAgICAgaWYgKG92ZXJmbG93WCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgICAgICBvdmVyZmxvd1ggPSAoc2Nyb2xsYmFyV2lkdGhzLmJvdHRvbSB8fCAvLyBob3Jpem9udGFsIHNjcm9sbGJhcnM/XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5TY3JvbGxIb3Jpem9udGFsbHkoKSAvLyBPUiBzY3JvbGxpbmcgcGFuZSB3aXRoIG1hc3NsZXNzIHNjcm9sbGJhcnM/XG4gICAgICAgICAgICApID8gJ3Njcm9sbCcgOiAnaGlkZGVuJztcbiAgICAgICAgfVxuICAgICAgICBpZiAob3ZlcmZsb3dZID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIG92ZXJmbG93WSA9IChzY3JvbGxiYXJXaWR0aHMubGVmdCB8fCBzY3JvbGxiYXJXaWR0aHMucmlnaHQgfHwgLy8gaG9yaXpvbnRhbCBzY3JvbGxiYXJzP1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuU2Nyb2xsVmVydGljYWxseSgpIC8vIE9SIHNjcm9sbGluZyBwYW5lIHdpdGggbWFzc2xlc3Mgc2Nyb2xsYmFycz9cbiAgICAgICAgICAgICkgPyAnc2Nyb2xsJyA6ICdoaWRkZW4nO1xuICAgICAgICB9XG4gICAgICAgIGFwcGx5U3R5bGUodGhpcy5lbCwgeyBvdmVyZmxvd1g6IG92ZXJmbG93WCwgb3ZlcmZsb3dZOiBvdmVyZmxvd1kgfSk7XG4gICAgfTtcbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLnNldEhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgYXBwbHlTdHlsZVByb3AodGhpcy5lbCwgJ2hlaWdodCcsIGhlaWdodCk7XG4gICAgfTtcbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmdldFNjcm9sbGJhcldpZHRocyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVkZ2VzID0gY29tcHV0ZUVkZ2VzKHRoaXMuZWwpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGVmdDogZWRnZXMuc2Nyb2xsYmFyTGVmdCxcbiAgICAgICAgICAgIHJpZ2h0OiBlZGdlcy5zY3JvbGxiYXJSaWdodCxcbiAgICAgICAgICAgIGJvdHRvbTogZWRnZXMuc2Nyb2xsYmFyQm90dG9tXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gU2Nyb2xsQ29tcG9uZW50O1xufShFbGVtZW50U2Nyb2xsQ29udHJvbGxlcikpO1xuXG52YXIgVGhlbWUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVGhlbWUoY2FsZW5kYXJPcHRpb25zKSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJPcHRpb25zID0gY2FsZW5kYXJPcHRpb25zO1xuICAgICAgICB0aGlzLnByb2Nlc3NJY29uT3ZlcnJpZGUoKTtcbiAgICB9XG4gICAgVGhlbWUucHJvdG90eXBlLnByb2Nlc3NJY29uT3ZlcnJpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmljb25PdmVycmlkZU9wdGlvbikge1xuICAgICAgICAgICAgdGhpcy5zZXRJY29uT3ZlcnJpZGUodGhpcy5jYWxlbmRhck9wdGlvbnNbdGhpcy5pY29uT3ZlcnJpZGVPcHRpb25dKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVGhlbWUucHJvdG90eXBlLnNldEljb25PdmVycmlkZSA9IGZ1bmN0aW9uIChpY29uT3ZlcnJpZGVIYXNoKSB7XG4gICAgICAgIHZhciBpY29uQ2xhc3Nlc0NvcHk7XG4gICAgICAgIHZhciBidXR0b25OYW1lO1xuICAgICAgICBpZiAodHlwZW9mIGljb25PdmVycmlkZUhhc2ggPT09ICdvYmplY3QnICYmIGljb25PdmVycmlkZUhhc2gpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgICAgICBpY29uQ2xhc3Nlc0NvcHkgPSBfX2Fzc2lnbih7fSwgdGhpcy5pY29uQ2xhc3Nlcyk7XG4gICAgICAgICAgICBmb3IgKGJ1dHRvbk5hbWUgaW4gaWNvbk92ZXJyaWRlSGFzaCkge1xuICAgICAgICAgICAgICAgIGljb25DbGFzc2VzQ29weVtidXR0b25OYW1lXSA9IHRoaXMuYXBwbHlJY29uT3ZlcnJpZGVQcmVmaXgoaWNvbk92ZXJyaWRlSGFzaFtidXR0b25OYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmljb25DbGFzc2VzID0gaWNvbkNsYXNzZXNDb3B5O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGljb25PdmVycmlkZUhhc2ggPT09IGZhbHNlKSB7XG4gICAgICAgICAgICB0aGlzLmljb25DbGFzc2VzID0ge307XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFRoZW1lLnByb3RvdHlwZS5hcHBseUljb25PdmVycmlkZVByZWZpeCA9IGZ1bmN0aW9uIChjbGFzc05hbWUpIHtcbiAgICAgICAgdmFyIHByZWZpeCA9IHRoaXMuaWNvbk92ZXJyaWRlUHJlZml4O1xuICAgICAgICBpZiAocHJlZml4ICYmIGNsYXNzTmFtZS5pbmRleE9mKHByZWZpeCkgIT09IDApIHsgLy8gaWYgbm90IGFscmVhZHkgcHJlc2VudFxuICAgICAgICAgICAgY2xhc3NOYW1lID0gcHJlZml4ICsgY2xhc3NOYW1lO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbGFzc05hbWU7XG4gICAgfTtcbiAgICBUaGVtZS5wcm90b3R5cGUuZ2V0Q2xhc3MgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsYXNzZXNba2V5XSB8fCAnJztcbiAgICB9O1xuICAgIFRoZW1lLnByb3RvdHlwZS5nZXRJY29uQ2xhc3MgPSBmdW5jdGlvbiAoYnV0dG9uTmFtZSkge1xuICAgICAgICB2YXIgY2xhc3NOYW1lID0gdGhpcy5pY29uQ2xhc3Nlc1tidXR0b25OYW1lXTtcbiAgICAgICAgaWYgKGNsYXNzTmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmFzZUljb25DbGFzcyArICcgJyArIGNsYXNzTmFtZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfTtcbiAgICBUaGVtZS5wcm90b3R5cGUuZ2V0Q3VzdG9tQnV0dG9uSWNvbkNsYXNzID0gZnVuY3Rpb24gKGN1c3RvbUJ1dHRvblByb3BzKSB7XG4gICAgICAgIHZhciBjbGFzc05hbWU7XG4gICAgICAgIGlmICh0aGlzLmljb25PdmVycmlkZUN1c3RvbUJ1dHRvbk9wdGlvbikge1xuICAgICAgICAgICAgY2xhc3NOYW1lID0gY3VzdG9tQnV0dG9uUHJvcHNbdGhpcy5pY29uT3ZlcnJpZGVDdXN0b21CdXR0b25PcHRpb25dO1xuICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmJhc2VJY29uQ2xhc3MgKyAnICcgKyB0aGlzLmFwcGx5SWNvbk92ZXJyaWRlUHJlZml4KGNsYXNzTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH07XG4gICAgcmV0dXJuIFRoZW1lO1xufSgpKTtcblRoZW1lLnByb3RvdHlwZS5jbGFzc2VzID0ge307XG5UaGVtZS5wcm90b3R5cGUuaWNvbkNsYXNzZXMgPSB7fTtcblRoZW1lLnByb3RvdHlwZS5iYXNlSWNvbkNsYXNzID0gJyc7XG5UaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlUHJlZml4ID0gJyc7XG5cbnZhciBndWlkID0gMDtcbnZhciBDb21wb25lbnRDb250ZXh0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbXBvbmVudENvbnRleHQoY2FsZW5kYXIsIHRoZW1lLCBkYXRlRW52LCBvcHRpb25zLCB2aWV3KSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICAgICAgdGhpcy50aGVtZSA9IHRoZW1lO1xuICAgICAgICB0aGlzLmRhdGVFbnYgPSBkYXRlRW52O1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICB0aGlzLnZpZXcgPSB2aWV3O1xuICAgICAgICB0aGlzLmlzUnRsID0gb3B0aW9ucy5kaXIgPT09ICdydGwnO1xuICAgICAgICB0aGlzLmV2ZW50T3JkZXJTcGVjcyA9IHBhcnNlRmllbGRTcGVjcyhvcHRpb25zLmV2ZW50T3JkZXIpO1xuICAgICAgICB0aGlzLm5leHREYXlUaHJlc2hvbGQgPSBjcmVhdGVEdXJhdGlvbihvcHRpb25zLm5leHREYXlUaHJlc2hvbGQpO1xuICAgIH1cbiAgICBDb21wb25lbnRDb250ZXh0LnByb3RvdHlwZS5leHRlbmQgPSBmdW5jdGlvbiAob3B0aW9ucywgdmlldykge1xuICAgICAgICByZXR1cm4gbmV3IENvbXBvbmVudENvbnRleHQodGhpcy5jYWxlbmRhciwgdGhpcy50aGVtZSwgdGhpcy5kYXRlRW52LCBvcHRpb25zIHx8IHRoaXMub3B0aW9ucywgdmlldyB8fCB0aGlzLnZpZXcpO1xuICAgIH07XG4gICAgcmV0dXJuIENvbXBvbmVudENvbnRleHQ7XG59KCkpO1xudmFyIENvbXBvbmVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gICAgICAgIHRoaXMuZXZlclJlbmRlcmVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMudWlkID0gU3RyaW5nKGd1aWQrKyk7XG4gICAgfVxuICAgIENvbXBvbmVudC5hZGRFcXVhbGl0eUZ1bmNzID0gZnVuY3Rpb24gKG5ld0Z1bmNzKSB7XG4gICAgICAgIHRoaXMucHJvdG90eXBlLmVxdWFsaXR5RnVuY3MgPSBfX2Fzc2lnbih7fSwgdGhpcy5wcm90b3R5cGUuZXF1YWxpdHlGdW5jcywgbmV3RnVuY3MpO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5yZWNlaXZlUHJvcHMgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5yZWNlaXZlQ29udGV4dChjb250ZXh0KTtcbiAgICAgICAgdmFyIF9hID0gcmVjeWNsZVByb3BzKHRoaXMucHJvcHMgfHwge30sIHByb3BzLCB0aGlzLmVxdWFsaXR5RnVuY3MpLCBhbnlDaGFuZ2VzID0gX2EuYW55Q2hhbmdlcywgY29tYm9Qcm9wcyA9IF9hLmNvbWJvUHJvcHM7XG4gICAgICAgIHRoaXMucHJvcHMgPSBjb21ib1Byb3BzO1xuICAgICAgICBpZiAoYW55Q2hhbmdlcykge1xuICAgICAgICAgICAgaWYgKHRoaXMuZXZlclJlbmRlcmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5iZWZvcmVVcGRhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVuZGVyKGNvbWJvUHJvcHMsIGNvbnRleHQpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZXZlclJlbmRlcmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZnRlclVwZGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXZlclJlbmRlcmVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUucmVjZWl2ZUNvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB2YXIgb2xkQ29udGV4dCA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgaWYgKCFvbGRDb250ZXh0KSB7XG4gICAgICAgICAgICB0aGlzLmZpcnN0Q29udGV4dChjb250ZXh0KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuZmlyc3RDb250ZXh0ID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuYmVmb3JlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5hZnRlclVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIC8vIGFmdGVyIGRlc3Ryb3kgaXMgY2FsbGVkLCB0aGlzIGNvbXBvbmVudCB3b24ndCBldmVyIGJlIHVzZWQgYWdhaW5cbiAgICBDb21wb25lbnQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICByZXR1cm4gQ29tcG9uZW50O1xufSgpKTtcbkNvbXBvbmVudC5wcm90b3R5cGUuZXF1YWxpdHlGdW5jcyA9IHt9O1xuLypcblJldXNlcyBvbGQgdmFsdWVzIHdoZW4gZXF1YWwuIElmIGFueXRoaW5nIGlzIHVuZXF1YWwsIHJldHVybnMgbmV3UHJvcHMgYXMtaXMuXG5HcmVhdCBmb3IgUHVyZUNvbXBvbmVudCwgYnV0IHdvbid0IGJlIGZlYXNpYmxlIHdpdGggUmVhY3QsIHNvIGp1c3QgZWxpbWluYXRlIGFuZCB1c2UgUmVhY3QncyBET00gZGlmZmluZy5cbiovXG5mdW5jdGlvbiByZWN5Y2xlUHJvcHMob2xkUHJvcHMsIG5ld1Byb3BzLCBlcXVhbGl0eUZ1bmNzKSB7XG4gICAgdmFyIGNvbWJvUHJvcHMgPSB7fTsgLy8gc29tZSBvbGQsIHNvbWUgbmV3XG4gICAgdmFyIGFueUNoYW5nZXMgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBrZXkgaW4gbmV3UHJvcHMpIHtcbiAgICAgICAgaWYgKGtleSBpbiBvbGRQcm9wcyAmJiAob2xkUHJvcHNba2V5XSA9PT0gbmV3UHJvcHNba2V5XSB8fFxuICAgICAgICAgICAgKGVxdWFsaXR5RnVuY3Nba2V5XSAmJiBlcXVhbGl0eUZ1bmNzW2tleV0ob2xkUHJvcHNba2V5XSwgbmV3UHJvcHNba2V5XSkpKSkge1xuICAgICAgICAgICAgLy8gZXF1YWwgdG8gb2xkPyB1c2Ugb2xkIHByb3BcbiAgICAgICAgICAgIGNvbWJvUHJvcHNba2V5XSA9IG9sZFByb3BzW2tleV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb21ib1Byb3BzW2tleV0gPSBuZXdQcm9wc1trZXldO1xuICAgICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIga2V5IGluIG9sZFByb3BzKSB7XG4gICAgICAgIGlmICghKGtleSBpbiBuZXdQcm9wcykpIHtcbiAgICAgICAgICAgIGFueUNoYW5nZXMgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgYW55Q2hhbmdlczogYW55Q2hhbmdlcywgY29tYm9Qcm9wczogY29tYm9Qcm9wcyB9O1xufVxuXG4vKlxuUFVSUE9TRVM6XG4tIGhvb2sgdXAgdG8gZmcsIGZpbGwsIGFuZCBtaXJyb3IgcmVuZGVyZXJzXG4tIGludGVyZmFjZSBmb3IgZHJhZ2dpbmcgYW5kIGhpdHNcbiovXG52YXIgRGF0ZUNvbXBvbmVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF0ZUNvbXBvbmVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXRlQ29tcG9uZW50KGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmVsID0gZWw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5lbCk7XG4gICAgfTtcbiAgICAvLyBIaXQgU3lzdGVtXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5idWlsZFBvc2l0aW9uQ2FjaGVzID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUucXVlcnlIaXQgPSBmdW5jdGlvbiAocG9zaXRpb25MZWZ0LCBwb3NpdGlvblRvcCwgZWxXaWR0aCwgZWxIZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7IC8vIHRoaXMgc2hvdWxkIGJlIGFic3RyYWN0XG4gICAgfTtcbiAgICAvLyBWYWxpZGF0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5pc0ludGVyYWN0aW9uVmFsaWQgPSBmdW5jdGlvbiAoaW50ZXJhY3Rpb24pIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdGhpcy5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICB2YXIgZGF0ZVByb2ZpbGUgPSB0aGlzLnByb3BzLmRhdGVQcm9maWxlOyAvLyBIQUNLXG4gICAgICAgIHZhciBpbnN0YW5jZXMgPSBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzLmluc3RhbmNlcztcbiAgICAgICAgaWYgKGRhdGVQcm9maWxlKSB7IC8vIEhBQ0sgZm9yIERheVRpbGVcbiAgICAgICAgICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFyYW5nZUNvbnRhaW5zUmFuZ2UoZGF0ZVByb2ZpbGUudmFsaWRSYW5nZSwgaW5zdGFuY2VzW2luc3RhbmNlSWRdLnJhbmdlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0ludGVyYWN0aW9uVmFsaWQoaW50ZXJhY3Rpb24sIGNhbGVuZGFyKTtcbiAgICB9O1xuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzRGF0ZVNlbGVjdGlvblZhbGlkID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzLmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBkYXRlUHJvZmlsZSA9IHRoaXMucHJvcHMuZGF0ZVByb2ZpbGU7IC8vIEhBQ0tcbiAgICAgICAgaWYgKGRhdGVQcm9maWxlICYmIC8vIEhBQ0sgZm9yIERheVRpbGVcbiAgICAgICAgICAgICFyYW5nZUNvbnRhaW5zUmFuZ2UoZGF0ZVByb2ZpbGUudmFsaWRSYW5nZSwgc2VsZWN0aW9uLnJhbmdlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0RhdGVTZWxlY3Rpb25WYWxpZChzZWxlY3Rpb24sIGNhbGVuZGFyKTtcbiAgICB9O1xuICAgIC8vIFBvaW50ZXIgSW50ZXJhY3Rpb24gVXRpbHNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzVmFsaWRTZWdEb3duRWwgPSBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLnByb3BzLmV2ZW50RHJhZyAmJiAvLyBIQUNLXG4gICAgICAgICAgICAhdGhpcy5wcm9wcy5ldmVudFJlc2l6ZSAmJiAvLyBIQUNLXG4gICAgICAgICAgICAhZWxlbWVudENsb3Nlc3QoZWwsICcuZmMtbWlycm9yJykgJiZcbiAgICAgICAgICAgICh0aGlzLmlzUG9wb3ZlcigpIHx8ICF0aGlzLmlzSW5Qb3BvdmVyKGVsKSk7XG4gICAgICAgIC8vIF5hYm92ZSBsaW5lIGVuc3VyZXMgd2UgZG9uJ3QgZGV0ZWN0IGEgc2VnIGludGVyYWN0aW9uIHdpdGhpbiBhIG5lc3RlZCBjb21wb25lbnQuXG4gICAgICAgIC8vIGl0J3MgYSBIQUNLIGJlY2F1c2UgaXQgb25seSBzdXBwb3J0cyBhIHBvcG92ZXIgYXMgdGhlIG5lc3RlZCBjb21wb25lbnQuXG4gICAgfTtcbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5pc1ZhbGlkRGF0ZURvd25FbCA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICB2YXIgc2VnRWwgPSBlbGVtZW50Q2xvc2VzdChlbCwgdGhpcy5mZ1NlZ1NlbGVjdG9yKTtcbiAgICAgICAgcmV0dXJuICghc2VnRWwgfHwgc2VnRWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYy1taXJyb3InKSkgJiZcbiAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1tb3JlJykgJiYgLy8gYSBcIm1vcmUuLlwiIGxpbmtcbiAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChlbCwgJ2FbZGF0YS1nb3RvXScpICYmIC8vIGEgY2xpY2thYmxlIG5hdiBsaW5rXG4gICAgICAgICAgICAhdGhpcy5pc0luUG9wb3ZlcihlbCk7XG4gICAgfTtcbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5pc1BvcG92ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLmNsYXNzTGlzdC5jb250YWlucygnZmMtcG9wb3ZlcicpO1xuICAgIH07XG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuaXNJblBvcG92ZXIgPSBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oZWxlbWVudENsb3Nlc3QoZWwsICcuZmMtcG9wb3ZlcicpKTtcbiAgICB9O1xuICAgIHJldHVybiBEYXRlQ29tcG9uZW50O1xufShDb21wb25lbnQpKTtcbkRhdGVDb21wb25lbnQucHJvdG90eXBlLmZnU2VnU2VsZWN0b3IgPSAnLmZjLWV2ZW50LWNvbnRhaW5lciA+IConO1xuRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuYmdTZWdTZWxlY3RvciA9ICcuZmMtYmdldmVudDpub3QoLmZjLW5vbmJ1c2luZXNzKSc7XG5cbnZhciB1aWQkMSA9IDA7XG5mdW5jdGlvbiBjcmVhdGVQbHVnaW4oaW5wdXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBpZDogU3RyaW5nKHVpZCQxKyspLFxuICAgICAgICBkZXBzOiBpbnB1dC5kZXBzIHx8IFtdLFxuICAgICAgICByZWR1Y2VyczogaW5wdXQucmVkdWNlcnMgfHwgW10sXG4gICAgICAgIGV2ZW50RGVmUGFyc2VyczogaW5wdXQuZXZlbnREZWZQYXJzZXJzIHx8IFtdLFxuICAgICAgICBpc0RyYWdnYWJsZVRyYW5zZm9ybWVyczogaW5wdXQuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBpbnB1dC5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2VycyB8fCBbXSxcbiAgICAgICAgZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzOiBpbnB1dC5ldmVudERlZk11dGF0aW9uQXBwbGllcnMgfHwgW10sXG4gICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IGlucHV0LmRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IGlucHV0LmRhdGVQb2ludFRyYW5zZm9ybXMgfHwgW10sXG4gICAgICAgIGRhdGVTcGFuVHJhbnNmb3JtczogaW5wdXQuZGF0ZVNwYW5UcmFuc2Zvcm1zIHx8IFtdLFxuICAgICAgICB2aWV3czogaW5wdXQudmlld3MgfHwge30sXG4gICAgICAgIHZpZXdQcm9wc1RyYW5zZm9ybWVyczogaW5wdXQudmlld1Byb3BzVHJhbnNmb3JtZXJzIHx8IFtdLFxuICAgICAgICBpc1Byb3BzVmFsaWQ6IGlucHV0LmlzUHJvcHNWYWxpZCB8fCBudWxsLFxuICAgICAgICBleHRlcm5hbERlZlRyYW5zZm9ybXM6IGlucHV0LmV4dGVybmFsRGVmVHJhbnNmb3JtcyB8fCBbXSxcbiAgICAgICAgZXZlbnRSZXNpemVKb2luVHJhbnNmb3JtczogaW5wdXQuZXZlbnRSZXNpemVKb2luVHJhbnNmb3JtcyB8fCBbXSxcbiAgICAgICAgdmlld0NvbnRhaW5lck1vZGlmaWVyczogaW5wdXQudmlld0NvbnRhaW5lck1vZGlmaWVycyB8fCBbXSxcbiAgICAgICAgZXZlbnREcm9wVHJhbnNmb3JtZXJzOiBpbnB1dC5ldmVudERyb3BUcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGNvbXBvbmVudEludGVyYWN0aW9uczogaW5wdXQuY29tcG9uZW50SW50ZXJhY3Rpb25zIHx8IFtdLFxuICAgICAgICBjYWxlbmRhckludGVyYWN0aW9uczogaW5wdXQuY2FsZW5kYXJJbnRlcmFjdGlvbnMgfHwgW10sXG4gICAgICAgIHRoZW1lQ2xhc3NlczogaW5wdXQudGhlbWVDbGFzc2VzIHx8IHt9LFxuICAgICAgICBldmVudFNvdXJjZURlZnM6IGlucHV0LmV2ZW50U291cmNlRGVmcyB8fCBbXSxcbiAgICAgICAgY21kRm9ybWF0dGVyOiBpbnB1dC5jbWRGb3JtYXR0ZXIsXG4gICAgICAgIHJlY3VycmluZ1R5cGVzOiBpbnB1dC5yZWN1cnJpbmdUeXBlcyB8fCBbXSxcbiAgICAgICAgbmFtZWRUaW1lWm9uZWRJbXBsOiBpbnB1dC5uYW1lZFRpbWVab25lZEltcGwsXG4gICAgICAgIGRlZmF1bHRWaWV3OiBpbnB1dC5kZWZhdWx0VmlldyB8fCAnJyxcbiAgICAgICAgZWxlbWVudERyYWdnaW5nSW1wbDogaW5wdXQuZWxlbWVudERyYWdnaW5nSW1wbCxcbiAgICAgICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IGlucHV0Lm9wdGlvbkNoYW5nZUhhbmRsZXJzIHx8IHt9XG4gICAgfTtcbn1cbnZhciBQbHVnaW5TeXN0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGx1Z2luU3lzdGVtKCkge1xuICAgICAgICB0aGlzLmhvb2tzID0ge1xuICAgICAgICAgICAgcmVkdWNlcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREZWZQYXJzZXJzOiBbXSxcbiAgICAgICAgICAgIGlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzOiBbXSxcbiAgICAgICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBbXSxcbiAgICAgICAgICAgIGV2ZW50RGVmTXV0YXRpb25BcHBsaWVyczogW10sXG4gICAgICAgICAgICBkYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzOiBbXSxcbiAgICAgICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IFtdLFxuICAgICAgICAgICAgZGF0ZVNwYW5UcmFuc2Zvcm1zOiBbXSxcbiAgICAgICAgICAgIHZpZXdzOiB7fSxcbiAgICAgICAgICAgIHZpZXdQcm9wc1RyYW5zZm9ybWVyczogW10sXG4gICAgICAgICAgICBpc1Byb3BzVmFsaWQ6IG51bGwsXG4gICAgICAgICAgICBleHRlcm5hbERlZlRyYW5zZm9ybXM6IFtdLFxuICAgICAgICAgICAgZXZlbnRSZXNpemVKb2luVHJhbnNmb3JtczogW10sXG4gICAgICAgICAgICB2aWV3Q29udGFpbmVyTW9kaWZpZXJzOiBbXSxcbiAgICAgICAgICAgIGV2ZW50RHJvcFRyYW5zZm9ybWVyczogW10sXG4gICAgICAgICAgICBjb21wb25lbnRJbnRlcmFjdGlvbnM6IFtdLFxuICAgICAgICAgICAgY2FsZW5kYXJJbnRlcmFjdGlvbnM6IFtdLFxuICAgICAgICAgICAgdGhlbWVDbGFzc2VzOiB7fSxcbiAgICAgICAgICAgIGV2ZW50U291cmNlRGVmczogW10sXG4gICAgICAgICAgICBjbWRGb3JtYXR0ZXI6IG51bGwsXG4gICAgICAgICAgICByZWN1cnJpbmdUeXBlczogW10sXG4gICAgICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IG51bGwsXG4gICAgICAgICAgICBkZWZhdWx0VmlldzogJycsXG4gICAgICAgICAgICBlbGVtZW50RHJhZ2dpbmdJbXBsOiBudWxsLFxuICAgICAgICAgICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IHt9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkZWRIYXNoID0ge307XG4gICAgfVxuICAgIFBsdWdpblN5c3RlbS5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKHBsdWdpbikge1xuICAgICAgICBpZiAoIXRoaXMuYWRkZWRIYXNoW3BsdWdpbi5pZF0pIHtcbiAgICAgICAgICAgIHRoaXMuYWRkZWRIYXNoW3BsdWdpbi5pZF0gPSB0cnVlO1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHBsdWdpbi5kZXBzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBkZXAgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgdGhpcy5hZGQoZGVwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaG9va3MgPSBjb21iaW5lSG9va3ModGhpcy5ob29rcywgcGx1Z2luKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFBsdWdpblN5c3RlbTtcbn0oKSk7XG5mdW5jdGlvbiBjb21iaW5lSG9va3MoaG9va3MwLCBob29rczEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICByZWR1Y2VyczogaG9va3MwLnJlZHVjZXJzLmNvbmNhdChob29rczEucmVkdWNlcnMpLFxuICAgICAgICBldmVudERlZlBhcnNlcnM6IGhvb2tzMC5ldmVudERlZlBhcnNlcnMuY29uY2F0KGhvb2tzMS5ldmVudERlZlBhcnNlcnMpLFxuICAgICAgICBpc0RyYWdnYWJsZVRyYW5zZm9ybWVyczogaG9va3MwLmlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnMpLFxuICAgICAgICBldmVudERyYWdNdXRhdGlvbk1hc3NhZ2VyczogaG9va3MwLmV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzLmNvbmNhdChob29rczEuZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnMpLFxuICAgICAgICBldmVudERlZk11dGF0aW9uQXBwbGllcnM6IGhvb2tzMC5ldmVudERlZk11dGF0aW9uQXBwbGllcnMuY29uY2F0KGhvb2tzMS5ldmVudERlZk11dGF0aW9uQXBwbGllcnMpLFxuICAgICAgICBkYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzOiBob29rczAuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycy5jb25jYXQoaG9va3MxLmRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnMpLFxuICAgICAgICBkYXRlUG9pbnRUcmFuc2Zvcm1zOiBob29rczAuZGF0ZVBvaW50VHJhbnNmb3Jtcy5jb25jYXQoaG9va3MxLmRhdGVQb2ludFRyYW5zZm9ybXMpLFxuICAgICAgICBkYXRlU3BhblRyYW5zZm9ybXM6IGhvb2tzMC5kYXRlU3BhblRyYW5zZm9ybXMuY29uY2F0KGhvb2tzMS5kYXRlU3BhblRyYW5zZm9ybXMpLFxuICAgICAgICB2aWV3czogX19hc3NpZ24oe30sIGhvb2tzMC52aWV3cywgaG9va3MxLnZpZXdzKSxcbiAgICAgICAgdmlld1Byb3BzVHJhbnNmb3JtZXJzOiBob29rczAudmlld1Byb3BzVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEudmlld1Byb3BzVHJhbnNmb3JtZXJzKSxcbiAgICAgICAgaXNQcm9wc1ZhbGlkOiBob29rczEuaXNQcm9wc1ZhbGlkIHx8IGhvb2tzMC5pc1Byb3BzVmFsaWQsXG4gICAgICAgIGV4dGVybmFsRGVmVHJhbnNmb3JtczogaG9va3MwLmV4dGVybmFsRGVmVHJhbnNmb3Jtcy5jb25jYXQoaG9va3MxLmV4dGVybmFsRGVmVHJhbnNmb3JtcyksXG4gICAgICAgIGV2ZW50UmVzaXplSm9pblRyYW5zZm9ybXM6IGhvb2tzMC5ldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zLmNvbmNhdChob29rczEuZXZlbnRSZXNpemVKb2luVHJhbnNmb3JtcyksXG4gICAgICAgIHZpZXdDb250YWluZXJNb2RpZmllcnM6IGhvb2tzMC52aWV3Q29udGFpbmVyTW9kaWZpZXJzLmNvbmNhdChob29rczEudmlld0NvbnRhaW5lck1vZGlmaWVycyksXG4gICAgICAgIGV2ZW50RHJvcFRyYW5zZm9ybWVyczogaG9va3MwLmV2ZW50RHJvcFRyYW5zZm9ybWVycy5jb25jYXQoaG9va3MxLmV2ZW50RHJvcFRyYW5zZm9ybWVycyksXG4gICAgICAgIGNhbGVuZGFySW50ZXJhY3Rpb25zOiBob29rczAuY2FsZW5kYXJJbnRlcmFjdGlvbnMuY29uY2F0KGhvb2tzMS5jYWxlbmRhckludGVyYWN0aW9ucyksXG4gICAgICAgIGNvbXBvbmVudEludGVyYWN0aW9uczogaG9va3MwLmNvbXBvbmVudEludGVyYWN0aW9ucy5jb25jYXQoaG9va3MxLmNvbXBvbmVudEludGVyYWN0aW9ucyksXG4gICAgICAgIHRoZW1lQ2xhc3NlczogX19hc3NpZ24oe30sIGhvb2tzMC50aGVtZUNsYXNzZXMsIGhvb2tzMS50aGVtZUNsYXNzZXMpLFxuICAgICAgICBldmVudFNvdXJjZURlZnM6IGhvb2tzMC5ldmVudFNvdXJjZURlZnMuY29uY2F0KGhvb2tzMS5ldmVudFNvdXJjZURlZnMpLFxuICAgICAgICBjbWRGb3JtYXR0ZXI6IGhvb2tzMS5jbWRGb3JtYXR0ZXIgfHwgaG9va3MwLmNtZEZvcm1hdHRlcixcbiAgICAgICAgcmVjdXJyaW5nVHlwZXM6IGhvb2tzMC5yZWN1cnJpbmdUeXBlcy5jb25jYXQoaG9va3MxLnJlY3VycmluZ1R5cGVzKSxcbiAgICAgICAgbmFtZWRUaW1lWm9uZWRJbXBsOiBob29rczEubmFtZWRUaW1lWm9uZWRJbXBsIHx8IGhvb2tzMC5uYW1lZFRpbWVab25lZEltcGwsXG4gICAgICAgIGRlZmF1bHRWaWV3OiBob29rczAuZGVmYXVsdFZpZXcgfHwgaG9va3MxLmRlZmF1bHRWaWV3LFxuICAgICAgICBlbGVtZW50RHJhZ2dpbmdJbXBsOiBob29rczAuZWxlbWVudERyYWdnaW5nSW1wbCB8fCBob29rczEuZWxlbWVudERyYWdnaW5nSW1wbCxcbiAgICAgICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IF9fYXNzaWduKHt9LCBob29rczAub3B0aW9uQ2hhbmdlSGFuZGxlcnMsIGhvb2tzMS5vcHRpb25DaGFuZ2VIYW5kbGVycylcbiAgICB9O1xufVxuXG52YXIgZXZlbnRTb3VyY2VEZWYgPSB7XG4gICAgaWdub3JlUmFuZ2U6IHRydWUsXG4gICAgcGFyc2VNZXRhOiBmdW5jdGlvbiAocmF3KSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHsgLy8gc2hvcnQgZm9ybVxuICAgICAgICAgICAgcmV0dXJuIHJhdztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KHJhdy5ldmVudHMpKSB7XG4gICAgICAgICAgICByZXR1cm4gcmF3LmV2ZW50cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICAgIGZldGNoOiBmdW5jdGlvbiAoYXJnLCBzdWNjZXNzKSB7XG4gICAgICAgIHN1Y2Nlc3Moe1xuICAgICAgICAgICAgcmF3RXZlbnRzOiBhcmcuZXZlbnRTb3VyY2UubWV0YVxuICAgICAgICB9KTtcbiAgICB9XG59O1xudmFyIEFycmF5RXZlbnRTb3VyY2VQbHVnaW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIGV2ZW50U291cmNlRGVmczogW2V2ZW50U291cmNlRGVmXVxufSk7XG5cbnZhciBldmVudFNvdXJjZURlZiQxID0ge1xuICAgIHBhcnNlTWV0YTogZnVuY3Rpb24gKHJhdykge1xuICAgICAgICBpZiAodHlwZW9mIHJhdyA9PT0gJ2Z1bmN0aW9uJykgeyAvLyBzaG9ydCBmb3JtXG4gICAgICAgICAgICByZXR1cm4gcmF3O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiByYXcuZXZlbnRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gcmF3LmV2ZW50cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICAgIGZldGNoOiBmdW5jdGlvbiAoYXJnLCBzdWNjZXNzLCBmYWlsdXJlKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gYXJnLmNhbGVuZGFyLmRhdGVFbnY7XG4gICAgICAgIHZhciBmdW5jID0gYXJnLmV2ZW50U291cmNlLm1ldGE7XG4gICAgICAgIHVucHJvbWlzaWZ5KGZ1bmMuYmluZChudWxsLCB7XG4gICAgICAgICAgICBzdGFydDogZGF0ZUVudi50b0RhdGUoYXJnLnJhbmdlLnN0YXJ0KSxcbiAgICAgICAgICAgIGVuZDogZGF0ZUVudi50b0RhdGUoYXJnLnJhbmdlLmVuZCksXG4gICAgICAgICAgICBzdGFydFN0cjogZGF0ZUVudi5mb3JtYXRJc28oYXJnLnJhbmdlLnN0YXJ0KSxcbiAgICAgICAgICAgIGVuZFN0cjogZGF0ZUVudi5mb3JtYXRJc28oYXJnLnJhbmdlLmVuZCksXG4gICAgICAgICAgICB0aW1lWm9uZTogZGF0ZUVudi50aW1lWm9uZVxuICAgICAgICB9KSwgZnVuY3Rpb24gKHJhd0V2ZW50cykge1xuICAgICAgICAgICAgc3VjY2Vzcyh7IHJhd0V2ZW50czogcmF3RXZlbnRzIH0pOyAvLyBuZWVkcyBhbiBvYmplY3QgcmVzcG9uc2VcbiAgICAgICAgfSwgZmFpbHVyZSAvLyBzZW5kIGVycm9yT2JqIGRpcmVjdGx5IHRvIGZhaWx1cmUgY2FsbGJhY2tcbiAgICAgICAgKTtcbiAgICB9XG59O1xudmFyIEZ1bmNFdmVudFNvdXJjZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgZXZlbnRTb3VyY2VEZWZzOiBbZXZlbnRTb3VyY2VEZWYkMV1cbn0pO1xuXG5mdW5jdGlvbiByZXF1ZXN0SnNvbihtZXRob2QsIHVybCwgcGFyYW1zLCBzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaykge1xuICAgIG1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpO1xuICAgIHZhciBib2R5ID0gbnVsbDtcbiAgICBpZiAobWV0aG9kID09PSAnR0VUJykge1xuICAgICAgICB1cmwgPSBpbmplY3RRdWVyeVN0cmluZ1BhcmFtcyh1cmwsIHBhcmFtcyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBib2R5ID0gZW5jb2RlUGFyYW1zKHBhcmFtcyk7XG4gICAgfVxuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICB4aHIub3BlbihtZXRob2QsIHVybCwgdHJ1ZSk7XG4gICAgaWYgKG1ldGhvZCAhPT0gJ0dFVCcpIHtcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnKTtcbiAgICB9XG4gICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gMjAwICYmIHhoci5zdGF0dXMgPCA0MDApIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IEpTT04ucGFyc2UoeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKHJlcywgeGhyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBmYWlsdXJlQ2FsbGJhY2soJ0ZhaWx1cmUgcGFyc2luZyBKU09OJywgeGhyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjaygnUmVxdWVzdCBmYWlsZWQnLCB4aHIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZmFpbHVyZUNhbGxiYWNrKCdSZXF1ZXN0IGZhaWxlZCcsIHhocik7XG4gICAgfTtcbiAgICB4aHIuc2VuZChib2R5KTtcbn1cbmZ1bmN0aW9uIGluamVjdFF1ZXJ5U3RyaW5nUGFyYW1zKHVybCwgcGFyYW1zKSB7XG4gICAgcmV0dXJuIHVybCArXG4gICAgICAgICh1cmwuaW5kZXhPZignPycpID09PSAtMSA/ICc/JyA6ICcmJykgK1xuICAgICAgICBlbmNvZGVQYXJhbXMocGFyYW1zKTtcbn1cbmZ1bmN0aW9uIGVuY29kZVBhcmFtcyhwYXJhbXMpIHtcbiAgICB2YXIgcGFydHMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgIHBhcnRzLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tleV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnRzLmpvaW4oJyYnKTtcbn1cblxudmFyIGV2ZW50U291cmNlRGVmJDIgPSB7XG4gICAgcGFyc2VNZXRhOiBmdW5jdGlvbiAocmF3KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmF3ID09PSAnc3RyaW5nJykgeyAvLyBzaG9ydCBmb3JtXG4gICAgICAgICAgICByYXcgPSB7IHVybDogcmF3IH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXJhdyB8fCB0eXBlb2YgcmF3ICE9PSAnb2JqZWN0JyB8fCAhcmF3LnVybCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHVybDogcmF3LnVybCxcbiAgICAgICAgICAgIG1ldGhvZDogKHJhdy5tZXRob2QgfHwgJ0dFVCcpLnRvVXBwZXJDYXNlKCksXG4gICAgICAgICAgICBleHRyYVBhcmFtczogcmF3LmV4dHJhUGFyYW1zLFxuICAgICAgICAgICAgc3RhcnRQYXJhbTogcmF3LnN0YXJ0UGFyYW0sXG4gICAgICAgICAgICBlbmRQYXJhbTogcmF3LmVuZFBhcmFtLFxuICAgICAgICAgICAgdGltZVpvbmVQYXJhbTogcmF3LnRpbWVab25lUGFyYW1cbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGZldGNoOiBmdW5jdGlvbiAoYXJnLCBzdWNjZXNzLCBmYWlsdXJlKSB7XG4gICAgICAgIHZhciBtZXRhID0gYXJnLmV2ZW50U291cmNlLm1ldGE7XG4gICAgICAgIHZhciByZXF1ZXN0UGFyYW1zID0gYnVpbGRSZXF1ZXN0UGFyYW1zKG1ldGEsIGFyZy5yYW5nZSwgYXJnLmNhbGVuZGFyKTtcbiAgICAgICAgcmVxdWVzdEpzb24obWV0YS5tZXRob2QsIG1ldGEudXJsLCByZXF1ZXN0UGFyYW1zLCBmdW5jdGlvbiAocmF3RXZlbnRzLCB4aHIpIHtcbiAgICAgICAgICAgIHN1Y2Nlc3MoeyByYXdFdmVudHM6IHJhd0V2ZW50cywgeGhyOiB4aHIgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvck1lc3NhZ2UsIHhocikge1xuICAgICAgICAgICAgZmFpbHVyZSh7IG1lc3NhZ2U6IGVycm9yTWVzc2FnZSwgeGhyOiB4aHIgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG52YXIgSnNvbkZlZWRFdmVudFNvdXJjZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgZXZlbnRTb3VyY2VEZWZzOiBbZXZlbnRTb3VyY2VEZWYkMl1cbn0pO1xuZnVuY3Rpb24gYnVpbGRSZXF1ZXN0UGFyYW1zKG1ldGEsIHJhbmdlLCBjYWxlbmRhcikge1xuICAgIHZhciBkYXRlRW52ID0gY2FsZW5kYXIuZGF0ZUVudjtcbiAgICB2YXIgc3RhcnRQYXJhbTtcbiAgICB2YXIgZW5kUGFyYW07XG4gICAgdmFyIHRpbWVab25lUGFyYW07XG4gICAgdmFyIGN1c3RvbVJlcXVlc3RQYXJhbXM7XG4gICAgdmFyIHBhcmFtcyA9IHt9O1xuICAgIHN0YXJ0UGFyYW0gPSBtZXRhLnN0YXJ0UGFyYW07XG4gICAgaWYgKHN0YXJ0UGFyYW0gPT0gbnVsbCkge1xuICAgICAgICBzdGFydFBhcmFtID0gY2FsZW5kYXIub3B0KCdzdGFydFBhcmFtJyk7XG4gICAgfVxuICAgIGVuZFBhcmFtID0gbWV0YS5lbmRQYXJhbTtcbiAgICBpZiAoZW5kUGFyYW0gPT0gbnVsbCkge1xuICAgICAgICBlbmRQYXJhbSA9IGNhbGVuZGFyLm9wdCgnZW5kUGFyYW0nKTtcbiAgICB9XG4gICAgdGltZVpvbmVQYXJhbSA9IG1ldGEudGltZVpvbmVQYXJhbTtcbiAgICBpZiAodGltZVpvbmVQYXJhbSA9PSBudWxsKSB7XG4gICAgICAgIHRpbWVab25lUGFyYW0gPSBjYWxlbmRhci5vcHQoJ3RpbWVab25lUGFyYW0nKTtcbiAgICB9XG4gICAgLy8gcmV0cmlldmUgYW55IG91dGJvdW5kIEdFVC9QT1NUIGRhdGEgZnJvbSB0aGUgb3B0aW9uc1xuICAgIGlmICh0eXBlb2YgbWV0YS5leHRyYVBhcmFtcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAvLyBzdXBwbGllZCBhcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGtleS92YWx1ZSBvYmplY3RcbiAgICAgICAgY3VzdG9tUmVxdWVzdFBhcmFtcyA9IG1ldGEuZXh0cmFQYXJhbXMoKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIHByb2JhYmx5IHN1cHBsaWVkIGFzIGEgc3RyYWlnaHQga2V5L3ZhbHVlIG9iamVjdFxuICAgICAgICBjdXN0b21SZXF1ZXN0UGFyYW1zID0gbWV0YS5leHRyYVBhcmFtcyB8fCB7fTtcbiAgICB9XG4gICAgX19hc3NpZ24ocGFyYW1zLCBjdXN0b21SZXF1ZXN0UGFyYW1zKTtcbiAgICBwYXJhbXNbc3RhcnRQYXJhbV0gPSBkYXRlRW52LmZvcm1hdElzbyhyYW5nZS5zdGFydCk7XG4gICAgcGFyYW1zW2VuZFBhcmFtXSA9IGRhdGVFbnYuZm9ybWF0SXNvKHJhbmdlLmVuZCk7XG4gICAgaWYgKGRhdGVFbnYudGltZVpvbmUgIT09ICdsb2NhbCcpIHtcbiAgICAgICAgcGFyYW1zW3RpbWVab25lUGFyYW1dID0gZGF0ZUVudi50aW1lWm9uZTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcmFtcztcbn1cblxudmFyIHJlY3VycmluZyA9IHtcbiAgICBwYXJzZTogZnVuY3Rpb24gKHJhd0V2ZW50LCBsZWZ0b3ZlclByb3BzLCBkYXRlRW52KSB7XG4gICAgICAgIHZhciBjcmVhdGVNYXJrZXIgPSBkYXRlRW52LmNyZWF0ZU1hcmtlci5iaW5kKGRhdGVFbnYpO1xuICAgICAgICB2YXIgcHJvY2Vzc29ycyA9IHtcbiAgICAgICAgICAgIGRheXNPZldlZWs6IG51bGwsXG4gICAgICAgICAgICBzdGFydFRpbWU6IGNyZWF0ZUR1cmF0aW9uLFxuICAgICAgICAgICAgZW5kVGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgICAgICAgICBzdGFydFJlY3VyOiBjcmVhdGVNYXJrZXIsXG4gICAgICAgICAgICBlbmRSZWN1cjogY3JlYXRlTWFya2VyXG4gICAgICAgIH07XG4gICAgICAgIHZhciBwcm9wcyA9IHJlZmluZVByb3BzKHJhd0V2ZW50LCBwcm9jZXNzb3JzLCB7fSwgbGVmdG92ZXJQcm9wcyk7XG4gICAgICAgIHZhciBhbnlWYWxpZCA9IGZhbHNlO1xuICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgaWYgKHByb3BzW3Byb3BOYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYW55VmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChhbnlWYWxpZCkge1xuICAgICAgICAgICAgdmFyIGR1cmF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIGlmICgnZHVyYXRpb24nIGluIGxlZnRvdmVyUHJvcHMpIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKGxlZnRvdmVyUHJvcHMuZHVyYXRpb24pO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBsZWZ0b3ZlclByb3BzLmR1cmF0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFkdXJhdGlvbiAmJiBwcm9wcy5zdGFydFRpbWUgJiYgcHJvcHMuZW5kVGltZSkge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gc3VidHJhY3REdXJhdGlvbnMocHJvcHMuZW5kVGltZSwgcHJvcHMuc3RhcnRUaW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgYWxsRGF5R3Vlc3M6IEJvb2xlYW4oIXByb3BzLnN0YXJ0VGltZSAmJiAhcHJvcHMuZW5kVGltZSksXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uLFxuICAgICAgICAgICAgICAgIHR5cGVEYXRhOiBwcm9wcyAvLyBkb2Vzbid0IG5lZWQgZW5kVGltZSBhbnltb3JlIGJ1dCBvaCB3ZWxsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgZXhwYW5kOiBmdW5jdGlvbiAodHlwZURhdGEsIGZyYW1pbmdSYW5nZSwgZGF0ZUVudikge1xuICAgICAgICB2YXIgY2xpcHBlZEZyYW1pbmdSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhmcmFtaW5nUmFuZ2UsIHsgc3RhcnQ6IHR5cGVEYXRhLnN0YXJ0UmVjdXIsIGVuZDogdHlwZURhdGEuZW5kUmVjdXIgfSk7XG4gICAgICAgIGlmIChjbGlwcGVkRnJhbWluZ1JhbmdlKSB7XG4gICAgICAgICAgICByZXR1cm4gZXhwYW5kUmFuZ2VzKHR5cGVEYXRhLmRheXNPZldlZWssIHR5cGVEYXRhLnN0YXJ0VGltZSwgY2xpcHBlZEZyYW1pbmdSYW5nZSwgZGF0ZUVudik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICB9XG59O1xudmFyIFNpbXBsZVJlY3VycmVuY2VQbHVnaW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIHJlY3VycmluZ1R5cGVzOiBbcmVjdXJyaW5nXVxufSk7XG5mdW5jdGlvbiBleHBhbmRSYW5nZXMoZGF5c09mV2Vlaywgc3RhcnRUaW1lLCBmcmFtaW5nUmFuZ2UsIGRhdGVFbnYpIHtcbiAgICB2YXIgZG93SGFzaCA9IGRheXNPZldlZWsgPyBhcnJheVRvSGFzaChkYXlzT2ZXZWVrKSA6IG51bGw7XG4gICAgdmFyIGRheU1hcmtlciA9IHN0YXJ0T2ZEYXkoZnJhbWluZ1JhbmdlLnN0YXJ0KTtcbiAgICB2YXIgZW5kTWFya2VyID0gZnJhbWluZ1JhbmdlLmVuZDtcbiAgICB2YXIgaW5zdGFuY2VTdGFydHMgPSBbXTtcbiAgICB3aGlsZSAoZGF5TWFya2VyIDwgZW5kTWFya2VyKSB7XG4gICAgICAgIHZhciBpbnN0YW5jZVN0YXJ0IFxuICAgICAgICAvLyBpZiBldmVyeWRheSwgb3IgdGhpcyBwYXJ0aWN1bGFyIGRheS1vZi13ZWVrXG4gICAgICAgID0gdm9pZCAwO1xuICAgICAgICAvLyBpZiBldmVyeWRheSwgb3IgdGhpcyBwYXJ0aWN1bGFyIGRheS1vZi13ZWVrXG4gICAgICAgIGlmICghZG93SGFzaCB8fCBkb3dIYXNoW2RheU1hcmtlci5nZXRVVENEYXkoKV0pIHtcbiAgICAgICAgICAgIGlmIChzdGFydFRpbWUpIHtcbiAgICAgICAgICAgICAgICBpbnN0YW5jZVN0YXJ0ID0gZGF0ZUVudi5hZGQoZGF5TWFya2VyLCBzdGFydFRpbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaW5zdGFuY2VTdGFydCA9IGRheU1hcmtlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGluc3RhbmNlU3RhcnRzLnB1c2goaW5zdGFuY2VTdGFydCk7XG4gICAgICAgIH1cbiAgICAgICAgZGF5TWFya2VyID0gYWRkRGF5cyhkYXlNYXJrZXIsIDEpO1xuICAgIH1cbiAgICByZXR1cm4gaW5zdGFuY2VTdGFydHM7XG59XG5cbnZhciBEZWZhdWx0T3B0aW9uQ2hhbmdlSGFuZGxlcnMgPSBjcmVhdGVQbHVnaW4oe1xuICAgIG9wdGlvbkNoYW5nZUhhbmRsZXJzOiB7XG4gICAgICAgIGV2ZW50czogZnVuY3Rpb24gKGV2ZW50cywgY2FsZW5kYXIsIGRlZXBFcXVhbCkge1xuICAgICAgICAgICAgaGFuZGxlRXZlbnRTb3VyY2VzKFtldmVudHNdLCBjYWxlbmRhciwgZGVlcEVxdWFsKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXZlbnRTb3VyY2VzOiBoYW5kbGVFdmVudFNvdXJjZXMsXG4gICAgICAgIHBsdWdpbnM6IGhhbmRsZVBsdWdpbnNcbiAgICB9XG59KTtcbmZ1bmN0aW9uIGhhbmRsZUV2ZW50U291cmNlcyhpbnB1dHMsIGNhbGVuZGFyLCBkZWVwRXF1YWwpIHtcbiAgICB2YXIgdW5mb3VuZFNvdXJjZXMgPSBoYXNoVmFsdWVzVG9BcnJheShjYWxlbmRhci5zdGF0ZS5ldmVudFNvdXJjZXMpO1xuICAgIHZhciBuZXdJbnB1dHMgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIGlucHV0c18xID0gaW5wdXRzOyBfaSA8IGlucHV0c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgaW5wdXQgPSBpbnB1dHNfMVtfaV07XG4gICAgICAgIHZhciBpbnB1dEZvdW5kID0gZmFsc2U7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdW5mb3VuZFNvdXJjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChkZWVwRXF1YWwodW5mb3VuZFNvdXJjZXNbaV0uX3JhdywgaW5wdXQpKSB7XG4gICAgICAgICAgICAgICAgdW5mb3VuZFNvdXJjZXMuc3BsaWNlKGksIDEpOyAvLyBkZWxldGVcbiAgICAgICAgICAgICAgICBpbnB1dEZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlucHV0Rm91bmQpIHtcbiAgICAgICAgICAgIG5ld0lucHV0cy5wdXNoKGlucHV0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBfYSA9IDAsIHVuZm91bmRTb3VyY2VzXzEgPSB1bmZvdW5kU291cmNlczsgX2EgPCB1bmZvdW5kU291cmNlc18xLmxlbmd0aDsgX2ErKykge1xuICAgICAgICB2YXIgdW5mb3VuZFNvdXJjZSA9IHVuZm91bmRTb3VyY2VzXzFbX2FdO1xuICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVNT1ZFX0VWRU5UX1NPVVJDRScsXG4gICAgICAgICAgICBzb3VyY2VJZDogdW5mb3VuZFNvdXJjZS5zb3VyY2VJZFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZm9yICh2YXIgX2IgPSAwLCBuZXdJbnB1dHNfMSA9IG5ld0lucHV0czsgX2IgPCBuZXdJbnB1dHNfMS5sZW5ndGg7IF9iKyspIHtcbiAgICAgICAgdmFyIG5ld0lucHV0ID0gbmV3SW5wdXRzXzFbX2JdO1xuICAgICAgICBjYWxlbmRhci5hZGRFdmVudFNvdXJjZShuZXdJbnB1dCk7XG4gICAgfVxufVxuLy8gc2hvcnRjb21pbmc6IHdvbid0IHJlbW92ZSBwbHVnaW5zXG5mdW5jdGlvbiBoYW5kbGVQbHVnaW5zKGlucHV0cywgY2FsZW5kYXIpIHtcbiAgICBjYWxlbmRhci5hZGRQbHVnaW5JbnB1dHMoaW5wdXRzKTsgLy8gd2lsbCBncmFjZWZ1bGx5IGhhbmRsZSBkdXBsaWNhdGVzXG59XG5cbnZhciBjb25maWcgPSB7fTsgLy8gVE9ETzogbWFrZSB0aGVzZSBvcHRpb25zXG52YXIgZ2xvYmFsRGVmYXVsdHMgPSB7XG4gICAgZGVmYXVsdFJhbmdlU2VwYXJhdG9yOiAnIC0gJyxcbiAgICB0aXRsZVJhbmdlU2VwYXJhdG9yOiAnIFxcdTIwMTMgJyxcbiAgICBkZWZhdWx0VGltZWRFdmVudER1cmF0aW9uOiAnMDE6MDA6MDAnLFxuICAgIGRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uOiB7IGRheTogMSB9LFxuICAgIGZvcmNlRXZlbnREdXJhdGlvbjogZmFsc2UsXG4gICAgbmV4dERheVRocmVzaG9sZDogJzAwOjAwOjAwJyxcbiAgICAvLyBkaXNwbGF5XG4gICAgY29sdW1uSGVhZGVyOiB0cnVlLFxuICAgIGRlZmF1bHRWaWV3OiAnJyxcbiAgICBhc3BlY3RSYXRpbzogMS4zNSxcbiAgICBoZWFkZXI6IHtcbiAgICAgICAgbGVmdDogJ3RpdGxlJyxcbiAgICAgICAgY2VudGVyOiAnJyxcbiAgICAgICAgcmlnaHQ6ICd0b2RheSBwcmV2LG5leHQnXG4gICAgfSxcbiAgICB3ZWVrZW5kczogdHJ1ZSxcbiAgICB3ZWVrTnVtYmVyczogZmFsc2UsXG4gICAgd2Vla051bWJlckNhbGN1bGF0aW9uOiAnbG9jYWwnLFxuICAgIGVkaXRhYmxlOiBmYWxzZSxcbiAgICAvLyBub3dJbmRpY2F0b3I6IGZhbHNlLFxuICAgIHNjcm9sbFRpbWU6ICcwNjowMDowMCcsXG4gICAgbWluVGltZTogJzAwOjAwOjAwJyxcbiAgICBtYXhUaW1lOiAnMjQ6MDA6MDAnLFxuICAgIHNob3dOb25DdXJyZW50RGF0ZXM6IHRydWUsXG4gICAgLy8gZXZlbnQgYWpheFxuICAgIGxhenlGZXRjaGluZzogdHJ1ZSxcbiAgICBzdGFydFBhcmFtOiAnc3RhcnQnLFxuICAgIGVuZFBhcmFtOiAnZW5kJyxcbiAgICB0aW1lWm9uZVBhcmFtOiAndGltZVpvbmUnLFxuICAgIHRpbWVab25lOiAnbG9jYWwnLFxuICAgIC8vIGFsbERheURlZmF1bHQ6IHVuZGVmaW5lZCxcbiAgICAvLyBsb2NhbGVcbiAgICBsb2NhbGVzOiBbXSxcbiAgICBsb2NhbGU6ICcnLFxuICAgIC8vIGRpcjogd2lsbCBnZXQgdGhpcyBmcm9tIHRoZSBkZWZhdWx0IGxvY2FsZVxuICAgIC8vIGJ1dHRvbkljb25zOiBudWxsLFxuICAgIC8vIGFsbG93cyBzZXR0aW5nIGEgbWluLWhlaWdodCB0byB0aGUgZXZlbnQgc2VnbWVudCB0byBwcmV2ZW50IHNob3J0IGV2ZW50cyBvdmVybGFwcGluZyBlYWNoIG90aGVyXG4gICAgdGltZUdyaWRFdmVudE1pbkhlaWdodDogMCxcbiAgICB0aGVtZVN5c3RlbTogJ3N0YW5kYXJkJyxcbiAgICAvLyBldmVudFJlc2l6YWJsZUZyb21TdGFydDogZmFsc2UsXG4gICAgZHJhZ1JldmVydER1cmF0aW9uOiA1MDAsXG4gICAgZHJhZ1Njcm9sbDogdHJ1ZSxcbiAgICBhbGxEYXlNYWludGFpbkR1cmF0aW9uOiBmYWxzZSxcbiAgICAvLyBzZWxlY3RhYmxlOiBmYWxzZSxcbiAgICB1bnNlbGVjdEF1dG86IHRydWUsXG4gICAgLy8gc2VsZWN0TWluRGlzdGFuY2U6IDAsXG4gICAgZHJvcEFjY2VwdDogJyonLFxuICAgIGV2ZW50T3JkZXI6ICdzdGFydCwtZHVyYXRpb24sYWxsRGF5LHRpdGxlJyxcbiAgICAvLyBeIGlmIHN0YXJ0IHRpZSwgbG9uZ2VyIGV2ZW50cyBnbyBiZWZvcmUgc2hvcnRlci4gZmluYWwgdGllLWJyZWFrZXIgaXMgdGl0bGUgdGV4dFxuICAgIC8vIHJlcmVuZGVyRGVsYXk6IG51bGwsXG4gICAgZXZlbnRMaW1pdDogZmFsc2UsXG4gICAgZXZlbnRMaW1pdENsaWNrOiAncG9wb3ZlcicsXG4gICAgZGF5UG9wb3ZlckZvcm1hdDogeyBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJywgeWVhcjogJ251bWVyaWMnIH0sXG4gICAgaGFuZGxlV2luZG93UmVzaXplOiB0cnVlLFxuICAgIHdpbmRvd1Jlc2l6ZURlbGF5OiAxMDAsXG4gICAgbG9uZ1ByZXNzRGVsYXk6IDEwMDAsXG4gICAgZXZlbnREcmFnTWluRGlzdGFuY2U6IDUgLy8gb25seSBhcHBsaWVzIHRvIG1vdXNlXG59O1xudmFyIHJ0bERlZmF1bHRzID0ge1xuICAgIGhlYWRlcjoge1xuICAgICAgICBsZWZ0OiAnbmV4dCxwcmV2IHRvZGF5JyxcbiAgICAgICAgY2VudGVyOiAnJyxcbiAgICAgICAgcmlnaHQ6ICd0aXRsZSdcbiAgICB9LFxuICAgIGJ1dHRvbkljb25zOiB7XG4gICAgICAgIC8vIFRPRE86IG1ha2UgUlRMIHN1cHBvcnQgdGhlIHJlc3BvbmliaWxpdHkgb2YgdGhlIHRoZW1lXG4gICAgICAgIHByZXY6ICdmYy1pY29uLWNoZXZyb24tcmlnaHQnLFxuICAgICAgICBuZXh0OiAnZmMtaWNvbi1jaGV2cm9uLWxlZnQnLFxuICAgICAgICBwcmV2WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtcmlnaHQnLFxuICAgICAgICBuZXh0WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtbGVmdCdcbiAgICB9XG59O1xudmFyIGNvbXBsZXhPcHRpb25zID0gW1xuICAgICdoZWFkZXInLFxuICAgICdmb290ZXInLFxuICAgICdidXR0b25UZXh0JyxcbiAgICAnYnV0dG9uSWNvbnMnXG5dO1xuLy8gTWVyZ2VzIGFuIGFycmF5IG9mIG9wdGlvbiBvYmplY3RzIGludG8gYSBzaW5nbGUgb2JqZWN0XG5mdW5jdGlvbiBtZXJnZU9wdGlvbnMob3B0aW9uT2Jqcykge1xuICAgIHJldHVybiBtZXJnZVByb3BzKG9wdGlvbk9ianMsIGNvbXBsZXhPcHRpb25zKTtcbn1cbi8vIFRPRE86IG1vdmUgdGhpcyBzdHVmZiB0byBhIFwicGx1Z2luXCItcmVsYXRlZCBmaWxlLi4uXG52YXIgSU5URVJOQUxfUExVR0lOUyA9IFtcbiAgICBBcnJheUV2ZW50U291cmNlUGx1Z2luLFxuICAgIEZ1bmNFdmVudFNvdXJjZVBsdWdpbixcbiAgICBKc29uRmVlZEV2ZW50U291cmNlUGx1Z2luLFxuICAgIFNpbXBsZVJlY3VycmVuY2VQbHVnaW4sXG4gICAgRGVmYXVsdE9wdGlvbkNoYW5nZUhhbmRsZXJzXG5dO1xuZnVuY3Rpb24gcmVmaW5lUGx1Z2luRGVmcyhwbHVnaW5JbnB1dHMpIHtcbiAgICB2YXIgcGx1Z2lucyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMCwgcGx1Z2luSW5wdXRzXzEgPSBwbHVnaW5JbnB1dHM7IF9pIDwgcGx1Z2luSW5wdXRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBwbHVnaW5JbnB1dCA9IHBsdWdpbklucHV0c18xW19pXTtcbiAgICAgICAgaWYgKHR5cGVvZiBwbHVnaW5JbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHZhciBnbG9iYWxOYW1lID0gJ0Z1bGxDYWxlbmRhcicgKyBjYXBpdGFsaXNlRmlyc3RMZXR0ZXIocGx1Z2luSW5wdXQpO1xuICAgICAgICAgICAgaWYgKCF3aW5kb3dbZ2xvYmFsTmFtZV0pIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1BsdWdpbiBmaWxlIG5vdCBsb2FkZWQgZm9yICcgKyBwbHVnaW5JbnB1dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBwbHVnaW5zLnB1c2god2luZG93W2dsb2JhbE5hbWVdLmRlZmF1bHQpOyAvLyBpcyBhbiBFUzYgbW9kdWxlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBwbHVnaW5zLnB1c2gocGx1Z2luSW5wdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJTlRFUk5BTF9QTFVHSU5TLmNvbmNhdChwbHVnaW5zKTtcbn1cblxudmFyIFJBV19FTl9MT0NBTEUgPSB7XG4gICAgY29kZTogJ2VuJyxcbiAgICB3ZWVrOiB7XG4gICAgICAgIGRvdzogMCxcbiAgICAgICAgZG95OiA0IC8vIDQgZGF5cyBuZWVkIHRvIGJlIHdpdGhpbiB0aGUgeWVhciB0byBiZSBjb25zaWRlcmVkIHRoZSBmaXJzdCB3ZWVrXG4gICAgfSxcbiAgICBkaXI6ICdsdHInLFxuICAgIGJ1dHRvblRleHQ6IHtcbiAgICAgICAgcHJldjogJ3ByZXYnLFxuICAgICAgICBuZXh0OiAnbmV4dCcsXG4gICAgICAgIHByZXZZZWFyOiAncHJldiB5ZWFyJyxcbiAgICAgICAgbmV4dFllYXI6ICduZXh0IHllYXInLFxuICAgICAgICB5ZWFyOiAneWVhcicsXG4gICAgICAgIHRvZGF5OiAndG9kYXknLFxuICAgICAgICBtb250aDogJ21vbnRoJyxcbiAgICAgICAgd2VlazogJ3dlZWsnLFxuICAgICAgICBkYXk6ICdkYXknLFxuICAgICAgICBsaXN0OiAnbGlzdCdcbiAgICB9LFxuICAgIHdlZWtMYWJlbDogJ1cnLFxuICAgIGFsbERheVRleHQ6ICdhbGwtZGF5JyxcbiAgICBldmVudExpbWl0VGV4dDogJ21vcmUnLFxuICAgIG5vRXZlbnRzTWVzc2FnZTogJ05vIGV2ZW50cyB0byBkaXNwbGF5J1xufTtcbmZ1bmN0aW9uIHBhcnNlUmF3TG9jYWxlcyhleHBsaWNpdFJhd0xvY2FsZXMpIHtcbiAgICB2YXIgZGVmYXVsdENvZGUgPSBleHBsaWNpdFJhd0xvY2FsZXMubGVuZ3RoID4gMCA/IGV4cGxpY2l0UmF3TG9jYWxlc1swXS5jb2RlIDogJ2VuJztcbiAgICB2YXIgZ2xvYmFsQXJyYXkgPSB3aW5kb3dbJ0Z1bGxDYWxlbmRhckxvY2FsZXNBbGwnXSB8fCBbXTsgLy8gZnJvbSBsb2NhbGVzLWFsbC5qc1xuICAgIHZhciBnbG9iYWxPYmplY3QgPSB3aW5kb3dbJ0Z1bGxDYWxlbmRhckxvY2FsZXMnXSB8fCB7fTsgLy8gZnJvbSBsb2NhbGVzLyouanMuIGtleXMgYXJlIG1lYW5pbmdsZXNzXG4gICAgdmFyIGFsbFJhd0xvY2FsZXMgPSBnbG9iYWxBcnJheS5jb25jYXQoLy8gZ2xvYmFsQXJyYXkgaXMgbG93IHByaW9cbiAgICBoYXNoVmFsdWVzVG9BcnJheShnbG9iYWxPYmplY3QpLCAvLyBtZWRpdW0gcHJpb1xuICAgIGV4cGxpY2l0UmF3TG9jYWxlcyAvLyBoaWdoZXN0IHByaW9cbiAgICApO1xuICAgIHZhciByYXdMb2NhbGVNYXAgPSB7XG4gICAgICAgIGVuOiBSQVdfRU5fTE9DQUxFIC8vIG5lY2Vzc2FyeT9cbiAgICB9O1xuICAgIGZvciAodmFyIF9pID0gMCwgYWxsUmF3TG9jYWxlc18xID0gYWxsUmF3TG9jYWxlczsgX2kgPCBhbGxSYXdMb2NhbGVzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciByYXdMb2NhbGUgPSBhbGxSYXdMb2NhbGVzXzFbX2ldO1xuICAgICAgICByYXdMb2NhbGVNYXBbcmF3TG9jYWxlLmNvZGVdID0gcmF3TG9jYWxlO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBtYXA6IHJhd0xvY2FsZU1hcCxcbiAgICAgICAgZGVmYXVsdENvZGU6IGRlZmF1bHRDb2RlXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGJ1aWxkTG9jYWxlKGlucHV0U2luZ3VsYXIsIGF2YWlsYWJsZSkge1xuICAgIGlmICh0eXBlb2YgaW5wdXRTaW5ndWxhciA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoaW5wdXRTaW5ndWxhcikpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlTG9jYWxlKGlucHV0U2luZ3VsYXIuY29kZSwgW2lucHV0U2luZ3VsYXIuY29kZV0sIGlucHV0U2luZ3VsYXIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHF1ZXJ5TG9jYWxlKGlucHV0U2luZ3VsYXIsIGF2YWlsYWJsZSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcXVlcnlMb2NhbGUoY29kZUFyZywgYXZhaWxhYmxlKSB7XG4gICAgdmFyIGNvZGVzID0gW10uY29uY2F0KGNvZGVBcmcgfHwgW10pOyAvLyB3aWxsIGNvbnZlcnQgdG8gYXJyYXlcbiAgICB2YXIgcmF3ID0gcXVlcnlSYXdMb2NhbGUoY29kZXMsIGF2YWlsYWJsZSkgfHwgUkFXX0VOX0xPQ0FMRTtcbiAgICByZXR1cm4gcGFyc2VMb2NhbGUoY29kZUFyZywgY29kZXMsIHJhdyk7XG59XG5mdW5jdGlvbiBxdWVyeVJhd0xvY2FsZShjb2RlcywgYXZhaWxhYmxlKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcGFydHMgPSBjb2Rlc1tpXS50b0xvY2FsZUxvd2VyQ2FzZSgpLnNwbGl0KCctJyk7XG4gICAgICAgIGZvciAodmFyIGogPSBwYXJ0cy5sZW5ndGg7IGogPiAwOyBqLS0pIHtcbiAgICAgICAgICAgIHZhciBzaW1wbGVJZCA9IHBhcnRzLnNsaWNlKDAsIGopLmpvaW4oJy0nKTtcbiAgICAgICAgICAgIGlmIChhdmFpbGFibGVbc2ltcGxlSWRdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF2YWlsYWJsZVtzaW1wbGVJZF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBwYXJzZUxvY2FsZShjb2RlQXJnLCBjb2RlcywgcmF3KSB7XG4gICAgdmFyIG1lcmdlZCA9IG1lcmdlUHJvcHMoW1JBV19FTl9MT0NBTEUsIHJhd10sIFsnYnV0dG9uVGV4dCddKTtcbiAgICBkZWxldGUgbWVyZ2VkLmNvZGU7IC8vIGRvbid0IHdhbnQgdGhpcyBwYXJ0IG9mIHRoZSBvcHRpb25zXG4gICAgdmFyIHdlZWsgPSBtZXJnZWQud2VlaztcbiAgICBkZWxldGUgbWVyZ2VkLndlZWs7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29kZUFyZzogY29kZUFyZyxcbiAgICAgICAgY29kZXM6IGNvZGVzLFxuICAgICAgICB3ZWVrOiB3ZWVrLFxuICAgICAgICBzaW1wbGVOdW1iZXJGb3JtYXQ6IG5ldyBJbnRsLk51bWJlckZvcm1hdChjb2RlQXJnKSxcbiAgICAgICAgb3B0aW9uczogbWVyZ2VkXG4gICAgfTtcbn1cblxudmFyIE9wdGlvbnNNYW5hZ2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE9wdGlvbnNNYW5hZ2VyKG92ZXJyaWRlcykge1xuICAgICAgICB0aGlzLm92ZXJyaWRlcyA9IF9fYXNzaWduKHt9LCBvdmVycmlkZXMpOyAvLyBtYWtlIGEgY29weVxuICAgICAgICB0aGlzLmR5bmFtaWNPdmVycmlkZXMgPSB7fTtcbiAgICAgICAgdGhpcy5jb21wdXRlKCk7XG4gICAgfVxuICAgIE9wdGlvbnNNYW5hZ2VyLnByb3RvdHlwZS5tdXRhdGUgPSBmdW5jdGlvbiAodXBkYXRlcywgcmVtb3ZhbHMsIGlzRHluYW1pYykge1xuICAgICAgICBpZiAoIU9iamVjdC5rZXlzKHVwZGF0ZXMpLmxlbmd0aCAmJiAhcmVtb3ZhbHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG92ZXJyaWRlSGFzaCA9IGlzRHluYW1pYyA/IHRoaXMuZHluYW1pY092ZXJyaWRlcyA6IHRoaXMub3ZlcnJpZGVzO1xuICAgICAgICBfX2Fzc2lnbihvdmVycmlkZUhhc2gsIHVwZGF0ZXMpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHJlbW92YWxzXzEgPSByZW1vdmFsczsgX2kgPCByZW1vdmFsc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcmVtb3ZhbHNfMVtfaV07XG4gICAgICAgICAgICBkZWxldGUgb3ZlcnJpZGVIYXNoW3Byb3BOYW1lXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbXB1dGUoKTtcbiAgICB9O1xuICAgIC8vIENvbXB1dGVzIHRoZSBmbGF0dGVuZWQgb3B0aW9ucyBoYXNoIGZvciB0aGUgY2FsZW5kYXIgYW5kIGFzc2lnbnMgdG8gYHRoaXMub3B0aW9uc2AuXG4gICAgLy8gQXNzdW1lcyB0aGlzLm92ZXJyaWRlcyBhbmQgdGhpcy5keW5hbWljT3ZlcnJpZGVzIGhhdmUgYWxyZWFkeSBiZWVuIGluaXRpYWxpemVkLlxuICAgIE9wdGlvbnNNYW5hZ2VyLnByb3RvdHlwZS5jb21wdXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBUT0RPOiBub3QgYSB2ZXJ5IGVmZmljaWVudCBzeXN0ZW1cbiAgICAgICAgdmFyIGxvY2FsZXMgPSBmaXJzdERlZmluZWQoLy8gZXhwbGljaXQgbG9jYWxlIG9wdGlvbiBnaXZlbj9cbiAgICAgICAgdGhpcy5keW5hbWljT3ZlcnJpZGVzLmxvY2FsZXMsIHRoaXMub3ZlcnJpZGVzLmxvY2FsZXMsIGdsb2JhbERlZmF1bHRzLmxvY2FsZXMpO1xuICAgICAgICB2YXIgbG9jYWxlID0gZmlyc3REZWZpbmVkKC8vIGV4cGxpY2l0IGxvY2FsZXMgb3B0aW9uIGdpdmVuP1xuICAgICAgICB0aGlzLmR5bmFtaWNPdmVycmlkZXMubG9jYWxlLCB0aGlzLm92ZXJyaWRlcy5sb2NhbGUsIGdsb2JhbERlZmF1bHRzLmxvY2FsZSk7XG4gICAgICAgIHZhciBhdmFpbGFibGUgPSBwYXJzZVJhd0xvY2FsZXMobG9jYWxlcyk7XG4gICAgICAgIHZhciBsb2NhbGVEZWZhdWx0cyA9IGJ1aWxkTG9jYWxlKGxvY2FsZSB8fCBhdmFpbGFibGUuZGVmYXVsdENvZGUsIGF2YWlsYWJsZS5tYXApLm9wdGlvbnM7XG4gICAgICAgIHZhciBkaXIgPSBmaXJzdERlZmluZWQoLy8gYmFzZWQgb24gb3B0aW9ucyBjb21wdXRlZCBzbyBmYXIsIGlzIGRpcmVjdGlvbiBSVEw/XG4gICAgICAgIHRoaXMuZHluYW1pY092ZXJyaWRlcy5kaXIsIHRoaXMub3ZlcnJpZGVzLmRpciwgbG9jYWxlRGVmYXVsdHMuZGlyKTtcbiAgICAgICAgdmFyIGRpckRlZmF1bHRzID0gZGlyID09PSAncnRsJyA/IHJ0bERlZmF1bHRzIDoge307XG4gICAgICAgIHRoaXMuZGlyRGVmYXVsdHMgPSBkaXJEZWZhdWx0cztcbiAgICAgICAgdGhpcy5sb2NhbGVEZWZhdWx0cyA9IGxvY2FsZURlZmF1bHRzO1xuICAgICAgICB0aGlzLmNvbXB1dGVkID0gbWVyZ2VPcHRpb25zKFtcbiAgICAgICAgICAgIGdsb2JhbERlZmF1bHRzLFxuICAgICAgICAgICAgZGlyRGVmYXVsdHMsXG4gICAgICAgICAgICBsb2NhbGVEZWZhdWx0cyxcbiAgICAgICAgICAgIHRoaXMub3ZlcnJpZGVzLFxuICAgICAgICAgICAgdGhpcy5keW5hbWljT3ZlcnJpZGVzXG4gICAgICAgIF0pO1xuICAgIH07XG4gICAgcmV0dXJuIE9wdGlvbnNNYW5hZ2VyO1xufSgpKTtcblxudmFyIGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXAgPSB7fTtcbmZ1bmN0aW9uIHJlZ2lzdGVyQ2FsZW5kYXJTeXN0ZW0obmFtZSwgdGhlQ2xhc3MpIHtcbiAgICBjYWxlbmRhclN5c3RlbUNsYXNzTWFwW25hbWVdID0gdGhlQ2xhc3M7XG59XG5mdW5jdGlvbiBjcmVhdGVDYWxlbmRhclN5c3RlbShuYW1lKSB7XG4gICAgcmV0dXJuIG5ldyBjYWxlbmRhclN5c3RlbUNsYXNzTWFwW25hbWVdKCk7XG59XG52YXIgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0oKSB7XG4gICAgfVxuICAgIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtLnByb3RvdHlwZS5nZXRNYXJrZXJZZWFyID0gZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZ2V0VVRDRnVsbFllYXIoKTtcbiAgICB9O1xuICAgIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtLnByb3RvdHlwZS5nZXRNYXJrZXJNb250aCA9IGZ1bmN0aW9uIChkKSB7XG4gICAgICAgIHJldHVybiBkLmdldFVUQ01vbnRoKCk7XG4gICAgfTtcbiAgICBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbS5wcm90b3R5cGUuZ2V0TWFya2VyRGF5ID0gZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZ2V0VVRDRGF0ZSgpO1xuICAgIH07XG4gICAgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0ucHJvdG90eXBlLmFycmF5VG9NYXJrZXIgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShhcnIpO1xuICAgIH07XG4gICAgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0ucHJvdG90eXBlLm1hcmtlclRvQXJyYXkgPSBmdW5jdGlvbiAobWFya2VyKSB7XG4gICAgICAgIHJldHVybiBkYXRlVG9VdGNBcnJheShtYXJrZXIpO1xuICAgIH07XG4gICAgcmV0dXJuIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtO1xufSgpKTtcbnJlZ2lzdGVyQ2FsZW5kYXJTeXN0ZW0oJ2dyZWdvcnknLCBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbSk7XG5cbnZhciBJU09fUkUgPSAvXlxccyooXFxkezR9KSgtKFxcZHsyfSkoLShcXGR7Mn0pKFtUIF0oXFxkezJ9KTooXFxkezJ9KSg6KFxcZHsyfSkoXFwuKFxcZCspKT8pPyhafCgoWy0rXSkoXFxkezJ9KSg6PyhcXGR7Mn0pKT8pKT8pPyk/KT8kLztcbmZ1bmN0aW9uIHBhcnNlKHN0cikge1xuICAgIHZhciBtID0gSVNPX1JFLmV4ZWMoc3RyKTtcbiAgICBpZiAobSkge1xuICAgICAgICB2YXIgbWFya2VyID0gbmV3IERhdGUoRGF0ZS5VVEMoTnVtYmVyKG1bMV0pLCBtWzNdID8gTnVtYmVyKG1bM10pIC0gMSA6IDAsIE51bWJlcihtWzVdIHx8IDEpLCBOdW1iZXIobVs3XSB8fCAwKSwgTnVtYmVyKG1bOF0gfHwgMCksIE51bWJlcihtWzEwXSB8fCAwKSwgbVsxMl0gPyBOdW1iZXIoJzAuJyArIG1bMTJdKSAqIDEwMDAgOiAwKSk7XG4gICAgICAgIGlmIChpc1ZhbGlkRGF0ZShtYXJrZXIpKSB7XG4gICAgICAgICAgICB2YXIgdGltZVpvbmVPZmZzZXQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKG1bMTNdKSB7XG4gICAgICAgICAgICAgICAgdGltZVpvbmVPZmZzZXQgPSAobVsxNV0gPT09ICctJyA/IC0xIDogMSkgKiAoTnVtYmVyKG1bMTZdIHx8IDApICogNjAgK1xuICAgICAgICAgICAgICAgICAgICBOdW1iZXIobVsxOF0gfHwgMCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBtYXJrZXI6IG1hcmtlcixcbiAgICAgICAgICAgICAgICBpc1RpbWVVbnNwZWNpZmllZDogIW1bNl0sXG4gICAgICAgICAgICAgICAgdGltZVpvbmVPZmZzZXQ6IHRpbWVab25lT2Zmc2V0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG52YXIgRGF0ZUVudiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEYXRlRW52KHNldHRpbmdzKSB7XG4gICAgICAgIHZhciB0aW1lWm9uZSA9IHRoaXMudGltZVpvbmUgPSBzZXR0aW5ncy50aW1lWm9uZTtcbiAgICAgICAgdmFyIGlzTmFtZWRUaW1lWm9uZSA9IHRpbWVab25lICE9PSAnbG9jYWwnICYmIHRpbWVab25lICE9PSAnVVRDJztcbiAgICAgICAgaWYgKHNldHRpbmdzLm5hbWVkVGltZVpvbmVJbXBsICYmIGlzTmFtZWRUaW1lWm9uZSkge1xuICAgICAgICAgICAgdGhpcy5uYW1lZFRpbWVab25lSW1wbCA9IG5ldyBzZXR0aW5ncy5uYW1lZFRpbWVab25lSW1wbCh0aW1lWm9uZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jYW5Db21wdXRlT2Zmc2V0ID0gQm9vbGVhbighaXNOYW1lZFRpbWVab25lIHx8IHRoaXMubmFtZWRUaW1lWm9uZUltcGwpO1xuICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtID0gY3JlYXRlQ2FsZW5kYXJTeXN0ZW0oc2V0dGluZ3MuY2FsZW5kYXJTeXN0ZW0pO1xuICAgICAgICB0aGlzLmxvY2FsZSA9IHNldHRpbmdzLmxvY2FsZTtcbiAgICAgICAgdGhpcy53ZWVrRG93ID0gc2V0dGluZ3MubG9jYWxlLndlZWsuZG93O1xuICAgICAgICB0aGlzLndlZWtEb3kgPSBzZXR0aW5ncy5sb2NhbGUud2Vlay5kb3k7XG4gICAgICAgIGlmIChzZXR0aW5ncy53ZWVrTnVtYmVyQ2FsY3VsYXRpb24gPT09ICdJU08nKSB7XG4gICAgICAgICAgICB0aGlzLndlZWtEb3cgPSAxO1xuICAgICAgICAgICAgdGhpcy53ZWVrRG95ID0gNDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzLmZpcnN0RGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgdGhpcy53ZWVrRG93ID0gc2V0dGluZ3MuZmlyc3REYXk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy53ZWVrTnVtYmVyQ2FsY3VsYXRpb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRoaXMud2Vla051bWJlckZ1bmMgPSBzZXR0aW5ncy53ZWVrTnVtYmVyQ2FsY3VsYXRpb247XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53ZWVrTGFiZWwgPSBzZXR0aW5ncy53ZWVrTGFiZWwgIT0gbnVsbCA/IHNldHRpbmdzLndlZWtMYWJlbCA6IHNldHRpbmdzLmxvY2FsZS5vcHRpb25zLndlZWtMYWJlbDtcbiAgICAgICAgdGhpcy5jbWRGb3JtYXR0ZXIgPSBzZXR0aW5ncy5jbWRGb3JtYXR0ZXI7XG4gICAgfVxuICAgIC8vIENyZWF0aW5nIC8gUGFyc2luZ1xuICAgIERhdGVFbnYucHJvdG90eXBlLmNyZWF0ZU1hcmtlciA9IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICB2YXIgbWV0YSA9IHRoaXMuY3JlYXRlTWFya2VyTWV0YShpbnB1dCk7XG4gICAgICAgIGlmIChtZXRhID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWV0YS5tYXJrZXI7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5jcmVhdGVOb3dNYXJrZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmNhbkNvbXB1dGVPZmZzZXQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRpbWVzdGFtcFRvTWFya2VyKG5ldyBEYXRlKCkudmFsdWVPZigpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIHdlIGNhbid0IGNvbXB1dGUgdGhlIGN1cnJlbnQgZGF0ZSB2YWwgZm9yIGEgdGltZXpvbmUsXG4gICAgICAgICAgICAvLyBiZXR0ZXIgdG8gZ2l2ZSB0aGUgY3VycmVudCBsb2NhbCBkYXRlIHZhbHMgdGhhbiBVVENcbiAgICAgICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShkYXRlVG9Mb2NhbEFycmF5KG5ldyBEYXRlKCkpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY3JlYXRlTWFya2VyTWV0YSA9IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2UoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtYXJrZXIgPSBudWxsO1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgbWFya2VyID0gdGhpcy50aW1lc3RhbXBUb01hcmtlcihpbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaW5wdXQgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgICBpbnB1dCA9IGlucHV0LnZhbHVlT2YoKTtcbiAgICAgICAgICAgIGlmICghaXNOYU4oaW5wdXQpKSB7XG4gICAgICAgICAgICAgICAgbWFya2VyID0gdGhpcy50aW1lc3RhbXBUb01hcmtlcihpbnB1dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgICAgIG1hcmtlciA9IGFycmF5VG9VdGNEYXRlKGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWFya2VyID09PSBudWxsIHx8ICFpc1ZhbGlkRGF0ZShtYXJrZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBtYXJrZXI6IG1hcmtlciwgaXNUaW1lVW5zcGVjaWZpZWQ6IGZhbHNlLCBmb3JjZWRUem86IG51bGwgfTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgdmFyIHBhcnRzID0gcGFyc2Uocyk7XG4gICAgICAgIGlmIChwYXJ0cyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hcmtlciA9IHBhcnRzLm1hcmtlcjtcbiAgICAgICAgdmFyIGZvcmNlZFR6byA9IG51bGw7XG4gICAgICAgIGlmIChwYXJ0cy50aW1lWm9uZU9mZnNldCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY2FuQ29tcHV0ZU9mZnNldCkge1xuICAgICAgICAgICAgICAgIG1hcmtlciA9IHRoaXMudGltZXN0YW1wVG9NYXJrZXIobWFya2VyLnZhbHVlT2YoKSAtIHBhcnRzLnRpbWVab25lT2Zmc2V0ICogNjAgKiAxMDAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvcmNlZFR6byA9IHBhcnRzLnRpbWVab25lT2Zmc2V0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IG1hcmtlcjogbWFya2VyLCBpc1RpbWVVbnNwZWNpZmllZDogcGFydHMuaXNUaW1lVW5zcGVjaWZpZWQsIGZvcmNlZFR6bzogZm9yY2VkVHpvIH07XG4gICAgfTtcbiAgICAvLyBBY2Nlc3NvcnNcbiAgICBEYXRlRW52LnByb3RvdHlwZS5nZXRZZWFyID0gZnVuY3Rpb24gKG1hcmtlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG1hcmtlcik7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5nZXRNb250aCA9IGZ1bmN0aW9uIChtYXJrZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyTW9udGgobWFya2VyKTtcbiAgICB9O1xuICAgIC8vIEFkZGluZyAvIFN1YnRyYWN0aW5nXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKG1hcmtlciwgZHVyKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMF0gKz0gZHVyLnllYXJzO1xuICAgICAgICBhWzFdICs9IGR1ci5tb250aHM7XG4gICAgICAgIGFbMl0gKz0gZHVyLmRheXM7XG4gICAgICAgIGFbNl0gKz0gZHVyLm1pbGxpc2Vjb25kcztcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLnN1YnRyYWN0ID0gZnVuY3Rpb24gKG1hcmtlciwgZHVyKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMF0gLT0gZHVyLnllYXJzO1xuICAgICAgICBhWzFdIC09IGR1ci5tb250aHM7XG4gICAgICAgIGFbMl0gLT0gZHVyLmRheXM7XG4gICAgICAgIGFbNl0gLT0gZHVyLm1pbGxpc2Vjb25kcztcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmFkZFllYXJzID0gZnVuY3Rpb24gKG1hcmtlciwgbikge1xuICAgICAgICB2YXIgYSA9IHRoaXMuY2FsZW5kYXJTeXN0ZW0ubWFya2VyVG9BcnJheShtYXJrZXIpO1xuICAgICAgICBhWzBdICs9IG47XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmFycmF5VG9NYXJrZXIoYSk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5hZGRNb250aHMgPSBmdW5jdGlvbiAobWFya2VyLCBuKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMV0gKz0gbjtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9O1xuICAgIC8vIERpZmZpbmcgV2hvbGUgVW5pdHNcbiAgICBEYXRlRW52LnByb3RvdHlwZS5kaWZmV2hvbGVZZWFycyA9IGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyU3lzdGVtID0gdGhpcy5jYWxlbmRhclN5c3RlbTtcbiAgICAgICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpICYmXG4gICAgICAgICAgICBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTApID09PSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTEpICYmXG4gICAgICAgICAgICBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtMCkgPT09IGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0xKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobTEpIC0gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtMCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5kaWZmV2hvbGVNb250aHMgPSBmdW5jdGlvbiAobTAsIG0xKSB7XG4gICAgICAgIHZhciBjYWxlbmRhclN5c3RlbSA9IHRoaXMuY2FsZW5kYXJTeXN0ZW07XG4gICAgICAgIGlmICh0aW1lQXNNcyhtMCkgPT09IHRpbWVBc01zKG0xKSAmJlxuICAgICAgICAgICAgY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyRGF5KG0wKSA9PT0gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyRGF5KG0xKSkge1xuICAgICAgICAgICAgcmV0dXJuIChjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtMSkgLSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtMCkpICtcbiAgICAgICAgICAgICAgICAoY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtMSkgLSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0wKSkgKiAxMjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIC8vIFJhbmdlIC8gRHVyYXRpb25cbiAgICBEYXRlRW52LnByb3RvdHlwZS5ncmVhdGVzdFdob2xlVW5pdCA9IGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgdmFyIG4gPSB0aGlzLmRpZmZXaG9sZVllYXJzKG0wLCBtMSk7XG4gICAgICAgIGlmIChuICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAneWVhcicsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IHRoaXMuZGlmZldob2xlTW9udGhzKG0wLCBtMSk7XG4gICAgICAgIGlmIChuICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnbW9udGgnLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmV2hvbGVXZWVrcyhtMCwgbTEpO1xuICAgICAgICBpZiAobiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3dlZWsnLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmV2hvbGVEYXlzKG0wLCBtMSk7XG4gICAgICAgIGlmIChuICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnZGF5JywgdmFsdWU6IG4gfTtcbiAgICAgICAgfVxuICAgICAgICBuID0gZGlmZkhvdXJzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ2hvdXInLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmTWludXRlcyhtMCwgbTEpO1xuICAgICAgICBpZiAoaXNJbnQobikpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdtaW51dGUnLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmU2Vjb25kcyhtMCwgbTEpO1xuICAgICAgICBpZiAoaXNJbnQobikpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdzZWNvbmQnLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHVuaXQ6ICdtaWxsaXNlY29uZCcsIHZhbHVlOiBtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkgfTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmNvdW50RHVyYXRpb25zQmV0d2VlbiA9IGZ1bmN0aW9uIChtMCwgbTEsIGQpIHtcbiAgICAgICAgLy8gVE9ETzogY2FuIHVzZSBncmVhdGVzdFdob2xlVW5pdFxuICAgICAgICB2YXIgZGlmZjtcbiAgICAgICAgaWYgKGQueWVhcnMpIHtcbiAgICAgICAgICAgIGRpZmYgPSB0aGlzLmRpZmZXaG9sZVllYXJzKG0wLCBtMSk7XG4gICAgICAgICAgICBpZiAoZGlmZiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmIC8gYXNSb3VnaFllYXJzKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChkLm1vbnRocykge1xuICAgICAgICAgICAgZGlmZiA9IHRoaXMuZGlmZldob2xlTW9udGhzKG0wLCBtMSk7XG4gICAgICAgICAgICBpZiAoZGlmZiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmIC8gYXNSb3VnaE1vbnRocyhkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZC5kYXlzKSB7XG4gICAgICAgICAgICBkaWZmID0gZGlmZldob2xlRGF5cyhtMCwgbTEpO1xuICAgICAgICAgICAgaWYgKGRpZmYgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZiAvIGFzUm91Z2hEYXlzKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvIGFzUm91Z2hNcyhkKTtcbiAgICB9O1xuICAgIC8vIFN0YXJ0LU9mXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuc3RhcnRPZiA9IGZ1bmN0aW9uIChtLCB1bml0KSB7XG4gICAgICAgIGlmICh1bml0ID09PSAneWVhcicpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2ZZZWFyKG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICdtb250aCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2ZNb250aChtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1bml0ID09PSAnd2VlaycpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2ZXZWVrKG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICdkYXknKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RhcnRPZkRheShtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1bml0ID09PSAnaG91cicpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGFydE9mSG91cihtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1bml0ID09PSAnbWludXRlJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZNaW51dGUobSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodW5pdCA9PT0gJ3NlY29uZCcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGFydE9mU2Vjb25kKG0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mWWVhciA9IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmFycmF5VG9NYXJrZXIoW1xuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0pXG4gICAgICAgIF0pO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuc3RhcnRPZk1vbnRoID0gZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihbXG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobSksXG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0pXG4gICAgICAgIF0pO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuc3RhcnRPZldlZWsgPSBmdW5jdGlvbiAobSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKFtcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtKSxcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyTW9udGgobSksXG4gICAgICAgICAgICBtLmdldFVUQ0RhdGUoKSAtICgobS5nZXRVVENEYXkoKSAtIHRoaXMud2Vla0RvdyArIDcpICUgNylcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICAvLyBXZWVrIE51bWJlclxuICAgIERhdGVFbnYucHJvdG90eXBlLmNvbXB1dGVXZWVrTnVtYmVyID0gZnVuY3Rpb24gKG1hcmtlcikge1xuICAgICAgICBpZiAodGhpcy53ZWVrTnVtYmVyRnVuYykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2Vla051bWJlckZ1bmModGhpcy50b0RhdGUobWFya2VyKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gd2Vla09mWWVhcihtYXJrZXIsIHRoaXMud2Vla0RvdywgdGhpcy53ZWVrRG95KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gVE9ETzogY2hva2Ugb24gdGltZVpvbmVOYW1lOiBsb25nXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24gKG1hcmtlciwgZm9ybWF0dGVyLCBkYXRlT3B0aW9ucykge1xuICAgICAgICBpZiAoZGF0ZU9wdGlvbnMgPT09IHZvaWQgMCkgeyBkYXRlT3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0KHtcbiAgICAgICAgICAgIG1hcmtlcjogbWFya2VyLFxuICAgICAgICAgICAgdGltZVpvbmVPZmZzZXQ6IGRhdGVPcHRpb25zLmZvcmNlZFR6byAhPSBudWxsID9cbiAgICAgICAgICAgICAgICBkYXRlT3B0aW9ucy5mb3JjZWRUem8gOlxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0Rm9yTWFya2VyKG1hcmtlcilcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5mb3JtYXRSYW5nZSA9IGZ1bmN0aW9uIChzdGFydCwgZW5kLCBmb3JtYXR0ZXIsIGRhdGVPcHRpb25zKSB7XG4gICAgICAgIGlmIChkYXRlT3B0aW9ucyA9PT0gdm9pZCAwKSB7IGRhdGVPcHRpb25zID0ge307IH1cbiAgICAgICAgaWYgKGRhdGVPcHRpb25zLmlzRW5kRXhjbHVzaXZlKSB7XG4gICAgICAgICAgICBlbmQgPSBhZGRNcyhlbmQsIC0xKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm9ybWF0dGVyLmZvcm1hdFJhbmdlKHtcbiAgICAgICAgICAgIG1hcmtlcjogc3RhcnQsXG4gICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZU9wdGlvbnMuZm9yY2VkU3RhcnRUem8gIT0gbnVsbCA/XG4gICAgICAgICAgICAgICAgZGF0ZU9wdGlvbnMuZm9yY2VkU3RhcnRUem8gOlxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0Rm9yTWFya2VyKHN0YXJ0KVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBtYXJrZXI6IGVuZCxcbiAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0OiBkYXRlT3B0aW9ucy5mb3JjZWRFbmRUem8gIT0gbnVsbCA/XG4gICAgICAgICAgICAgICAgZGF0ZU9wdGlvbnMuZm9yY2VkRW5kVHpvIDpcbiAgICAgICAgICAgICAgICB0aGlzLm9mZnNldEZvck1hcmtlcihlbmQpXG4gICAgICAgIH0sIHRoaXMpO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuZm9ybWF0SXNvID0gZnVuY3Rpb24gKG1hcmtlciwgZXh0cmFPcHRpb25zKSB7XG4gICAgICAgIGlmIChleHRyYU9wdGlvbnMgPT09IHZvaWQgMCkgeyBleHRyYU9wdGlvbnMgPSB7fTsgfVxuICAgICAgICB2YXIgdGltZVpvbmVPZmZzZXQgPSBudWxsO1xuICAgICAgICBpZiAoIWV4dHJhT3B0aW9ucy5vbWl0VGltZVpvbmVPZmZzZXQpIHtcbiAgICAgICAgICAgIGlmIChleHRyYU9wdGlvbnMuZm9yY2VkVHpvICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCA9IGV4dHJhT3B0aW9ucy5mb3JjZWRUem87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCA9IHRoaXMub2Zmc2V0Rm9yTWFya2VyKG1hcmtlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJ1aWxkSXNvU3RyaW5nKG1hcmtlciwgdGltZVpvbmVPZmZzZXQsIGV4dHJhT3B0aW9ucy5vbWl0VGltZSk7XG4gICAgfTtcbiAgICAvLyBUaW1lWm9uZVxuICAgIERhdGVFbnYucHJvdG90eXBlLnRpbWVzdGFtcFRvTWFya2VyID0gZnVuY3Rpb24gKG1zKSB7XG4gICAgICAgIGlmICh0aGlzLnRpbWVab25lID09PSAnbG9jYWwnKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoZGF0ZVRvTG9jYWxBcnJheShuZXcgRGF0ZShtcykpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnRpbWVab25lID09PSAnVVRDJyB8fCAhdGhpcy5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG1zKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZSh0aGlzLm5hbWVkVGltZVpvbmVJbXBsLnRpbWVzdGFtcFRvQXJyYXkobXMpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUub2Zmc2V0Rm9yTWFya2VyID0gZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgaWYgKHRoaXMudGltZVpvbmUgPT09ICdsb2NhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiAtYXJyYXlUb0xvY2FsRGF0ZShkYXRlVG9VdGNBcnJheShtKSkuZ2V0VGltZXpvbmVPZmZzZXQoKTsgLy8gY29udmVydCBcImludmVyc2VcIiBvZmZzZXQgdG8gXCJub3JtYWxcIiBvZmZzZXRcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnRpbWVab25lID09PSAnVVRDJykge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFtZWRUaW1lWm9uZUltcGwub2Zmc2V0Rm9yQXJyYXkoZGF0ZVRvVXRjQXJyYXkobSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLy8gQ29udmVyc2lvblxuICAgIERhdGVFbnYucHJvdG90eXBlLnRvRGF0ZSA9IGZ1bmN0aW9uIChtLCBmb3JjZWRUem8pIHtcbiAgICAgICAgaWYgKHRoaXMudGltZVpvbmUgPT09ICdsb2NhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiBhcnJheVRvTG9jYWxEYXRlKGRhdGVUb1V0Y0FycmF5KG0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnRpbWVab25lID09PSAnVVRDJykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG0udmFsdWVPZigpKTsgLy8gbWFrZSBzdXJlIGl0J3MgYSBjb3B5XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXRoaXMubmFtZWRUaW1lWm9uZUltcGwpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShtLnZhbHVlT2YoKSAtIChmb3JjZWRUem8gfHwgMCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG0udmFsdWVPZigpIC1cbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVkVGltZVpvbmVJbXBsLm9mZnNldEZvckFycmF5KGRhdGVUb1V0Y0FycmF5KG0pKSAqIDEwMDAgKiA2MCAvLyBjb252ZXJ0IG1pbnV0ZXMgLT4gbXNcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBEYXRlRW52O1xufSgpKTtcblxudmFyIFNJTVBMRV9TT1VSQ0VfUFJPUFMgPSB7XG4gICAgaWQ6IFN0cmluZyxcbiAgICBhbGxEYXlEZWZhdWx0OiBCb29sZWFuLFxuICAgIGV2ZW50RGF0YVRyYW5zZm9ybTogRnVuY3Rpb24sXG4gICAgc3VjY2VzczogRnVuY3Rpb24sXG4gICAgZmFpbHVyZTogRnVuY3Rpb25cbn07XG52YXIgdWlkJDIgPSAwO1xuZnVuY3Rpb24gZG9lc1NvdXJjZU5lZWRSYW5nZShldmVudFNvdXJjZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgZGVmcyA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudFNvdXJjZURlZnM7XG4gICAgcmV0dXJuICFkZWZzW2V2ZW50U291cmNlLnNvdXJjZURlZklkXS5pZ25vcmVSYW5nZTtcbn1cbmZ1bmN0aW9uIHBhcnNlRXZlbnRTb3VyY2UocmF3LCBjYWxlbmRhcikge1xuICAgIHZhciBkZWZzID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50U291cmNlRGVmcztcbiAgICBmb3IgKHZhciBpID0gZGVmcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgeyAvLyBsYXRlci1hZGRlZCBwbHVnaW5zIHRha2UgcHJlY2VkZW5jZVxuICAgICAgICB2YXIgZGVmID0gZGVmc1tpXTtcbiAgICAgICAgdmFyIG1ldGEgPSBkZWYucGFyc2VNZXRhKHJhdyk7XG4gICAgICAgIGlmIChtZXRhKSB7XG4gICAgICAgICAgICB2YXIgcmVzID0gcGFyc2VFdmVudFNvdXJjZVByb3BzKHR5cGVvZiByYXcgPT09ICdvYmplY3QnID8gcmF3IDoge30sIG1ldGEsIGksIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIHJlcy5fcmF3ID0gcmF3O1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIHBhcnNlRXZlbnRTb3VyY2VQcm9wcyhyYXcsIG1ldGEsIHNvdXJjZURlZklkLCBjYWxlbmRhcikge1xuICAgIHZhciBsZWZ0b3ZlcnMwID0ge307XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3LCBTSU1QTEVfU09VUkNFX1BST1BTLCB7fSwgbGVmdG92ZXJzMCk7XG4gICAgdmFyIGxlZnRvdmVyczEgPSB7fTtcbiAgICB2YXIgdWkgPSBwcm9jZXNzVW5zY29wZWRVaVByb3BzKGxlZnRvdmVyczAsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMxKTtcbiAgICBwcm9wcy5pc0ZldGNoaW5nID0gZmFsc2U7XG4gICAgcHJvcHMubGF0ZXN0RmV0Y2hJZCA9ICcnO1xuICAgIHByb3BzLmZldGNoUmFuZ2UgPSBudWxsO1xuICAgIHByb3BzLnB1YmxpY0lkID0gU3RyaW5nKHJhdy5pZCB8fCAnJyk7XG4gICAgcHJvcHMuc291cmNlSWQgPSBTdHJpbmcodWlkJDIrKyk7XG4gICAgcHJvcHMuc291cmNlRGVmSWQgPSBzb3VyY2VEZWZJZDtcbiAgICBwcm9wcy5tZXRhID0gbWV0YTtcbiAgICBwcm9wcy51aSA9IHVpO1xuICAgIHByb3BzLmV4dGVuZGVkUHJvcHMgPSBsZWZ0b3ZlcnMxO1xuICAgIHJldHVybiBwcm9wcztcbn1cblxuZnVuY3Rpb24gcmVkdWNlRXZlbnRTb3VyY2VzIChldmVudFNvdXJjZXMsIGFjdGlvbiwgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdBRERfRVZFTlRfU09VUkNFUyc6IC8vIGFscmVhZHkgcGFyc2VkXG4gICAgICAgICAgICByZXR1cm4gYWRkU291cmNlcyhldmVudFNvdXJjZXMsIGFjdGlvbi5zb3VyY2VzLCBkYXRlUHJvZmlsZSA/IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIDogbnVsbCwgY2FsZW5kYXIpO1xuICAgICAgICBjYXNlICdSRU1PVkVfRVZFTlRfU09VUkNFJzpcbiAgICAgICAgICAgIHJldHVybiByZW1vdmVTb3VyY2UoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlSWQpO1xuICAgICAgICBjYXNlICdQUkVWJzogLy8gVE9ETzogaG93IGRvIHdlIHRyYWNrIGFsbCBhY3Rpb25zIHRoYXQgYWZmZWN0IGRhdGVQcm9maWxlIDooXG4gICAgICAgIGNhc2UgJ05FWFQnOlxuICAgICAgICBjYXNlICdTRVRfREFURSc6XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgaWYgKGRhdGVQcm9maWxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoRGlydHlTb3VyY2VzKGV2ZW50U291cmNlcywgZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBldmVudFNvdXJjZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0ZFVENIX0VWRU5UX1NPVVJDRVMnOlxuICAgICAgICBjYXNlICdDSEFOR0VfVElNRVpPTkUnOlxuICAgICAgICAgICAgcmV0dXJuIGZldGNoU291cmNlc0J5SWRzKGV2ZW50U291cmNlcywgYWN0aW9uLnNvdXJjZUlkcyA/XG4gICAgICAgICAgICAgICAgYXJyYXlUb0hhc2goYWN0aW9uLnNvdXJjZUlkcykgOlxuICAgICAgICAgICAgICAgIGV4Y2x1ZGVTdGF0aWNTb3VyY2VzKGV2ZW50U291cmNlcywgY2FsZW5kYXIpLCBkYXRlUHJvZmlsZSA/IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIDogbnVsbCwgY2FsZW5kYXIpO1xuICAgICAgICBjYXNlICdSRUNFSVZFX0VWRU5UUyc6XG4gICAgICAgIGNhc2UgJ1JFQ0VJVkVfRVZFTlRfRVJST1InOlxuICAgICAgICAgICAgcmV0dXJuIHJlY2VpdmVSZXNwb25zZShldmVudFNvdXJjZXMsIGFjdGlvbi5zb3VyY2VJZCwgYWN0aW9uLmZldGNoSWQsIGFjdGlvbi5mZXRjaFJhbmdlKTtcbiAgICAgICAgY2FzZSAnUkVNT1ZFX0FMTF9FVkVOVF9TT1VSQ0VTJzpcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBldmVudFNvdXJjZXM7XG4gICAgfVxufVxudmFyIHVpZCQzID0gMDtcbmZ1bmN0aW9uIGFkZFNvdXJjZXMoZXZlbnRTb3VyY2VIYXNoLCBzb3VyY2VzLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIHZhciBoYXNoID0ge307XG4gICAgZm9yICh2YXIgX2kgPSAwLCBzb3VyY2VzXzEgPSBzb3VyY2VzOyBfaSA8IHNvdXJjZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNfMVtfaV07XG4gICAgICAgIGhhc2hbc291cmNlLnNvdXJjZUlkXSA9IHNvdXJjZTtcbiAgICB9XG4gICAgaWYgKGZldGNoUmFuZ2UpIHtcbiAgICAgICAgaGFzaCA9IGZldGNoRGlydHlTb3VyY2VzKGhhc2gsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICB9XG4gICAgcmV0dXJuIF9fYXNzaWduKHt9LCBldmVudFNvdXJjZUhhc2gsIGhhc2gpO1xufVxuZnVuY3Rpb24gcmVtb3ZlU291cmNlKGV2ZW50U291cmNlSGFzaCwgc291cmNlSWQpIHtcbiAgICByZXR1cm4gZmlsdGVySGFzaChldmVudFNvdXJjZUhhc2gsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gZXZlbnRTb3VyY2Uuc291cmNlSWQgIT09IHNvdXJjZUlkO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gZmV0Y2hEaXJ0eVNvdXJjZXMoc291cmNlSGFzaCwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gZmV0Y2hTb3VyY2VzQnlJZHMoc291cmNlSGFzaCwgZmlsdGVySGFzaChzb3VyY2VIYXNoLCBmdW5jdGlvbiAoZXZlbnRTb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIGlzU291cmNlRGlydHkoZXZlbnRTb3VyY2UsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICB9KSwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xufVxuZnVuY3Rpb24gaXNTb3VyY2VEaXJ0eShldmVudFNvdXJjZSwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpIHtcbiAgICBpZiAoIWRvZXNTb3VyY2VOZWVkUmFuZ2UoZXZlbnRTb3VyY2UsIGNhbGVuZGFyKSkge1xuICAgICAgICByZXR1cm4gIWV2ZW50U291cmNlLmxhdGVzdEZldGNoSWQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gIWNhbGVuZGFyLm9wdCgnbGF6eUZldGNoaW5nJykgfHxcbiAgICAgICAgICAgICFldmVudFNvdXJjZS5mZXRjaFJhbmdlIHx8XG4gICAgICAgICAgICBldmVudFNvdXJjZS5pc0ZldGNoaW5nIHx8IC8vIGFsd2F5cyBjYW5jZWwgb3V0ZGF0ZWQgaW4tcHJvZ3Jlc3MgZmV0Y2hlc1xuICAgICAgICAgICAgZmV0Y2hSYW5nZS5zdGFydCA8IGV2ZW50U291cmNlLmZldGNoUmFuZ2Uuc3RhcnQgfHxcbiAgICAgICAgICAgIGZldGNoUmFuZ2UuZW5kID4gZXZlbnRTb3VyY2UuZmV0Y2hSYW5nZS5lbmQ7XG4gICAgfVxufVxuZnVuY3Rpb24gZmV0Y2hTb3VyY2VzQnlJZHMocHJldlNvdXJjZXMsIHNvdXJjZUlkSGFzaCwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgbmV4dFNvdXJjZXMgPSB7fTtcbiAgICBmb3IgKHZhciBzb3VyY2VJZCBpbiBwcmV2U291cmNlcykge1xuICAgICAgICB2YXIgc291cmNlID0gcHJldlNvdXJjZXNbc291cmNlSWRdO1xuICAgICAgICBpZiAoc291cmNlSWRIYXNoW3NvdXJjZUlkXSkge1xuICAgICAgICAgICAgbmV4dFNvdXJjZXNbc291cmNlSWRdID0gZmV0Y2hTb3VyY2Uoc291cmNlLCBmZXRjaFJhbmdlLCBjYWxlbmRhcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBuZXh0U291cmNlc1tzb3VyY2VJZF0gPSBzb3VyY2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5leHRTb3VyY2VzO1xufVxuZnVuY3Rpb24gZmV0Y2hTb3VyY2UoZXZlbnRTb3VyY2UsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIHNvdXJjZURlZiA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudFNvdXJjZURlZnNbZXZlbnRTb3VyY2Uuc291cmNlRGVmSWRdO1xuICAgIHZhciBmZXRjaElkID0gU3RyaW5nKHVpZCQzKyspO1xuICAgIHNvdXJjZURlZi5mZXRjaCh7XG4gICAgICAgIGV2ZW50U291cmNlOiBldmVudFNvdXJjZSxcbiAgICAgICAgY2FsZW5kYXI6IGNhbGVuZGFyLFxuICAgICAgICByYW5nZTogZmV0Y2hSYW5nZVxuICAgIH0sIGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgdmFyIHJhd0V2ZW50cyA9IHJlcy5yYXdFdmVudHM7XG4gICAgICAgIHZhciBjYWxTdWNjZXNzID0gY2FsZW5kYXIub3B0KCdldmVudFNvdXJjZVN1Y2Nlc3MnKTtcbiAgICAgICAgdmFyIGNhbFN1Y2Nlc3NSZXM7XG4gICAgICAgIHZhciBzb3VyY2VTdWNjZXNzUmVzO1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgc291cmNlU3VjY2Vzc1JlcyA9IGV2ZW50U291cmNlLnN1Y2Nlc3MocmF3RXZlbnRzLCByZXMueGhyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2FsU3VjY2Vzcykge1xuICAgICAgICAgICAgY2FsU3VjY2Vzc1JlcyA9IGNhbFN1Y2Nlc3MocmF3RXZlbnRzLCByZXMueGhyKTtcbiAgICAgICAgfVxuICAgICAgICByYXdFdmVudHMgPSBzb3VyY2VTdWNjZXNzUmVzIHx8IGNhbFN1Y2Nlc3NSZXMgfHwgcmF3RXZlbnRzO1xuICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVDRUlWRV9FVkVOVFMnLFxuICAgICAgICAgICAgc291cmNlSWQ6IGV2ZW50U291cmNlLnNvdXJjZUlkLFxuICAgICAgICAgICAgZmV0Y2hJZDogZmV0Y2hJZCxcbiAgICAgICAgICAgIGZldGNoUmFuZ2U6IGZldGNoUmFuZ2UsXG4gICAgICAgICAgICByYXdFdmVudHM6IHJhd0V2ZW50c1xuICAgICAgICB9KTtcbiAgICB9LCBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgdmFyIGNhbGxGYWlsdXJlID0gY2FsZW5kYXIub3B0KCdldmVudFNvdXJjZUZhaWx1cmUnKTtcbiAgICAgICAgY29uc29sZS53YXJuKGVycm9yLm1lc3NhZ2UsIGVycm9yKTtcbiAgICAgICAgaWYgKGV2ZW50U291cmNlLmZhaWx1cmUpIHtcbiAgICAgICAgICAgIGV2ZW50U291cmNlLmZhaWx1cmUoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjYWxsRmFpbHVyZSkge1xuICAgICAgICAgICAgY2FsbEZhaWx1cmUoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRUNFSVZFX0VWRU5UX0VSUk9SJyxcbiAgICAgICAgICAgIHNvdXJjZUlkOiBldmVudFNvdXJjZS5zb3VyY2VJZCxcbiAgICAgICAgICAgIGZldGNoSWQ6IGZldGNoSWQsXG4gICAgICAgICAgICBmZXRjaFJhbmdlOiBmZXRjaFJhbmdlLFxuICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBfX2Fzc2lnbih7fSwgZXZlbnRTb3VyY2UsIHsgaXNGZXRjaGluZzogdHJ1ZSwgbGF0ZXN0RmV0Y2hJZDogZmV0Y2hJZCB9KTtcbn1cbmZ1bmN0aW9uIHJlY2VpdmVSZXNwb25zZShzb3VyY2VIYXNoLCBzb3VyY2VJZCwgZmV0Y2hJZCwgZmV0Y2hSYW5nZSkge1xuICAgIHZhciBfYTtcbiAgICB2YXIgZXZlbnRTb3VyY2UgPSBzb3VyY2VIYXNoW3NvdXJjZUlkXTtcbiAgICBpZiAoZXZlbnRTb3VyY2UgJiYgLy8gbm90IGFscmVhZHkgcmVtb3ZlZFxuICAgICAgICBmZXRjaElkID09PSBldmVudFNvdXJjZS5sYXRlc3RGZXRjaElkKSB7XG4gICAgICAgIHJldHVybiBfX2Fzc2lnbih7fSwgc291cmNlSGFzaCwgKF9hID0ge30sIF9hW3NvdXJjZUlkXSA9IF9fYXNzaWduKHt9LCBldmVudFNvdXJjZSwgeyBpc0ZldGNoaW5nOiBmYWxzZSwgZmV0Y2hSYW5nZTogZmV0Y2hSYW5nZSAvLyBhbHNvIHNlcnZlcyBhcyBhIG1hcmtlciB0aGF0IGF0IGxlYXN0IG9uZSBmZXRjaCBoYXMgY29tcGxldGVkXG4gICAgICAgICB9KSwgX2EpKTtcbiAgICB9XG4gICAgcmV0dXJuIHNvdXJjZUhhc2g7XG59XG5mdW5jdGlvbiBleGNsdWRlU3RhdGljU291cmNlcyhldmVudFNvdXJjZXMsIGNhbGVuZGFyKSB7XG4gICAgcmV0dXJuIGZpbHRlckhhc2goZXZlbnRTb3VyY2VzLCBmdW5jdGlvbiAoZXZlbnRTb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIGRvZXNTb3VyY2VOZWVkUmFuZ2UoZXZlbnRTb3VyY2UsIGNhbGVuZGFyKTtcbiAgICB9KTtcbn1cblxudmFyIERhdGVQcm9maWxlR2VuZXJhdG9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIERhdGVQcm9maWxlR2VuZXJhdG9yKHZpZXdTcGVjLCBjYWxlbmRhcikge1xuICAgICAgICB0aGlzLnZpZXdTcGVjID0gdmlld1NwZWM7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHZpZXdTcGVjLm9wdGlvbnM7XG4gICAgICAgIHRoaXMuZGF0ZUVudiA9IGNhbGVuZGFyLmRhdGVFbnY7XG4gICAgICAgIHRoaXMuY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICAgICAgdGhpcy5pbml0SGlkZGVuRGF5cygpO1xuICAgIH1cbiAgICAvKiBEYXRlIFJhbmdlIENvbXB1dGF0aW9uXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAvLyBCdWlsZHMgYSBzdHJ1Y3R1cmUgd2l0aCBpbmZvIGFib3V0IHdoYXQgdGhlIGRhdGVzL3JhbmdlcyB3aWxsIGJlIGZvciB0aGUgXCJwcmV2XCIgdmlldy5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRQcmV2ID0gZnVuY3Rpb24gKGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHZhciBwcmV2RGF0ZSA9IGRhdGVFbnYuc3VidHJhY3QoZGF0ZUVudi5zdGFydE9mKGN1cnJlbnREYXRlLCBjdXJyZW50RGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdCksIC8vIGltcG9ydGFudCBmb3Igc3RhcnQtb2YtbW9udGhcbiAgICAgICAgY3VycmVudERhdGVQcm9maWxlLmRhdGVJbmNyZW1lbnQpO1xuICAgICAgICByZXR1cm4gdGhpcy5idWlsZChwcmV2RGF0ZSwgLTEpO1xuICAgIH07XG4gICAgLy8gQnVpbGRzIGEgc3RydWN0dXJlIHdpdGggaW5mbyBhYm91dCB3aGF0IHRoZSBkYXRlcy9yYW5nZXMgd2lsbCBiZSBmb3IgdGhlIFwibmV4dFwiIHZpZXcuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkTmV4dCA9IGZ1bmN0aW9uIChjdXJyZW50RGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgbmV4dERhdGUgPSBkYXRlRW52LmFkZChkYXRlRW52LnN0YXJ0T2YoY3VycmVudERhdGUsIGN1cnJlbnREYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2VVbml0KSwgLy8gaW1wb3J0YW50IGZvciBzdGFydC1vZi1tb250aFxuICAgICAgICBjdXJyZW50RGF0ZVByb2ZpbGUuZGF0ZUluY3JlbWVudCk7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkKG5leHREYXRlLCAxKTtcbiAgICB9O1xuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSBob2xkaW5nIGRhdGVzL3JhbmdlcyBmb3IgcmVuZGVyaW5nIGFyb3VuZCB0aGUgZ2l2ZW4gZGF0ZS5cbiAgICAvLyBPcHRpb25hbCBkaXJlY3Rpb24gcGFyYW0gaW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGUgaXMgYmVpbmcgaW5jcmVtZW50ZWQvZGVjcmVtZW50ZWRcbiAgICAvLyBmcm9tIGl0cyBwcmV2aW91cyB2YWx1ZS4gZGVjcmVtZW50ZWQgPSAtMSwgaW5jcmVtZW50ZWQgPSAxIChkZWZhdWx0KS5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGQgPSBmdW5jdGlvbiAoY3VycmVudERhdGUsIGRpcmVjdGlvbiwgZm9yY2VUb1ZhbGlkKSB7XG4gICAgICAgIGlmIChmb3JjZVRvVmFsaWQgPT09IHZvaWQgMCkgeyBmb3JjZVRvVmFsaWQgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgdmFsaWRSYW5nZTtcbiAgICAgICAgdmFyIG1pblRpbWUgPSBudWxsO1xuICAgICAgICB2YXIgbWF4VGltZSA9IG51bGw7XG4gICAgICAgIHZhciBjdXJyZW50SW5mbztcbiAgICAgICAgdmFyIGlzUmFuZ2VBbGxEYXk7XG4gICAgICAgIHZhciByZW5kZXJSYW5nZTtcbiAgICAgICAgdmFyIGFjdGl2ZVJhbmdlO1xuICAgICAgICB2YXIgaXNWYWxpZDtcbiAgICAgICAgdmFsaWRSYW5nZSA9IHRoaXMuYnVpbGRWYWxpZFJhbmdlKCk7XG4gICAgICAgIHZhbGlkUmFuZ2UgPSB0aGlzLnRyaW1IaWRkZW5EYXlzKHZhbGlkUmFuZ2UpO1xuICAgICAgICBpZiAoZm9yY2VUb1ZhbGlkKSB7XG4gICAgICAgICAgICBjdXJyZW50RGF0ZSA9IGNvbnN0cmFpbk1hcmtlclRvUmFuZ2UoY3VycmVudERhdGUsIHZhbGlkUmFuZ2UpO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRJbmZvID0gdGhpcy5idWlsZEN1cnJlbnRSYW5nZUluZm8oY3VycmVudERhdGUsIGRpcmVjdGlvbik7XG4gICAgICAgIGlzUmFuZ2VBbGxEYXkgPSAvXih5ZWFyfG1vbnRofHdlZWt8ZGF5KSQvLnRlc3QoY3VycmVudEluZm8udW5pdCk7XG4gICAgICAgIHJlbmRlclJhbmdlID0gdGhpcy5idWlsZFJlbmRlclJhbmdlKHRoaXMudHJpbUhpZGRlbkRheXMoY3VycmVudEluZm8ucmFuZ2UpLCBjdXJyZW50SW5mby51bml0LCBpc1JhbmdlQWxsRGF5KTtcbiAgICAgICAgcmVuZGVyUmFuZ2UgPSB0aGlzLnRyaW1IaWRkZW5EYXlzKHJlbmRlclJhbmdlKTtcbiAgICAgICAgYWN0aXZlUmFuZ2UgPSByZW5kZXJSYW5nZTtcbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuc2hvd05vbkN1cnJlbnREYXRlcykge1xuICAgICAgICAgICAgYWN0aXZlUmFuZ2UgPSBpbnRlcnNlY3RSYW5nZXMoYWN0aXZlUmFuZ2UsIGN1cnJlbnRJbmZvLnJhbmdlKTtcbiAgICAgICAgfVxuICAgICAgICBtaW5UaW1lID0gY3JlYXRlRHVyYXRpb24odGhpcy5vcHRpb25zLm1pblRpbWUpO1xuICAgICAgICBtYXhUaW1lID0gY3JlYXRlRHVyYXRpb24odGhpcy5vcHRpb25zLm1heFRpbWUpO1xuICAgICAgICBhY3RpdmVSYW5nZSA9IHRoaXMuYWRqdXN0QWN0aXZlUmFuZ2UoYWN0aXZlUmFuZ2UsIG1pblRpbWUsIG1heFRpbWUpO1xuICAgICAgICBhY3RpdmVSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhhY3RpdmVSYW5nZSwgdmFsaWRSYW5nZSk7IC8vIG1pZ2h0IHJldHVybiBudWxsXG4gICAgICAgIC8vIGl0J3MgaW52YWxpZCBpZiB0aGUgb3JpZ2luYWxseSByZXF1ZXN0ZWQgZGF0ZSBpcyBub3QgY29udGFpbmVkLFxuICAgICAgICAvLyBvciBpZiB0aGUgcmFuZ2UgaXMgY29tcGxldGVseSBvdXRzaWRlIG9mIHRoZSB2YWxpZCByYW5nZS5cbiAgICAgICAgaXNWYWxpZCA9IHJhbmdlc0ludGVyc2VjdChjdXJyZW50SW5mby5yYW5nZSwgdmFsaWRSYW5nZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvLyBjb25zdHJhaW50IGZvciB3aGVyZSBwcmV2L25leHQgb3BlcmF0aW9ucyBjYW4gZ28gYW5kIHdoZXJlIGV2ZW50cyBjYW4gYmUgZHJhZ2dlZC9yZXNpemVkIHRvLlxuICAgICAgICAgICAgLy8gYW4gb2JqZWN0IHdpdGggb3B0aW9uYWwgc3RhcnQgYW5kIGVuZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgdmFsaWRSYW5nZTogdmFsaWRSYW5nZSxcbiAgICAgICAgICAgIC8vIHJhbmdlIHRoZSB2aWV3IGlzIGZvcm1hbGx5IHJlc3BvbnNpYmxlIGZvci5cbiAgICAgICAgICAgIC8vIGZvciBleGFtcGxlLCBhIG1vbnRoIHZpZXcgbWlnaHQgaGF2ZSAxc3QtMzFzdCwgZXhjbHVkaW5nIHBhZGRlZCBkYXRlc1xuICAgICAgICAgICAgY3VycmVudFJhbmdlOiBjdXJyZW50SW5mby5yYW5nZSxcbiAgICAgICAgICAgIC8vIG5hbWUgb2YgbGFyZ2VzdCB1bml0IGJlaW5nIGRpc3BsYXllZCwgbGlrZSBcIm1vbnRoXCIgb3IgXCJ3ZWVrXCJcbiAgICAgICAgICAgIGN1cnJlbnRSYW5nZVVuaXQ6IGN1cnJlbnRJbmZvLnVuaXQsXG4gICAgICAgICAgICBpc1JhbmdlQWxsRGF5OiBpc1JhbmdlQWxsRGF5LFxuICAgICAgICAgICAgLy8gZGF0ZXMgdGhhdCBkaXNwbGF5IGV2ZW50cyBhbmQgYWNjZXB0IGRyYWctbi1kcm9wXG4gICAgICAgICAgICAvLyB3aWxsIGJlIGBudWxsYCBpZiBubyBkYXRlcyBhY2NlcHQgZXZlbnRzXG4gICAgICAgICAgICBhY3RpdmVSYW5nZTogYWN0aXZlUmFuZ2UsXG4gICAgICAgICAgICAvLyBkYXRlIHJhbmdlIHdpdGggYSByZW5kZXJlZCBza2VsZXRvblxuICAgICAgICAgICAgLy8gaW5jbHVkZXMgbm90LWFjdGl2ZSBkYXlzIHRoYXQgbmVlZCBzb21lIHNvcnQgb2YgRE9NXG4gICAgICAgICAgICByZW5kZXJSYW5nZTogcmVuZGVyUmFuZ2UsXG4gICAgICAgICAgICAvLyBEdXJhdGlvbiBvYmplY3QgdGhhdCBkZW5vdGVzIHRoZSBmaXJzdCB2aXNpYmxlIHRpbWUgb2YgYW55IGdpdmVuIGRheVxuICAgICAgICAgICAgbWluVGltZTogbWluVGltZSxcbiAgICAgICAgICAgIC8vIER1cmF0aW9uIG9iamVjdCB0aGF0IGRlbm90ZXMgdGhlIGV4Y2x1c2l2ZSB2aXNpYmxlIGVuZCB0aW1lIG9mIGFueSBnaXZlbiBkYXlcbiAgICAgICAgICAgIG1heFRpbWU6IG1heFRpbWUsXG4gICAgICAgICAgICBpc1ZhbGlkOiBpc1ZhbGlkLFxuICAgICAgICAgICAgLy8gaG93IGZhciB0aGUgY3VycmVudCBkYXRlIHdpbGwgbW92ZSBmb3IgYSBwcmV2L25leHQgb3BlcmF0aW9uXG4gICAgICAgICAgICBkYXRlSW5jcmVtZW50OiB0aGlzLmJ1aWxkRGF0ZUluY3JlbWVudChjdXJyZW50SW5mby5kdXJhdGlvbilcbiAgICAgICAgICAgIC8vIHBhc3MgYSBmYWxsYmFjayAobWlnaHQgYmUgbnVsbCkgXlxuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gQnVpbGRzIGFuIG9iamVjdCB3aXRoIG9wdGlvbmFsIHN0YXJ0L2VuZCBwcm9wZXJ0aWVzLlxuICAgIC8vIEluZGljYXRlcyB0aGUgbWluaW11bS9tYXhpbXVtIGRhdGVzIHRvIGRpc3BsYXkuXG4gICAgLy8gbm90IHJlc3BvbnNpYmxlIGZvciB0cmltbWluZyBoaWRkZW4gZGF5cy5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRWYWxpZFJhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRSYW5nZU9wdGlvbigndmFsaWRSYW5nZScsIHRoaXMuY2FsZW5kYXIuZ2V0Tm93KCkpIHx8XG4gICAgICAgICAgICB7IHN0YXJ0OiBudWxsLCBlbmQ6IG51bGwgfTsgLy8gY29tcGxldGVseSBvcGVuLWVuZGVkXG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYSBzdHJ1Y3R1cmUgd2l0aCBpbmZvIGFib3V0IHRoZSBcImN1cnJlbnRcIiByYW5nZSwgdGhlIHJhbmdlIHRoYXQgaXNcbiAgICAvLyBoaWdobGlnaHRlZCBhcyBiZWluZyB0aGUgY3VycmVudCBtb250aCBmb3IgZXhhbXBsZS5cbiAgICAvLyBTZWUgYnVpbGQoKSBmb3IgYSBkZXNjcmlwdGlvbiBvZiBgZGlyZWN0aW9uYC5cbiAgICAvLyBHdWFyYW50ZWVkIHRvIGhhdmUgYHJhbmdlYCBhbmQgYHVuaXRgIHByb3BlcnRpZXMuIGBkdXJhdGlvbmAgaXMgb3B0aW9uYWwuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkQ3VycmVudFJhbmdlSW5mbyA9IGZ1bmN0aW9uIChkYXRlLCBkaXJlY3Rpb24pIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgdmlld1NwZWMgPSBfYS52aWV3U3BlYywgZGF0ZUVudiA9IF9hLmRhdGVFbnY7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IG51bGw7XG4gICAgICAgIHZhciB1bml0ID0gbnVsbDtcbiAgICAgICAgdmFyIHJhbmdlID0gbnVsbDtcbiAgICAgICAgdmFyIGRheUNvdW50O1xuICAgICAgICBpZiAodmlld1NwZWMuZHVyYXRpb24pIHtcbiAgICAgICAgICAgIGR1cmF0aW9uID0gdmlld1NwZWMuZHVyYXRpb247XG4gICAgICAgICAgICB1bml0ID0gdmlld1NwZWMuZHVyYXRpb25Vbml0O1xuICAgICAgICAgICAgcmFuZ2UgPSB0aGlzLmJ1aWxkUmFuZ2VGcm9tRHVyYXRpb24oZGF0ZSwgZGlyZWN0aW9uLCBkdXJhdGlvbiwgdW5pdCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoKGRheUNvdW50ID0gdGhpcy5vcHRpb25zLmRheUNvdW50KSkge1xuICAgICAgICAgICAgdW5pdCA9ICdkYXknO1xuICAgICAgICAgICAgcmFuZ2UgPSB0aGlzLmJ1aWxkUmFuZ2VGcm9tRGF5Q291bnQoZGF0ZSwgZGlyZWN0aW9uLCBkYXlDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoKHJhbmdlID0gdGhpcy5idWlsZEN1c3RvbVZpc2libGVSYW5nZShkYXRlKSkpIHtcbiAgICAgICAgICAgIHVuaXQgPSBkYXRlRW52LmdyZWF0ZXN0V2hvbGVVbml0KHJhbmdlLnN0YXJ0LCByYW5nZS5lbmQpLnVuaXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkdXJhdGlvbiA9IHRoaXMuZ2V0RmFsbGJhY2tEdXJhdGlvbigpO1xuICAgICAgICAgICAgdW5pdCA9IGdyZWF0ZXN0RHVyYXRpb25EZW5vbWluYXRvcihkdXJhdGlvbikudW5pdDtcbiAgICAgICAgICAgIHJhbmdlID0gdGhpcy5idWlsZFJhbmdlRnJvbUR1cmF0aW9uKGRhdGUsIGRpcmVjdGlvbiwgZHVyYXRpb24sIHVuaXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IGR1cmF0aW9uOiBkdXJhdGlvbiwgdW5pdDogdW5pdCwgcmFuZ2U6IHJhbmdlIH07XG4gICAgfTtcbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuZ2V0RmFsbGJhY2tEdXJhdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHsgZGF5OiAxIH0pO1xuICAgIH07XG4gICAgLy8gUmV0dXJucyBhIG5ldyBhY3RpdmVSYW5nZSB0byBoYXZlIHRpbWUgdmFsdWVzICh1bi1hbWJpZ3VhdGUpXG4gICAgLy8gbWluVGltZSBvciBtYXhUaW1lIGNhdXNlcyB0aGUgcmFuZ2UgdG8gZXhwYW5kLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5hZGp1c3RBY3RpdmVSYW5nZSA9IGZ1bmN0aW9uIChyYW5nZSwgbWluVGltZSwgbWF4VGltZSkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIHN0YXJ0ID0gcmFuZ2Uuc3RhcnQ7XG4gICAgICAgIHZhciBlbmQgPSByYW5nZS5lbmQ7XG4gICAgICAgIGlmICh0aGlzLnZpZXdTcGVjLmNsYXNzLnByb3RvdHlwZS51c2VzTWluTWF4VGltZSkge1xuICAgICAgICAgICAgLy8gZXhwYW5kIGFjdGl2ZSByYW5nZSBpZiBtaW5UaW1lIGlzIG5lZ2F0aXZlICh3aHkgbm90IHdoZW4gcG9zaXRpdmU/KVxuICAgICAgICAgICAgaWYgKGFzUm91Z2hEYXlzKG1pblRpbWUpIDwgMCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gc3RhcnRPZkRheShzdGFydCk7IC8vIG5lY2Vzc2FyeT9cbiAgICAgICAgICAgICAgICBzdGFydCA9IGRhdGVFbnYuYWRkKHN0YXJ0LCBtaW5UaW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGV4cGFuZCBhY3RpdmUgcmFuZ2UgaWYgbWF4VGltZSBpcyBiZXlvbmQgb25lIGRheSAod2h5IG5vdCB3aGVuIHBvc2l0aXZlPylcbiAgICAgICAgICAgIGlmIChhc1JvdWdoRGF5cyhtYXhUaW1lKSA+IDEpIHtcbiAgICAgICAgICAgICAgICBlbmQgPSBzdGFydE9mRGF5KGVuZCk7IC8vIG5lY2Vzc2FyeT9cbiAgICAgICAgICAgICAgICBlbmQgPSBhZGREYXlzKGVuZCwgLTEpO1xuICAgICAgICAgICAgICAgIGVuZCA9IGRhdGVFbnYuYWRkKGVuZCwgbWF4VGltZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgIH07XG4gICAgLy8gQnVpbGRzIHRoZSBcImN1cnJlbnRcIiByYW5nZSB3aGVuIGl0IGlzIHNwZWNpZmllZCBhcyBhbiBleHBsaWNpdCBkdXJhdGlvbi5cbiAgICAvLyBgdW5pdGAgaXMgdGhlIGFscmVhZHktY29tcHV0ZWQgZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yIHVuaXQgb2YgZHVyYXRpb24uXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkUmFuZ2VGcm9tRHVyYXRpb24gPSBmdW5jdGlvbiAoZGF0ZSwgZGlyZWN0aW9uLCBkdXJhdGlvbiwgdW5pdCkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIGFsaWdubWVudCA9IHRoaXMub3B0aW9ucy5kYXRlQWxpZ25tZW50O1xuICAgICAgICB2YXIgZGF0ZUluY3JlbWVudElucHV0O1xuICAgICAgICB2YXIgZGF0ZUluY3JlbWVudER1cmF0aW9uO1xuICAgICAgICB2YXIgc3RhcnQ7XG4gICAgICAgIHZhciBlbmQ7XG4gICAgICAgIHZhciByZXM7XG4gICAgICAgIC8vIGNvbXB1dGUgd2hhdCB0aGUgYWxpZ25tZW50IHNob3VsZCBiZVxuICAgICAgICBpZiAoIWFsaWdubWVudCkge1xuICAgICAgICAgICAgZGF0ZUluY3JlbWVudElucHV0ID0gdGhpcy5vcHRpb25zLmRhdGVJbmNyZW1lbnQ7XG4gICAgICAgICAgICBpZiAoZGF0ZUluY3JlbWVudElucHV0KSB7XG4gICAgICAgICAgICAgICAgZGF0ZUluY3JlbWVudER1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24oZGF0ZUluY3JlbWVudElucHV0KTtcbiAgICAgICAgICAgICAgICAvLyB1c2UgdGhlIHNtYWxsZXIgb2YgdGhlIHR3byB1bml0c1xuICAgICAgICAgICAgICAgIGlmIChhc1JvdWdoTXMoZGF0ZUluY3JlbWVudER1cmF0aW9uKSA8IGFzUm91Z2hNcyhkdXJhdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25tZW50ID0gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGRhdGVJbmNyZW1lbnREdXJhdGlvbiwgIWdldFdlZWtzRnJvbUlucHV0KGRhdGVJbmNyZW1lbnRJbnB1dCkpLnVuaXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnQgPSB1bml0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGFsaWdubWVudCA9IHVuaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgdGhlIHZpZXcgZGlzcGxheXMgYSBzaW5nbGUgZGF5IG9yIHNtYWxsZXJcbiAgICAgICAgaWYgKGFzUm91Z2hEYXlzKGR1cmF0aW9uKSA8PSAxKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0hpZGRlbkRheShzdGFydCkpIHtcbiAgICAgICAgICAgICAgICBzdGFydCA9IHRoaXMuc2tpcEhpZGRlbkRheXMoc3RhcnQsIGRpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBjb21wdXRlUmVzKCkge1xuICAgICAgICAgICAgc3RhcnQgPSBkYXRlRW52LnN0YXJ0T2YoZGF0ZSwgYWxpZ25tZW50KTtcbiAgICAgICAgICAgIGVuZCA9IGRhdGVFbnYuYWRkKHN0YXJ0LCBkdXJhdGlvbik7XG4gICAgICAgICAgICByZXMgPSB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfTtcbiAgICAgICAgfVxuICAgICAgICBjb21wdXRlUmVzKCk7XG4gICAgICAgIC8vIGlmIHJhbmdlIGlzIGNvbXBsZXRlbHkgZW52ZWxvcGVkIGJ5IGhpZGRlbiBkYXlzLCBnbyBwYXN0IHRoZSBoaWRkZW4gZGF5c1xuICAgICAgICBpZiAoIXRoaXMudHJpbUhpZGRlbkRheXMocmVzKSkge1xuICAgICAgICAgICAgZGF0ZSA9IHRoaXMuc2tpcEhpZGRlbkRheXMoZGF0ZSwgZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIGNvbXB1dGVSZXMoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgLy8gQnVpbGRzIHRoZSBcImN1cnJlbnRcIiByYW5nZSB3aGVuIGEgZGF5Q291bnQgaXMgc3BlY2lmaWVkLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFJhbmdlRnJvbURheUNvdW50ID0gZnVuY3Rpb24gKGRhdGUsIGRpcmVjdGlvbiwgZGF5Q291bnQpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHZhciBjdXN0b21BbGlnbm1lbnQgPSB0aGlzLm9wdGlvbnMuZGF0ZUFsaWdubWVudDtcbiAgICAgICAgdmFyIHJ1bm5pbmdDb3VudCA9IDA7XG4gICAgICAgIHZhciBzdGFydCA9IGRhdGU7XG4gICAgICAgIHZhciBlbmQ7XG4gICAgICAgIGlmIChjdXN0b21BbGlnbm1lbnQpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5zdGFydE9mKHN0YXJ0LCBjdXN0b21BbGlnbm1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXJ0ID0gc3RhcnRPZkRheShzdGFydCk7XG4gICAgICAgIHN0YXJ0ID0gdGhpcy5za2lwSGlkZGVuRGF5cyhzdGFydCwgZGlyZWN0aW9uKTtcbiAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIGVuZCA9IGFkZERheXMoZW5kLCAxKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0hpZGRlbkRheShlbmQpKSB7XG4gICAgICAgICAgICAgICAgcnVubmluZ0NvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gd2hpbGUgKHJ1bm5pbmdDb3VudCA8IGRheUNvdW50KTtcbiAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgIH07XG4gICAgLy8gQnVpbGRzIGEgbm9ybWFsaXplZCByYW5nZSBvYmplY3QgZm9yIHRoZSBcInZpc2libGVcIiByYW5nZSxcbiAgICAvLyB3aGljaCBpcyBhIHdheSB0byBkZWZpbmUgdGhlIGN1cnJlbnRSYW5nZSBhbmQgYWN0aXZlUmFuZ2UgYXQgdGhlIHNhbWUgdGltZS5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRDdXN0b21WaXNpYmxlUmFuZ2UgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIHZpc2libGVSYW5nZSA9IHRoaXMuZ2V0UmFuZ2VPcHRpb24oJ3Zpc2libGVSYW5nZScsIGRhdGVFbnYudG9EYXRlKGRhdGUpKTtcbiAgICAgICAgaWYgKHZpc2libGVSYW5nZSAmJiAodmlzaWJsZVJhbmdlLnN0YXJ0ID09IG51bGwgfHwgdmlzaWJsZVJhbmdlLmVuZCA9PSBudWxsKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZpc2libGVSYW5nZTtcbiAgICB9O1xuICAgIC8vIENvbXB1dGVzIHRoZSByYW5nZSB0aGF0IHdpbGwgcmVwcmVzZW50IHRoZSBlbGVtZW50L2NlbGxzIGZvciAqcmVuZGVyaW5nKixcbiAgICAvLyBidXQgd2hpY2ggbWF5IGhhdmUgdm9pZGVkIGRheXMvdGltZXMuXG4gICAgLy8gbm90IHJlc3BvbnNpYmxlIGZvciB0cmltbWluZyBoaWRkZW4gZGF5cy5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRSZW5kZXJSYW5nZSA9IGZ1bmN0aW9uIChjdXJyZW50UmFuZ2UsIGN1cnJlbnRSYW5nZVVuaXQsIGlzUmFuZ2VBbGxEYXkpIHtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRSYW5nZTtcbiAgICB9O1xuICAgIC8vIENvbXB1dGUgdGhlIGR1cmF0aW9uIHZhbHVlIHRoYXQgc2hvdWxkIGJlIGFkZGVkL3N1YnN0cmFjdGVkIHRvIHRoZSBjdXJyZW50IGRhdGVcbiAgICAvLyB3aGVuIGEgcHJldi9uZXh0IG9wZXJhdGlvbiBoYXBwZW5zLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZERhdGVJbmNyZW1lbnQgPSBmdW5jdGlvbiAoZmFsbGJhY2spIHtcbiAgICAgICAgdmFyIGRhdGVJbmNyZW1lbnRJbnB1dCA9IHRoaXMub3B0aW9ucy5kYXRlSW5jcmVtZW50O1xuICAgICAgICB2YXIgY3VzdG9tQWxpZ25tZW50O1xuICAgICAgICBpZiAoZGF0ZUluY3JlbWVudElucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oZGF0ZUluY3JlbWVudElucHV0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgoY3VzdG9tQWxpZ25tZW50ID0gdGhpcy5vcHRpb25zLmRhdGVBbGlnbm1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oMSwgY3VzdG9tQWxpZ25tZW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChmYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbGxiYWNrO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHsgZGF5czogMSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gQXJndW1lbnRzIGFmdGVyIG5hbWUgd2lsbCBiZSBmb3J3YXJkZWQgdG8gYSBoeXBvdGhldGljYWwgZnVuY3Rpb24gdmFsdWVcbiAgICAvLyBXQVJOSU5HOiBwYXNzZWQtaW4gYXJndW1lbnRzIHdpbGwgYmUgZ2l2ZW4gdG8gZ2VuZXJhdG9yIGZ1bmN0aW9ucyBhcy1pcyBhbmQgY2FuIGNhdXNlIHNpZGUtZWZmZWN0cy5cbiAgICAvLyBBbHdheXMgY2xvbmUgeW91ciBvYmplY3RzIGlmIHlvdSBmZWFyIG11dGF0aW9uLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5nZXRSYW5nZU9wdGlvbiA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHZhciBvdGhlckFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAxOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIG90aGVyQXJnc1tfaSAtIDFdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdmFsID0gdGhpcy5vcHRpb25zW25hbWVdO1xuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdmFsID0gdmFsLmFwcGx5KG51bGwsIG90aGVyQXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbCkge1xuICAgICAgICAgICAgdmFsID0gcGFyc2VSYW5nZSh2YWwsIHRoaXMuZGF0ZUVudik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbCkge1xuICAgICAgICAgICAgdmFsID0gY29tcHV0ZVZpc2libGVEYXlSYW5nZSh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfTtcbiAgICAvKiBIaWRkZW4gRGF5c1xuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgLy8gSW5pdGlhbGl6ZXMgaW50ZXJuYWwgdmFyaWFibGVzIHJlbGF0ZWQgdG8gY2FsY3VsYXRpbmcgaGlkZGVuIGRheXMtb2Ytd2Vla1xuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5pbml0SGlkZGVuRGF5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGhpZGRlbkRheXMgPSB0aGlzLm9wdGlvbnMuaGlkZGVuRGF5cyB8fCBbXTsgLy8gYXJyYXkgb2YgZGF5LW9mLXdlZWsgaW5kaWNlcyB0aGF0IGFyZSBoaWRkZW5cbiAgICAgICAgdmFyIGlzSGlkZGVuRGF5SGFzaCA9IFtdOyAvLyBpcyB0aGUgZGF5LW9mLXdlZWsgaGlkZGVuPyAoaGFzaCB3aXRoIGRheS1vZi13ZWVrLWluZGV4IC0+IGJvb2wpXG4gICAgICAgIHZhciBkYXlDbnQgPSAwO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy53ZWVrZW5kcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGhpZGRlbkRheXMucHVzaCgwLCA2KTsgLy8gMD1zdW5kYXksIDY9c2F0dXJkYXlcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoIShpc0hpZGRlbkRheUhhc2hbaV0gPSBoaWRkZW5EYXlzLmluZGV4T2YoaSkgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGRheUNudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghZGF5Q250KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgaGlkZGVuRGF5cycpOyAvLyBhbGwgZGF5cyB3ZXJlIGhpZGRlbj8gYmFkLlxuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXNIaWRkZW5EYXlIYXNoID0gaXNIaWRkZW5EYXlIYXNoO1xuICAgIH07XG4gICAgLy8gUmVtb3ZlIGRheXMgZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgdGhlIHJhbmdlIHRoYXQgYXJlIGNvbXB1dGVkIGFzIGhpZGRlbi5cbiAgICAvLyBJZiB0aGUgd2hvbGUgcmFuZ2UgaXMgdHJpbW1lZCBvZmYsIHJldHVybnMgbnVsbFxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS50cmltSGlkZGVuRGF5cyA9IGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgICB2YXIgc3RhcnQgPSByYW5nZS5zdGFydDtcbiAgICAgICAgdmFyIGVuZCA9IHJhbmdlLmVuZDtcbiAgICAgICAgaWYgKHN0YXJ0KSB7XG4gICAgICAgICAgICBzdGFydCA9IHRoaXMuc2tpcEhpZGRlbkRheXMoc3RhcnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbmQpIHtcbiAgICAgICAgICAgIGVuZCA9IHRoaXMuc2tpcEhpZGRlbkRheXMoZW5kLCAtMSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXJ0ID09IG51bGwgfHwgZW5kID09IG51bGwgfHwgc3RhcnQgPCBlbmQpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIC8vIElzIHRoZSBjdXJyZW50IGRheSBoaWRkZW4/XG4gICAgLy8gYGRheWAgaXMgYSBkYXktb2Ytd2VlayBpbmRleCAoMC02KSwgb3IgYSBEYXRlICh1c2VkIGZvciBVVEMpXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmlzSGlkZGVuRGF5ID0gZnVuY3Rpb24gKGRheSkge1xuICAgICAgICBpZiAoZGF5IGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICAgICAgZGF5ID0gZGF5LmdldFVUQ0RheSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmlzSGlkZGVuRGF5SGFzaFtkYXldO1xuICAgIH07XG4gICAgLy8gSW5jcmVtZW50aW5nIHRoZSBjdXJyZW50IGRheSB1bnRpbCBpdCBpcyBubyBsb25nZXIgYSBoaWRkZW4gZGF5LCByZXR1cm5pbmcgYSBjb3B5LlxuICAgIC8vIERPRVMgTk9UIENPTlNJREVSIHZhbGlkUmFuZ2UhXG4gICAgLy8gSWYgdGhlIGluaXRpYWwgdmFsdWUgb2YgYGRhdGVgIGlzIG5vdCBhIGhpZGRlbiBkYXksIGRvbid0IGRvIGFueXRoaW5nLlxuICAgIC8vIFBhc3MgYGlzRXhjbHVzaXZlYCBhcyBgdHJ1ZWAgaWYgeW91IGFyZSBkZWFsaW5nIHdpdGggYW4gZW5kIGRhdGUuXG4gICAgLy8gYGluY2AgZGVmYXVsdHMgdG8gYDFgIChpbmNyZW1lbnQgb25lIGRheSBmb3J3YXJkIGVhY2ggdGltZSlcbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuc2tpcEhpZGRlbkRheXMgPSBmdW5jdGlvbiAoZGF0ZSwgaW5jLCBpc0V4Y2x1c2l2ZSkge1xuICAgICAgICBpZiAoaW5jID09PSB2b2lkIDApIHsgaW5jID0gMTsgfVxuICAgICAgICBpZiAoaXNFeGNsdXNpdmUgPT09IHZvaWQgMCkgeyBpc0V4Y2x1c2l2ZSA9IGZhbHNlOyB9XG4gICAgICAgIHdoaWxlICh0aGlzLmlzSGlkZGVuRGF5SGFzaFsoZGF0ZS5nZXRVVENEYXkoKSArIChpc0V4Y2x1c2l2ZSA/IGluYyA6IDApICsgNykgJSA3XSkge1xuICAgICAgICAgICAgZGF0ZSA9IGFkZERheXMoZGF0ZSwgaW5jKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9O1xuICAgIHJldHVybiBEYXRlUHJvZmlsZUdlbmVyYXRvcjtcbn0oKSk7XG4vLyBUT0RPOiBmaW5kIGEgd2F5IHRvIGF2b2lkIGNvbXBhcmluZyBEYXRlUHJvZmlsZXMuIGl0J3MgdGVkaW91c1xuZnVuY3Rpb24gaXNEYXRlUHJvZmlsZXNFcXVhbChwMCwgcDEpIHtcbiAgICByZXR1cm4gcmFuZ2VzRXF1YWwocDAudmFsaWRSYW5nZSwgcDEudmFsaWRSYW5nZSkgJiZcbiAgICAgICAgcmFuZ2VzRXF1YWwocDAuYWN0aXZlUmFuZ2UsIHAxLmFjdGl2ZVJhbmdlKSAmJlxuICAgICAgICByYW5nZXNFcXVhbChwMC5yZW5kZXJSYW5nZSwgcDEucmVuZGVyUmFuZ2UpICYmXG4gICAgICAgIGR1cmF0aW9uc0VxdWFsKHAwLm1pblRpbWUsIHAxLm1pblRpbWUpICYmXG4gICAgICAgIGR1cmF0aW9uc0VxdWFsKHAwLm1heFRpbWUsIHAxLm1heFRpbWUpO1xuICAgIC8qXG4gICAgVE9ETzogY29tcGFyZSBtb3JlP1xuICAgICAgY3VycmVudFJhbmdlOiBEYXRlUmFuZ2VcbiAgICAgIGN1cnJlbnRSYW5nZVVuaXQ6IHN0cmluZ1xuICAgICAgaXNSYW5nZUFsbERheTogYm9vbGVhblxuICAgICAgaXNWYWxpZDogYm9vbGVhblxuICAgICAgZGF0ZUluY3JlbWVudDogRHVyYXRpb25cbiAgICAqL1xufVxuXG5mdW5jdGlvbiByZWR1Y2UgKHN0YXRlLCBhY3Rpb24sIGNhbGVuZGFyKSB7XG4gICAgdmFyIHZpZXdUeXBlID0gcmVkdWNlVmlld1R5cGUoc3RhdGUudmlld1R5cGUsIGFjdGlvbik7XG4gICAgdmFyIGRhdGVQcm9maWxlID0gcmVkdWNlRGF0ZVByb2ZpbGUoc3RhdGUuZGF0ZVByb2ZpbGUsIGFjdGlvbiwgc3RhdGUuY3VycmVudERhdGUsIHZpZXdUeXBlLCBjYWxlbmRhcik7XG4gICAgdmFyIGV2ZW50U291cmNlcyA9IHJlZHVjZUV2ZW50U291cmNlcyhzdGF0ZS5ldmVudFNvdXJjZXMsIGFjdGlvbiwgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyKTtcbiAgICB2YXIgbmV4dFN0YXRlID0gX19hc3NpZ24oe30sIHN0YXRlLCB7IHZpZXdUeXBlOiB2aWV3VHlwZSxcbiAgICAgICAgZGF0ZVByb2ZpbGU6IGRhdGVQcm9maWxlLCBjdXJyZW50RGF0ZTogcmVkdWNlQ3VycmVudERhdGUoc3RhdGUuY3VycmVudERhdGUsIGFjdGlvbiwgZGF0ZVByb2ZpbGUpLCBldmVudFNvdXJjZXM6IGV2ZW50U291cmNlcywgZXZlbnRTdG9yZTogcmVkdWNlRXZlbnRTdG9yZShzdGF0ZS5ldmVudFN0b3JlLCBhY3Rpb24sIGV2ZW50U291cmNlcywgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyKSwgZGF0ZVNlbGVjdGlvbjogcmVkdWNlRGF0ZVNlbGVjdGlvbihzdGF0ZS5kYXRlU2VsZWN0aW9uLCBhY3Rpb24sIGNhbGVuZGFyKSwgZXZlbnRTZWxlY3Rpb246IHJlZHVjZVNlbGVjdGVkRXZlbnQoc3RhdGUuZXZlbnRTZWxlY3Rpb24sIGFjdGlvbiksIGV2ZW50RHJhZzogcmVkdWNlRXZlbnREcmFnKHN0YXRlLmV2ZW50RHJhZywgYWN0aW9uLCBldmVudFNvdXJjZXMsIGNhbGVuZGFyKSwgZXZlbnRSZXNpemU6IHJlZHVjZUV2ZW50UmVzaXplKHN0YXRlLmV2ZW50UmVzaXplLCBhY3Rpb24sIGV2ZW50U291cmNlcywgY2FsZW5kYXIpLCBldmVudFNvdXJjZUxvYWRpbmdMZXZlbDogY29tcHV0ZUxvYWRpbmdMZXZlbChldmVudFNvdXJjZXMpLCBsb2FkaW5nTGV2ZWw6IGNvbXB1dGVMb2FkaW5nTGV2ZWwoZXZlbnRTb3VyY2VzKSB9KTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLnJlZHVjZXJzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgcmVkdWNlckZ1bmMgPSBfYVtfaV07XG4gICAgICAgIG5leHRTdGF0ZSA9IHJlZHVjZXJGdW5jKG5leHRTdGF0ZSwgYWN0aW9uLCBjYWxlbmRhcik7XG4gICAgfVxuICAgIC8vIGNvbnNvbGUubG9nKGFjdGlvbi50eXBlLCBuZXh0U3RhdGUpXG4gICAgcmV0dXJuIG5leHRTdGF0ZTtcbn1cbmZ1bmN0aW9uIHJlZHVjZVZpZXdUeXBlKGN1cnJlbnRWaWV3VHlwZSwgYWN0aW9uKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRVRfVklFV19UWVBFJzpcbiAgICAgICAgICAgIHJldHVybiBhY3Rpb24udmlld1R5cGU7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudFZpZXdUeXBlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZHVjZURhdGVQcm9maWxlKGN1cnJlbnREYXRlUHJvZmlsZSwgYWN0aW9uLCBjdXJyZW50RGF0ZSwgdmlld1R5cGUsIGNhbGVuZGFyKSB7XG4gICAgdmFyIG5ld0RhdGVQcm9maWxlO1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnUFJFVic6XG4gICAgICAgICAgICBuZXdEYXRlUHJvZmlsZSA9IGNhbGVuZGFyLmRhdGVQcm9maWxlR2VuZXJhdG9yc1t2aWV3VHlwZV0uYnVpbGRQcmV2KGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ05FWFQnOlxuICAgICAgICAgICAgbmV3RGF0ZVByb2ZpbGUgPSBjYWxlbmRhci5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdLmJ1aWxkTmV4dChjdXJyZW50RGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdTRVRfREFURSc6XG4gICAgICAgICAgICBpZiAoIWN1cnJlbnREYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSB8fFxuICAgICAgICAgICAgICAgICFyYW5nZUNvbnRhaW5zTWFya2VyKGN1cnJlbnREYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2UsIGFjdGlvbi5kYXRlTWFya2VyKSkge1xuICAgICAgICAgICAgICAgIG5ld0RhdGVQcm9maWxlID0gY2FsZW5kYXIuZGF0ZVByb2ZpbGVHZW5lcmF0b3JzW3ZpZXdUeXBlXS5idWlsZChhY3Rpb24uZGF0ZU1hcmtlciwgdW5kZWZpbmVkLCB0cnVlIC8vIGZvcmNlVG9WYWxpZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnU0VUX1ZJRVdfVFlQRSc6XG4gICAgICAgICAgICB2YXIgZ2VuZXJhdG9yID0gY2FsZW5kYXIuZGF0ZVByb2ZpbGVHZW5lcmF0b3JzW3ZpZXdUeXBlXTtcbiAgICAgICAgICAgIGlmICghZ2VuZXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHZpZXdUeXBlID9cbiAgICAgICAgICAgICAgICAgICAgJ1RoZSBGdWxsQ2FsZW5kYXIgdmlldyBcIicgKyB2aWV3VHlwZSArICdcIiBkb2VzIG5vdCBleGlzdC4gTWFrZSBzdXJlIHlvdXIgcGx1Z2lucyBhcmUgbG9hZGVkIGNvcnJlY3RseS4nIDpcbiAgICAgICAgICAgICAgICAgICAgJ05vIGF2YWlsYWJsZSBGdWxsQ2FsZW5kYXIgdmlldyBwbHVnaW5zLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3RGF0ZVByb2ZpbGUgPSBnZW5lcmF0b3IuYnVpbGQoYWN0aW9uLmRhdGVNYXJrZXIgfHwgY3VycmVudERhdGUsIHVuZGVmaW5lZCwgdHJ1ZSAvLyBmb3JjZVRvVmFsaWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgaWYgKG5ld0RhdGVQcm9maWxlICYmXG4gICAgICAgIG5ld0RhdGVQcm9maWxlLmlzVmFsaWQgJiZcbiAgICAgICAgIShjdXJyZW50RGF0ZVByb2ZpbGUgJiYgaXNEYXRlUHJvZmlsZXNFcXVhbChjdXJyZW50RGF0ZVByb2ZpbGUsIG5ld0RhdGVQcm9maWxlKSkpIHtcbiAgICAgICAgcmV0dXJuIG5ld0RhdGVQcm9maWxlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnREYXRlUHJvZmlsZTtcbiAgICB9XG59XG5mdW5jdGlvbiByZWR1Y2VDdXJyZW50RGF0ZShjdXJyZW50RGF0ZSwgYWN0aW9uLCBkYXRlUHJvZmlsZSkge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnUFJFVic6XG4gICAgICAgIGNhc2UgJ05FWFQnOlxuICAgICAgICAgICAgaWYgKCFyYW5nZUNvbnRhaW5zTWFya2VyKGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZSwgY3VycmVudERhdGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50RGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAnU0VUX0RBVEUnOlxuICAgICAgICBjYXNlICdTRVRfVklFV19UWVBFJzpcbiAgICAgICAgICAgIHZhciBuZXdEYXRlID0gYWN0aW9uLmRhdGVNYXJrZXIgfHwgY3VycmVudERhdGU7XG4gICAgICAgICAgICBpZiAoZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgJiYgIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIG5ld0RhdGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5zdGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXdEYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnREYXRlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZHVjZURhdGVTZWxlY3Rpb24oY3VycmVudFNlbGVjdGlvbiwgYWN0aW9uLCBjYWxlbmRhcikge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnU0VMRUNUX0RBVEVTJzpcbiAgICAgICAgICAgIHJldHVybiBhY3Rpb24uc2VsZWN0aW9uO1xuICAgICAgICBjYXNlICdVTlNFTEVDVF9EQVRFUyc6XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50U2VsZWN0aW9uO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZHVjZVNlbGVjdGVkRXZlbnQoY3VycmVudEluc3RhbmNlSWQsIGFjdGlvbikge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnU0VMRUNUX0VWRU5UJzpcbiAgICAgICAgICAgIHJldHVybiBhY3Rpb24uZXZlbnRJbnN0YW5jZUlkO1xuICAgICAgICBjYXNlICdVTlNFTEVDVF9FVkVOVCc6XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudEluc3RhbmNlSWQ7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlRXZlbnREcmFnKGN1cnJlbnREcmFnLCBhY3Rpb24sIHNvdXJjZXMsIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRVRfRVZFTlRfRFJBRyc6XG4gICAgICAgICAgICB2YXIgbmV3RHJhZyA9IGFjdGlvbi5zdGF0ZTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IG5ld0RyYWcuYWZmZWN0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogbmV3RHJhZy5tdXRhdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IG5ld0RyYWcuaXNFdmVudCxcbiAgICAgICAgICAgICAgICBvcmlnU2VnOiBuZXdEcmFnLm9yaWdTZWdcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgJ1VOU0VUX0VWRU5UX0RSQUcnOlxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudERyYWc7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlRXZlbnRSZXNpemUoY3VycmVudFJlc2l6ZSwgYWN0aW9uLCBzb3VyY2VzLCBjYWxlbmRhcikge1xuICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnU0VUX0VWRU5UX1JFU0laRSc6XG4gICAgICAgICAgICB2YXIgbmV3UmVzaXplID0gYWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogbmV3UmVzaXplLmFmZmVjdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IG5ld1Jlc2l6ZS5tdXRhdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IG5ld1Jlc2l6ZS5pc0V2ZW50LFxuICAgICAgICAgICAgICAgIG9yaWdTZWc6IG5ld1Jlc2l6ZS5vcmlnU2VnXG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlICdVTlNFVF9FVkVOVF9SRVNJWkUnOlxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudFJlc2l6ZTtcbiAgICB9XG59XG5mdW5jdGlvbiBjb21wdXRlTG9hZGluZ0xldmVsKGV2ZW50U291cmNlcykge1xuICAgIHZhciBjbnQgPSAwO1xuICAgIGZvciAodmFyIHNvdXJjZUlkIGluIGV2ZW50U291cmNlcykge1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2VzW3NvdXJjZUlkXS5pc0ZldGNoaW5nKSB7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY250O1xufVxuXG52YXIgU1RBTkRBUkRfUFJPUFMgPSB7XG4gICAgc3RhcnQ6IG51bGwsXG4gICAgZW5kOiBudWxsLFxuICAgIGFsbERheTogQm9vbGVhblxufTtcbmZ1bmN0aW9uIHBhcnNlRGF0ZVNwYW4ocmF3LCBkYXRlRW52LCBkZWZhdWx0RHVyYXRpb24pIHtcbiAgICB2YXIgc3BhbiA9IHBhcnNlT3BlbkRhdGVTcGFuKHJhdywgZGF0ZUVudik7XG4gICAgdmFyIHJhbmdlID0gc3Bhbi5yYW5nZTtcbiAgICBpZiAoIXJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoIXJhbmdlLmVuZCkge1xuICAgICAgICBpZiAoZGVmYXVsdER1cmF0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmFuZ2UuZW5kID0gZGF0ZUVudi5hZGQocmFuZ2Uuc3RhcnQsIGRlZmF1bHREdXJhdGlvbik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNwYW47XG59XG4vKlxuVE9ETzogc29tZWhvdyBjb21iaW5lIHdpdGggcGFyc2VSYW5nZT9cbldpbGwgcmV0dXJuIG51bGwgaWYgdGhlIHN0YXJ0L2VuZCBwcm9wcyB3ZXJlIHByZXNlbnQgYnV0IHBhcnNlZCBpbnZhbGlkbHkuXG4qL1xuZnVuY3Rpb24gcGFyc2VPcGVuRGF0ZVNwYW4ocmF3LCBkYXRlRW52KSB7XG4gICAgdmFyIGxlZnRvdmVycyA9IHt9O1xuICAgIHZhciBzdGFuZGFyZFByb3BzID0gcmVmaW5lUHJvcHMocmF3LCBTVEFOREFSRF9QUk9QUywge30sIGxlZnRvdmVycyk7XG4gICAgdmFyIHN0YXJ0TWV0YSA9IHN0YW5kYXJkUHJvcHMuc3RhcnQgPyBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoc3RhbmRhcmRQcm9wcy5zdGFydCkgOiBudWxsO1xuICAgIHZhciBlbmRNZXRhID0gc3RhbmRhcmRQcm9wcy5lbmQgPyBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoc3RhbmRhcmRQcm9wcy5lbmQpIDogbnVsbDtcbiAgICB2YXIgYWxsRGF5ID0gc3RhbmRhcmRQcm9wcy5hbGxEYXk7XG4gICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgIGFsbERheSA9IChzdGFydE1ldGEgJiYgc3RhcnRNZXRhLmlzVGltZVVuc3BlY2lmaWVkKSAmJlxuICAgICAgICAgICAgKCFlbmRNZXRhIHx8IGVuZE1ldGEuaXNUaW1lVW5zcGVjaWZpZWQpO1xuICAgIH1cbiAgICAvLyB1c2UgdGhpcyBsZWZ0b3ZlciBvYmplY3QgYXMgdGhlIHNlbGVjdGlvbiBvYmplY3RcbiAgICBsZWZ0b3ZlcnMucmFuZ2UgPSB7XG4gICAgICAgIHN0YXJ0OiBzdGFydE1ldGEgPyBzdGFydE1ldGEubWFya2VyIDogbnVsbCxcbiAgICAgICAgZW5kOiBlbmRNZXRhID8gZW5kTWV0YS5tYXJrZXIgOiBudWxsXG4gICAgfTtcbiAgICBsZWZ0b3ZlcnMuYWxsRGF5ID0gYWxsRGF5O1xuICAgIHJldHVybiBsZWZ0b3ZlcnM7XG59XG5mdW5jdGlvbiBpc0RhdGVTcGFuc0VxdWFsKHNwYW4wLCBzcGFuMSkge1xuICAgIHJldHVybiByYW5nZXNFcXVhbChzcGFuMC5yYW5nZSwgc3BhbjEucmFuZ2UpICYmXG4gICAgICAgIHNwYW4wLmFsbERheSA9PT0gc3BhbjEuYWxsRGF5ICYmXG4gICAgICAgIGlzU3BhblByb3BzRXF1YWwoc3BhbjAsIHNwYW4xKTtcbn1cbi8vIHRoZSBOT04tREFURS1SRUxBVEVEIHByb3BzXG5mdW5jdGlvbiBpc1NwYW5Qcm9wc0VxdWFsKHNwYW4wLCBzcGFuMSkge1xuICAgIGZvciAodmFyIHByb3BOYW1lIGluIHNwYW4xKSB7XG4gICAgICAgIGlmIChwcm9wTmFtZSAhPT0gJ3JhbmdlJyAmJiBwcm9wTmFtZSAhPT0gJ2FsbERheScpIHtcbiAgICAgICAgICAgIGlmIChzcGFuMFtwcm9wTmFtZV0gIT09IHNwYW4xW3Byb3BOYW1lXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBhcmUgdGhlcmUgYW55IHByb3BzIHRoYXQgc3BhbjAgaGFzIHRoYXQgc3BhbjEgRE9FU04nVCBoYXZlP1xuICAgIC8vIGJvdGggaGF2ZSByYW5nZS9hbGxEYXksIHNvIG5vIG5lZWQgdG8gc3BlY2lhbC1jYXNlLlxuICAgIGZvciAodmFyIHByb3BOYW1lIGluIHNwYW4wKSB7XG4gICAgICAgIGlmICghKHByb3BOYW1lIGluIHNwYW4xKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gYnVpbGREYXRlU3BhbkFwaShzcGFuLCBkYXRlRW52KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IGRhdGVFbnYudG9EYXRlKHNwYW4ucmFuZ2Uuc3RhcnQpLFxuICAgICAgICBlbmQ6IGRhdGVFbnYudG9EYXRlKHNwYW4ucmFuZ2UuZW5kKSxcbiAgICAgICAgc3RhcnRTdHI6IGRhdGVFbnYuZm9ybWF0SXNvKHNwYW4ucmFuZ2Uuc3RhcnQsIHsgb21pdFRpbWU6IHNwYW4uYWxsRGF5IH0pLFxuICAgICAgICBlbmRTdHI6IGRhdGVFbnYuZm9ybWF0SXNvKHNwYW4ucmFuZ2UuZW5kLCB7IG9taXRUaW1lOiBzcGFuLmFsbERheSB9KSxcbiAgICAgICAgYWxsRGF5OiBzcGFuLmFsbERheVxuICAgIH07XG59XG5mdW5jdGlvbiBidWlsZERhdGVQb2ludEFwaShzcGFuLCBkYXRlRW52KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGF0ZTogZGF0ZUVudi50b0RhdGUoc3Bhbi5yYW5nZS5zdGFydCksXG4gICAgICAgIGRhdGVTdHI6IGRhdGVFbnYuZm9ybWF0SXNvKHNwYW4ucmFuZ2Uuc3RhcnQsIHsgb21pdFRpbWU6IHNwYW4uYWxsRGF5IH0pLFxuICAgICAgICBhbGxEYXk6IHNwYW4uYWxsRGF5XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGZhYnJpY2F0ZUV2ZW50UmFuZ2UoZGF0ZVNwYW4sIGV2ZW50VWlCYXNlcywgY2FsZW5kYXIpIHtcbiAgICB2YXIgZGVmID0gcGFyc2VFdmVudERlZih7IGVkaXRhYmxlOiBmYWxzZSB9LCAnJywgLy8gc291cmNlSWRcbiAgICBkYXRlU3Bhbi5hbGxEYXksIHRydWUsIC8vIGhhc0VuZFxuICAgIGNhbGVuZGFyKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBkZWY6IGRlZixcbiAgICAgICAgdWk6IGNvbXBpbGVFdmVudFVpKGRlZiwgZXZlbnRVaUJhc2VzKSxcbiAgICAgICAgaW5zdGFuY2U6IGNyZWF0ZUV2ZW50SW5zdGFuY2UoZGVmLmRlZklkLCBkYXRlU3Bhbi5yYW5nZSksXG4gICAgICAgIHJhbmdlOiBkYXRlU3Bhbi5yYW5nZSxcbiAgICAgICAgaXNTdGFydDogdHJ1ZSxcbiAgICAgICAgaXNFbmQ6IHRydWVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBjb21waWxlVmlld0RlZnMoZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncykge1xuICAgIHZhciBoYXNoID0ge307XG4gICAgdmFyIHZpZXdUeXBlO1xuICAgIGZvciAodmlld1R5cGUgaW4gZGVmYXVsdENvbmZpZ3MpIHtcbiAgICAgICAgZW5zdXJlVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgfVxuICAgIGZvciAodmlld1R5cGUgaW4gb3ZlcnJpZGVDb25maWdzKSB7XG4gICAgICAgIGVuc3VyZVZpZXdEZWYodmlld1R5cGUsIGhhc2gsIGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpO1xuICAgIH1cbiAgICByZXR1cm4gaGFzaDtcbn1cbmZ1bmN0aW9uIGVuc3VyZVZpZXdEZWYodmlld1R5cGUsIGhhc2gsIGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpIHtcbiAgICBpZiAoaGFzaFt2aWV3VHlwZV0pIHtcbiAgICAgICAgcmV0dXJuIGhhc2hbdmlld1R5cGVdO1xuICAgIH1cbiAgICB2YXIgdmlld0RlZiA9IGJ1aWxkVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgaWYgKHZpZXdEZWYpIHtcbiAgICAgICAgaGFzaFt2aWV3VHlwZV0gPSB2aWV3RGVmO1xuICAgIH1cbiAgICByZXR1cm4gdmlld0RlZjtcbn1cbmZ1bmN0aW9uIGJ1aWxkVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncykge1xuICAgIHZhciBkZWZhdWx0Q29uZmlnID0gZGVmYXVsdENvbmZpZ3Nbdmlld1R5cGVdO1xuICAgIHZhciBvdmVycmlkZUNvbmZpZyA9IG92ZXJyaWRlQ29uZmlnc1t2aWV3VHlwZV07XG4gICAgdmFyIHF1ZXJ5UHJvcCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiAoZGVmYXVsdENvbmZpZyAmJiBkZWZhdWx0Q29uZmlnW25hbWVdICE9PSBudWxsKSA/IGRlZmF1bHRDb25maWdbbmFtZV0gOlxuICAgICAgICAgICAgKChvdmVycmlkZUNvbmZpZyAmJiBvdmVycmlkZUNvbmZpZ1tuYW1lXSAhPT0gbnVsbCkgPyBvdmVycmlkZUNvbmZpZ1tuYW1lXSA6IG51bGwpO1xuICAgIH07XG4gICAgdmFyIHRoZUNsYXNzID0gcXVlcnlQcm9wKCdjbGFzcycpO1xuICAgIHZhciBzdXBlclR5cGUgPSBxdWVyeVByb3AoJ3N1cGVyVHlwZScpO1xuICAgIGlmICghc3VwZXJUeXBlICYmIHRoZUNsYXNzKSB7XG4gICAgICAgIHN1cGVyVHlwZSA9XG4gICAgICAgICAgICBmaW5kVmlld05hbWVCeVN1YmNsYXNzKHRoZUNsYXNzLCBvdmVycmlkZUNvbmZpZ3MpIHx8XG4gICAgICAgICAgICAgICAgZmluZFZpZXdOYW1lQnlTdWJjbGFzcyh0aGVDbGFzcywgZGVmYXVsdENvbmZpZ3MpO1xuICAgIH1cbiAgICB2YXIgc3VwZXJEZWYgPSBudWxsO1xuICAgIGlmIChzdXBlclR5cGUpIHtcbiAgICAgICAgaWYgKHN1cGVyVHlwZSA9PT0gdmlld1R5cGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBoYXZlIGEgY3VzdG9tIHZpZXcgdHlwZSB0aGF0IHJlZmVyZW5jZXMgaXRzZWxmJyk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXJEZWYgPSBlbnN1cmVWaWV3RGVmKHN1cGVyVHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgfVxuICAgIGlmICghdGhlQ2xhc3MgJiYgc3VwZXJEZWYpIHtcbiAgICAgICAgdGhlQ2xhc3MgPSBzdXBlckRlZi5jbGFzcztcbiAgICB9XG4gICAgaWYgKCF0aGVDbGFzcykge1xuICAgICAgICByZXR1cm4gbnVsbDsgLy8gZG9uJ3QgdGhyb3cgYSB3YXJuaW5nLCBtaWdodCBiZSBzZXR0aW5ncyBmb3IgYSBzaW5nbGUtdW5pdCB2aWV3XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IHZpZXdUeXBlLFxuICAgICAgICBjbGFzczogdGhlQ2xhc3MsXG4gICAgICAgIGRlZmF1bHRzOiBfX2Fzc2lnbih7fSwgKHN1cGVyRGVmID8gc3VwZXJEZWYuZGVmYXVsdHMgOiB7fSksIChkZWZhdWx0Q29uZmlnID8gZGVmYXVsdENvbmZpZy5vcHRpb25zIDoge30pKSxcbiAgICAgICAgb3ZlcnJpZGVzOiBfX2Fzc2lnbih7fSwgKHN1cGVyRGVmID8gc3VwZXJEZWYub3ZlcnJpZGVzIDoge30pLCAob3ZlcnJpZGVDb25maWcgPyBvdmVycmlkZUNvbmZpZy5vcHRpb25zIDoge30pKVxuICAgIH07XG59XG5mdW5jdGlvbiBmaW5kVmlld05hbWVCeVN1YmNsYXNzKHZpZXdTdWJjbGFzcywgY29uZmlncykge1xuICAgIHZhciBzdXBlclByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZpZXdTdWJjbGFzcy5wcm90b3R5cGUpO1xuICAgIGZvciAodmFyIHZpZXdUeXBlIGluIGNvbmZpZ3MpIHtcbiAgICAgICAgdmFyIHBhcnNlZCA9IGNvbmZpZ3Nbdmlld1R5cGVdO1xuICAgICAgICAvLyBuZWVkIERJUkVDVCBzdWJjbGFzcywgc28gaW5zdGFuY2VvZiB3b24ndCBkbyBpdFxuICAgICAgICBpZiAocGFyc2VkLmNsYXNzICYmIHBhcnNlZC5jbGFzcy5wcm90b3R5cGUgPT09IHN1cGVyUHJvdG8pIHtcbiAgICAgICAgICAgIHJldHVybiB2aWV3VHlwZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJyc7XG59XG5cbmZ1bmN0aW9uIHBhcnNlVmlld0NvbmZpZ3MoaW5wdXRzKSB7XG4gICAgcmV0dXJuIG1hcEhhc2goaW5wdXRzLCBwYXJzZVZpZXdDb25maWcpO1xufVxudmFyIFZJRVdfREVGX1BST1BTID0ge1xuICAgIHR5cGU6IFN0cmluZyxcbiAgICBjbGFzczogbnVsbFxufTtcbmZ1bmN0aW9uIHBhcnNlVmlld0NvbmZpZyhpbnB1dCkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgaW5wdXQgPSB7IGNsYXNzOiBpbnB1dCB9O1xuICAgIH1cbiAgICB2YXIgb3B0aW9ucyA9IHt9O1xuICAgIHZhciBwcm9wcyA9IHJlZmluZVByb3BzKGlucHV0LCBWSUVXX0RFRl9QUk9QUywge30sIG9wdGlvbnMpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHN1cGVyVHlwZTogcHJvcHMudHlwZSxcbiAgICAgICAgY2xhc3M6IHByb3BzLmNsYXNzLFxuICAgICAgICBvcHRpb25zOiBvcHRpb25zXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYnVpbGRWaWV3U3BlY3MoZGVmYXVsdElucHV0cywgb3B0aW9uc01hbmFnZXIpIHtcbiAgICB2YXIgZGVmYXVsdENvbmZpZ3MgPSBwYXJzZVZpZXdDb25maWdzKGRlZmF1bHRJbnB1dHMpO1xuICAgIHZhciBvdmVycmlkZUNvbmZpZ3MgPSBwYXJzZVZpZXdDb25maWdzKG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcy52aWV3cyk7XG4gICAgdmFyIHZpZXdEZWZzID0gY29tcGlsZVZpZXdEZWZzKGRlZmF1bHRDb25maWdzLCBvdmVycmlkZUNvbmZpZ3MpO1xuICAgIHJldHVybiBtYXBIYXNoKHZpZXdEZWZzLCBmdW5jdGlvbiAodmlld0RlZikge1xuICAgICAgICByZXR1cm4gYnVpbGRWaWV3U3BlYyh2aWV3RGVmLCBvdmVycmlkZUNvbmZpZ3MsIG9wdGlvbnNNYW5hZ2VyKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGJ1aWxkVmlld1NwZWModmlld0RlZiwgb3ZlcnJpZGVDb25maWdzLCBvcHRpb25zTWFuYWdlcikge1xuICAgIHZhciBkdXJhdGlvbklucHV0ID0gdmlld0RlZi5vdmVycmlkZXMuZHVyYXRpb24gfHxcbiAgICAgICAgdmlld0RlZi5kZWZhdWx0cy5kdXJhdGlvbiB8fFxuICAgICAgICBvcHRpb25zTWFuYWdlci5keW5hbWljT3ZlcnJpZGVzLmR1cmF0aW9uIHx8XG4gICAgICAgIG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcy5kdXJhdGlvbjtcbiAgICB2YXIgZHVyYXRpb24gPSBudWxsO1xuICAgIHZhciBkdXJhdGlvblVuaXQgPSAnJztcbiAgICB2YXIgc2luZ2xlVW5pdCA9ICcnO1xuICAgIHZhciBzaW5nbGVVbml0T3ZlcnJpZGVzID0ge307XG4gICAgaWYgKGR1cmF0aW9uSW5wdXQpIHtcbiAgICAgICAgZHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbihkdXJhdGlvbklucHV0KTtcbiAgICAgICAgaWYgKGR1cmF0aW9uKSB7IC8vIHZhbGlkP1xuICAgICAgICAgICAgdmFyIGRlbm9tID0gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGR1cmF0aW9uLCAhZ2V0V2Vla3NGcm9tSW5wdXQoZHVyYXRpb25JbnB1dCkpO1xuICAgICAgICAgICAgZHVyYXRpb25Vbml0ID0gZGVub20udW5pdDtcbiAgICAgICAgICAgIGlmIChkZW5vbS52YWx1ZSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZVVuaXQgPSBkdXJhdGlvblVuaXQ7XG4gICAgICAgICAgICAgICAgc2luZ2xlVW5pdE92ZXJyaWRlcyA9IG92ZXJyaWRlQ29uZmlnc1tkdXJhdGlvblVuaXRdID8gb3ZlcnJpZGVDb25maWdzW2R1cmF0aW9uVW5pdF0ub3B0aW9ucyA6IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHZhciBxdWVyeUJ1dHRvblRleHQgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICB2YXIgYnV0dG9uVGV4dE1hcCA9IG9wdGlvbnMuYnV0dG9uVGV4dCB8fCB7fTtcbiAgICAgICAgdmFyIGJ1dHRvblRleHRLZXkgPSB2aWV3RGVmLmRlZmF1bHRzLmJ1dHRvblRleHRLZXk7XG4gICAgICAgIGlmIChidXR0b25UZXh0S2V5ICE9IG51bGwgJiYgYnV0dG9uVGV4dE1hcFtidXR0b25UZXh0S2V5XSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYnV0dG9uVGV4dE1hcFtidXR0b25UZXh0S2V5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9uVGV4dE1hcFt2aWV3RGVmLnR5cGVdICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBidXR0b25UZXh0TWFwW3ZpZXdEZWYudHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1dHRvblRleHRNYXBbc2luZ2xlVW5pdF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGJ1dHRvblRleHRNYXBbc2luZ2xlVW5pdF07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IHZpZXdEZWYudHlwZSxcbiAgICAgICAgY2xhc3M6IHZpZXdEZWYuY2xhc3MsXG4gICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgZHVyYXRpb25Vbml0OiBkdXJhdGlvblVuaXQsXG4gICAgICAgIHNpbmdsZVVuaXQ6IHNpbmdsZVVuaXQsXG4gICAgICAgIG9wdGlvbnM6IF9fYXNzaWduKHt9LCBnbG9iYWxEZWZhdWx0cywgdmlld0RlZi5kZWZhdWx0cywgb3B0aW9uc01hbmFnZXIuZGlyRGVmYXVsdHMsIG9wdGlvbnNNYW5hZ2VyLmxvY2FsZURlZmF1bHRzLCBvcHRpb25zTWFuYWdlci5vdmVycmlkZXMsIHNpbmdsZVVuaXRPdmVycmlkZXMsIHZpZXdEZWYub3ZlcnJpZGVzLCBvcHRpb25zTWFuYWdlci5keW5hbWljT3ZlcnJpZGVzKSxcbiAgICAgICAgYnV0dG9uVGV4dE92ZXJyaWRlOiBxdWVyeUJ1dHRvblRleHQob3B0aW9uc01hbmFnZXIuZHluYW1pY092ZXJyaWRlcykgfHxcbiAgICAgICAgICAgIHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5vdmVycmlkZXMpIHx8IC8vIGNvbnN0cnVjdG9yLXNwZWNpZmllZCBidXR0b25UZXh0IGxvb2t1cCBoYXNoIHRha2VzIHByZWNlZGVuY2VcbiAgICAgICAgICAgIHZpZXdEZWYub3ZlcnJpZGVzLmJ1dHRvblRleHQsXG4gICAgICAgIGJ1dHRvblRleHREZWZhdWx0OiBxdWVyeUJ1dHRvblRleHQob3B0aW9uc01hbmFnZXIubG9jYWxlRGVmYXVsdHMpIHx8XG4gICAgICAgICAgICBxdWVyeUJ1dHRvblRleHQob3B0aW9uc01hbmFnZXIuZGlyRGVmYXVsdHMpIHx8XG4gICAgICAgICAgICB2aWV3RGVmLmRlZmF1bHRzLmJ1dHRvblRleHQgfHxcbiAgICAgICAgICAgIHF1ZXJ5QnV0dG9uVGV4dChnbG9iYWxEZWZhdWx0cykgfHxcbiAgICAgICAgICAgIHZpZXdEZWYudHlwZSAvLyBmYWxsIGJhY2sgdG8gZ2l2ZW4gdmlldyBuYW1lXG4gICAgfTtcbn1cblxudmFyIFRvb2xiYXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFRvb2xiYXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVG9vbGJhcihleHRyYUNsYXNzTmFtZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5fcmVuZGVyTGF5b3V0ID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJMYXlvdXQsIF90aGlzLnVucmVuZGVyTGF5b3V0KTtcbiAgICAgICAgX3RoaXMuX3VwZGF0ZVRpdGxlID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy51cGRhdGVUaXRsZSwgbnVsbCwgW190aGlzLl9yZW5kZXJMYXlvdXRdKTtcbiAgICAgICAgX3RoaXMuX3VwZGF0ZUFjdGl2ZUJ1dHRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMudXBkYXRlQWN0aXZlQnV0dG9uLCBudWxsLCBbX3RoaXMuX3JlbmRlckxheW91dF0pO1xuICAgICAgICBfdGhpcy5fdXBkYXRlVG9kYXkgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnVwZGF0ZVRvZGF5LCBudWxsLCBbX3RoaXMuX3JlbmRlckxheW91dF0pO1xuICAgICAgICBfdGhpcy5fdXBkYXRlUHJldiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMudXBkYXRlUHJldiwgbnVsbCwgW190aGlzLl9yZW5kZXJMYXlvdXRdKTtcbiAgICAgICAgX3RoaXMuX3VwZGF0ZU5leHQgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnVwZGF0ZU5leHQsIG51bGwsIFtfdGhpcy5fcmVuZGVyTGF5b3V0XSk7XG4gICAgICAgIF90aGlzLmVsID0gY3JlYXRlRWxlbWVudCgnZGl2JywgeyBjbGFzc05hbWU6ICdmYy10b29sYmFyICcgKyBleHRyYUNsYXNzTmFtZSB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBUb29sYmFyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5fcmVuZGVyTGF5b3V0LnVucmVuZGVyKCk7IC8vIHNob3VsZCB1bnJlbmRlciBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmVsKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcykge1xuICAgICAgICB0aGlzLl9yZW5kZXJMYXlvdXQocHJvcHMubGF5b3V0KTtcbiAgICAgICAgdGhpcy5fdXBkYXRlVGl0bGUocHJvcHMudGl0bGUpO1xuICAgICAgICB0aGlzLl91cGRhdGVBY3RpdmVCdXR0b24ocHJvcHMuYWN0aXZlQnV0dG9uKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlVG9kYXkocHJvcHMuaXNUb2RheUVuYWJsZWQpO1xuICAgICAgICB0aGlzLl91cGRhdGVQcmV2KHByb3BzLmlzUHJldkVuYWJsZWQpO1xuICAgICAgICB0aGlzLl91cGRhdGVOZXh0KHByb3BzLmlzTmV4dEVuYWJsZWQpO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUucmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gKGxheW91dCkge1xuICAgICAgICB2YXIgZWwgPSB0aGlzLmVsO1xuICAgICAgICB0aGlzLnZpZXdzV2l0aEJ1dHRvbnMgPSBbXTtcbiAgICAgICAgYXBwZW5kVG9FbGVtZW50KGVsLCB0aGlzLnJlbmRlclNlY3Rpb24oJ2xlZnQnLCBsYXlvdXQubGVmdCkpO1xuICAgICAgICBhcHBlbmRUb0VsZW1lbnQoZWwsIHRoaXMucmVuZGVyU2VjdGlvbignY2VudGVyJywgbGF5b3V0LmNlbnRlcikpO1xuICAgICAgICBhcHBlbmRUb0VsZW1lbnQoZWwsIHRoaXMucmVuZGVyU2VjdGlvbigncmlnaHQnLCBsYXlvdXQucmlnaHQpKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVucmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmVsLmlubmVySFRNTCA9ICcnO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUucmVuZGVyU2VjdGlvbiA9IGZ1bmN0aW9uIChwb3NpdGlvbiwgYnV0dG9uU3RyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29udGV4dCwgdGhlbWUgPSBfYS50aGVtZSwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhcjtcbiAgICAgICAgdmFyIG9wdGlvbnNNYW5hZ2VyID0gY2FsZW5kYXIub3B0aW9uc01hbmFnZXI7XG4gICAgICAgIHZhciB2aWV3U3BlY3MgPSBjYWxlbmRhci52aWV3U3BlY3M7XG4gICAgICAgIHZhciBzZWN0aW9uRWwgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLScgKyBwb3NpdGlvbiB9KTtcbiAgICAgICAgdmFyIGNhbGVuZGFyQ3VzdG9tQnV0dG9ucyA9IG9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkLmN1c3RvbUJ1dHRvbnMgfHwge307XG4gICAgICAgIHZhciBjYWxlbmRhckJ1dHRvblRleHRPdmVycmlkZXMgPSBvcHRpb25zTWFuYWdlci5vdmVycmlkZXMuYnV0dG9uVGV4dCB8fCB7fTtcbiAgICAgICAgdmFyIGNhbGVuZGFyQnV0dG9uVGV4dCA9IG9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkLmJ1dHRvblRleHQgfHwge307XG4gICAgICAgIGlmIChidXR0b25TdHIpIHtcbiAgICAgICAgICAgIGJ1dHRvblN0ci5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24gKGJ1dHRvbkdyb3VwU3RyLCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdyb3VwQ2hpbGRyZW4gPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaXNPbmx5QnV0dG9ucyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdmFyIGdyb3VwRWw7XG4gICAgICAgICAgICAgICAgYnV0dG9uR3JvdXBTdHIuc3BsaXQoJywnKS5mb3JFYWNoKGZ1bmN0aW9uIChidXR0b25OYW1lLCBqKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjdXN0b21CdXR0b25Qcm9wcztcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpZXdTcGVjO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uQ2xpY2s7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25JY29uOyAvLyBvbmx5IG9uZSBvZiB0aGVzZSB3aWxsIGJlIHNldFxuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uVGV4dDsgLy8gXCJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbklubmVySHRtbDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbkNsYXNzZXM7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25FbDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbkFyaWFBdHRyO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYnV0dG9uTmFtZSA9PT0gJ3RpdGxlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBDaGlsZHJlbi5wdXNoKGh0bWxUb0VsZW1lbnQoJzxoMj4mbmJzcDs8L2gyPicpKTsgLy8gd2UgYWx3YXlzIHdhbnQgaXQgdG8gdGFrZSB1cCBoZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzT25seUJ1dHRvbnMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoY3VzdG9tQnV0dG9uUHJvcHMgPSBjYWxlbmRhckN1c3RvbUJ1dHRvbnNbYnV0dG9uTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQ2xpY2sgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1c3RvbUJ1dHRvblByb3BzLmNsaWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21CdXR0b25Qcm9wcy5jbGljay5jYWxsKGJ1dHRvbkVsLCBldik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25JY29uID0gdGhlbWUuZ2V0Q3VzdG9tQnV0dG9uSWNvbkNsYXNzKGN1c3RvbUJ1dHRvblByb3BzKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvbkljb24gPSB0aGVtZS5nZXRJY29uQ2xhc3MoYnV0dG9uTmFtZSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25UZXh0ID0gY3VzdG9tQnV0dG9uUHJvcHMudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICgodmlld1NwZWMgPSB2aWV3U3BlY3NbYnV0dG9uTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudmlld3NXaXRoQnV0dG9ucy5wdXNoKGJ1dHRvbk5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbkNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxlbmRhci5jaGFuZ2VWaWV3KGJ1dHRvbk5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSB2aWV3U3BlYy5idXR0b25UZXh0T3ZlcnJpZGUpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25JY29uID0gdGhlbWUuZ2V0SWNvbkNsYXNzKGJ1dHRvbk5hbWUpKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uVGV4dCA9IHZpZXdTcGVjLmJ1dHRvblRleHREZWZhdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNhbGVuZGFyW2J1dHRvbk5hbWVdKSB7IC8vIGEgY2FsZW5kYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQ2xpY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyW2J1dHRvbk5hbWVdKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uVGV4dCA9IGNhbGVuZGFyQnV0dG9uVGV4dE92ZXJyaWRlc1tidXR0b25OYW1lXSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvbkljb24gPSB0aGVtZS5nZXRJY29uQ2xhc3MoYnV0dG9uTmFtZSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25UZXh0ID0gY2FsZW5kYXJCdXR0b25UZXh0W2J1dHRvbk5hbWVdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgICAgICAgIF4gZXZlcnl0aGluZyBlbHNlIGlzIGNvbnNpZGVyZWQgZGVmYXVsdFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJ1dHRvbkNsaWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQ2xhc3NlcyA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2ZjLScgKyBidXR0b25OYW1lICsgJy1idXR0b24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZS5nZXRDbGFzcygnYnV0dG9uJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChidXR0b25UZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbklubmVySHRtbCA9IGh0bWxFc2NhcGUoYnV0dG9uVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbkFyaWFBdHRyID0gJyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJ1dHRvbkljb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uSW5uZXJIdG1sID0gXCI8c3BhbiBjbGFzcz0nXCIgKyBidXR0b25JY29uICsgXCInPjwvc3Bhbj5cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQXJpYUF0dHIgPSAnIGFyaWEtbGFiZWw9XCInICsgYnV0dG9uTmFtZSArICdcIic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbkVsID0gaHRtbFRvRWxlbWVudCgvLyB0eXBlPVwiYnV0dG9uXCIgc28gdGhhdCBpdCBkb2Vzbid0IHN1Ym1pdCBhIGZvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCInICsgYnV0dG9uQ2xhc3Nlcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQXJpYUF0dHIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPicgKyBidXR0b25Jbm5lckh0bWwgKyAnPC9idXR0b24+Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uRWwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBidXR0b25DbGljayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBDaGlsZHJlbi5wdXNoKGJ1dHRvbkVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChncm91cENoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBFbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uR3JvdXBDbGFzc05hbWUgPSB0aGVtZS5nZXRDbGFzcygnYnV0dG9uR3JvdXAnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzT25seUJ1dHRvbnMgJiYgYnV0dG9uR3JvdXBDbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwRWwuY2xhc3NMaXN0LmFkZChidXR0b25Hcm91cENsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXBwZW5kVG9FbGVtZW50KGdyb3VwRWwsIGdyb3VwQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgICAgICBzZWN0aW9uRWwuYXBwZW5kQ2hpbGQoZ3JvdXBFbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQoc2VjdGlvbkVsLCBncm91cENoaWxkcmVuKTsgLy8gMSBvciAwIGNoaWxkcmVuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlY3Rpb25FbDtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZVRvZGF5ID0gZnVuY3Rpb24gKGlzVG9kYXlFbmFibGVkKSB7XG4gICAgICAgIHRoaXMudG9nZ2xlQnV0dG9uRW5hYmxlZCgndG9kYXknLCBpc1RvZGF5RW5hYmxlZCk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS51cGRhdGVQcmV2ID0gZnVuY3Rpb24gKGlzUHJldkVuYWJsZWQpIHtcbiAgICAgICAgdGhpcy50b2dnbGVCdXR0b25FbmFibGVkKCdwcmV2JywgaXNQcmV2RW5hYmxlZCk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS51cGRhdGVOZXh0ID0gZnVuY3Rpb24gKGlzTmV4dEVuYWJsZWQpIHtcbiAgICAgICAgdGhpcy50b2dnbGVCdXR0b25FbmFibGVkKCduZXh0JywgaXNOZXh0RW5hYmxlZCk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS51cGRhdGVUaXRsZSA9IGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgICAgIGZpbmRFbGVtZW50cyh0aGlzLmVsLCAnaDInKS5mb3JFYWNoKGZ1bmN0aW9uICh0aXRsZUVsKSB7XG4gICAgICAgICAgICB0aXRsZUVsLmlubmVyVGV4dCA9IHRleHQ7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUudXBkYXRlQWN0aXZlQnV0dG9uID0gZnVuY3Rpb24gKGJ1dHRvbk5hbWUpIHtcbiAgICAgICAgdmFyIHRoZW1lID0gdGhpcy5jb250ZXh0LnRoZW1lO1xuICAgICAgICB2YXIgY2xhc3NOYW1lID0gdGhlbWUuZ2V0Q2xhc3MoJ2J1dHRvbkFjdGl2ZScpO1xuICAgICAgICBmaW5kRWxlbWVudHModGhpcy5lbCwgJ2J1dHRvbicpLmZvckVhY2goZnVuY3Rpb24gKGJ1dHRvbkVsKSB7XG4gICAgICAgICAgICBpZiAoYnV0dG9uTmFtZSAmJiBidXR0b25FbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLScgKyBidXR0b25OYW1lICsgJy1idXR0b24nKSkge1xuICAgICAgICAgICAgICAgIGJ1dHRvbkVsLmNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1dHRvbkVsLmNsYXNzTGlzdC5yZW1vdmUoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS50b2dnbGVCdXR0b25FbmFibGVkID0gZnVuY3Rpb24gKGJ1dHRvbk5hbWUsIGJvb2wpIHtcbiAgICAgICAgZmluZEVsZW1lbnRzKHRoaXMuZWwsICcuZmMtJyArIGJ1dHRvbk5hbWUgKyAnLWJ1dHRvbicpLmZvckVhY2goZnVuY3Rpb24gKGJ1dHRvbkVsKSB7XG4gICAgICAgICAgICBidXR0b25FbC5kaXNhYmxlZCA9ICFib29sO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBUb29sYmFyO1xufShDb21wb25lbnQpKTtcblxudmFyIENhbGVuZGFyQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhDYWxlbmRhckNvbXBvbmVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDYWxlbmRhckNvbXBvbmVudChlbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbENsYXNzTmFtZXMgPSBbXTtcbiAgICAgICAgX3RoaXMucmVuZGVyU2tlbGV0b24gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLl9yZW5kZXJTa2VsZXRvbiwgX3RoaXMuX3VucmVuZGVyU2tlbGV0b24pO1xuICAgICAgICBfdGhpcy5yZW5kZXJUb29sYmFycyA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclRvb2xiYXJzLCBfdGhpcy5fdW5yZW5kZXJUb29sYmFycywgW190aGlzLnJlbmRlclNrZWxldG9uXSk7XG4gICAgICAgIF90aGlzLmJ1aWxkQ29tcG9uZW50Q29udGV4dCA9IG1lbW9pemUoYnVpbGRDb21wb25lbnRDb250ZXh0KTtcbiAgICAgICAgX3RoaXMuYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyA9IG1lbW9pemUoYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyk7XG4gICAgICAgIF90aGlzLmVsID0gZWw7XG4gICAgICAgIF90aGlzLmNvbXB1dGVUaXRsZSA9IG1lbW9pemUoY29tcHV0ZVRpdGxlKTtcbiAgICAgICAgX3RoaXMucGFyc2VCdXNpbmVzc0hvdXJzID0gbWVtb2l6ZShmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUJ1c2luZXNzSG91cnMoaW5wdXQsIF90aGlzLmNvbnRleHQuY2FsZW5kYXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzLCBjb250ZXh0KSB7XG4gICAgICAgIHRoaXMuZnJlZXplSGVpZ2h0KCk7XG4gICAgICAgIHZhciB0aXRsZSA9IHRoaXMuY29tcHV0ZVRpdGxlKHByb3BzLmRhdGVQcm9maWxlLCBwcm9wcy52aWV3U3BlYy5vcHRpb25zKTtcbiAgICAgICAgdGhpcy5yZW5kZXJTa2VsZXRvbihjb250ZXh0KTtcbiAgICAgICAgdGhpcy5yZW5kZXJUb29sYmFycyhwcm9wcy52aWV3U3BlYywgcHJvcHMuZGF0ZVByb2ZpbGUsIHByb3BzLmN1cnJlbnREYXRlLCB0aXRsZSk7XG4gICAgICAgIHRoaXMucmVuZGVyVmlldyhwcm9wcywgdGl0bGUpO1xuICAgICAgICB0aGlzLnVwZGF0ZVNpemUoKTtcbiAgICAgICAgdGhpcy50aGF3SGVpZ2h0KCk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZm9vdGVyKSB7XG4gICAgICAgICAgICB0aGlzLmZvb3Rlci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJTa2VsZXRvbi51bnJlbmRlcigpOyAvLyB3aWxsIGNhbGwgZGVzdHJveVZpZXdcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUuX3JlbmRlclNrZWxldG9uID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy51cGRhdGVFbENsYXNzTmFtZXMoY29udGV4dCk7XG4gICAgICAgIHByZXBlbmRUb0VsZW1lbnQodGhpcy5lbCwgdGhpcy5jb250ZW50RWwgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLXZpZXctY29udGFpbmVyJyB9KSk7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3Mudmlld0NvbnRhaW5lck1vZGlmaWVyczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBtb2RpZnlWaWV3Q29udGFpbmVyID0gX2FbX2ldO1xuICAgICAgICAgICAgbW9kaWZ5Vmlld0NvbnRhaW5lcih0aGlzLmNvbnRlbnRFbCwgY2FsZW5kYXIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHdlaXJkIHRvIGhhdmUgdGhpcyBoZXJlXG4gICAgICAgIGlmICh0aGlzLnZpZXcpIHtcbiAgICAgICAgICAgIHRoaXMuc2F2ZWRTY3JvbGwgPSB0aGlzLnZpZXcucXVlcnlTY3JvbGwoKTtcbiAgICAgICAgICAgIHRoaXMudmlldy5kZXN0cm95KCk7XG4gICAgICAgICAgICB0aGlzLnZpZXcgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5jb250ZW50RWwpO1xuICAgICAgICB0aGlzLnJlbW92ZUVsQ2xhc3NOYW1lcygpO1xuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnJlbW92ZUVsQ2xhc3NOYW1lcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNsYXNzTGlzdCA9IHRoaXMuZWwuY2xhc3NMaXN0O1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5lbENsYXNzTmFtZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NOYW1lID0gX2FbX2ldO1xuICAgICAgICAgICAgY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWxDbGFzc05hbWVzID0gW107XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUudXBkYXRlRWxDbGFzc05hbWVzID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVFbENsYXNzTmFtZXMoKTtcbiAgICAgICAgdmFyIHRoZW1lID0gY29udGV4dC50aGVtZSwgb3B0aW9ucyA9IGNvbnRleHQub3B0aW9ucztcbiAgICAgICAgdGhpcy5lbENsYXNzTmFtZXMgPSBbXG4gICAgICAgICAgICAnZmMnLFxuICAgICAgICAgICAgJ2ZjLScgKyBvcHRpb25zLmRpcixcbiAgICAgICAgICAgIHRoZW1lLmdldENsYXNzKCd3aWRnZXQnKVxuICAgICAgICBdO1xuICAgICAgICB2YXIgY2xhc3NMaXN0ID0gdGhpcy5lbC5jbGFzc0xpc3Q7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmVsQ2xhc3NOYW1lczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBjbGFzc05hbWUgPSBfYVtfaV07XG4gICAgICAgICAgICBjbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5fcmVuZGVyVG9vbGJhcnMgPSBmdW5jdGlvbiAodmlld1NwZWMsIGRhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSwgdGl0bGUpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgY29udGV4dCA9IF9hLmNvbnRleHQsIGhlYWRlciA9IF9hLmhlYWRlciwgZm9vdGVyID0gX2EuZm9vdGVyO1xuICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbnRleHQub3B0aW9ucywgY2FsZW5kYXIgPSBjb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICB2YXIgaGVhZGVyTGF5b3V0ID0gb3B0aW9ucy5oZWFkZXI7XG4gICAgICAgIHZhciBmb290ZXJMYXlvdXQgPSBvcHRpb25zLmZvb3RlcjtcbiAgICAgICAgdmFyIGRhdGVQcm9maWxlR2VuZXJhdG9yID0gdGhpcy5wcm9wcy5kYXRlUHJvZmlsZUdlbmVyYXRvcjtcbiAgICAgICAgdmFyIG5vdyA9IGNhbGVuZGFyLmdldE5vdygpO1xuICAgICAgICB2YXIgdG9kYXlJbmZvID0gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGQobm93KTtcbiAgICAgICAgdmFyIHByZXZJbmZvID0gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGRQcmV2KGRhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSk7XG4gICAgICAgIHZhciBuZXh0SW5mbyA9IGRhdGVQcm9maWxlR2VuZXJhdG9yLmJ1aWxkTmV4dChkYXRlUHJvZmlsZSwgY3VycmVudERhdGUpO1xuICAgICAgICB2YXIgdG9vbGJhclByb3BzID0ge1xuICAgICAgICAgICAgdGl0bGU6IHRpdGxlLFxuICAgICAgICAgICAgYWN0aXZlQnV0dG9uOiB2aWV3U3BlYy50eXBlLFxuICAgICAgICAgICAgaXNUb2RheUVuYWJsZWQ6IHRvZGF5SW5mby5pc1ZhbGlkICYmICFyYW5nZUNvbnRhaW5zTWFya2VyKGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZSwgbm93KSxcbiAgICAgICAgICAgIGlzUHJldkVuYWJsZWQ6IHByZXZJbmZvLmlzVmFsaWQsXG4gICAgICAgICAgICBpc05leHRFbmFibGVkOiBuZXh0SW5mby5pc1ZhbGlkXG4gICAgICAgIH07XG4gICAgICAgIGlmIChoZWFkZXJMYXlvdXQpIHtcbiAgICAgICAgICAgIGlmICghaGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgaGVhZGVyID0gdGhpcy5oZWFkZXIgPSBuZXcgVG9vbGJhcignZmMtaGVhZGVyLXRvb2xiYXInKTtcbiAgICAgICAgICAgICAgICBwcmVwZW5kVG9FbGVtZW50KHRoaXMuZWwsIGhlYWRlci5lbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoZWFkZXIucmVjZWl2ZVByb3BzKF9fYXNzaWduKHsgbGF5b3V0OiBoZWFkZXJMYXlvdXQgfSwgdG9vbGJhclByb3BzKSwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaGVhZGVyKSB7XG4gICAgICAgICAgICBoZWFkZXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgaGVhZGVyID0gdGhpcy5oZWFkZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb290ZXJMYXlvdXQpIHtcbiAgICAgICAgICAgIGlmICghZm9vdGVyKSB7XG4gICAgICAgICAgICAgICAgZm9vdGVyID0gdGhpcy5mb290ZXIgPSBuZXcgVG9vbGJhcignZmMtZm9vdGVyLXRvb2xiYXInKTtcbiAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQodGhpcy5lbCwgZm9vdGVyLmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvb3Rlci5yZWNlaXZlUHJvcHMoX19hc3NpZ24oeyBsYXlvdXQ6IGZvb3RlckxheW91dCB9LCB0b29sYmFyUHJvcHMpLCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChmb290ZXIpIHtcbiAgICAgICAgICAgIGZvb3Rlci5kZXN0cm95KCk7XG4gICAgICAgICAgICBmb290ZXIgPSB0aGlzLmZvb3RlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5fdW5yZW5kZXJUb29sYmFycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlci5kZXN0cm95KCk7XG4gICAgICAgICAgICB0aGlzLmhlYWRlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZm9vdGVyKSB7XG4gICAgICAgICAgICB0aGlzLmZvb3Rlci5kZXN0cm95KCk7XG4gICAgICAgICAgICB0aGlzLmZvb3RlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5yZW5kZXJWaWV3ID0gZnVuY3Rpb24gKHByb3BzLCB0aXRsZSkge1xuICAgICAgICB2YXIgdmlldyA9IHRoaXMudmlldztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIHZpZXdTcGVjID0gcHJvcHMudmlld1NwZWMsIGRhdGVQcm9maWxlR2VuZXJhdG9yID0gcHJvcHMuZGF0ZVByb2ZpbGVHZW5lcmF0b3I7XG4gICAgICAgIGlmICghdmlldyB8fCB2aWV3LnZpZXdTcGVjICE9PSB2aWV3U3BlYykge1xuICAgICAgICAgICAgaWYgKHZpZXcpIHtcbiAgICAgICAgICAgICAgICB2aWV3LmRlc3Ryb3koKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZpZXcgPSB0aGlzLnZpZXcgPSBuZXcgdmlld1NwZWNbJ2NsYXNzJ10odmlld1NwZWMsIHRoaXMuY29udGVudEVsKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNhdmVkU2Nyb2xsKSB7XG4gICAgICAgICAgICAgICAgdmlldy5hZGRTY3JvbGwodGhpcy5zYXZlZFNjcm9sbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zYXZlZFNjcm9sbCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmlldy50aXRsZSA9IHRpdGxlOyAvLyBmb3IgdGhlIEFQSVxuICAgICAgICB2YXIgdmlld1Byb3BzID0ge1xuICAgICAgICAgICAgZGF0ZVByb2ZpbGVHZW5lcmF0b3I6IGRhdGVQcm9maWxlR2VuZXJhdG9yLFxuICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IHByb3BzLmRhdGVQcm9maWxlLFxuICAgICAgICAgICAgYnVzaW5lc3NIb3VyczogdGhpcy5wYXJzZUJ1c2luZXNzSG91cnModmlld1NwZWMub3B0aW9ucy5idXNpbmVzc0hvdXJzKSxcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IHByb3BzLmV2ZW50U3RvcmUsXG4gICAgICAgICAgICBldmVudFVpQmFzZXM6IHByb3BzLmV2ZW50VWlCYXNlcyxcbiAgICAgICAgICAgIGRhdGVTZWxlY3Rpb246IHByb3BzLmRhdGVTZWxlY3Rpb24sXG4gICAgICAgICAgICBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb24sXG4gICAgICAgICAgICBldmVudERyYWc6IHByb3BzLmV2ZW50RHJhZyxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplOiBwcm9wcy5ldmVudFJlc2l6ZVxuICAgICAgICB9O1xuICAgICAgICB2YXIgdHJhbnNmb3JtZXJzID0gdGhpcy5idWlsZFZpZXdQcm9wVHJhbnNmb3JtZXJzKGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy52aWV3UHJvcHNUcmFuc2Zvcm1lcnMpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHRyYW5zZm9ybWVyc18xID0gdHJhbnNmb3JtZXJzOyBfaSA8IHRyYW5zZm9ybWVyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybWVyID0gdHJhbnNmb3JtZXJzXzFbX2ldO1xuICAgICAgICAgICAgX19hc3NpZ24odmlld1Byb3BzLCB0cmFuc2Zvcm1lci50cmFuc2Zvcm0odmlld1Byb3BzLCB2aWV3U3BlYywgcHJvcHMsIG9wdGlvbnMpKTtcbiAgICAgICAgfVxuICAgICAgICB2aWV3LnJlY2VpdmVQcm9wcyh2aWV3UHJvcHMsIHRoaXMuYnVpbGRDb21wb25lbnRDb250ZXh0KHRoaXMuY29udGV4dCwgdmlld1NwZWMsIHZpZXcpKTtcbiAgICB9O1xuICAgIC8vIFNpemluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnVwZGF0ZVNpemUgPSBmdW5jdGlvbiAoaXNSZXNpemUpIHtcbiAgICAgICAgaWYgKGlzUmVzaXplID09PSB2b2lkIDApIHsgaXNSZXNpemUgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgdmlldyA9IHRoaXMudmlldztcbiAgICAgICAgaWYgKCF2aWV3KSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIHdoeT9cbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNSZXNpemUgfHwgdGhpcy5pc0hlaWdodEF1dG8gPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5jb21wdXRlSGVpZ2h0VmFycygpO1xuICAgICAgICB9XG4gICAgICAgIHZpZXcudXBkYXRlU2l6ZShpc1Jlc2l6ZSwgdGhpcy52aWV3SGVpZ2h0LCB0aGlzLmlzSGVpZ2h0QXV0byk7XG4gICAgICAgIHZpZXcudXBkYXRlTm93SW5kaWNhdG9yKCk7IC8vIHdlIG5lZWQgdG8gZ3VhcmFudGVlIHRoaXMgd2lsbCBydW4gYWZ0ZXIgdXBkYXRlU2l6ZVxuICAgICAgICB2aWV3LnBvcFNjcm9sbChpc1Jlc2l6ZSk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUuY29tcHV0ZUhlaWdodFZhcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXMuY29udGV4dC5jYWxlbmRhcjsgLy8geXVjay4gbmVlZCB0byBoYW5kbGUgZHluYW1pYyBvcHRpb25zXG4gICAgICAgIHZhciBoZWlnaHRJbnB1dCA9IGNhbGVuZGFyLm9wdCgnaGVpZ2h0Jyk7XG4gICAgICAgIHZhciBjb250ZW50SGVpZ2h0SW5wdXQgPSBjYWxlbmRhci5vcHQoJ2NvbnRlbnRIZWlnaHQnKTtcbiAgICAgICAgdGhpcy5pc0hlaWdodEF1dG8gPSBoZWlnaHRJbnB1dCA9PT0gJ2F1dG8nIHx8IGNvbnRlbnRIZWlnaHRJbnB1dCA9PT0gJ2F1dG8nO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnRlbnRIZWlnaHRJbnB1dCA9PT0gJ251bWJlcicpIHsgLy8gZXhpc3RzIGFuZCBub3QgJ2F1dG8nXG4gICAgICAgICAgICB0aGlzLnZpZXdIZWlnaHQgPSBjb250ZW50SGVpZ2h0SW5wdXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGNvbnRlbnRIZWlnaHRJbnB1dCA9PT0gJ2Z1bmN0aW9uJykgeyAvLyBleGlzdHMgYW5kIGlzIGEgZnVuY3Rpb25cbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IGNvbnRlbnRIZWlnaHRJbnB1dCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBoZWlnaHRJbnB1dCA9PT0gJ251bWJlcicpIHsgLy8gZXhpc3RzIGFuZCBub3QgJ2F1dG8nXG4gICAgICAgICAgICB0aGlzLnZpZXdIZWlnaHQgPSBoZWlnaHRJbnB1dCAtIHRoaXMucXVlcnlUb29sYmFyc0hlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBoZWlnaHRJbnB1dCA9PT0gJ2Z1bmN0aW9uJykgeyAvLyBleGlzdHMgYW5kIGlzIGEgZnVuY3Rpb25cbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IGhlaWdodElucHV0KCkgLSB0aGlzLnF1ZXJ5VG9vbGJhcnNIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChoZWlnaHRJbnB1dCA9PT0gJ3BhcmVudCcpIHsgLy8gc2V0IHRvIGhlaWdodCBvZiBwYXJlbnQgZWxlbWVudFxuICAgICAgICAgICAgdmFyIHBhcmVudEVsID0gdGhpcy5lbC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgdGhpcy52aWV3SGVpZ2h0ID0gcGFyZW50RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IC0gdGhpcy5xdWVyeVRvb2xiYXJzSGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdIZWlnaHQgPSBNYXRoLnJvdW5kKHRoaXMuY29udGVudEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC9cbiAgICAgICAgICAgICAgICBNYXRoLm1heChjYWxlbmRhci5vcHQoJ2FzcGVjdFJhdGlvJyksIC41KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5xdWVyeVRvb2xiYXJzSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGVpZ2h0ID0gMDtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyKSB7XG4gICAgICAgICAgICBoZWlnaHQgKz0gY29tcHV0ZUhlaWdodEFuZE1hcmdpbnModGhpcy5oZWFkZXIuZWwpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmZvb3Rlcikge1xuICAgICAgICAgICAgaGVpZ2h0ICs9IGNvbXB1dGVIZWlnaHRBbmRNYXJnaW5zKHRoaXMuZm9vdGVyLmVsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGVpZ2h0O1xuICAgIH07XG4gICAgLy8gSGVpZ2h0IFwiRnJlZXppbmdcIlxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLmZyZWV6ZUhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmVsLCB7XG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMuZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0LFxuICAgICAgICAgICAgb3ZlcmZsb3c6ICdoaWRkZW4nXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnRoYXdIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFwcGx5U3R5bGUodGhpcy5lbCwge1xuICAgICAgICAgICAgaGVpZ2h0OiAnJyxcbiAgICAgICAgICAgIG92ZXJmbG93OiAnJ1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBDYWxlbmRhckNvbXBvbmVudDtcbn0oQ29tcG9uZW50KSk7XG4vLyBUaXRsZSBhbmQgRGF0ZSBGb3JtYXR0aW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gQ29tcHV0ZXMgd2hhdCB0aGUgdGl0bGUgYXQgdGhlIHRvcCBvZiB0aGUgY2FsZW5kYXIgc2hvdWxkIGJlIGZvciB0aGlzIHZpZXdcbmZ1bmN0aW9uIGNvbXB1dGVUaXRsZShkYXRlUHJvZmlsZSwgdmlld09wdGlvbnMpIHtcbiAgICB2YXIgcmFuZ2U7XG4gICAgLy8gZm9yIHZpZXdzIHRoYXQgc3BhbiBhIGxhcmdlIHVuaXQgb2YgdGltZSwgc2hvdyB0aGUgcHJvcGVyIGludGVydmFsLCBpZ25vcmluZyBzdHJheSBkYXlzIGJlZm9yZSBhbmQgYWZ0ZXJcbiAgICBpZiAoL14oeWVhcnxtb250aCkkLy50ZXN0KGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpKSB7XG4gICAgICAgIHJhbmdlID0gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gZm9yIGRheSB1bml0cyBvciBzbWFsbGVyLCB1c2UgdGhlIGFjdHVhbCBkYXkgcmFuZ2VcbiAgICAgICAgcmFuZ2UgPSBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY29udGV4dC5kYXRlRW52LmZvcm1hdFJhbmdlKHJhbmdlLnN0YXJ0LCByYW5nZS5lbmQsIGNyZWF0ZUZvcm1hdHRlcih2aWV3T3B0aW9ucy50aXRsZUZvcm1hdCB8fCBjb21wdXRlVGl0bGVGb3JtYXQoZGF0ZVByb2ZpbGUpLCB2aWV3T3B0aW9ucy50aXRsZVJhbmdlU2VwYXJhdG9yKSwgeyBpc0VuZEV4Y2x1c2l2ZTogZGF0ZVByb2ZpbGUuaXNSYW5nZUFsbERheSB9KTtcbn1cbi8vIEdlbmVyYXRlcyB0aGUgZm9ybWF0IHN0cmluZyB0aGF0IHNob3VsZCBiZSB1c2VkIHRvIGdlbmVyYXRlIHRoZSB0aXRsZSBmb3IgdGhlIGN1cnJlbnQgZGF0ZSByYW5nZS5cbi8vIEF0dGVtcHRzIHRvIGNvbXB1dGUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgZm9ybWF0IGlmIG5vdCBleHBsaWNpdGx5IHNwZWNpZmllZCB3aXRoIGB0aXRsZUZvcm1hdGAuXG5mdW5jdGlvbiBjb21wdXRlVGl0bGVGb3JtYXQoZGF0ZVByb2ZpbGUpIHtcbiAgICB2YXIgY3VycmVudFJhbmdlVW5pdCA9IGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQ7XG4gICAgaWYgKGN1cnJlbnRSYW5nZVVuaXQgPT09ICd5ZWFyJykge1xuICAgICAgICByZXR1cm4geyB5ZWFyOiAnbnVtZXJpYycgfTtcbiAgICB9XG4gICAgZWxzZSBpZiAoY3VycmVudFJhbmdlVW5pdCA9PT0gJ21vbnRoJykge1xuICAgICAgICByZXR1cm4geyB5ZWFyOiAnbnVtZXJpYycsIG1vbnRoOiAnbG9uZycgfTsgLy8gbGlrZSBcIlNlcHRlbWJlciAyMDE0XCJcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBkYXlzID0gZGlmZldob2xlRGF5cyhkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2Uuc3RhcnQsIGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5lbmQpO1xuICAgICAgICBpZiAoZGF5cyAhPT0gbnVsbCAmJiBkYXlzID4gMSkge1xuICAgICAgICAgICAgLy8gbXVsdGktZGF5IHJhbmdlLiBzaG9ydGVyLCBsaWtlIFwiU2VwIDkgLSAxMCAyMDE0XCJcbiAgICAgICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdzaG9ydCcsIGRheTogJ251bWVyaWMnIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBvbmUgZGF5LiBsb25nZXIsIGxpa2UgXCJTZXB0ZW1iZXIgOSAyMDE0XCJcbiAgICAgICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdsb25nJywgZGF5OiAnbnVtZXJpYycgfTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8vIGJ1aWxkIGEgY29udGV4dCBzY29wZWQgdG8gdGhlIHZpZXdcbmZ1bmN0aW9uIGJ1aWxkQ29tcG9uZW50Q29udGV4dChjb250ZXh0LCB2aWV3U3BlYywgdmlldykge1xuICAgIHJldHVybiBjb250ZXh0LmV4dGVuZCh2aWV3U3BlYy5vcHRpb25zLCB2aWV3KTtcbn1cbi8vIFBsdWdpblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGJ1aWxkVmlld1Byb3BUcmFuc2Zvcm1lcnModGhlQ2xhc3Nlcykge1xuICAgIHJldHVybiB0aGVDbGFzc2VzLm1hcChmdW5jdGlvbiAodGhlQ2xhc3MpIHtcbiAgICAgICAgcmV0dXJuIG5ldyB0aGVDbGFzcygpO1xuICAgIH0pO1xufVxuXG52YXIgSW50ZXJhY3Rpb24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSW50ZXJhY3Rpb24oc2V0dGluZ3MpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnQgPSBzZXR0aW5ncy5jb21wb25lbnQ7XG4gICAgfVxuICAgIEludGVyYWN0aW9uLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgcmV0dXJuIEludGVyYWN0aW9uO1xufSgpKTtcbmZ1bmN0aW9uIHBhcnNlSW50ZXJhY3Rpb25TZXR0aW5ncyhjb21wb25lbnQsIGlucHV0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29tcG9uZW50OiBjb21wb25lbnQsXG4gICAgICAgIGVsOiBpbnB1dC5lbCxcbiAgICAgICAgdXNlRXZlbnRDZW50ZXI6IGlucHV0LnVzZUV2ZW50Q2VudGVyICE9IG51bGwgPyBpbnB1dC51c2VFdmVudENlbnRlciA6IHRydWVcbiAgICB9O1xufVxuZnVuY3Rpb24gaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpIHtcbiAgICB2YXIgX2E7XG4gICAgcmV0dXJuIF9hID0ge30sXG4gICAgICAgIF9hW3NldHRpbmdzLmNvbXBvbmVudC51aWRdID0gc2V0dGluZ3MsXG4gICAgICAgIF9hO1xufVxuLy8gZ2xvYmFsIHN0YXRlXG52YXIgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlID0ge307XG5cbi8qXG5EZXRlY3RzIHdoZW4gdGhlIHVzZXIgY2xpY2tzIG9uIGFuIGV2ZW50IHdpdGhpbiBhIERhdGVDb21wb25lbnRcbiovXG52YXIgRXZlbnRDbGlja2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRXZlbnRDbGlja2luZywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFdmVudENsaWNraW5nKHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHNldHRpbmdzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5oYW5kbGVTZWdDbGljayA9IGZ1bmN0aW9uIChldiwgc2VnRWwpIHtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnQgPSBfdGhpcy5jb21wb25lbnQ7XG4gICAgICAgICAgICB2YXIgX2EgPSBjb21wb25lbnQuY29udGV4dCwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhciwgdmlldyA9IF9hLnZpZXc7XG4gICAgICAgICAgICB2YXIgc2VnID0gZ2V0RWxTZWcoc2VnRWwpO1xuICAgICAgICAgICAgaWYgKHNlZyAmJiAvLyBtaWdodCBiZSB0aGUgPGRpdj4gc3Vycm91bmRpbmcgdGhlIG1vcmUgbGlua1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudC5pc1ZhbGlkU2VnRG93bkVsKGV2LnRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICAvLyBvdXIgd2F5IHRvIHNpbXVsYXRlIGEgbGluayBjbGljayBmb3IgZWxlbWVudHMgdGhhdCBjYW4ndCBiZSA8YT4gdGFnc1xuICAgICAgICAgICAgICAgIC8vIGdyYWIgYmVmb3JlIHRyaWdnZXIgZmlyZWQgaW4gY2FzZSB0cmlnZ2VyIHRyYXNoZXMgRE9NIHRocnUgcmVyZW5kZXJpbmdcbiAgICAgICAgICAgICAgICB2YXIgaGFzVXJsQ29udGFpbmVyID0gZWxlbWVudENsb3Nlc3QoZXYudGFyZ2V0LCAnLmZjLWhhcy11cmwnKTtcbiAgICAgICAgICAgICAgICB2YXIgdXJsID0gaGFzVXJsQ29udGFpbmVyID8gaGFzVXJsQ29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ2FbaHJlZl0nKS5ocmVmIDogJyc7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudENsaWNrJywgW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbDogc2VnRWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgaWYgKHVybCAmJiAhZXYuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjb21wb25lbnQgPSBzZXR0aW5ncy5jb21wb25lbnQ7XG4gICAgICAgIF90aGlzLmRlc3Ryb3kgPSBsaXN0ZW5CeVNlbGVjdG9yKGNvbXBvbmVudC5lbCwgJ2NsaWNrJywgY29tcG9uZW50LmZnU2VnU2VsZWN0b3IgKyAnLCcgKyBjb21wb25lbnQuYmdTZWdTZWxlY3RvciwgX3RoaXMuaGFuZGxlU2VnQ2xpY2spO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIHJldHVybiBFdmVudENsaWNraW5nO1xufShJbnRlcmFjdGlvbikpO1xuXG4vKlxuVHJpZ2dlcnMgZXZlbnRzIGFuZCBhZGRzL3JlbW92ZXMgY29yZSBjbGFzc05hbWVzIHdoZW4gdGhlIHVzZXIncyBwb2ludGVyXG5lbnRlcnMvbGVhdmVzIGV2ZW50LWVsZW1lbnRzIG9mIGEgY29tcG9uZW50LlxuKi9cbnZhciBFdmVudEhvdmVyaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhFdmVudEhvdmVyaW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEV2ZW50SG92ZXJpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIC8vIGZvciBzaW11bGF0aW5nIGFuIGV2ZW50TW91c2VMZWF2ZSB3aGVuIHRoZSBldmVudCBlbCBpcyBkZXN0cm95ZWQgd2hpbGUgbW91c2UgaXMgb3ZlciBpdFxuICAgICAgICBfdGhpcy5oYW5kbGVFdmVudEVsUmVtb3ZlID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBpZiAoZWwgPT09IF90aGlzLmN1cnJlbnRTZWdFbCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmhhbmRsZVNlZ0xlYXZlKG51bGwsIF90aGlzLmN1cnJlbnRTZWdFbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVNlZ0VudGVyID0gZnVuY3Rpb24gKGV2LCBzZWdFbCkge1xuICAgICAgICAgICAgaWYgKGdldEVsU2VnKHNlZ0VsKSkgeyAvLyBUT0RPOiBiZXR0ZXIgd2F5IHRvIG1ha2Ugc3VyZSBub3QgaG92ZXJpbmcgb3ZlciBtb3JlKyBsaW5rIG9yIGl0cyB3cmFwcGVyXG4gICAgICAgICAgICAgICAgc2VnRWwuY2xhc3NMaXN0LmFkZCgnZmMtYWxsb3ctbW91c2UtcmVzaXplJyk7XG4gICAgICAgICAgICAgICAgX3RoaXMuY3VycmVudFNlZ0VsID0gc2VnRWw7XG4gICAgICAgICAgICAgICAgX3RoaXMudHJpZ2dlckV2ZW50KCdldmVudE1vdXNlRW50ZXInLCBldiwgc2VnRWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVTZWdMZWF2ZSA9IGZ1bmN0aW9uIChldiwgc2VnRWwpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jdXJyZW50U2VnRWwpIHtcbiAgICAgICAgICAgICAgICBzZWdFbC5jbGFzc0xpc3QucmVtb3ZlKCdmYy1hbGxvdy1tb3VzZS1yZXNpemUnKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jdXJyZW50U2VnRWwgPSBudWxsO1xuICAgICAgICAgICAgICAgIF90aGlzLnRyaWdnZXJFdmVudCgnZXZlbnRNb3VzZUxlYXZlJywgZXYsIHNlZ0VsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgX3RoaXMucmVtb3ZlSG92ZXJMaXN0ZW5lcnMgPSBsaXN0ZW5Ub0hvdmVyQnlTZWxlY3Rvcihjb21wb25lbnQuZWwsIGNvbXBvbmVudC5mZ1NlZ1NlbGVjdG9yICsgJywnICsgY29tcG9uZW50LmJnU2VnU2VsZWN0b3IsIF90aGlzLmhhbmRsZVNlZ0VudGVyLCBfdGhpcy5oYW5kbGVTZWdMZWF2ZSk7XG4gICAgICAgIC8vIGhvdyB0byBtYWtlIHN1cmUgY29tcG9uZW50IGFscmVhZHkgaGFzIGNvbnRleHQ/XG4gICAgICAgIGNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyLm9uKCdldmVudEVsUmVtb3ZlJywgX3RoaXMuaGFuZGxlRXZlbnRFbFJlbW92ZSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRXZlbnRIb3ZlcmluZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVIb3Zlckxpc3RlbmVycygpO1xuICAgICAgICB0aGlzLmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyLm9mZignZXZlbnRFbFJlbW92ZScsIHRoaXMuaGFuZGxlRXZlbnRFbFJlbW92ZSk7XG4gICAgfTtcbiAgICBFdmVudEhvdmVyaW5nLnByb3RvdHlwZS50cmlnZ2VyRXZlbnQgPSBmdW5jdGlvbiAocHVibGljRXZOYW1lLCBldiwgc2VnRWwpIHtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50O1xuICAgICAgICB2YXIgX2EgPSBjb21wb25lbnQuY29udGV4dCwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhciwgdmlldyA9IF9hLnZpZXc7XG4gICAgICAgIHZhciBzZWcgPSBnZXRFbFNlZyhzZWdFbCk7XG4gICAgICAgIGlmICghZXYgfHwgY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwoZXYudGFyZ2V0KSkge1xuICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKHB1YmxpY0V2TmFtZSwgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IHNlZ0VsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEV2ZW50SG92ZXJpbmc7XG59KEludGVyYWN0aW9uKSk7XG5cbnZhciBTdGFuZGFyZFRoZW1lID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTdGFuZGFyZFRoZW1lLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN0YW5kYXJkVGhlbWUoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIFN0YW5kYXJkVGhlbWU7XG59KFRoZW1lKSk7XG5TdGFuZGFyZFRoZW1lLnByb3RvdHlwZS5jbGFzc2VzID0ge1xuICAgIHdpZGdldDogJ2ZjLXVudGhlbWVkJyxcbiAgICB3aWRnZXRIZWFkZXI6ICdmYy13aWRnZXQtaGVhZGVyJyxcbiAgICB3aWRnZXRDb250ZW50OiAnZmMtd2lkZ2V0LWNvbnRlbnQnLFxuICAgIGJ1dHRvbkdyb3VwOiAnZmMtYnV0dG9uLWdyb3VwJyxcbiAgICBidXR0b246ICdmYy1idXR0b24gZmMtYnV0dG9uLXByaW1hcnknLFxuICAgIGJ1dHRvbkFjdGl2ZTogJ2ZjLWJ1dHRvbi1hY3RpdmUnLFxuICAgIHBvcG92ZXJIZWFkZXI6ICdmYy13aWRnZXQtaGVhZGVyJyxcbiAgICBwb3BvdmVyQ29udGVudDogJ2ZjLXdpZGdldC1jb250ZW50JyxcbiAgICAvLyBkYXkgZ3JpZFxuICAgIGhlYWRlclJvdzogJ2ZjLXdpZGdldC1oZWFkZXInLFxuICAgIGRheVJvdzogJ2ZjLXdpZGdldC1jb250ZW50JyxcbiAgICAvLyBsaXN0IHZpZXdcbiAgICBsaXN0VmlldzogJ2ZjLXdpZGdldC1jb250ZW50J1xufTtcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmJhc2VJY29uQ2xhc3MgPSAnZmMtaWNvbic7XG5TdGFuZGFyZFRoZW1lLnByb3RvdHlwZS5pY29uQ2xhc3NlcyA9IHtcbiAgICBjbG9zZTogJ2ZjLWljb24teCcsXG4gICAgcHJldjogJ2ZjLWljb24tY2hldnJvbi1sZWZ0JyxcbiAgICBuZXh0OiAnZmMtaWNvbi1jaGV2cm9uLXJpZ2h0JyxcbiAgICBwcmV2WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtbGVmdCcsXG4gICAgbmV4dFllYXI6ICdmYy1pY29uLWNoZXZyb25zLXJpZ2h0J1xufTtcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25PdmVycmlkZU9wdGlvbiA9ICdidXR0b25JY29ucyc7XG5TdGFuZGFyZFRoZW1lLnByb3RvdHlwZS5pY29uT3ZlcnJpZGVDdXN0b21CdXR0b25PcHRpb24gPSAnaWNvbic7XG5TdGFuZGFyZFRoZW1lLnByb3RvdHlwZS5pY29uT3ZlcnJpZGVQcmVmaXggPSAnZmMtaWNvbi0nO1xuXG52YXIgQ2FsZW5kYXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ2FsZW5kYXIoZWwsIG92ZXJyaWRlcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmJ1aWxkQ29tcG9uZW50Q29udGV4dCA9IG1lbW9pemUoYnVpbGRDb21wb25lbnRDb250ZXh0JDEpO1xuICAgICAgICB0aGlzLnBhcnNlUmF3TG9jYWxlcyA9IG1lbW9pemUocGFyc2VSYXdMb2NhbGVzKTtcbiAgICAgICAgdGhpcy5idWlsZExvY2FsZSA9IG1lbW9pemUoYnVpbGRMb2NhbGUpO1xuICAgICAgICB0aGlzLmJ1aWxkRGF0ZUVudiA9IG1lbW9pemUoYnVpbGREYXRlRW52KTtcbiAgICAgICAgdGhpcy5idWlsZFRoZW1lID0gbWVtb2l6ZShidWlsZFRoZW1lKTtcbiAgICAgICAgdGhpcy5idWlsZEV2ZW50VWlTaW5nbGVCYXNlID0gbWVtb2l6ZSh0aGlzLl9idWlsZEV2ZW50VWlTaW5nbGVCYXNlKTtcbiAgICAgICAgdGhpcy5idWlsZFNlbGVjdGlvbkNvbmZpZyA9IG1lbW9pemUodGhpcy5fYnVpbGRTZWxlY3Rpb25Db25maWcpO1xuICAgICAgICB0aGlzLmJ1aWxkRXZlbnRVaUJ5U291cmNlID0gbWVtb2l6ZU91dHB1dChidWlsZEV2ZW50VWlCeVNvdXJjZSwgaXNQcm9wc0VxdWFsKTtcbiAgICAgICAgdGhpcy5idWlsZEV2ZW50VWlCYXNlcyA9IG1lbW9pemUoYnVpbGRFdmVudFVpQmFzZXMpO1xuICAgICAgICB0aGlzLmludGVyYWN0aW9uc1N0b3JlID0ge307XG4gICAgICAgIHRoaXMuYWN0aW9uUXVldWUgPSBbXTtcbiAgICAgICAgdGhpcy5pc1JlZHVjaW5nID0gZmFsc2U7XG4gICAgICAgIC8vIGlzRGlzcGxheWluZzogYm9vbGVhbiA9IGZhbHNlIC8vIGluc3RhbGxlZCBpbiBET00/IGFjY2VwdGluZyByZW5kZXJzP1xuICAgICAgICB0aGlzLm5lZWRzUmVyZW5kZXIgPSBmYWxzZTsgLy8gbmVlZHMgYSByZW5kZXI/XG4gICAgICAgIHRoaXMuaXNSZW5kZXJpbmcgPSBmYWxzZTsgLy8gY3VycmVudGx5IGluIHRoZSBleGVjdXRlUmVuZGVyIGZ1bmN0aW9uP1xuICAgICAgICB0aGlzLnJlbmRlcmluZ1BhdXNlRGVwdGggPSAwO1xuICAgICAgICB0aGlzLmJ1aWxkRGVsYXllZFJlcmVuZGVyID0gbWVtb2l6ZShidWlsZERlbGF5ZWRSZXJlbmRlcik7XG4gICAgICAgIHRoaXMuYWZ0ZXJTaXppbmdUcmlnZ2VycyA9IHt9O1xuICAgICAgICB0aGlzLmlzVmlld1VwZGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0RhdGVzVXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzRXZlbnRzVXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgICAgIHRoaXMub3B0aW9uc01hbmFnZXIgPSBuZXcgT3B0aW9uc01hbmFnZXIob3ZlcnJpZGVzIHx8IHt9KTtcbiAgICAgICAgdGhpcy5wbHVnaW5TeXN0ZW0gPSBuZXcgUGx1Z2luU3lzdGVtKCk7XG4gICAgICAgIC8vIG9ubHkgZG8gb25jZS4gZG9uJ3QgZG8gaW4gaGFuZGxlT3B0aW9ucy4gYmVjYXVzZSBjYW4ndCByZW1vdmUgcGx1Z2luc1xuICAgICAgICB0aGlzLmFkZFBsdWdpbklucHV0cyh0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkLnBsdWdpbnMgfHwgW10pO1xuICAgICAgICB0aGlzLmhhbmRsZU9wdGlvbnModGhpcy5vcHRpb25zTWFuYWdlci5jb21wdXRlZCk7XG4gICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCdfaW5pdCcpOyAvLyBmb3IgdGVzdHNcbiAgICAgICAgdGhpcy5oeWRyYXRlKCk7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJJbnRlcmFjdGlvbnMgPSB0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5jYWxlbmRhckludGVyYWN0aW9uc1xuICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAoY2FsZW5kYXJJbnRlcmFjdGlvbkNsYXNzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IGNhbGVuZGFySW50ZXJhY3Rpb25DbGFzcyhfdGhpcyk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYWRkUGx1Z2luSW5wdXRzID0gZnVuY3Rpb24gKHBsdWdpbklucHV0cykge1xuICAgICAgICB2YXIgcGx1Z2luRGVmcyA9IHJlZmluZVBsdWdpbkRlZnMocGx1Z2luSW5wdXRzKTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBwbHVnaW5EZWZzXzEgPSBwbHVnaW5EZWZzOyBfaSA8IHBsdWdpbkRlZnNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBwbHVnaW5EZWYgPSBwbHVnaW5EZWZzXzFbX2ldO1xuICAgICAgICAgICAgdGhpcy5wbHVnaW5TeXN0ZW0uYWRkKHBsdWdpbkRlZik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDYWxlbmRhci5wcm90b3R5cGUsIFwidmlld1wiLCB7XG4gICAgICAgIC8vIHB1YmxpYyBBUElcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wb25lbnQgPyB0aGlzLmNvbXBvbmVudC52aWV3IDogbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgLy8gUHVibGljIEFQSSBmb3IgcmVuZGVyaW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuY29tcG9uZW50KSB7XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IG5ldyBDYWxlbmRhckNvbXBvbmVudCh0aGlzLmVsKTtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyYWJsZUV2ZW50U3RvcmUgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgIHRoaXMuYmluZEhhbmRsZXJzKCk7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGVSZW5kZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdFJlcmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5jb21wb25lbnQpIHtcbiAgICAgICAgICAgIHRoaXMudW5iaW5kSGFuZGxlcnMoKTtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LmRlc3Ryb3koKTsgLy8gZG9uJ3QgbnVsbC1vdXQuIGluIGNhc2UgQVBJIG5lZWRzIGFjY2Vzc1xuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSBudWxsOyAvLyB1bW0gPz8/XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5jYWxlbmRhckludGVyYWN0aW9uczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgaW50ZXJhY3Rpb24gPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24uZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ19kZXN0cm95ZWQnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gSGFuZGxlcnNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5iaW5kSGFuZGxlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIGV2ZW50IGRlbGVnYXRpb24gZm9yIG5hdiBsaW5rc1xuICAgICAgICB0aGlzLnJlbW92ZU5hdkxpbmtMaXN0ZW5lciA9IGxpc3RlbkJ5U2VsZWN0b3IodGhpcy5lbCwgJ2NsaWNrJywgJ2FbZGF0YS1nb3RvXScsIGZ1bmN0aW9uIChldiwgYW5jaG9yRWwpIHtcbiAgICAgICAgICAgIHZhciBnb3RvT3B0aW9ucyA9IGFuY2hvckVsLmdldEF0dHJpYnV0ZSgnZGF0YS1nb3RvJyk7XG4gICAgICAgICAgICBnb3RvT3B0aW9ucyA9IGdvdG9PcHRpb25zID8gSlNPTi5wYXJzZShnb3RvT3B0aW9ucykgOiB7fTtcbiAgICAgICAgICAgIHZhciBkYXRlRW52ID0gX3RoaXMuZGF0ZUVudjtcbiAgICAgICAgICAgIHZhciBkYXRlTWFya2VyID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoZ290b09wdGlvbnMuZGF0ZSk7XG4gICAgICAgICAgICB2YXIgdmlld1R5cGUgPSBnb3RvT3B0aW9ucy50eXBlO1xuICAgICAgICAgICAgLy8gcHJvcGVydHkgbGlrZSBcIm5hdkxpbmtEYXlDbGlja1wiLiBtaWdodCBiZSBhIHN0cmluZyBvciBhIGZ1bmN0aW9uXG4gICAgICAgICAgICB2YXIgY3VzdG9tQWN0aW9uID0gX3RoaXMudmlld09wdCgnbmF2TGluaycgKyBjYXBpdGFsaXNlRmlyc3RMZXR0ZXIodmlld1R5cGUpICsgJ0NsaWNrJyk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGN1c3RvbUFjdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGN1c3RvbUFjdGlvbihkYXRlRW52LnRvRGF0ZShkYXRlTWFya2VyKSwgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjdXN0b21BY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZXdUeXBlID0gY3VzdG9tQWN0aW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy56b29tVG8oZGF0ZU1hcmtlciwgdmlld1R5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRoaXMub3B0KCdoYW5kbGVXaW5kb3dSZXNpemUnKSkge1xuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMud2luZG93UmVzaXplUHJveHkgPSBkZWJvdW5jZSgvLyBwcmV2ZW50cyByYXBpZCBjYWxsc1xuICAgICAgICAgICAgdGhpcy53aW5kb3dSZXNpemUuYmluZCh0aGlzKSwgdGhpcy5vcHQoJ3dpbmRvd1Jlc2l6ZURlbGF5JykpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnVuYmluZEhhbmRsZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlbW92ZU5hdkxpbmtMaXN0ZW5lcigpO1xuICAgICAgICBpZiAodGhpcy53aW5kb3dSZXNpemVQcm94eSkge1xuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMud2luZG93UmVzaXplUHJveHkpO1xuICAgICAgICAgICAgdGhpcy53aW5kb3dSZXNpemVQcm94eSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIERpc3BhdGNoZXJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5oeWRyYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnN0YXRlID0gdGhpcy5idWlsZEluaXRpYWxTdGF0ZSgpO1xuICAgICAgICB2YXIgcmF3U291cmNlcyA9IHRoaXMub3B0KCdldmVudFNvdXJjZXMnKSB8fCBbXTtcbiAgICAgICAgdmFyIHNpbmdsZVJhd1NvdXJjZSA9IHRoaXMub3B0KCdldmVudHMnKTtcbiAgICAgICAgdmFyIHNvdXJjZXMgPSBbXTsgLy8gcGFyc2VkXG4gICAgICAgIGlmIChzaW5nbGVSYXdTb3VyY2UpIHtcbiAgICAgICAgICAgIHJhd1NvdXJjZXMudW5zaGlmdChzaW5nbGVSYXdTb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgcmF3U291cmNlc18xID0gcmF3U291cmNlczsgX2kgPCByYXdTb3VyY2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcmF3U291cmNlID0gcmF3U291cmNlc18xW19pXTtcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSBwYXJzZUV2ZW50U291cmNlKHJhd1NvdXJjZSwgdGhpcyk7XG4gICAgICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5iYXRjaFJlbmRlcmluZyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdJTklUJyB9KTsgLy8gcGFzcyBpbiBzb3VyY2VzIGhlcmU/XG4gICAgICAgICAgICBfdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdBRERfRVZFTlRfU09VUkNFUycsIHNvdXJjZXM6IHNvdXJjZXMgfSk7XG4gICAgICAgICAgICBfdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9WSUVXX1RZUEUnLFxuICAgICAgICAgICAgICAgIHZpZXdUeXBlOiBfdGhpcy5vcHQoJ2RlZmF1bHRWaWV3JykgfHwgX3RoaXMucGx1Z2luU3lzdGVtLmhvb2tzLmRlZmF1bHRWaWV3XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYnVpbGRJbml0aWFsU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2aWV3VHlwZTogbnVsbCxcbiAgICAgICAgICAgIGxvYWRpbmdMZXZlbDogMCxcbiAgICAgICAgICAgIGV2ZW50U291cmNlTG9hZGluZ0xldmVsOiAwLFxuICAgICAgICAgICAgY3VycmVudERhdGU6IHRoaXMuZ2V0SW5pdGlhbERhdGUoKSxcbiAgICAgICAgICAgIGRhdGVQcm9maWxlOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRTb3VyY2VzOiB7fSxcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvbjogbnVsbCxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiAnJyxcbiAgICAgICAgICAgIGV2ZW50RHJhZzogbnVsbCxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplOiBudWxsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZGlzcGF0Y2ggPSBmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgIHRoaXMuYWN0aW9uUXVldWUucHVzaChhY3Rpb24pO1xuICAgICAgICBpZiAoIXRoaXMuaXNSZWR1Y2luZykge1xuICAgICAgICAgICAgdGhpcy5pc1JlZHVjaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBvbGRTdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5hY3Rpb25RdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gdGhpcy5yZWR1Y2UodGhpcy5zdGF0ZSwgdGhpcy5hY3Rpb25RdWV1ZS5zaGlmdCgpLCB0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBuZXdTdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgICAgICAgICB0aGlzLmlzUmVkdWNpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICghb2xkU3RhdGUubG9hZGluZ0xldmVsICYmIG5ld1N0YXRlLmxvYWRpbmdMZXZlbCkge1xuICAgICAgICAgICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCdsb2FkaW5nJywgW3RydWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG9sZFN0YXRlLmxvYWRpbmdMZXZlbCAmJiAhbmV3U3RhdGUubG9hZGluZ0xldmVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ2xvYWRpbmcnLCBbZmFsc2VdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB2aWV3ID0gdGhpcy5jb21wb25lbnQgJiYgdGhpcy5jb21wb25lbnQudmlldztcbiAgICAgICAgICAgIGlmIChvbGRTdGF0ZS5ldmVudFN0b3JlICE9PSBuZXdTdGF0ZS5ldmVudFN0b3JlKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFN0YXRlLmV2ZW50U3RvcmUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0V2ZW50c1VwZGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvbGRTdGF0ZS5kYXRlUHJvZmlsZSAhPT0gbmV3U3RhdGUuZGF0ZVByb2ZpbGUpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkU3RhdGUuZGF0ZVByb2ZpbGUgJiYgdmlldykgeyAvLyB3aHkgd291bGQgdmlldyBiZSBudWxsIT9cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ2RhdGVzRGVzdHJveScsIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsOiB2aWV3LmVsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmlzRGF0ZXNVcGRhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvbGRTdGF0ZS52aWV3VHlwZSAhPT0gbmV3U3RhdGUudmlld1R5cGUpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkU3RhdGUudmlld1R5cGUgJiYgdmlldykgeyAvLyB3aHkgd291bGQgdmlldyBiZSBudWxsIT9cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ3ZpZXdTa2VsZXRvbkRlc3Ryb3knLCBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlldzogdmlldyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbDogdmlldy5lbFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5pc1ZpZXdVcGRhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVxdWVzdFJlcmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWR1Y2UgPSBmdW5jdGlvbiAoc3RhdGUsIGFjdGlvbiwgY2FsZW5kYXIpIHtcbiAgICAgICAgcmV0dXJuIHJlZHVjZShzdGF0ZSwgYWN0aW9uLCBjYWxlbmRhcik7XG4gICAgfTtcbiAgICAvLyBSZW5kZXIgUXVldWVcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZXF1ZXN0UmVyZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMubmVlZHNSZXJlbmRlciA9IHRydWU7XG4gICAgICAgIHRoaXMuZGVsYXllZFJlcmVuZGVyKCk7IC8vIHdpbGwgY2FsbCBhIGRlYm91bmNlZC12ZXJzaW9uIG9mIHRyeVJlcmVuZGVyXG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudHJ5UmVyZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiAvLyBtdXN0IGJlIGFjY2VwdGluZyByZW5kZXJzXG4gICAgICAgICAgICB0aGlzLm5lZWRzUmVyZW5kZXIgJiYgLy8gaW5kaWNhdGVzIHRoYXQgYSByZXJlbmRlciB3YXMgcmVxdWVzdGVkXG4gICAgICAgICAgICAhdGhpcy5yZW5kZXJpbmdQYXVzZURlcHRoICYmIC8vIG5vdCBwYXVzZWRcbiAgICAgICAgICAgICF0aGlzLmlzUmVuZGVyaW5nIC8vIG5vdCBjdXJyZW50bHkgaW4gdGhlIHJlbmRlciBsb29wXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5leGVjdXRlUmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5iYXRjaFJlbmRlcmluZyA9IGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgIHRoaXMucmVuZGVyaW5nUGF1c2VEZXB0aCsrO1xuICAgICAgICBmdW5jKCk7XG4gICAgICAgIHRoaXMucmVuZGVyaW5nUGF1c2VEZXB0aC0tO1xuICAgICAgICBpZiAodGhpcy5uZWVkc1JlcmVuZGVyKSB7XG4gICAgICAgICAgICB0aGlzLnJlcXVlc3RSZXJlbmRlcigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBSZW5kZXJpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5leGVjdXRlUmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBjbGVhciB0aGVzZSBCRUZPUkUgdGhlIHJlbmRlciBzbyB0aGF0IG5ldyB2YWx1ZXMgd2lsbCBhY2N1bXVsYXRlIGR1cmluZyByZW5kZXJcbiAgICAgICAgdGhpcy5uZWVkc1JlcmVuZGVyID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNSZW5kZXJpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLnJlbmRlckNvbXBvbmVudCgpO1xuICAgICAgICB0aGlzLmlzUmVuZGVyaW5nID0gZmFsc2U7XG4gICAgICAgIC8vIHJlY2VpdmVkIGEgcmVyZW5kZXIgcmVxdWVzdCB3aGlsZSByZW5kZXJpbmdcbiAgICAgICAgaWYgKHRoaXMubmVlZHNSZXJlbmRlcikge1xuICAgICAgICAgICAgdGhpcy5kZWxheWVkUmVyZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLypcbiAgICBkb24ndCBjYWxsIHRoaXMgZGlyZWN0bHkuIHVzZSBleGVjdXRlUmVuZGVyIGluc3RlYWRcbiAgICAqL1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZW5kZXJDb21wb25lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMsIHN0YXRlID0gX2Euc3RhdGUsIGNvbXBvbmVudCA9IF9hLmNvbXBvbmVudDtcbiAgICAgICAgdmFyIHZpZXdUeXBlID0gc3RhdGUudmlld1R5cGU7XG4gICAgICAgIHZhciB2aWV3U3BlYyA9IHRoaXMudmlld1NwZWNzW3ZpZXdUeXBlXTtcbiAgICAgICAgaWYgKCF2aWV3U3BlYykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVmlldyB0eXBlIFxcXCJcIiArIHZpZXdUeXBlICsgXCJcXFwiIGlzIG5vdCB2YWxpZFwiKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBldmVudCBzb3VyY2VzIGFyZSBzdGlsbCBsb2FkaW5nIGFuZCBwcm9ncmVzc2l2ZSByZW5kZXJpbmcgaGFzbid0IGJlZW4gZW5hYmxlZCxcbiAgICAgICAgLy8ga2VlcCByZW5kZXJpbmcgdGhlIGxhc3QgZnVsbHkgbG9hZGVkIHNldCBvZiBldmVudHNcbiAgICAgICAgdmFyIHJlbmRlcmFibGVFdmVudFN0b3JlID0gdGhpcy5yZW5kZXJhYmxlRXZlbnRTdG9yZSA9XG4gICAgICAgICAgICAoc3RhdGUuZXZlbnRTb3VyY2VMb2FkaW5nTGV2ZWwgJiYgIXRoaXMub3B0KCdwcm9ncmVzc2l2ZUV2ZW50UmVuZGVyaW5nJykpID9cbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmFibGVFdmVudFN0b3JlIDpcbiAgICAgICAgICAgICAgICBzdGF0ZS5ldmVudFN0b3JlO1xuICAgICAgICB2YXIgZXZlbnRVaVNpbmdsZUJhc2UgPSB0aGlzLmJ1aWxkRXZlbnRVaVNpbmdsZUJhc2Uodmlld1NwZWMub3B0aW9ucyk7XG4gICAgICAgIHZhciBldmVudFVpQnlTb3VyY2UgPSB0aGlzLmJ1aWxkRXZlbnRVaUJ5U291cmNlKHN0YXRlLmV2ZW50U291cmNlcyk7XG4gICAgICAgIHZhciBldmVudFVpQmFzZXMgPSB0aGlzLmV2ZW50VWlCYXNlcyA9IHRoaXMuYnVpbGRFdmVudFVpQmFzZXMocmVuZGVyYWJsZUV2ZW50U3RvcmUuZGVmcywgZXZlbnRVaVNpbmdsZUJhc2UsIGV2ZW50VWlCeVNvdXJjZSk7XG4gICAgICAgIGNvbXBvbmVudC5yZWNlaXZlUHJvcHMoX19hc3NpZ24oe30sIHN0YXRlLCB7IHZpZXdTcGVjOiB2aWV3U3BlYywgZGF0ZVByb2ZpbGVHZW5lcmF0b3I6IHRoaXMuZGF0ZVByb2ZpbGVHZW5lcmF0b3JzW3ZpZXdUeXBlXSwgZGF0ZVByb2ZpbGU6IHN0YXRlLmRhdGVQcm9maWxlLCBldmVudFN0b3JlOiByZW5kZXJhYmxlRXZlbnRTdG9yZSwgZXZlbnRVaUJhc2VzOiBldmVudFVpQmFzZXMsIGRhdGVTZWxlY3Rpb246IHN0YXRlLmRhdGVTZWxlY3Rpb24sIGV2ZW50U2VsZWN0aW9uOiBzdGF0ZS5ldmVudFNlbGVjdGlvbiwgZXZlbnREcmFnOiBzdGF0ZS5ldmVudERyYWcsIGV2ZW50UmVzaXplOiBzdGF0ZS5ldmVudFJlc2l6ZSB9KSwgdGhpcy5idWlsZENvbXBvbmVudENvbnRleHQodGhpcy50aGVtZSwgdGhpcy5kYXRlRW52LCB0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkKSk7XG4gICAgICAgIGlmICh0aGlzLmlzVmlld1VwZGF0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaXNWaWV3VXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ3ZpZXdTa2VsZXRvblJlbmRlcicsIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IGNvbXBvbmVudC52aWV3LFxuICAgICAgICAgICAgICAgICAgICBlbDogY29tcG9uZW50LnZpZXcuZWxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0RhdGVzVXBkYXRlZCkge1xuICAgICAgICAgICAgdGhpcy5pc0RhdGVzVXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ2RhdGVzUmVuZGVyJywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmlldzogY29tcG9uZW50LnZpZXcsXG4gICAgICAgICAgICAgICAgICAgIGVsOiBjb21wb25lbnQudmlldy5lbFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzRXZlbnRzVXBkYXRlZCkge1xuICAgICAgICAgICAgdGhpcy5pc0V2ZW50c1VwZGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbGVhc2VBZnRlclNpemluZ1RyaWdnZXJzKCk7XG4gICAgfTtcbiAgICAvLyBPcHRpb25zXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuc2V0T3B0aW9uID0gZnVuY3Rpb24gKG5hbWUsIHZhbCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHRoaXMubXV0YXRlT3B0aW9ucygoX2EgPSB7fSwgX2FbbmFtZV0gPSB2YWwsIF9hKSwgW10sIHRydWUpO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldE9wdGlvbiA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkW25hbWVdO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLm9wdCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkW25hbWVdO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnZpZXdPcHQgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3T3B0cygpW25hbWVdO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnZpZXdPcHRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3U3BlY3NbdGhpcy5zdGF0ZS52aWV3VHlwZV0ub3B0aW9ucztcbiAgICB9O1xuICAgIC8qXG4gICAgaGFuZGxlcyBvcHRpb24gY2hhbmdlcyAobGlrZSBhIGRpZmYpXG4gICAgKi9cbiAgICBDYWxlbmRhci5wcm90b3R5cGUubXV0YXRlT3B0aW9ucyA9IGZ1bmN0aW9uICh1cGRhdGVzLCByZW1vdmFscywgaXNEeW5hbWljLCBkZWVwRXF1YWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNoYW5nZUhhbmRsZXJzID0gdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3Mub3B0aW9uQ2hhbmdlSGFuZGxlcnM7XG4gICAgICAgIHZhciBub3JtYWxVcGRhdGVzID0ge307XG4gICAgICAgIHZhciBzcGVjaWFsVXBkYXRlcyA9IHt9O1xuICAgICAgICB2YXIgb2xkRGF0ZUVudiA9IHRoaXMuZGF0ZUVudjsgLy8gZG8gdGhpcyBiZWZvcmUgaGFuZGxlT3B0aW9uc1xuICAgICAgICB2YXIgaXNUaW1lWm9uZURpcnR5ID0gZmFsc2U7XG4gICAgICAgIHZhciBpc1NpemVEaXJ0eSA9IGZhbHNlO1xuICAgICAgICB2YXIgYW55RGlmZmljdWx0T3B0aW9ucyA9IEJvb2xlYW4ocmVtb3ZhbHMubGVuZ3RoKTtcbiAgICAgICAgZm9yICh2YXIgbmFtZV8xIGluIHVwZGF0ZXMpIHtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VIYW5kbGVyc1tuYW1lXzFdKSB7XG4gICAgICAgICAgICAgICAgc3BlY2lhbFVwZGF0ZXNbbmFtZV8xXSA9IHVwZGF0ZXNbbmFtZV8xXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vcm1hbFVwZGF0ZXNbbmFtZV8xXSA9IHVwZGF0ZXNbbmFtZV8xXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBuYW1lXzIgaW4gbm9ybWFsVXBkYXRlcykge1xuICAgICAgICAgICAgaWYgKC9eKGhlaWdodHxjb250ZW50SGVpZ2h0fGFzcGVjdFJhdGlvKSQvLnRlc3QobmFtZV8yKSkge1xuICAgICAgICAgICAgICAgIGlzU2l6ZURpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKC9eKGRlZmF1bHREYXRlfGRlZmF1bHRWaWV3KSQvLnRlc3QobmFtZV8yKSkgO1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYW55RGlmZmljdWx0T3B0aW9ucyA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKG5hbWVfMiA9PT0gJ3RpbWVab25lJykge1xuICAgICAgICAgICAgICAgICAgICBpc1RpbWVab25lRGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wdGlvbnNNYW5hZ2VyLm11dGF0ZShub3JtYWxVcGRhdGVzLCByZW1vdmFscywgaXNEeW5hbWljKTtcbiAgICAgICAgaWYgKGFueURpZmZpY3VsdE9wdGlvbnMpIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlT3B0aW9ucyh0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJhdGNoUmVuZGVyaW5nKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChhbnlEaWZmaWN1bHRPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVGltZVpvbmVEaXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnQ0hBTkdFX1RJTUVaT05FJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGVFbnY6IG9sZERhdGVFbnZcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8qIEhBQ0tcbiAgICAgICAgICAgICAgICBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGNhbGxpbmcgdGhpcy5yZXF1ZXN0UmVyZW5kZXIoKVxuICAgICAgICAgICAgICAgIGJ1dCByZWNvbXB1dGVzIHRoZSBzdGF0ZSdzIGRhdGVQcm9maWxlXG4gICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBfdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdTRVRfVklFV19UWVBFJyxcbiAgICAgICAgICAgICAgICAgICAgdmlld1R5cGU6IF90aGlzLnN0YXRlLnZpZXdUeXBlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpc1NpemVEaXJ0eSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZVNpemUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHNwZWNpYWwgdXBkYXRlc1xuICAgICAgICAgICAgaWYgKGRlZXBFcXVhbCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIG5hbWVfMyBpbiBzcGVjaWFsVXBkYXRlcykge1xuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VIYW5kbGVyc1tuYW1lXzNdKHNwZWNpYWxVcGRhdGVzW25hbWVfM10sIF90aGlzLCBkZWVwRXF1YWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvKlxuICAgIHJlYnVpbGRzIHRoaW5ncyBiYXNlZCBvZmYgb2YgYSBjb21wbGV0ZSBzZXQgb2YgcmVmaW5lZCBvcHRpb25zXG4gICAgKi9cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuaGFuZGxlT3B0aW9ucyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwbHVnaW5Ib29rcyA9IHRoaXMucGx1Z2luU3lzdGVtLmhvb2tzO1xuICAgICAgICB0aGlzLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24ob3B0aW9ucy5kZWZhdWx0QWxsRGF5RXZlbnREdXJhdGlvbik7XG4gICAgICAgIHRoaXMuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKG9wdGlvbnMuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbik7XG4gICAgICAgIHRoaXMuZGVsYXllZFJlcmVuZGVyID0gdGhpcy5idWlsZERlbGF5ZWRSZXJlbmRlcihvcHRpb25zLnJlcmVuZGVyRGVsYXkpO1xuICAgICAgICB0aGlzLnRoZW1lID0gdGhpcy5idWlsZFRoZW1lKG9wdGlvbnMpO1xuICAgICAgICB2YXIgYXZhaWxhYmxlID0gdGhpcy5wYXJzZVJhd0xvY2FsZXMob3B0aW9ucy5sb2NhbGVzKTtcbiAgICAgICAgdGhpcy5hdmFpbGFibGVSYXdMb2NhbGVzID0gYXZhaWxhYmxlLm1hcDtcbiAgICAgICAgdmFyIGxvY2FsZSA9IHRoaXMuYnVpbGRMb2NhbGUob3B0aW9ucy5sb2NhbGUgfHwgYXZhaWxhYmxlLmRlZmF1bHRDb2RlLCBhdmFpbGFibGUubWFwKTtcbiAgICAgICAgdGhpcy5kYXRlRW52ID0gdGhpcy5idWlsZERhdGVFbnYobG9jYWxlLCBvcHRpb25zLnRpbWVab25lLCBwbHVnaW5Ib29rcy5uYW1lZFRpbWVab25lZEltcGwsIG9wdGlvbnMuZmlyc3REYXksIG9wdGlvbnMud2Vla051bWJlckNhbGN1bGF0aW9uLCBvcHRpb25zLndlZWtMYWJlbCwgcGx1Z2luSG9va3MuY21kRm9ybWF0dGVyKTtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25Db25maWcgPSB0aGlzLmJ1aWxkU2VsZWN0aW9uQ29uZmlnKG9wdGlvbnMpOyAvLyBuZWVkcyBkYXRlRW52LiBkbyBhZnRlciA6KFxuICAgICAgICAvLyBpbmVmZmVjaWVudCB0byBkbyBldmVyeSB0aW1lP1xuICAgICAgICB0aGlzLnZpZXdTcGVjcyA9IGJ1aWxkVmlld1NwZWNzKHBsdWdpbkhvb2tzLnZpZXdzLCB0aGlzLm9wdGlvbnNNYW5hZ2VyKTtcbiAgICAgICAgLy8gaW5lZmZlY2llbnQgdG8gZG8gZXZlcnkgdGltZT9cbiAgICAgICAgdGhpcy5kYXRlUHJvZmlsZUdlbmVyYXRvcnMgPSBtYXBIYXNoKHRoaXMudmlld1NwZWNzLCBmdW5jdGlvbiAodmlld1NwZWMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgdmlld1NwZWMuY2xhc3MucHJvdG90eXBlLmRhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3Modmlld1NwZWMsIF90aGlzKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0QXZhaWxhYmxlTG9jYWxlQ29kZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLmF2YWlsYWJsZVJhd0xvY2FsZXMpO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLl9idWlsZFNlbGVjdGlvbkNvbmZpZyA9IGZ1bmN0aW9uIChyYXdPcHRzKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzU2NvcGVkVWlQcm9wcygnc2VsZWN0JywgcmF3T3B0cywgdGhpcyk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuX2J1aWxkRXZlbnRVaVNpbmdsZUJhc2UgPSBmdW5jdGlvbiAocmF3T3B0cykge1xuICAgICAgICBpZiAocmF3T3B0cy5lZGl0YWJsZSkgeyAvLyBzbyAnZWRpdGFibGUnIGFmZmVjdGVkIGV2ZW50c1xuICAgICAgICAgICAgcmF3T3B0cyA9IF9fYXNzaWduKHt9LCByYXdPcHRzLCB7IGV2ZW50RWRpdGFibGU6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHByb2Nlc3NTY29wZWRVaVByb3BzKCdldmVudCcsIHJhd09wdHMsIHRoaXMpO1xuICAgIH07XG4gICAgLy8gVHJpZ2dlclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmhhc1B1YmxpY0hhbmRsZXJzID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzSGFuZGxlcnMobmFtZSkgfHxcbiAgICAgICAgICAgIHRoaXMub3B0KG5hbWUpOyAvLyBoYW5kbGVyIHNwZWNpZmllZCBpbiBvcHRpb25zXG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucHVibGljbHlUcmlnZ2VyID0gZnVuY3Rpb24gKG5hbWUsIGFyZ3MpIHtcbiAgICAgICAgdmFyIG9wdEhhbmRsZXIgPSB0aGlzLm9wdChuYW1lKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyV2l0aChuYW1lLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgaWYgKG9wdEhhbmRsZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHRIYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucHVibGljbHlUcmlnZ2VyQWZ0ZXJTaXppbmcgPSBmdW5jdGlvbiAobmFtZSwgYXJncykge1xuICAgICAgICB2YXIgYWZ0ZXJTaXppbmdUcmlnZ2VycyA9IHRoaXMuYWZ0ZXJTaXppbmdUcmlnZ2VycztcbiAgICAgICAgKGFmdGVyU2l6aW5nVHJpZ2dlcnNbbmFtZV0gfHwgKGFmdGVyU2l6aW5nVHJpZ2dlcnNbbmFtZV0gPSBbXSkpLnB1c2goYXJncyk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVsZWFzZUFmdGVyU2l6aW5nVHJpZ2dlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhZnRlclNpemluZ1RyaWdnZXJzID0gdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzO1xuICAgICAgICBmb3IgKHZhciBuYW1lXzQgaW4gYWZ0ZXJTaXppbmdUcmlnZ2Vycykge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGFmdGVyU2l6aW5nVHJpZ2dlcnNbbmFtZV80XTsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcihuYW1lXzQsIGFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWZ0ZXJTaXppbmdUcmlnZ2VycyA9IHt9O1xuICAgIH07XG4gICAgLy8gVmlld1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gUmV0dXJucyBhIGJvb2xlYW4gYWJvdXQgd2hldGhlciB0aGUgdmlldyBpcyBva2F5IHRvIGluc3RhbnRpYXRlIGF0IHNvbWUgcG9pbnRcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuaXNWYWxpZFZpZXdUeXBlID0gZnVuY3Rpb24gKHZpZXdUeXBlKSB7XG4gICAgICAgIHJldHVybiBCb29sZWFuKHRoaXMudmlld1NwZWNzW3ZpZXdUeXBlXSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuY2hhbmdlVmlldyA9IGZ1bmN0aW9uICh2aWV3VHlwZSwgZGF0ZU9yUmFuZ2UpIHtcbiAgICAgICAgdmFyIGRhdGVNYXJrZXIgPSBudWxsO1xuICAgICAgICBpZiAoZGF0ZU9yUmFuZ2UpIHtcbiAgICAgICAgICAgIGlmIChkYXRlT3JSYW5nZS5zdGFydCAmJiBkYXRlT3JSYW5nZS5lbmQpIHsgLy8gYSByYW5nZVxuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9uc01hbmFnZXIubXV0YXRlKHsgdmlzaWJsZVJhbmdlOiBkYXRlT3JSYW5nZSB9LCBbXSk7IC8vIHdpbGwgbm90IHJlcmVuZGVyXG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVPcHRpb25zKHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQpOyAvLyAuLi5idXQgeXVja1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7IC8vIGEgZGF0ZVxuICAgICAgICAgICAgICAgIGRhdGVNYXJrZXIgPSB0aGlzLmRhdGVFbnYuY3JlYXRlTWFya2VyKGRhdGVPclJhbmdlKTsgLy8ganVzdCBsaWtlIGdvdG9EYXRlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdTRVRfVklFV19UWVBFJyxcbiAgICAgICAgICAgIHZpZXdUeXBlOiB2aWV3VHlwZSxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IGRhdGVNYXJrZXJcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBGb3JjZXMgbmF2aWdhdGlvbiB0byBhIHZpZXcgZm9yIHRoZSBnaXZlbiBkYXRlLlxuICAgIC8vIGB2aWV3VHlwZWAgY2FuIGJlIGEgc3BlY2lmaWMgdmlldyBuYW1lIG9yIGEgZ2VuZXJpYyBvbmUgbGlrZSBcIndlZWtcIiBvciBcImRheVwiLlxuICAgIC8vIG5lZWRzIHRvIGNoYW5nZVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS56b29tVG8gPSBmdW5jdGlvbiAoZGF0ZU1hcmtlciwgdmlld1R5cGUpIHtcbiAgICAgICAgdmFyIHNwZWM7XG4gICAgICAgIHZpZXdUeXBlID0gdmlld1R5cGUgfHwgJ2RheSc7IC8vIGRheSBpcyBkZWZhdWx0IHpvb21cbiAgICAgICAgc3BlYyA9IHRoaXMudmlld1NwZWNzW3ZpZXdUeXBlXSB8fFxuICAgICAgICAgICAgdGhpcy5nZXRVbml0Vmlld1NwZWModmlld1R5cGUpO1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIGlmIChzcGVjKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX1ZJRVdfVFlQRScsXG4gICAgICAgICAgICAgICAgdmlld1R5cGU6IHNwZWMudHlwZSxcbiAgICAgICAgICAgICAgICBkYXRlTWFya2VyOiBkYXRlTWFya2VyXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdTRVRfREFURScsXG4gICAgICAgICAgICAgICAgZGF0ZU1hcmtlcjogZGF0ZU1hcmtlclxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgZHVyYXRpb24gc2luZ3VsYXIgdW5pdCwgbGlrZSBcIndlZWtcIiBvciBcImRheVwiLCBmaW5kcyBhIG1hdGNoaW5nIHZpZXcgc3BlYy5cbiAgICAvLyBQcmVmZXJlbmNlIGlzIGdpdmVuIHRvIHZpZXdzIHRoYXQgaGF2ZSBjb3JyZXNwb25kaW5nIGJ1dHRvbnMuXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldFVuaXRWaWV3U3BlYyA9IGZ1bmN0aW9uICh1bml0KSB7XG4gICAgICAgIHZhciBjb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudDtcbiAgICAgICAgdmFyIHZpZXdUeXBlcyA9IFtdO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHNwZWM7XG4gICAgICAgIC8vIHB1dCB2aWV3cyB0aGF0IGhhdmUgYnV0dG9ucyBmaXJzdC4gdGhlcmUgd2lsbCBiZSBkdXBsaWNhdGVzLCBidXQgb2hcbiAgICAgICAgaWYgKGNvbXBvbmVudC5oZWFkZXIpIHtcbiAgICAgICAgICAgIHZpZXdUeXBlcy5wdXNoLmFwcGx5KHZpZXdUeXBlcywgY29tcG9uZW50LmhlYWRlci52aWV3c1dpdGhCdXR0b25zKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29tcG9uZW50LmZvb3Rlcikge1xuICAgICAgICAgICAgdmlld1R5cGVzLnB1c2guYXBwbHkodmlld1R5cGVzLCBjb21wb25lbnQuZm9vdGVyLnZpZXdzV2l0aEJ1dHRvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIHZpZXdUeXBlIGluIHRoaXMudmlld1NwZWNzKSB7XG4gICAgICAgICAgICB2aWV3VHlwZXMucHVzaCh2aWV3VHlwZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHZpZXdUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc3BlYyA9IHRoaXMudmlld1NwZWNzW3ZpZXdUeXBlc1tpXV07XG4gICAgICAgICAgICBpZiAoc3BlYykge1xuICAgICAgICAgICAgICAgIGlmIChzcGVjLnNpbmdsZVVuaXQgPT09IHVuaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNwZWM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBDdXJyZW50IERhdGVcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRJbml0aWFsRGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRlZmF1bHREYXRlSW5wdXQgPSB0aGlzLm9wdCgnZGVmYXVsdERhdGUnKTtcbiAgICAgICAgLy8gY29tcHV0ZSB0aGUgaW5pdGlhbCBhbWJpZy10aW1lem9uZSBkYXRlXG4gICAgICAgIGlmIChkZWZhdWx0RGF0ZUlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGVFbnYuY3JlYXRlTWFya2VyKGRlZmF1bHREYXRlSW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Tm93KCk7IC8vIGdldE5vdyBhbHJlYWR5IHJldHVybnMgdW56b25lZFxuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucHJldiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ1BSRVYnIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLm5leHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdORVhUJyB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wcmV2WWVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdTRVRfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiB0aGlzLmRhdGVFbnYuYWRkWWVhcnModGhpcy5zdGF0ZS5jdXJyZW50RGF0ZSwgLTEpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLm5leHRZZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZGF0ZUVudi5hZGRZZWFycyh0aGlzLnN0YXRlLmN1cnJlbnREYXRlLCAxKVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50b2RheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdTRVRfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiB0aGlzLmdldE5vdygpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdvdG9EYXRlID0gZnVuY3Rpb24gKHpvbmVkRGF0ZUlucHV0KSB7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnU0VUX0RBVEUnLFxuICAgICAgICAgICAgZGF0ZU1hcmtlcjogdGhpcy5kYXRlRW52LmNyZWF0ZU1hcmtlcih6b25lZERhdGVJbnB1dClcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuaW5jcmVtZW50RGF0ZSA9IGZ1bmN0aW9uIChkZWx0YUlucHV0KSB7XG4gICAgICAgIHZhciBkZWx0YSA9IGNyZWF0ZUR1cmF0aW9uKGRlbHRhSW5wdXQpO1xuICAgICAgICBpZiAoZGVsdGEpIHsgLy8gZWxzZSwgd2FybiBhYm91dCBpbnZhbGlkIGlucHV0P1xuICAgICAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgICAgICBkYXRlTWFya2VyOiB0aGlzLmRhdGVFbnYuYWRkKHRoaXMuc3RhdGUuY3VycmVudERhdGUsIGRlbHRhKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGZvciBleHRlcm5hbCBBUElcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0RGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi50b0RhdGUodGhpcy5zdGF0ZS5jdXJyZW50RGF0ZSk7XG4gICAgfTtcbiAgICAvLyBEYXRlIEZvcm1hdHRpbmcgVXRpbHNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5mb3JtYXREYXRlID0gZnVuY3Rpb24gKGQsIGZvcm1hdHRlcikge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0KGRhdGVFbnYuY3JlYXRlTWFya2VyKGQpLCBjcmVhdGVGb3JtYXR0ZXIoZm9ybWF0dGVyKSk7XG4gICAgfTtcbiAgICAvLyBgc2V0dGluZ3NgIGlzIGZvciBmb3JtYXR0ZXIgQU5EIGlzRW5kRXhjbHVzaXZlXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKGQwLCBkMSwgc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdFJhbmdlKGRhdGVFbnYuY3JlYXRlTWFya2VyKGQwKSwgZGF0ZUVudi5jcmVhdGVNYXJrZXIoZDEpLCBjcmVhdGVGb3JtYXR0ZXIoc2V0dGluZ3MsIHRoaXMub3B0KCdkZWZhdWx0UmFuZ2VTZXBhcmF0b3InKSksIHNldHRpbmdzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5mb3JtYXRJc28gPSBmdW5jdGlvbiAoZCwgb21pdFRpbWUpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdElzbyhkYXRlRW52LmNyZWF0ZU1hcmtlcihkKSwgeyBvbWl0VGltZTogb21pdFRpbWUgfSk7XG4gICAgfTtcbiAgICAvLyBTaXppbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS53aW5kb3dSZXNpemUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzSGFuZGxpbmdXaW5kb3dSZXNpemUgJiZcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50ICYmIC8vIHdoeT9cbiAgICAgICAgICAgIGV2LnRhcmdldCA9PT0gd2luZG93IC8vIG5vdCBhIGpxdWkgcmVzaXplIGV2ZW50XG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5pc0hhbmRsaW5nV2luZG93UmVzaXplID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ3dpbmRvd1Jlc2l6ZScsIFt0aGlzLnZpZXddKTtcbiAgICAgICAgICAgIHRoaXMuaXNIYW5kbGluZ1dpbmRvd1Jlc2l6ZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudXBkYXRlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50KSB7IC8vIHdoZW4/XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudC51cGRhdGVTaXplKHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBDb21wb25lbnQgUmVnaXN0cmF0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCA9IGZ1bmN0aW9uIChjb21wb25lbnQsIHNldHRpbmdzSW5wdXQpIHtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gcGFyc2VJbnRlcmFjdGlvblNldHRpbmdzKGNvbXBvbmVudCwgc2V0dGluZ3NJbnB1dCk7XG4gICAgICAgIHZhciBERUZBVUxUX0lOVEVSQUNUSU9OUyA9IFtcbiAgICAgICAgICAgIEV2ZW50Q2xpY2tpbmcsXG4gICAgICAgICAgICBFdmVudEhvdmVyaW5nXG4gICAgICAgIF07XG4gICAgICAgIHZhciBpbnRlcmFjdGlvbkNsYXNzZXMgPSBERUZBVUxUX0lOVEVSQUNUSU9OUy5jb25jYXQodGhpcy5wbHVnaW5TeXN0ZW0uaG9va3MuY29tcG9uZW50SW50ZXJhY3Rpb25zKTtcbiAgICAgICAgdmFyIGludGVyYWN0aW9ucyA9IGludGVyYWN0aW9uQ2xhc3Nlcy5tYXAoZnVuY3Rpb24gKGludGVyYWN0aW9uQ2xhc3MpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgaW50ZXJhY3Rpb25DbGFzcyhzZXR0aW5ncyk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmludGVyYWN0aW9uc1N0b3JlW2NvbXBvbmVudC51aWRdID0gaW50ZXJhY3Rpb25zO1xuICAgICAgICBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmVbY29tcG9uZW50LnVpZF0gPSBzZXR0aW5ncztcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQgPSBmdW5jdGlvbiAoY29tcG9uZW50KSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmludGVyYWN0aW9uc1N0b3JlW2NvbXBvbmVudC51aWRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGxpc3RlbmVyID0gX2FbX2ldO1xuICAgICAgICAgICAgbGlzdGVuZXIuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLmludGVyYWN0aW9uc1N0b3JlW2NvbXBvbmVudC51aWRdO1xuICAgICAgICBkZWxldGUgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlW2NvbXBvbmVudC51aWRdO1xuICAgIH07XG4gICAgLy8gRGF0ZSBTZWxlY3Rpb24gLyBFdmVudCBTZWxlY3Rpb24gLyBEYXlDbGlja1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gdGhpcyBwdWJsaWMgbWV0aG9kIHJlY2VpdmVzIHN0YXJ0L2VuZCBkYXRlcyBpbiBhbnkgZm9ybWF0LCB3aXRoIGFueSB0aW1lem9uZVxuICAgIC8vIE5PVEU6IGFyZ3Mgd2VyZSBjaGFuZ2VkIGZyb20gdjNcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuc2VsZWN0ID0gZnVuY3Rpb24gKGRhdGVPck9iaiwgZW5kRGF0ZSkge1xuICAgICAgICB2YXIgc2VsZWN0aW9uSW5wdXQ7XG4gICAgICAgIGlmIChlbmREYXRlID09IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChkYXRlT3JPYmouc3RhcnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbklucHV0ID0gZGF0ZU9yT2JqO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uSW5wdXQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBkYXRlT3JPYmosXG4gICAgICAgICAgICAgICAgICAgIGVuZDogbnVsbFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzZWxlY3Rpb25JbnB1dCA9IHtcbiAgICAgICAgICAgICAgICBzdGFydDogZGF0ZU9yT2JqLFxuICAgICAgICAgICAgICAgIGVuZDogZW5kRGF0ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2VsZWN0aW9uID0gcGFyc2VEYXRlU3BhbihzZWxlY3Rpb25JbnB1dCwgdGhpcy5kYXRlRW52LCBjcmVhdGVEdXJhdGlvbih7IGRheXM6IDEgfSkgLy8gVE9ETzogY2FjaGUgdGhpcz9cbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHNlbGVjdGlvbikgeyAvLyB0aHJvdyBwYXJzZSBlcnJvciBvdGhlcndpc2U/XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ1NFTEVDVF9EQVRFUycsIHNlbGVjdGlvbjogc2VsZWN0aW9uIH0pO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyRGF0ZVNlbGVjdChzZWxlY3Rpb24pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBwdWJsaWMgbWV0aG9kXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnVuc2VsZWN0ID0gZnVuY3Rpb24gKHBldikge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5kYXRlU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VMRUNUX0RBVEVTJyB9KTtcbiAgICAgICAgICAgIHRoaXMudHJpZ2dlckRhdGVVbnNlbGVjdChwZXYpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudHJpZ2dlckRhdGVTZWxlY3QgPSBmdW5jdGlvbiAoc2VsZWN0aW9uLCBwZXYpIHtcbiAgICAgICAgdmFyIGFyZyA9IF9fYXNzaWduKHt9LCB0aGlzLmJ1aWxkRGF0ZVNwYW5BcGkoc2VsZWN0aW9uKSwgeyBqc0V2ZW50OiBwZXYgPyBwZXYub3JpZ0V2ZW50IDogbnVsbCwgdmlldzogdGhpcy52aWV3IH0pO1xuICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignc2VsZWN0JywgW2FyZ10pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnRyaWdnZXJEYXRlVW5zZWxlY3QgPSBmdW5jdGlvbiAocGV2KSB7XG4gICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCd1bnNlbGVjdCcsIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBqc0V2ZW50OiBwZXYgPyBwZXYub3JpZ0V2ZW50IDogbnVsbCxcbiAgICAgICAgICAgICAgICB2aWV3OiB0aGlzLnZpZXdcbiAgICAgICAgICAgIH1cbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICAvLyBUT0RPOiByZWNlaXZlIHBldj9cbiAgICBDYWxlbmRhci5wcm90b3R5cGUudHJpZ2dlckRhdGVDbGljayA9IGZ1bmN0aW9uIChkYXRlU3BhbiwgZGF5RWwsIHZpZXcsIGV2KSB7XG4gICAgICAgIHZhciBhcmcgPSBfX2Fzc2lnbih7fSwgdGhpcy5idWlsZERhdGVQb2ludEFwaShkYXRlU3BhbiksIHsgZGF5RWw6IGRheUVsLCBqc0V2ZW50OiBldiwgLy8gSXMgdGhpcyBhbHdheXMgYSBtb3VzZSBldmVudD8gU2VlICM0NjU1XG4gICAgICAgICAgICB2aWV3OiB2aWV3IH0pO1xuICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignZGF0ZUNsaWNrJywgW2FyZ10pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmJ1aWxkRGF0ZVBvaW50QXBpID0gZnVuY3Rpb24gKGRhdGVTcGFuKSB7XG4gICAgICAgIHZhciBwcm9wcyA9IHt9O1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3MuZGF0ZVBvaW50VHJhbnNmb3JtczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSBfYVtfaV07XG4gICAgICAgICAgICBfX2Fzc2lnbihwcm9wcywgdHJhbnNmb3JtKGRhdGVTcGFuLCB0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgX19hc3NpZ24ocHJvcHMsIGJ1aWxkRGF0ZVBvaW50QXBpKGRhdGVTcGFuLCB0aGlzLmRhdGVFbnYpKTtcbiAgICAgICAgcmV0dXJuIHByb3BzO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmJ1aWxkRGF0ZVNwYW5BcGkgPSBmdW5jdGlvbiAoZGF0ZVNwYW4pIHtcbiAgICAgICAgdmFyIHByb3BzID0ge307XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5kYXRlU3BhblRyYW5zZm9ybXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNmb3JtID0gX2FbX2ldO1xuICAgICAgICAgICAgX19hc3NpZ24ocHJvcHMsIHRyYW5zZm9ybShkYXRlU3BhbiwgdGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIF9fYXNzaWduKHByb3BzLCBidWlsZERhdGVTcGFuQXBpKGRhdGVTcGFuLCB0aGlzLmRhdGVFbnYpKTtcbiAgICAgICAgcmV0dXJuIHByb3BzO1xuICAgIH07XG4gICAgLy8gRGF0ZSBVdGlsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gUmV0dXJucyBhIERhdGVNYXJrZXIgZm9yIHRoZSBjdXJyZW50IGRhdGUsIGFzIGRlZmluZWQgYnkgdGhlIGNsaWVudCdzIGNvbXB1dGVyIG9yIGZyb20gdGhlIGBub3dgIG9wdGlvblxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXROb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBub3cgPSB0aGlzLm9wdCgnbm93Jyk7XG4gICAgICAgIGlmICh0eXBlb2Ygbm93ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBub3cgPSBub3coKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm93ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGVFbnYuY3JlYXRlTm93TWFya2VyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi5jcmVhdGVNYXJrZXIobm93KTtcbiAgICB9O1xuICAgIC8vIEV2ZW50LURhdGUgVXRpbGl0aWVzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBHaXZlbiBhbiBldmVudCdzIGFsbERheSBzdGF0dXMgYW5kIHN0YXJ0IGRhdGUsIHJldHVybiB3aGF0IGl0cyBmYWxsYmFjayBlbmQgZGF0ZSBzaG91bGQgYmUuXG4gICAgLy8gVE9ETzogcmVuYW1lIHRvIGNvbXB1dGVEZWZhdWx0RXZlbnRFbmRcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0RGVmYXVsdEV2ZW50RW5kID0gZnVuY3Rpb24gKGFsbERheSwgbWFya2VyKSB7XG4gICAgICAgIHZhciBlbmQgPSBtYXJrZXI7XG4gICAgICAgIGlmIChhbGxEYXkpIHtcbiAgICAgICAgICAgIGVuZCA9IHN0YXJ0T2ZEYXkoZW5kKTtcbiAgICAgICAgICAgIGVuZCA9IHRoaXMuZGF0ZUVudi5hZGQoZW5kLCB0aGlzLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGVuZCA9IHRoaXMuZGF0ZUVudi5hZGQoZW5kLCB0aGlzLmRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbmQ7XG4gICAgfTtcbiAgICAvLyBQdWJsaWMgRXZlbnRzIEFQSVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmFkZEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50SW5wdXQsIHNvdXJjZUlucHV0KSB7XG4gICAgICAgIGlmIChldmVudElucHV0IGluc3RhbmNlb2YgRXZlbnRBcGkpIHtcbiAgICAgICAgICAgIHZhciBkZWYgPSBldmVudElucHV0Ll9kZWY7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBldmVudElucHV0Ll9pbnN0YW5jZTtcbiAgICAgICAgICAgIC8vIG5vdCBhbHJlYWR5IHByZXNlbnQ/IGRvbid0IHdhbnQgdG8gYWRkIGFuIG9sZCBzbmFwc2hvdFxuICAgICAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmV2ZW50U3RvcmUuZGVmc1tkZWYuZGVmSWRdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdBRERfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogZXZlbnRUdXBsZVRvU3RvcmUoeyBkZWY6IGRlZiwgaW5zdGFuY2U6IGluc3RhbmNlIH0pIC8vIFRPRE86IGJldHRlciB1dGlsIGZvciB0d28gYXJncz9cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBldmVudElucHV0O1xuICAgICAgICB9XG4gICAgICAgIHZhciBzb3VyY2VJZDtcbiAgICAgICAgaWYgKHNvdXJjZUlucHV0IGluc3RhbmNlb2YgRXZlbnRTb3VyY2VBcGkpIHtcbiAgICAgICAgICAgIHNvdXJjZUlkID0gc291cmNlSW5wdXQuaW50ZXJuYWxFdmVudFNvdXJjZS5zb3VyY2VJZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChzb3VyY2VJbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlQXBpID0gdGhpcy5nZXRFdmVudFNvdXJjZUJ5SWQoc291cmNlSW5wdXQpOyAvLyBUT0RPOiB1c2UgYW4gaW50ZXJuYWwgZnVuY3Rpb25cbiAgICAgICAgICAgIGlmICghc291cmNlQXBpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdDb3VsZCBub3QgZmluZCBhbiBldmVudCBzb3VyY2Ugd2l0aCBJRCBcIicgKyBzb3VyY2VJbnB1dCArICdcIicpOyAvLyBUT0RPOiB0ZXN0XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VJZCA9IHNvdXJjZUFwaS5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciB0dXBsZSA9IHBhcnNlRXZlbnQoZXZlbnRJbnB1dCwgc291cmNlSWQsIHRoaXMpO1xuICAgICAgICBpZiAodHVwbGUpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdBRERfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFR1cGxlVG9TdG9yZSh0dXBsZSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudEFwaSh0aGlzLCB0dXBsZS5kZWYsIHR1cGxlLmRlZi5yZWN1cnJpbmdEZWYgPyBudWxsIDogdHVwbGUuaW5zdGFuY2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLy8gVE9ETzogb3B0aW1pemVcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0RXZlbnRCeUlkID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuc3RhdGUuZXZlbnRTdG9yZSwgZGVmcyA9IF9hLmRlZnMsIGluc3RhbmNlcyA9IF9hLmluc3RhbmNlcztcbiAgICAgICAgaWQgPSBTdHJpbmcoaWQpO1xuICAgICAgICBmb3IgKHZhciBkZWZJZCBpbiBkZWZzKSB7XG4gICAgICAgICAgICB2YXIgZGVmID0gZGVmc1tkZWZJZF07XG4gICAgICAgICAgICBpZiAoZGVmLnB1YmxpY0lkID09PSBpZCkge1xuICAgICAgICAgICAgICAgIGlmIChkZWYucmVjdXJyaW5nRGVmKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZlbnRBcGkodGhpcywgZGVmLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5zdGFuY2UuZGVmSWQgPT09IGRlZi5kZWZJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZlbnRBcGkodGhpcywgZGVmLCBpbnN0YW5jZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0RXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLnN0YXRlLmV2ZW50U3RvcmUsIGRlZnMgPSBfYS5kZWZzLCBpbnN0YW5jZXMgPSBfYS5pbnN0YW5jZXM7XG4gICAgICAgIHZhciBldmVudEFwaXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaWRdO1xuICAgICAgICAgICAgdmFyIGRlZiA9IGRlZnNbaW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICAgICAgZXZlbnRBcGlzLnB1c2gobmV3IEV2ZW50QXBpKHRoaXMsIGRlZiwgaW5zdGFuY2UpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXZlbnRBcGlzO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlbW92ZUFsbEV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdSRU1PVkVfQUxMX0VWRU5UUycgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVyZW5kZXJFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUkVTRVRfRVZFTlRTJyB9KTtcbiAgICB9O1xuICAgIC8vIFB1YmxpYyBFdmVudCBTb3VyY2VzIEFQSVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldEV2ZW50U291cmNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNvdXJjZUhhc2ggPSB0aGlzLnN0YXRlLmV2ZW50U291cmNlcztcbiAgICAgICAgdmFyIHNvdXJjZUFwaXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaW50ZXJuYWxJZCBpbiBzb3VyY2VIYXNoKSB7XG4gICAgICAgICAgICBzb3VyY2VBcGlzLnB1c2gobmV3IEV2ZW50U291cmNlQXBpKHRoaXMsIHNvdXJjZUhhc2hbaW50ZXJuYWxJZF0pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc291cmNlQXBpcztcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRFdmVudFNvdXJjZUJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgdmFyIHNvdXJjZUhhc2ggPSB0aGlzLnN0YXRlLmV2ZW50U291cmNlcztcbiAgICAgICAgaWQgPSBTdHJpbmcoaWQpO1xuICAgICAgICBmb3IgKHZhciBzb3VyY2VJZCBpbiBzb3VyY2VIYXNoKSB7XG4gICAgICAgICAgICBpZiAoc291cmNlSGFzaFtzb3VyY2VJZF0ucHVibGljSWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudFNvdXJjZUFwaSh0aGlzLCBzb3VyY2VIYXNoW3NvdXJjZUlkXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYWRkRXZlbnRTb3VyY2UgPSBmdW5jdGlvbiAoc291cmNlSW5wdXQpIHtcbiAgICAgICAgaWYgKHNvdXJjZUlucHV0IGluc3RhbmNlb2YgRXZlbnRTb3VyY2VBcGkpIHtcbiAgICAgICAgICAgIC8vIG5vdCBhbHJlYWR5IHByZXNlbnQ/IGRvbid0IHdhbnQgdG8gYWRkIGFuIG9sZCBzbmFwc2hvdFxuICAgICAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmV2ZW50U291cmNlc1tzb3VyY2VJbnB1dC5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnQUREX0VWRU5UX1NPVVJDRVMnLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VzOiBbc291cmNlSW5wdXQuaW50ZXJuYWxFdmVudFNvdXJjZV1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzb3VyY2VJbnB1dDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXZlbnRTb3VyY2UgPSBwYXJzZUV2ZW50U291cmNlKHNvdXJjZUlucHV0LCB0aGlzKTtcbiAgICAgICAgaWYgKGV2ZW50U291cmNlKSB7IC8vIFRPRE86IGVycm9yIG90aGVyd2lzZT9cbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnQUREX0VWRU5UX1NPVVJDRVMnLCBzb3VyY2VzOiBbZXZlbnRTb3VyY2VdIH0pO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudFNvdXJjZUFwaSh0aGlzLCBldmVudFNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVtb3ZlQWxsRXZlbnRTb3VyY2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ1JFTU9WRV9BTExfRVZFTlRfU09VUkNFUycgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVmZXRjaEV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdGRVRDSF9FVkVOVF9TT1VSQ0VTJyB9KTtcbiAgICB9O1xuICAgIC8vIFNjcm9sbFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnNjcm9sbFRvVGltZSA9IGZ1bmN0aW9uICh0aW1lSW5wdXQpIHtcbiAgICAgICAgdmFyIGR1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24odGltZUlucHV0KTtcbiAgICAgICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudC52aWV3LnNjcm9sbFRvRHVyYXRpb24oZHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gQ2FsZW5kYXI7XG59KCkpO1xuRW1pdHRlck1peGluLm1peEludG8oQ2FsZW5kYXIpO1xuLy8gZm9yIG1lbW9pemVyc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGJ1aWxkQ29tcG9uZW50Q29udGV4dCQxKHRoZW1lLCBkYXRlRW52LCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRDb250ZXh0KHRoaXMsIHRoZW1lLCBkYXRlRW52LCBvcHRpb25zLCBudWxsKTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRGF0ZUVudihsb2NhbGUsIHRpbWVab25lLCBuYW1lZFRpbWVab25lSW1wbCwgZmlyc3REYXksIHdlZWtOdW1iZXJDYWxjdWxhdGlvbiwgd2Vla0xhYmVsLCBjbWRGb3JtYXR0ZXIpIHtcbiAgICByZXR1cm4gbmV3IERhdGVFbnYoe1xuICAgICAgICBjYWxlbmRhclN5c3RlbTogJ2dyZWdvcnknLFxuICAgICAgICB0aW1lWm9uZTogdGltZVpvbmUsXG4gICAgICAgIG5hbWVkVGltZVpvbmVJbXBsOiBuYW1lZFRpbWVab25lSW1wbCxcbiAgICAgICAgbG9jYWxlOiBsb2NhbGUsXG4gICAgICAgIHdlZWtOdW1iZXJDYWxjdWxhdGlvbjogd2Vla051bWJlckNhbGN1bGF0aW9uLFxuICAgICAgICBmaXJzdERheTogZmlyc3REYXksXG4gICAgICAgIHdlZWtMYWJlbDogd2Vla0xhYmVsLFxuICAgICAgICBjbWRGb3JtYXR0ZXI6IGNtZEZvcm1hdHRlclxuICAgIH0pO1xufVxuZnVuY3Rpb24gYnVpbGRUaGVtZShjYWxlbmRhck9wdGlvbnMpIHtcbiAgICB2YXIgdGhlbWVDbGFzcyA9IHRoaXMucGx1Z2luU3lzdGVtLmhvb2tzLnRoZW1lQ2xhc3Nlc1tjYWxlbmRhck9wdGlvbnMudGhlbWVTeXN0ZW1dIHx8IFN0YW5kYXJkVGhlbWU7XG4gICAgcmV0dXJuIG5ldyB0aGVtZUNsYXNzKGNhbGVuZGFyT3B0aW9ucyk7XG59XG5mdW5jdGlvbiBidWlsZERlbGF5ZWRSZXJlbmRlcih3YWl0KSB7XG4gICAgdmFyIGZ1bmMgPSB0aGlzLnRyeVJlcmVuZGVyLmJpbmQodGhpcyk7XG4gICAgaWYgKHdhaXQgIT0gbnVsbCkge1xuICAgICAgICBmdW5jID0gZGVib3VuY2UoZnVuYywgd2FpdCk7XG4gICAgfVxuICAgIHJldHVybiBmdW5jO1xufVxuZnVuY3Rpb24gYnVpbGRFdmVudFVpQnlTb3VyY2UoZXZlbnRTb3VyY2VzKSB7XG4gICAgcmV0dXJuIG1hcEhhc2goZXZlbnRTb3VyY2VzLCBmdW5jdGlvbiAoZXZlbnRTb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50U291cmNlLnVpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gYnVpbGRFdmVudFVpQmFzZXMoZXZlbnREZWZzLCBldmVudFVpU2luZ2xlQmFzZSwgZXZlbnRVaUJ5U291cmNlKSB7XG4gICAgdmFyIGV2ZW50VWlCYXNlcyA9IHsgJyc6IGV2ZW50VWlTaW5nbGVCYXNlIH07XG4gICAgZm9yICh2YXIgZGVmSWQgaW4gZXZlbnREZWZzKSB7XG4gICAgICAgIHZhciBkZWYgPSBldmVudERlZnNbZGVmSWRdO1xuICAgICAgICBpZiAoZGVmLnNvdXJjZUlkICYmIGV2ZW50VWlCeVNvdXJjZVtkZWYuc291cmNlSWRdKSB7XG4gICAgICAgICAgICBldmVudFVpQmFzZXNbZGVmSWRdID0gZXZlbnRVaUJ5U291cmNlW2RlZi5zb3VyY2VJZF07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGV2ZW50VWlCYXNlcztcbn1cblxudmFyIFZpZXcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFZpZXcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVmlldyh2aWV3U3BlYywgcGFyZW50RWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY3JlYXRlRWxlbWVudCgnZGl2JywgeyBjbGFzc05hbWU6ICdmYy12aWV3IGZjLScgKyB2aWV3U3BlYy50eXBlICsgJy12aWV3JyB9KSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucmVuZGVyRGF0ZXNNZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckRhdGVzV3JhcCwgX3RoaXMudW5yZW5kZXJEYXRlc1dyYXApO1xuICAgICAgICBfdGhpcy5yZW5kZXJCdXNpbmVzc0hvdXJzTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJCdXNpbmVzc0hvdXJzLCBfdGhpcy51bnJlbmRlckJ1c2luZXNzSG91cnMsIFtfdGhpcy5yZW5kZXJEYXRlc01lbV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uV3JhcCwgX3RoaXMudW5yZW5kZXJEYXRlU2VsZWN0aW9uV3JhcCwgW190aGlzLnJlbmRlckRhdGVzTWVtXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50c01lbSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMucmVuZGVyRXZlbnRzLCBfdGhpcy51bnJlbmRlckV2ZW50cywgW190aGlzLnJlbmRlckRhdGVzTWVtXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAsIF90aGlzLnVucmVuZGVyRXZlbnRTZWxlY3Rpb25XcmFwLCBbX3RoaXMucmVuZGVyRXZlbnRzTWVtXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50RHJhZ01lbSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMucmVuZGVyRXZlbnREcmFnV3JhcCwgX3RoaXMudW5yZW5kZXJFdmVudERyYWdXcmFwLCBbX3RoaXMucmVuZGVyRGF0ZXNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRSZXNpemVNZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckV2ZW50UmVzaXplV3JhcCwgX3RoaXMudW5yZW5kZXJFdmVudFJlc2l6ZVdyYXAsIFtfdGhpcy5yZW5kZXJEYXRlc01lbV0pO1xuICAgICAgICBfdGhpcy52aWV3U3BlYyA9IHZpZXdTcGVjO1xuICAgICAgICBfdGhpcy50eXBlID0gdmlld1NwZWMudHlwZTtcbiAgICAgICAgcGFyZW50RWwuYXBwZW5kQ2hpbGQoX3RoaXMuZWwpO1xuICAgICAgICBfdGhpcy5pbml0aWFsaXplKCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVmlldy5wcm90b3R5cGUuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShWaWV3LnByb3RvdHlwZSwgXCJhY3RpdmVTdGFydFwiLCB7XG4gICAgICAgIC8vIERhdGUgU2V0dGluZy9VbnNldHRpbmdcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYudG9EYXRlKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2Uuc3RhcnQpO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoVmlldy5wcm90b3R5cGUsIFwiYWN0aXZlRW5kXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYudG9EYXRlKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UuZW5kKTtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFZpZXcucHJvdG90eXBlLCBcImN1cnJlbnRTdGFydFwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dC5kYXRlRW52LnRvRGF0ZSh0aGlzLnByb3BzLmRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5zdGFydCk7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShWaWV3LnByb3RvdHlwZSwgXCJjdXJyZW50RW5kXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYudG9EYXRlKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLmVuZCk7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIC8vIEdlbmVyYWwgUmVuZGVyaW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJEYXRlc01lbShwcm9wcy5kYXRlUHJvZmlsZSk7XG4gICAgICAgIHRoaXMucmVuZGVyQnVzaW5lc3NIb3Vyc01lbShwcm9wcy5idXNpbmVzc0hvdXJzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uTWVtKHByb3BzLmRhdGVTZWxlY3Rpb24pO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50c01lbShwcm9wcy5ldmVudFN0b3JlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbk1lbShwcm9wcy5ldmVudFNlbGVjdGlvbik7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnREcmFnTWVtKHByb3BzLmV2ZW50RHJhZyk7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnRSZXNpemVNZW0ocHJvcHMuZXZlbnRSZXNpemUpO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuYmVmb3JlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZFNjcm9sbCh0aGlzLnF1ZXJ5U2Nyb2xsKCkpO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMucmVuZGVyRGF0ZXNNZW0udW5yZW5kZXIoKTsgLy8gc2hvdWxkIHVucmVuZGVyIGV2ZXJ5dGhpbmcgZWxzZVxuICAgIH07XG4gICAgLy8gU2l6aW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKGlzUmVzaXplLCB2aWV3SGVpZ2h0LCBpc0F1dG8pIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdGhpcy5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICBpZiAoaXNSZXNpemUpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkU2Nyb2xsKHRoaXMucXVlcnlTY3JvbGwoKSk7IC8vIE5PVEU6IHNhbWUgY29kZSBhcyBpbiBiZWZvcmVVcGRhdGVcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNSZXNpemUgfHwgLy8gSEFDS1MuLi5cbiAgICAgICAgICAgIGNhbGVuZGFyLmlzVmlld1VwZGF0ZWQgfHxcbiAgICAgICAgICAgIGNhbGVuZGFyLmlzRGF0ZXNVcGRhdGVkIHx8XG4gICAgICAgICAgICBjYWxlbmRhci5pc0V2ZW50c1VwZGF0ZWQpIHtcbiAgICAgICAgICAgIC8vIHNvcnQgb2YgdGhlIGNhdGNoLWFsbCBzaXppbmdcbiAgICAgICAgICAgIC8vIGFueXRoaW5nIHRoYXQgbWlnaHQgY2F1c2UgZGltZW5zaW9uIGNoYW5nZXNcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQmFzZVNpemUoaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0byk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTk9URTogcG9wU2Nyb2xsIGlzIGNhbGxlZCBieSBDYWxlbmRhckNvbXBvbmVudFxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudXBkYXRlQmFzZVNpemUgPSBmdW5jdGlvbiAoaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0bykge1xuICAgIH07XG4gICAgLy8gRGF0ZSBSZW5kZXJpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckRhdGVzV3JhcCA9IGZ1bmN0aW9uIChkYXRlUHJvZmlsZSkge1xuICAgICAgICB0aGlzLnJlbmRlckRhdGVzKGRhdGVQcm9maWxlKTtcbiAgICAgICAgdGhpcy5hZGRTY3JvbGwoe1xuICAgICAgICAgICAgZHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uKHRoaXMuY29udGV4dC5vcHRpb25zLnNjcm9sbFRpbWUpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJEYXRlc1dyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3RvcE5vd0luZGljYXRvcigpO1xuICAgICAgICB0aGlzLnVucmVuZGVyRGF0ZXMoKTtcbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckRhdGVzID0gZnVuY3Rpb24gKGRhdGVQcm9maWxlKSB7IH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJEYXRlcyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAvLyBCdXNpbmVzcyBIb3Vyc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyQnVzaW5lc3NIb3VycyA9IGZ1bmN0aW9uIChidXNpbmVzc0hvdXJzKSB7IH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJCdXNpbmVzc0hvdXJzID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgIC8vIERhdGUgU2VsZWN0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJEYXRlU2VsZWN0aW9uV3JhcCA9IGZ1bmN0aW9uIChzZWxlY3Rpb24pIHtcbiAgICAgICAgaWYgKHNlbGVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uKHNlbGVjdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRGF0ZVNlbGVjdGlvbldyYXAgPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7XG4gICAgICAgIGlmIChzZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMudW5yZW5kZXJEYXRlU2VsZWN0aW9uKHNlbGVjdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckRhdGVTZWxlY3Rpb24gPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7IH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJEYXRlU2VsZWN0aW9uID0gZnVuY3Rpb24gKHNlbGVjdGlvbikgeyB9O1xuICAgIC8vIEV2ZW50IFJlbmRlcmluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnRzID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckV2ZW50cyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAvLyB1dGlsIGZvciBzdWJjbGFzc2VzXG4gICAgVmlldy5wcm90b3R5cGUuc2xpY2VFdmVudHMgPSBmdW5jdGlvbiAoZXZlbnRTdG9yZSwgYWxsRGF5KSB7XG4gICAgICAgIHZhciBwcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICAgIHJldHVybiBzbGljZUV2ZW50U3RvcmUoZXZlbnRTdG9yZSwgcHJvcHMuZXZlbnRVaUJhc2VzLCBwcm9wcy5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgYWxsRGF5ID8gdGhpcy5jb250ZXh0Lm5leHREYXlUaHJlc2hvbGQgOiBudWxsKS5mZztcbiAgICB9O1xuICAgIC8vIEV2ZW50IFNlbGVjdGlvblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnRTZWxlY3Rpb25XcmFwID0gZnVuY3Rpb24gKGluc3RhbmNlSWQpIHtcbiAgICAgICAgaWYgKGluc3RhbmNlSWQpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyRXZlbnRTZWxlY3Rpb24oaW5zdGFuY2VJZCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRTZWxlY3Rpb25XcmFwID0gZnVuY3Rpb24gKGluc3RhbmNlSWQpIHtcbiAgICAgICAgaWYgKGluc3RhbmNlSWQpIHtcbiAgICAgICAgICAgIHRoaXMudW5yZW5kZXJFdmVudFNlbGVjdGlvbihpbnN0YW5jZUlkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkgeyB9O1xuICAgIC8vIEV2ZW50IERyYWdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckV2ZW50RHJhZ1dyYXAgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckV2ZW50RHJhZyhzdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnREcmFnV3JhcCA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMudW5yZW5kZXJFdmVudERyYWcoc3RhdGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudERyYWcgPSBmdW5jdGlvbiAoc3RhdGUpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkgeyB9O1xuICAgIC8vIEV2ZW50IFJlc2l6ZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnRSZXNpemVXcmFwID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZShzdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRSZXNpemVXcmFwID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckV2ZW50UmVzaXplKHN0YXRlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnRSZXNpemUgPSBmdW5jdGlvbiAoc3RhdGUpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckV2ZW50UmVzaXplID0gZnVuY3Rpb24gKHN0YXRlKSB7IH07XG4gICAgLyogTm93IEluZGljYXRvclxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgLy8gSW1tZWRpYXRlbHkgcmVuZGVyIHRoZSBjdXJyZW50IHRpbWUgaW5kaWNhdG9yIGFuZCBiZWdpbnMgcmUtcmVuZGVyaW5nIGl0IGF0IGFuIGludGVydmFsLFxuICAgIC8vIHdoaWNoIGlzIGRlZmluZWQgYnkgdGhpcy5nZXROb3dJbmRpY2F0b3JVbml0KCkuXG4gICAgLy8gVE9ETzogc29tZWhvdyBkbyB0aGlzIGZvciB0aGUgY3VycmVudCB3aG9sZSBkYXkncyBiYWNrZ3JvdW5kIHRvb1xuICAgIC8vIFVTQUdFOiBtdXN0IGJlIGNhbGxlZCBtYW51YWxseSBmcm9tIHN1YmNsYXNzZXMnIHJlbmRlciBtZXRob2RzISBkb24ndCBuZWVkIHRvIGNhbGwgc3RvcE5vd0luZGljYXRvciB0aG9cbiAgICBWaWV3LnByb3RvdHlwZS5zdGFydE5vd0luZGljYXRvciA9IGZ1bmN0aW9uIChkYXRlUHJvZmlsZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCBkYXRlRW52ID0gX2EuZGF0ZUVudiwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgIHZhciB1bml0O1xuICAgICAgICB2YXIgdXBkYXRlO1xuICAgICAgICB2YXIgZGVsYXk7IC8vIG1zIHdhaXQgdmFsdWVcbiAgICAgICAgaWYgKG9wdGlvbnMubm93SW5kaWNhdG9yICYmICF0aGlzLmluaXRpYWxOb3dEYXRlKSB7XG4gICAgICAgICAgICB1bml0ID0gdGhpcy5nZXROb3dJbmRpY2F0b3JVbml0KGRhdGVQcm9maWxlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcik7XG4gICAgICAgICAgICBpZiAodW5pdCkge1xuICAgICAgICAgICAgICAgIHVwZGF0ZSA9IHRoaXMudXBkYXRlTm93SW5kaWNhdG9yLmJpbmQodGhpcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsTm93RGF0ZSA9IGNhbGVuZGFyLmdldE5vdygpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbE5vd1F1ZXJpZWRNcyA9IG5ldyBEYXRlKCkudmFsdWVPZigpO1xuICAgICAgICAgICAgICAgIC8vIHdhaXQgdW50aWwgdGhlIGJlZ2lubmluZyBvZiB0aGUgbmV4dCBpbnRlcnZhbFxuICAgICAgICAgICAgICAgIGRlbGF5ID0gZGF0ZUVudi5hZGQoZGF0ZUVudi5zdGFydE9mKHRoaXMuaW5pdGlhbE5vd0RhdGUsIHVuaXQpLCBjcmVhdGVEdXJhdGlvbigxLCB1bml0KSkudmFsdWVPZigpIC0gdGhpcy5pbml0aWFsTm93RGF0ZS52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogbWF5YmUgYWx3YXlzIHVzZSBzZXRUaW1lb3V0LCB3YWl0aW5nIHVudGlsIHN0YXJ0IG9mIG5leHQgdW5pdFxuICAgICAgICAgICAgICAgIHRoaXMubm93SW5kaWNhdG9yVGltZW91dElEID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm5vd0luZGljYXRvclRpbWVvdXRJRCA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodW5pdCA9PT0gJ3NlY29uZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5ID0gMTAwMDsgLy8gZXZlcnkgc2Vjb25kXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxheSA9IDEwMDAgKiA2MDsgLy8gb3RoZXJ3aXNlLCBldmVyeSBtaW51dGVcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ub3dJbmRpY2F0b3JJbnRlcnZhbElEID0gc2V0SW50ZXJ2YWwodXBkYXRlLCBkZWxheSk7IC8vIHVwZGF0ZSBldmVyeSBpbnRlcnZhbFxuICAgICAgICAgICAgICAgIH0sIGRlbGF5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJlbmRlcmluZyB3aWxsIGJlIGluaXRpYXRlZCBpbiB1cGRhdGVTaXplXG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHJlcmVuZGVycyB0aGUgbm93IGluZGljYXRvciwgY29tcHV0aW5nIHRoZSBuZXcgY3VycmVudCB0aW1lIGZyb20gdGhlIGFtb3VudCBvZiB0aW1lIHRoYXQgaGFzIHBhc3NlZFxuICAgIC8vIHNpbmNlIHRoZSBpbml0aWFsIGdldE5vdyBjYWxsLlxuICAgIFZpZXcucHJvdG90eXBlLnVwZGF0ZU5vd0luZGljYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUgJiYgLy8gYSB3YXkgdG8gZGV0ZXJtaW5lIGlmIGRhdGVzIHdlcmUgcmVuZGVyZWQgeWV0XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxOb3dEYXRlIC8vIGFjdGl2YXRlZCBiZWZvcmU/XG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlck5vd0luZGljYXRvcigpOyAvLyB3b24ndCB1bnJlbmRlciBpZiB1bm5lY2Vzc2FyeVxuICAgICAgICAgICAgdGhpcy5yZW5kZXJOb3dJbmRpY2F0b3IoYWRkTXModGhpcy5pbml0aWFsTm93RGF0ZSwgbmV3IERhdGUoKS52YWx1ZU9mKCkgLSB0aGlzLmluaXRpYWxOb3dRdWVyaWVkTXMpKTtcbiAgICAgICAgICAgIHRoaXMuaXNOb3dJbmRpY2F0b3JSZW5kZXJlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEltbWVkaWF0ZWx5IHVucmVuZGVycyB0aGUgdmlldydzIGN1cnJlbnQgdGltZSBpbmRpY2F0b3IgYW5kIHN0b3BzIGFueSByZS1yZW5kZXJpbmcgdGltZXJzLlxuICAgIC8vIFdvbid0IGNhdXNlIHNpZGUgZWZmZWN0cyBpZiBpbmRpY2F0b3IgaXNuJ3QgcmVuZGVyZWQuXG4gICAgVmlldy5wcm90b3R5cGUuc3RvcE5vd0luZGljYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMubm93SW5kaWNhdG9yVGltZW91dElEKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5ub3dJbmRpY2F0b3JUaW1lb3V0SUQpO1xuICAgICAgICAgICAgdGhpcy5ub3dJbmRpY2F0b3JUaW1lb3V0SUQgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm5vd0luZGljYXRvckludGVydmFsSUQpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5ub3dJbmRpY2F0b3JJbnRlcnZhbElEKTtcbiAgICAgICAgICAgIHRoaXMubm93SW5kaWNhdG9ySW50ZXJ2YWxJRCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNOb3dJbmRpY2F0b3JSZW5kZXJlZCkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlck5vd0luZGljYXRvcigpO1xuICAgICAgICAgICAgdGhpcy5pc05vd0luZGljYXRvclJlbmRlcmVkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLmdldE5vd0luZGljYXRvclVuaXQgPSBmdW5jdGlvbiAoZGF0ZVByb2ZpbGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKSB7XG4gICAgICAgIC8vIHN1YmNsYXNzZXMgc2hvdWxkIGltcGxlbWVudFxuICAgIH07XG4gICAgLy8gUmVuZGVycyBhIGN1cnJlbnQgdGltZSBpbmRpY2F0b3IgYXQgdGhlIGdpdmVuIGRhdGV0aW1lXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyTm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgLy8gU1VCQ0xBU1NFUyBNVVNUIFBBU1MgVE8gQ0hJTERSRU4hXG4gICAgfTtcbiAgICAvLyBVbmRvZXMgdGhlIHJlbmRlcmluZyBhY3Rpb25zIGZyb20gcmVuZGVyTm93SW5kaWNhdG9yXG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJOb3dJbmRpY2F0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFNVQkNMQVNTRVMgTVVTVCBQQVNTIFRPIENISUxEUkVOIVxuICAgIH07XG4gICAgLyogU2Nyb2xsZXJcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIFZpZXcucHJvdG90eXBlLmFkZFNjcm9sbCA9IGZ1bmN0aW9uIChzY3JvbGwsIGlzRm9yY2VkKSB7XG4gICAgICAgIGlmIChpc0ZvcmNlZCkge1xuICAgICAgICAgICAgc2Nyb2xsLmlzRm9yY2VkID0gaXNGb3JjZWQ7XG4gICAgICAgIH1cbiAgICAgICAgX19hc3NpZ24odGhpcy5xdWV1ZWRTY3JvbGwgfHwgKHRoaXMucXVldWVkU2Nyb2xsID0ge30pLCBzY3JvbGwpO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucG9wU2Nyb2xsID0gZnVuY3Rpb24gKGlzUmVzaXplKSB7XG4gICAgICAgIHRoaXMuYXBwbHlRdWV1ZWRTY3JvbGwoaXNSZXNpemUpO1xuICAgICAgICB0aGlzLnF1ZXVlZFNjcm9sbCA9IG51bGw7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5hcHBseVF1ZXVlZFNjcm9sbCA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSkge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZWRTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMuYXBwbHlTY3JvbGwodGhpcy5xdWV1ZWRTY3JvbGwsIGlzUmVzaXplKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucXVlcnlTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzY3JvbGwgPSB7fTtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUpIHsgLy8gZGF0ZXMgcmVuZGVyZWQgeWV0P1xuICAgICAgICAgICAgX19hc3NpZ24oc2Nyb2xsLCB0aGlzLnF1ZXJ5RGF0ZVNjcm9sbCgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2Nyb2xsO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuYXBwbHlTY3JvbGwgPSBmdW5jdGlvbiAoc2Nyb2xsLCBpc1Jlc2l6ZSkge1xuICAgICAgICB2YXIgZHVyYXRpb24gPSBzY3JvbGwuZHVyYXRpb24sIGlzRm9yY2VkID0gc2Nyb2xsLmlzRm9yY2VkO1xuICAgICAgICBpZiAoZHVyYXRpb24gIT0gbnVsbCAmJiAhaXNGb3JjZWQpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBzY3JvbGwuZHVyYXRpb247XG4gICAgICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSkgeyAvLyBkYXRlcyByZW5kZXJlZCB5ZXQ/XG4gICAgICAgICAgICAgICAgX19hc3NpZ24oc2Nyb2xsLCB0aGlzLmNvbXB1dGVEYXRlU2Nyb2xsKGR1cmF0aW9uKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUpIHsgLy8gZGF0ZXMgcmVuZGVyZWQgeWV0P1xuICAgICAgICAgICAgdGhpcy5hcHBseURhdGVTY3JvbGwoc2Nyb2xsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuY29tcHV0ZURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoZHVyYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIHt9OyAvLyBzdWJjbGFzc2VzIG11c3QgaW1wbGVtZW50XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5xdWVyeURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7fTsgLy8gc3ViY2xhc3NlcyBtdXN0IGltcGxlbWVudFxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuYXBwbHlEYXRlU2Nyb2xsID0gZnVuY3Rpb24gKHNjcm9sbCkge1xuICAgICAgICAvLyBzdWJjbGFzc2VzIG11c3QgaW1wbGVtZW50XG4gICAgfTtcbiAgICAvLyBmb3IgQVBJXG4gICAgVmlldy5wcm90b3R5cGUuc2Nyb2xsVG9EdXJhdGlvbiA9IGZ1bmN0aW9uIChkdXJhdGlvbikge1xuICAgICAgICB0aGlzLmFwcGx5U2Nyb2xsKHsgZHVyYXRpb246IGR1cmF0aW9uIH0sIGZhbHNlKTtcbiAgICB9O1xuICAgIHJldHVybiBWaWV3O1xufShEYXRlQ29tcG9uZW50KSk7XG5FbWl0dGVyTWl4aW4ubWl4SW50byhWaWV3KTtcblZpZXcucHJvdG90eXBlLnVzZXNNaW5NYXhUaW1lID0gZmFsc2U7XG5WaWV3LnByb3RvdHlwZS5kYXRlUHJvZmlsZUdlbmVyYXRvckNsYXNzID0gRGF0ZVByb2ZpbGVHZW5lcmF0b3I7XG5cbnZhciBGZ0V2ZW50UmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRmdFdmVudFJlbmRlcmVyKCkge1xuICAgICAgICB0aGlzLnNlZ3MgPSBbXTtcbiAgICAgICAgdGhpcy5pc1NpemVEaXJ0eSA9IGZhbHNlO1xuICAgIH1cbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLnJlbmRlclNlZ3MgPSBmdW5jdGlvbiAoY29udGV4dCwgc2VncywgbWlycm9ySW5mbykge1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB0aGlzLnJhbmdlVXBkYXRlZCgpOyAvLyBjYWxsZWQgdG9vIGZyZXF1ZW50bHkgOihcbiAgICAgICAgLy8gcmVuZGVyIGFuIGAuZWxgIG9uIGVhY2ggc2VnXG4gICAgICAgIC8vIHJldHVybnMgYSBzdWJzZXQgb2YgdGhlIHNlZ3MuIHNlZ3MgdGhhdCB3ZXJlIGFjdHVhbGx5IHJlbmRlcmVkXG4gICAgICAgIHNlZ3MgPSB0aGlzLnJlbmRlclNlZ0VscyhzZWdzLCBtaXJyb3JJbmZvKTtcbiAgICAgICAgdGhpcy5zZWdzID0gc2VncztcbiAgICAgICAgdGhpcy5hdHRhY2hTZWdzKHNlZ3MsIG1pcnJvckluZm8pO1xuICAgICAgICB0aGlzLmlzU2l6ZURpcnR5ID0gdHJ1ZTtcbiAgICAgICAgdHJpZ2dlclJlbmRlcmVkU2Vncyh0aGlzLmNvbnRleHQsIHRoaXMuc2VncywgQm9vbGVhbihtaXJyb3JJbmZvKSk7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLnVucmVuZGVyID0gZnVuY3Rpb24gKGNvbnRleHQsIF9zZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHRyaWdnZXJXaWxsUmVtb3ZlU2Vncyh0aGlzLmNvbnRleHQsIHRoaXMuc2VncywgQm9vbGVhbihtaXJyb3JJbmZvKSk7XG4gICAgICAgIHRoaXMuZGV0YWNoU2Vncyh0aGlzLnNlZ3MpO1xuICAgICAgICB0aGlzLnNlZ3MgPSBbXTtcbiAgICB9O1xuICAgIC8vIFVwZGF0ZXMgdmFsdWVzIHRoYXQgcmVseSBvbiBvcHRpb25zIGFuZCBhbHNvIHJlbGF0ZSB0byByYW5nZVxuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmFuZ2VVcGRhdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuY29udGV4dC5vcHRpb25zO1xuICAgICAgICB2YXIgZGlzcGxheUV2ZW50VGltZTtcbiAgICAgICAgdmFyIGRpc3BsYXlFdmVudEVuZDtcbiAgICAgICAgdGhpcy5ldmVudFRpbWVGb3JtYXQgPSBjcmVhdGVGb3JtYXR0ZXIob3B0aW9ucy5ldmVudFRpbWVGb3JtYXQgfHwgdGhpcy5jb21wdXRlRXZlbnRUaW1lRm9ybWF0KCksIG9wdGlvbnMuZGVmYXVsdFJhbmdlU2VwYXJhdG9yKTtcbiAgICAgICAgZGlzcGxheUV2ZW50VGltZSA9IG9wdGlvbnMuZGlzcGxheUV2ZW50VGltZTtcbiAgICAgICAgaWYgKGRpc3BsYXlFdmVudFRpbWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgZGlzcGxheUV2ZW50VGltZSA9IHRoaXMuY29tcHV0ZURpc3BsYXlFdmVudFRpbWUoKTsgLy8gbWlnaHQgYmUgYmFzZWQgb2ZmIG9mIHJhbmdlXG4gICAgICAgIH1cbiAgICAgICAgZGlzcGxheUV2ZW50RW5kID0gb3B0aW9ucy5kaXNwbGF5RXZlbnRFbmQ7XG4gICAgICAgIGlmIChkaXNwbGF5RXZlbnRFbmQgPT0gbnVsbCkge1xuICAgICAgICAgICAgZGlzcGxheUV2ZW50RW5kID0gdGhpcy5jb21wdXRlRGlzcGxheUV2ZW50RW5kKCk7IC8vIG1pZ2h0IGJlIGJhc2VkIG9mZiBvZiByYW5nZVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGxheUV2ZW50VGltZSA9IGRpc3BsYXlFdmVudFRpbWU7XG4gICAgICAgIHRoaXMuZGlzcGxheUV2ZW50RW5kID0gZGlzcGxheUV2ZW50RW5kO1xuICAgIH07XG4gICAgLy8gUmVuZGVycyBhbmQgYXNzaWducyBhbiBgZWxgIHByb3BlcnR5IGZvciBlYWNoIGZvcmVncm91bmQgZXZlbnQgc2VnbWVudC5cbiAgICAvLyBPbmx5IHJldHVybnMgc2VnbWVudHMgdGhhdCBzdWNjZXNzZnVsbHkgcmVuZGVyZWQuXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdFbHMgPSBmdW5jdGlvbiAoc2VncywgbWlycm9ySW5mbykge1xuICAgICAgICB2YXIgaHRtbCA9ICcnO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgaWYgKHNlZ3MubGVuZ3RoKSB7IC8vIGRvbid0IGJ1aWxkIGFuIGVtcHR5IGh0bWwgc3RyaW5nXG4gICAgICAgICAgICAvLyBidWlsZCBhIGxhcmdlIGNvbmNhdGVuYXRpb24gb2YgZXZlbnQgc2VnbWVudCBIVE1MXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gdGhpcy5yZW5kZXJTZWdIdG1sKHNlZ3NbaV0sIG1pcnJvckluZm8pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gR3JhYiBpbmRpdmlkdWFsIGVsZW1lbnRzIGZyb20gdGhlIGNvbWJpbmVkIEhUTUwgc3RyaW5nLiBVc2UgZWFjaCBhcyB0aGUgZGVmYXVsdCByZW5kZXJpbmcuXG4gICAgICAgICAgICAvLyBUaGVuLCBjb21wdXRlIHRoZSAnZWwnIGZvciBlYWNoIHNlZ21lbnQuIEFuIGVsIG1pZ2h0IGJlIG51bGwgaWYgdGhlIGV2ZW50UmVuZGVyIGNhbGxiYWNrIHJldHVybmVkIGZhbHNlLlxuICAgICAgICAgICAgaHRtbFRvRWxlbWVudHMoaHRtbCkuZm9yRWFjaChmdW5jdGlvbiAoZWwsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmVsID0gZWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWdzID0gZmlsdGVyU2Vnc1ZpYUVscyh0aGlzLmNvbnRleHQsIHNlZ3MsIEJvb2xlYW4obWlycm9ySW5mbykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH07XG4gICAgLy8gR2VuZXJpYyB1dGlsaXR5IGZvciBnZW5lcmF0aW5nIHRoZSBIVE1MIGNsYXNzTmFtZXMgZm9yIGFuIGV2ZW50IHNlZ21lbnQncyBlbGVtZW50XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5nZXRTZWdDbGFzc2VzID0gZnVuY3Rpb24gKHNlZywgaXNEcmFnZ2FibGUsIGlzUmVzaXphYmxlLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHZhciBjbGFzc2VzID0gW1xuICAgICAgICAgICAgJ2ZjLWV2ZW50JyxcbiAgICAgICAgICAgIHNlZy5pc1N0YXJ0ID8gJ2ZjLXN0YXJ0JyA6ICdmYy1ub3Qtc3RhcnQnLFxuICAgICAgICAgICAgc2VnLmlzRW5kID8gJ2ZjLWVuZCcgOiAnZmMtbm90LWVuZCdcbiAgICAgICAgXS5jb25jYXQoc2VnLmV2ZW50UmFuZ2UudWkuY2xhc3NOYW1lcyk7XG4gICAgICAgIGlmIChpc0RyYWdnYWJsZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1kcmFnZ2FibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNSZXNpemFibGUpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtcmVzaXphYmxlJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1pcnJvckluZm8pIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtbWlycm9yJyk7XG4gICAgICAgICAgICBpZiAobWlycm9ySW5mby5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1kcmFnZ2luZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1pcnJvckluZm8uaXNSZXNpemluZykge1xuICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtcmVzaXppbmcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2xhc3NlcztcbiAgICB9O1xuICAgIC8vIENvbXB1dGUgdGhlIHRleHQgdGhhdCBzaG91bGQgYmUgZGlzcGxheWVkIG9uIGFuIGV2ZW50J3MgZWxlbWVudC5cbiAgICAvLyBgcmFuZ2VgIGNhbiBiZSB0aGUgRXZlbnQgb2JqZWN0IGl0c2VsZiwgb3Igc29tZXRoaW5nIHJhbmdlLWxpa2UsIHdpdGggYXQgbGVhc3QgYSBgc3RhcnRgLlxuICAgIC8vIElmIGV2ZW50IHRpbWVzIGFyZSBkaXNhYmxlZCwgb3IgdGhlIGV2ZW50IGhhcyBubyB0aW1lLCB3aWxsIHJldHVybiBhIGJsYW5rIHN0cmluZy5cbiAgICAvLyBJZiBub3Qgc3BlY2lmaWVkLCBmb3JtYXR0ZXIgd2lsbCBkZWZhdWx0IHRvIHRoZSBldmVudFRpbWVGb3JtYXQgc2V0dGluZyxcbiAgICAvLyBhbmQgZGlzcGxheUVuZCB3aWxsIGRlZmF1bHQgdG8gdGhlIGRpc3BsYXlFdmVudEVuZCBzZXR0aW5nLlxuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZ2V0VGltZVRleHQgPSBmdW5jdGlvbiAoZXZlbnRSYW5nZSwgZm9ybWF0dGVyLCBkaXNwbGF5RW5kKSB7XG4gICAgICAgIHZhciBkZWYgPSBldmVudFJhbmdlLmRlZiwgaW5zdGFuY2UgPSBldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0VGltZVRleHQoaW5zdGFuY2UucmFuZ2Uuc3RhcnQsIGRlZi5oYXNFbmQgPyBpbnN0YW5jZS5yYW5nZS5lbmQgOiBudWxsLCBkZWYuYWxsRGF5LCBmb3JtYXR0ZXIsIGRpc3BsYXlFbmQsIGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvLCBpbnN0YW5jZS5mb3JjZWRFbmRUem8pO1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5fZ2V0VGltZVRleHQgPSBmdW5jdGlvbiAoc3RhcnQsIGVuZCwgYWxsRGF5LCBmb3JtYXR0ZXIsIGRpc3BsYXlFbmQsIGZvcmNlZFN0YXJ0VHpvLCBmb3JjZWRFbmRUem8pIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmNvbnRleHQuZGF0ZUVudjtcbiAgICAgICAgaWYgKGZvcm1hdHRlciA9PSBudWxsKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZXIgPSB0aGlzLmV2ZW50VGltZUZvcm1hdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGlzcGxheUVuZCA9PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwbGF5RW5kID0gdGhpcy5kaXNwbGF5RXZlbnRFbmQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZGlzcGxheUV2ZW50VGltZSAmJiAhYWxsRGF5KSB7XG4gICAgICAgICAgICBpZiAoZGlzcGxheUVuZCAmJiBlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXRSYW5nZShzdGFydCwgZW5kLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yY2VkU3RhcnRUem86IGZvcmNlZFN0YXJ0VHpvLFxuICAgICAgICAgICAgICAgICAgICBmb3JjZWRFbmRUem86IGZvcmNlZEVuZFR6b1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0KHN0YXJ0LCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yY2VkVHpvOiBmb3JjZWRTdGFydFR6b1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZUV2ZW50VGltZUZvcm1hdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGhvdXI6ICdudW1lcmljJyxcbiAgICAgICAgICAgIG1pbnV0ZTogJzItZGlnaXQnLFxuICAgICAgICAgICAgb21pdFplcm9NaW51dGU6IHRydWVcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZURpc3BsYXlFdmVudFRpbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRGlzcGxheUV2ZW50RW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIC8vIFV0aWxpdHkgZm9yIGdlbmVyYXRpbmcgZXZlbnQgc2tpbi1yZWxhdGVkIENTUyBwcm9wZXJ0aWVzXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5nZXRTa2luQ3NzID0gZnVuY3Rpb24gKHVpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnYmFja2dyb3VuZC1jb2xvcic6IHVpLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgICdib3JkZXItY29sb3InOiB1aS5ib3JkZXJDb2xvcixcbiAgICAgICAgICAgIGNvbG9yOiB1aS50ZXh0Q29sb3JcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuc29ydEV2ZW50U2VncyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIHZhciBzcGVjcyA9IHRoaXMuY29udGV4dC5ldmVudE9yZGVyU3BlY3M7XG4gICAgICAgIHZhciBvYmpzID0gc2Vncy5tYXAoYnVpbGRTZWdDb21wYXJlT2JqKTtcbiAgICAgICAgb2Jqcy5zb3J0KGZ1bmN0aW9uIChvYmowLCBvYmoxKSB7XG4gICAgICAgICAgICByZXR1cm4gY29tcGFyZUJ5RmllbGRTcGVjcyhvYmowLCBvYmoxLCBzcGVjcyk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gb2Jqcy5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgIHJldHVybiBjLl9zZWc7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlU2l6ZXMgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICAgICAgaWYgKGZvcmNlIHx8IHRoaXMuaXNTaXplRGlydHkpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcHV0ZVNlZ1NpemVzKHRoaXMuc2Vncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuYXNzaWduU2l6ZXMgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICAgICAgaWYgKGZvcmNlIHx8IHRoaXMuaXNTaXplRGlydHkpIHtcbiAgICAgICAgICAgIHRoaXMuYXNzaWduU2VnU2l6ZXModGhpcy5zZWdzKTtcbiAgICAgICAgICAgIHRoaXMuaXNTaXplRGlydHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlU2VnU2l6ZXMgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TZWdTaXplcyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgfTtcbiAgICAvLyBNYW5pcHVsYXRpb24gb24gcmVuZGVyZWQgc2Vnc1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuaGlkZUJ5SGFzaCA9IGZ1bmN0aW9uIChoYXNoKSB7XG4gICAgICAgIGlmIChoYXNoKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zZWdzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBzZWcgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKGhhc2hbc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmVsLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuc2hvd0J5SGFzaCA9IGZ1bmN0aW9uIChoYXNoKSB7XG4gICAgICAgIGlmIChoYXNoKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zZWdzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBzZWcgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKGhhc2hbc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmVsLnN0eWxlLnZpc2liaWxpdHkgPSAnJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuc2VsZWN0QnlJbnN0YW5jZUlkID0gZnVuY3Rpb24gKGluc3RhbmNlSWQpIHtcbiAgICAgICAgaWYgKGluc3RhbmNlSWQpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNlZ3M7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlZyA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZSA9IHNlZy5ldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICAgICAgICAgIGlmIChldmVudEluc3RhbmNlICYmIGV2ZW50SW5zdGFuY2UuaW5zdGFuY2VJZCA9PT0gaW5zdGFuY2VJZCAmJlxuICAgICAgICAgICAgICAgICAgICBzZWcuZWwgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwuY2xhc3NMaXN0LmFkZCgnZmMtc2VsZWN0ZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUudW5zZWxlY3RCeUluc3RhbmNlSWQgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2VnczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VnID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIGlmIChzZWcuZWwpIHsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtc2VsZWN0ZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBGZ0V2ZW50UmVuZGVyZXI7XG59KCkpO1xuLy8gcmV0dXJucyBhIG9iamVjdCB3aXRoIGFsbCBwcmltaXRpdmUgcHJvcHMgdGhhdCBjYW4gYmUgY29tcGFyZWRcbmZ1bmN0aW9uIGJ1aWxkU2VnQ29tcGFyZU9iaihzZWcpIHtcbiAgICB2YXIgZXZlbnREZWYgPSBzZWcuZXZlbnRSYW5nZS5kZWY7XG4gICAgdmFyIHJhbmdlID0gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UucmFuZ2U7XG4gICAgdmFyIHN0YXJ0ID0gcmFuZ2Uuc3RhcnQgPyByYW5nZS5zdGFydC52YWx1ZU9mKCkgOiAwOyAvLyBUT0RPOiBiZXR0ZXIgc3VwcG9ydCBmb3Igb3Blbi1yYW5nZSBldmVudHNcbiAgICB2YXIgZW5kID0gcmFuZ2UuZW5kID8gcmFuZ2UuZW5kLnZhbHVlT2YoKSA6IDA7IC8vIFwiXG4gICAgcmV0dXJuIF9fYXNzaWduKHt9LCBldmVudERlZi5leHRlbmRlZFByb3BzLCBldmVudERlZiwgeyBpZDogZXZlbnREZWYucHVibGljSWQsIHN0YXJ0OiBzdGFydCxcbiAgICAgICAgZW5kOiBlbmQsIGR1cmF0aW9uOiBlbmQgLSBzdGFydCwgYWxsRGF5OiBOdW1iZXIoZXZlbnREZWYuYWxsRGF5KSwgX3NlZzogc2VnIC8vIGZvciBsYXRlciByZXRyaWV2YWxcbiAgICAgfSk7XG59XG5cbi8qXG5UT0RPOiB3aGVuIHJlZmFjdG9yaW5nIHRoaXMgY2xhc3MsIG1ha2UgYSBuZXcgRmlsbFJlbmRlcmVyIGluc3RhbmNlIGZvciBlYWNoIGB0eXBlYFxuKi9cbnZhciBGaWxsUmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRmlsbFJlbmRlcmVyKCkge1xuICAgICAgICB0aGlzLmZpbGxTZWdUYWcgPSAnZGl2JztcbiAgICAgICAgdGhpcy5kaXJ0eVNpemVGbGFncyA9IHt9O1xuICAgICAgICB0aGlzLmNvbnRhaW5lckVsc0J5VHlwZSA9IHt9O1xuICAgICAgICB0aGlzLnNlZ3NCeVR5cGUgPSB7fTtcbiAgICB9XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5nZXRTZWdzQnlUeXBlID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Vnc0J5VHlwZVt0eXBlXSB8fCBbXTtcbiAgICB9O1xuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VncyA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0LCBzZWdzKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdmFyIHJlbmRlcmVkU2VncyA9IHRoaXMucmVuZGVyU2VnRWxzKHR5cGUsIHNlZ3MpOyAvLyBhc3NpZ25lcyBgLmVsYCB0byBlYWNoIHNlZy4gcmV0dXJucyBzdWNjZXNzZnVsbHkgcmVuZGVyZWQgc2Vnc1xuICAgICAgICB2YXIgY29udGFpbmVyRWxzID0gdGhpcy5hdHRhY2hTZWdzKHR5cGUsIHJlbmRlcmVkU2Vncyk7XG4gICAgICAgIGlmIChjb250YWluZXJFbHMpIHtcbiAgICAgICAgICAgIChfYSA9ICh0aGlzLmNvbnRhaW5lckVsc0J5VHlwZVt0eXBlXSB8fCAodGhpcy5jb250YWluZXJFbHNCeVR5cGVbdHlwZV0gPSBbXSkpKS5wdXNoLmFwcGx5KF9hLCBjb250YWluZXJFbHMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Vnc0J5VHlwZVt0eXBlXSA9IHJlbmRlcmVkU2VncztcbiAgICAgICAgaWYgKHR5cGUgPT09ICdiZ0V2ZW50Jykge1xuICAgICAgICAgICAgdHJpZ2dlclJlbmRlcmVkU2Vncyhjb250ZXh0LCByZW5kZXJlZFNlZ3MsIGZhbHNlKTsgLy8gaXNNaXJyb3I9ZmFsc2VcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpcnR5U2l6ZUZsYWdzW3R5cGVdID0gdHJ1ZTtcbiAgICB9O1xuICAgIC8vIFVucmVuZGVycyBhIHNwZWNpZmljIHR5cGUgb2YgZmlsbCB0aGF0IGlzIGN1cnJlbnRseSByZW5kZXJlZCBvbiB0aGUgZ3JpZFxuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUudW5yZW5kZXIgPSBmdW5jdGlvbiAodHlwZSwgY29udGV4dCkge1xuICAgICAgICB2YXIgc2VncyA9IHRoaXMuc2Vnc0J5VHlwZVt0eXBlXTtcbiAgICAgICAgaWYgKHNlZ3MpIHtcbiAgICAgICAgICAgIGlmICh0eXBlID09PSAnYmdFdmVudCcpIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyV2lsbFJlbW92ZVNlZ3MoY29udGV4dCwgc2VncywgZmFsc2UpOyAvLyBpc01pcnJvcj1mYWxzZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kZXRhY2hTZWdzKHR5cGUsIHNlZ3MpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBSZW5kZXJzIGFuZCBhc3NpZ25zIGFuIGBlbGAgcHJvcGVydHkgZm9yIGVhY2ggZmlsbCBzZWdtZW50LiBHZW5lcmljIGVub3VnaCB0byB3b3JrIHdpdGggZGlmZmVyZW50IHR5cGVzLlxuICAgIC8vIE9ubHkgcmV0dXJucyBzZWdtZW50cyB0aGF0IHN1Y2Nlc3NmdWxseSByZW5kZXJlZC5cbiAgICBGaWxsUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlclNlZ0VscyA9IGZ1bmN0aW9uICh0eXBlLCBzZWdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBodG1sID0gJyc7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBpZiAoc2Vncy5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIGJ1aWxkIGEgbGFyZ2UgY29uY2F0ZW5hdGlvbiBvZiBzZWdtZW50IEhUTUxcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSB0aGlzLnJlbmRlclNlZ0h0bWwodHlwZSwgc2Vnc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBHcmFiIGluZGl2aWR1YWwgZWxlbWVudHMgZnJvbSB0aGUgY29tYmluZWQgSFRNTCBzdHJpbmcuIFVzZSBlYWNoIGFzIHRoZSBkZWZhdWx0IHJlbmRlcmluZy5cbiAgICAgICAgICAgIC8vIFRoZW4sIGNvbXB1dGUgdGhlICdlbCcgZm9yIGVhY2ggc2VnbWVudC5cbiAgICAgICAgICAgIGh0bWxUb0VsZW1lbnRzKGh0bWwpLmZvckVhY2goZnVuY3Rpb24gKGVsLCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlZyA9IHNlZ3NbaV07XG4gICAgICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbCA9IGVsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdiZ0V2ZW50Jykge1xuICAgICAgICAgICAgICAgIHNlZ3MgPSBmaWx0ZXJTZWdzVmlhRWxzKHRoaXMuY29udGV4dCwgc2VncywgZmFsc2UgLy8gaXNNaXJyb3IuIGJhY2tncm91bmQgZXZlbnRzIGNhbiBuZXZlciBiZSBtaXJyb3IgZWxlbWVudHNcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY29ycmVjdCBlbGVtZW50IHR5cGU/ICh3b3VsZCBiZSBiYWQgaWYgYSBub24tVEQgd2VyZSBpbnNlcnRlZCBpbnRvIGEgdGFibGUgZm9yIGV4YW1wbGUpXG4gICAgICAgICAgICBzZWdzID0gc2Vncy5maWx0ZXIoZnVuY3Rpb24gKHNlZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBlbGVtZW50TWF0Y2hlcyhzZWcuZWwsIF90aGlzLmZpbGxTZWdUYWcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgdGhlIEhUTUwgbmVlZGVkIGZvciBvbmUgZmlsbCBzZWdtZW50LiBHZW5lcmljIGVub3VnaCB0byB3b3JrIHdpdGggZGlmZmVyZW50IHR5cGVzLlxuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnSHRtbCA9IGZ1bmN0aW9uICh0eXBlLCBzZWcpIHtcbiAgICAgICAgdmFyIGNzcyA9IG51bGw7XG4gICAgICAgIHZhciBjbGFzc05hbWVzID0gW107XG4gICAgICAgIGlmICh0eXBlICE9PSAnaGlnaGxpZ2h0JyAmJiB0eXBlICE9PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgICAgIGNzcyA9IHtcbiAgICAgICAgICAgICAgICAnYmFja2dyb3VuZC1jb2xvcic6IHNlZy5ldmVudFJhbmdlLnVpLmJhY2tncm91bmRDb2xvclxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSAhPT0gJ2hpZ2hsaWdodCcpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMgPSBjbGFzc05hbWVzLmNvbmNhdChzZWcuZXZlbnRSYW5nZS51aS5jbGFzc05hbWVzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2J1c2luZXNzSG91cnMnKSB7XG4gICAgICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLWJnZXZlbnQnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtJyArIHR5cGUudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICc8JyArIHRoaXMuZmlsbFNlZ1RhZyArXG4gICAgICAgICAgICAoY2xhc3NOYW1lcy5sZW5ndGggPyAnIGNsYXNzPVwiJyArIGNsYXNzTmFtZXMuam9pbignICcpICsgJ1wiJyA6ICcnKSArXG4gICAgICAgICAgICAoY3NzID8gJyBzdHlsZT1cIicgKyBjc3NUb1N0cihjc3MpICsgJ1wiJyA6ICcnKSArXG4gICAgICAgICAgICAnPjwvJyArIHRoaXMuZmlsbFNlZ1RhZyArICc+JztcbiAgICB9O1xuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUuZGV0YWNoU2VncyA9IGZ1bmN0aW9uICh0eXBlLCBzZWdzKSB7XG4gICAgICAgIHZhciBjb250YWluZXJFbHMgPSB0aGlzLmNvbnRhaW5lckVsc0J5VHlwZVt0eXBlXTtcbiAgICAgICAgaWYgKGNvbnRhaW5lckVscykge1xuICAgICAgICAgICAgY29udGFpbmVyRWxzLmZvckVhY2gocmVtb3ZlRWxlbWVudCk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jb250YWluZXJFbHNCeVR5cGVbdHlwZV07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZVNpemVzID0gZnVuY3Rpb24gKGZvcmNlKSB7XG4gICAgICAgIGZvciAodmFyIHR5cGUgaW4gdGhpcy5zZWdzQnlUeXBlKSB7XG4gICAgICAgICAgICBpZiAoZm9yY2UgfHwgdGhpcy5kaXJ0eVNpemVGbGFnc1t0eXBlXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29tcHV0ZVNlZ1NpemVzKHRoaXMuc2Vnc0J5VHlwZVt0eXBlXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUuYXNzaWduU2l6ZXMgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICAgICAgZm9yICh2YXIgdHlwZSBpbiB0aGlzLnNlZ3NCeVR5cGUpIHtcbiAgICAgICAgICAgIGlmIChmb3JjZSB8fCB0aGlzLmRpcnR5U2l6ZUZsYWdzW3R5cGVdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hc3NpZ25TZWdTaXplcyh0aGlzLnNlZ3NCeVR5cGVbdHlwZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlydHlTaXplRmxhZ3MgPSB7fTtcbiAgICB9O1xuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZVNlZ1NpemVzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICB9O1xuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUuYXNzaWduU2VnU2l6ZXMgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgIH07XG4gICAgcmV0dXJuIEZpbGxSZW5kZXJlcjtcbn0oKSk7XG5cbnZhciBOYW1lZFRpbWVab25lSW1wbCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBOYW1lZFRpbWVab25lSW1wbCh0aW1lWm9uZU5hbWUpIHtcbiAgICAgICAgdGhpcy50aW1lWm9uZU5hbWUgPSB0aW1lWm9uZU5hbWU7XG4gICAgfVxuICAgIHJldHVybiBOYW1lZFRpbWVab25lSW1wbDtcbn0oKSk7XG5cbi8qXG5BbiBhYnN0cmFjdGlvbiBmb3IgYSBkcmFnZ2luZyBpbnRlcmFjdGlvbiBvcmlnaW5hdGluZyBvbiBhbiBldmVudC5cbkRvZXMgaGlnaGVyLWxldmVsIHRoaW5ncyB0aGFuIFBvaW50ZXJEcmFnZ2VyLCBzdWNoIGFzIHBvc3NpYmx5OlxuLSBhIFwibWlycm9yXCIgdGhhdCBtb3ZlcyB3aXRoIHRoZSBwb2ludGVyXG4tIGEgbWluaW11bSBudW1iZXIgb2YgcGl4ZWxzIG9yIG90aGVyIGNyaXRlcmlhIGZvciBhIHRydWUgZHJhZyB0byBiZWdpblxuXG5zdWJjbGFzc2VzIG11c3QgZW1pdDpcbi0gcG9pbnRlcmRvd25cbi0gZHJhZ3N0YXJ0XG4tIGRyYWdtb3ZlXG4tIHBvaW50ZXJ1cFxuLSBkcmFnZW5kXG4qL1xudmFyIEVsZW1lbnREcmFnZ2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFbGVtZW50RHJhZ2dpbmcoZWwpIHtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXJNaXhpbigpO1xuICAgIH1cbiAgICBFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICBFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldE1pcnJvcklzVmlzaWJsZSA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIC8vIG9wdGlvbmFsIGlmIHN1YmNsYXNzIGRvZXNuJ3Qgd2FudCB0byBzdXBwb3J0IGEgbWlycm9yXG4gICAgfTtcbiAgICBFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldE1pcnJvck5lZWRzUmV2ZXJ0ID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgLy8gb3B0aW9uYWwgaWYgc3ViY2xhc3MgZG9lc24ndCB3YW50IHRvIHN1cHBvcnQgYSBtaXJyb3JcbiAgICB9O1xuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0QXV0b1Njcm9sbEVuYWJsZWQgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICAvLyBvcHRpb25hbFxuICAgIH07XG4gICAgcmV0dXJuIEVsZW1lbnREcmFnZ2luZztcbn0oKSk7XG5cbmZ1bmN0aW9uIGZvcm1hdERhdGUoZGF0ZUlucHV0LCBzZXR0aW5ncykge1xuICAgIGlmIChzZXR0aW5ncyA9PT0gdm9pZCAwKSB7IHNldHRpbmdzID0ge307IH1cbiAgICB2YXIgZGF0ZUVudiA9IGJ1aWxkRGF0ZUVudiQxKHNldHRpbmdzKTtcbiAgICB2YXIgZm9ybWF0dGVyID0gY3JlYXRlRm9ybWF0dGVyKHNldHRpbmdzKTtcbiAgICB2YXIgZGF0ZU1ldGEgPSBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoZGF0ZUlucHV0KTtcbiAgICBpZiAoIWRhdGVNZXRhKSB7IC8vIFRPRE86IHdhcm5pbmc/XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0KGRhdGVNZXRhLm1hcmtlciwgZm9ybWF0dGVyLCB7XG4gICAgICAgIGZvcmNlZFR6bzogZGF0ZU1ldGEuZm9yY2VkVHpvXG4gICAgfSk7XG59XG5mdW5jdGlvbiBmb3JtYXRSYW5nZShzdGFydElucHV0LCBlbmRJbnB1dCwgc2V0dGluZ3MgLy8gbWl4dHVyZSBvZiBlbnYgYW5kIGZvcm1hdHRlciBzZXR0aW5nc1xuKSB7XG4gICAgdmFyIGRhdGVFbnYgPSBidWlsZERhdGVFbnYkMSh0eXBlb2Ygc2V0dGluZ3MgPT09ICdvYmplY3QnICYmIHNldHRpbmdzID8gc2V0dGluZ3MgOiB7fSk7IC8vIHBhc3MgaW4gaWYgbm9uLW51bGwgb2JqZWN0XG4gICAgdmFyIGZvcm1hdHRlciA9IGNyZWF0ZUZvcm1hdHRlcihzZXR0aW5ncywgZ2xvYmFsRGVmYXVsdHMuZGVmYXVsdFJhbmdlU2VwYXJhdG9yKTtcbiAgICB2YXIgc3RhcnRNZXRhID0gZGF0ZUVudi5jcmVhdGVNYXJrZXJNZXRhKHN0YXJ0SW5wdXQpO1xuICAgIHZhciBlbmRNZXRhID0gZGF0ZUVudi5jcmVhdGVNYXJrZXJNZXRhKGVuZElucHV0KTtcbiAgICBpZiAoIXN0YXJ0TWV0YSB8fCAhZW5kTWV0YSkgeyAvLyBUT0RPOiB3YXJuaW5nP1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiBkYXRlRW52LmZvcm1hdFJhbmdlKHN0YXJ0TWV0YS5tYXJrZXIsIGVuZE1ldGEubWFya2VyLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgZm9yY2VkU3RhcnRUem86IHN0YXJ0TWV0YS5mb3JjZWRUem8sXG4gICAgICAgIGZvcmNlZEVuZFR6bzogZW5kTWV0YS5mb3JjZWRUem8sXG4gICAgICAgIGlzRW5kRXhjbHVzaXZlOiBzZXR0aW5ncy5pc0VuZEV4Y2x1c2l2ZVxuICAgIH0pO1xufVxuLy8gVE9ETzogbW9yZSBEUlkgYW5kIG9wdGltaXplZFxuZnVuY3Rpb24gYnVpbGREYXRlRW52JDEoc2V0dGluZ3MpIHtcbiAgICB2YXIgbG9jYWxlID0gYnVpbGRMb2NhbGUoc2V0dGluZ3MubG9jYWxlIHx8ICdlbicsIHBhcnNlUmF3TG9jYWxlcyhbXSkubWFwKTsgLy8gVE9ETzogZG9uJ3QgaGFyZGNvZGUgJ2VuJyBldmVyeXdoZXJlXG4gICAgLy8gZW5zdXJlIHJlcXVpcmVkIHNldHRpbmdzXG4gICAgc2V0dGluZ3MgPSBfX2Fzc2lnbih7IHRpbWVab25lOiBnbG9iYWxEZWZhdWx0cy50aW1lWm9uZSwgY2FsZW5kYXJTeXN0ZW06ICdncmVnb3J5JyB9LCBzZXR0aW5ncywgeyBsb2NhbGU6IGxvY2FsZSB9KTtcbiAgICByZXR1cm4gbmV3IERhdGVFbnYoc2V0dGluZ3MpO1xufVxuXG52YXIgRFJBR19NRVRBX1BST1BTID0ge1xuICAgIHN0YXJ0VGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgZHVyYXRpb246IGNyZWF0ZUR1cmF0aW9uLFxuICAgIGNyZWF0ZTogQm9vbGVhbixcbiAgICBzb3VyY2VJZDogU3RyaW5nXG59O1xudmFyIERSQUdfTUVUQV9ERUZBVUxUUyA9IHtcbiAgICBjcmVhdGU6IHRydWVcbn07XG5mdW5jdGlvbiBwYXJzZURyYWdNZXRhKHJhdykge1xuICAgIHZhciBsZWZ0b3ZlclByb3BzID0ge307XG4gICAgdmFyIHJlZmluZWQgPSByZWZpbmVQcm9wcyhyYXcsIERSQUdfTUVUQV9QUk9QUywgRFJBR19NRVRBX0RFRkFVTFRTLCBsZWZ0b3ZlclByb3BzKTtcbiAgICByZWZpbmVkLmxlZnRvdmVyUHJvcHMgPSBsZWZ0b3ZlclByb3BzO1xuICAgIHJldHVybiByZWZpbmVkO1xufVxuXG4vLyBDb21wdXRlcyBhIGRlZmF1bHQgY29sdW1uIGhlYWRlciBmb3JtYXR0aW5nIHN0cmluZyBpZiBgY29sRm9ybWF0YCBpcyBub3QgZXhwbGljaXRseSBkZWZpbmVkXG5mdW5jdGlvbiBjb21wdXRlRmFsbGJhY2tIZWFkZXJGb3JtYXQoZGF0ZXNSZXBEaXN0aW5jdERheXMsIGRheUNudCkge1xuICAgIC8vIGlmIG1vcmUgdGhhbiBvbmUgd2VlayByb3csIG9yIGlmIHRoZXJlIGFyZSBhIGxvdCBvZiBjb2x1bW5zIHdpdGggbm90IG11Y2ggc3BhY2UsXG4gICAgLy8gcHV0IGp1c3QgdGhlIGRheSBudW1iZXJzIHdpbGwgYmUgaW4gZWFjaCBjZWxsXG4gICAgaWYgKCFkYXRlc1JlcERpc3RpbmN0RGF5cyB8fCBkYXlDbnQgPiAxMCkge1xuICAgICAgICByZXR1cm4geyB3ZWVrZGF5OiAnc2hvcnQnIH07IC8vIFwiU2F0XCJcbiAgICB9XG4gICAgZWxzZSBpZiAoZGF5Q250ID4gMSkge1xuICAgICAgICByZXR1cm4geyB3ZWVrZGF5OiAnc2hvcnQnLCBtb250aDogJ251bWVyaWMnLCBkYXk6ICdudW1lcmljJywgb21pdENvbW1hczogdHJ1ZSB9OyAvLyBcIlNhdCAxMS8xMlwiXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4geyB3ZWVrZGF5OiAnbG9uZycgfTsgLy8gXCJTYXR1cmRheVwiXG4gICAgfVxufVxuZnVuY3Rpb24gcmVuZGVyRGF0ZUNlbGwoZGF0ZU1hcmtlciwgZGF0ZVByb2ZpbGUsIGRhdGVzUmVwRGlzdGluY3REYXlzLCBjb2xDbnQsIGNvbEhlYWRGb3JtYXQsIGNvbnRleHQsIGNvbHNwYW4sIG90aGVyQXR0cnMpIHtcbiAgICB2YXIgZGF0ZUVudiA9IGNvbnRleHQuZGF0ZUVudiwgdGhlbWUgPSBjb250ZXh0LnRoZW1lLCBvcHRpb25zID0gY29udGV4dC5vcHRpb25zO1xuICAgIHZhciBpc0RhdGVWYWxpZCA9IHJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGRhdGVNYXJrZXIpOyAvLyBUT0RPOiBjYWxsZWQgdG9vIGZyZXF1ZW50bHkuIGNhY2hlIHNvbWVob3cuXG4gICAgdmFyIGNsYXNzTmFtZXMgPSBbXG4gICAgICAgICdmYy1kYXktaGVhZGVyJyxcbiAgICAgICAgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldEhlYWRlcicpXG4gICAgXTtcbiAgICB2YXIgaW5uZXJIdG1sO1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jb2x1bW5IZWFkZXJIdG1sID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGlubmVySHRtbCA9IG9wdGlvbnMuY29sdW1uSGVhZGVySHRtbChkYXRlRW52LnRvRGF0ZShkYXRlTWFya2VyKSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmNvbHVtbkhlYWRlclRleHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgaW5uZXJIdG1sID0gaHRtbEVzY2FwZShvcHRpb25zLmNvbHVtbkhlYWRlclRleHQoZGF0ZUVudi50b0RhdGUoZGF0ZU1hcmtlcikpKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlubmVySHRtbCA9IGh0bWxFc2NhcGUoZGF0ZUVudi5mb3JtYXQoZGF0ZU1hcmtlciwgY29sSGVhZEZvcm1hdCkpO1xuICAgIH1cbiAgICAvLyBpZiBvbmx5IG9uZSByb3cgb2YgZGF5cywgdGhlIGNsYXNzTmFtZXMgb24gdGhlIGhlYWRlciBjYW4gcmVwcmVzZW50IHRoZSBzcGVjaWZpYyBkYXlzIGJlbmVhdGhcbiAgICBpZiAoZGF0ZXNSZXBEaXN0aW5jdERheXMpIHtcbiAgICAgICAgY2xhc3NOYW1lcyA9IGNsYXNzTmFtZXMuY29uY2F0KFxuICAgICAgICAvLyBpbmNsdWRlcyB0aGUgZGF5LW9mLXdlZWsgY2xhc3NcbiAgICAgICAgLy8gbm9UaGVtZUhpZ2hsaWdodD10cnVlIChkb24ndCBoaWdobGlnaHQgdGhlIGhlYWRlcilcbiAgICAgICAgZ2V0RGF5Q2xhc3NlcyhkYXRlTWFya2VyLCBkYXRlUHJvZmlsZSwgY29udGV4dCwgdHJ1ZSkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy0nICsgREFZX0lEU1tkYXRlTWFya2VyLmdldFVUQ0RheSgpXSk7IC8vIG9ubHkgYWRkIHRoZSBkYXktb2Ytd2VlayBjbGFzc1xuICAgIH1cbiAgICByZXR1cm4gJycgK1xuICAgICAgICAnPHRoIGNsYXNzPVwiJyArIGNsYXNzTmFtZXMuam9pbignICcpICsgJ1wiJyArXG4gICAgICAgICgoaXNEYXRlVmFsaWQgJiYgZGF0ZXNSZXBEaXN0aW5jdERheXMpID9cbiAgICAgICAgICAgICcgZGF0YS1kYXRlPVwiJyArIGRhdGVFbnYuZm9ybWF0SXNvKGRhdGVNYXJrZXIsIHsgb21pdFRpbWU6IHRydWUgfSkgKyAnXCInIDpcbiAgICAgICAgICAgICcnKSArXG4gICAgICAgIChjb2xzcGFuID4gMSA/XG4gICAgICAgICAgICAnIGNvbHNwYW49XCInICsgY29sc3BhbiArICdcIicgOlxuICAgICAgICAgICAgJycpICtcbiAgICAgICAgKG90aGVyQXR0cnMgP1xuICAgICAgICAgICAgJyAnICsgb3RoZXJBdHRycyA6XG4gICAgICAgICAgICAnJykgK1xuICAgICAgICAnPicgK1xuICAgICAgICAoaXNEYXRlVmFsaWQgP1xuICAgICAgICAgICAgLy8gZG9uJ3QgbWFrZSBhIGxpbmsgaWYgdGhlIGhlYWRpbmcgY291bGQgcmVwcmVzZW50IG11bHRpcGxlIGRheXMsIG9yIGlmIHRoZXJlJ3Mgb25seSBvbmUgZGF5IChmb3JjZU9mZilcbiAgICAgICAgICAgIGJ1aWxkR290b0FuY2hvckh0bWwob3B0aW9ucywgZGF0ZUVudiwgeyBkYXRlOiBkYXRlTWFya2VyLCBmb3JjZU9mZjogIWRhdGVzUmVwRGlzdGluY3REYXlzIHx8IGNvbENudCA9PT0gMSB9LCBpbm5lckh0bWwpIDpcbiAgICAgICAgICAgIC8vIGlmIG5vdCB2YWxpZCwgZGlzcGxheSB0ZXh0LCBidXQgbm8gbGlua1xuICAgICAgICAgICAgaW5uZXJIdG1sKSArXG4gICAgICAgICc8L3RoPic7XG59XG5cbnZhciBEYXlIZWFkZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUhlYWRlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlIZWFkZXIocGFyZW50RWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucmVuZGVyU2tlbGV0b24gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLl9yZW5kZXJTa2VsZXRvbiwgX3RoaXMuX3VucmVuZGVyU2tlbGV0b24pO1xuICAgICAgICBfdGhpcy5wYXJlbnRFbCA9IHBhcmVudEVsO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERheUhlYWRlci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBkYXRlcyA9IHByb3BzLmRhdGVzLCBkYXRlc1JlcERpc3RpbmN0RGF5cyA9IHByb3BzLmRhdGVzUmVwRGlzdGluY3REYXlzO1xuICAgICAgICB2YXIgcGFydHMgPSBbXTtcbiAgICAgICAgdGhpcy5yZW5kZXJTa2VsZXRvbihjb250ZXh0KTtcbiAgICAgICAgaWYgKHByb3BzLnJlbmRlckludHJvSHRtbCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChwcm9wcy5yZW5kZXJJbnRyb0h0bWwoKSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbEhlYWRGb3JtYXQgPSBjcmVhdGVGb3JtYXR0ZXIoY29udGV4dC5vcHRpb25zLmNvbHVtbkhlYWRlckZvcm1hdCB8fFxuICAgICAgICAgICAgY29tcHV0ZUZhbGxiYWNrSGVhZGVyRm9ybWF0KGRhdGVzUmVwRGlzdGluY3REYXlzLCBkYXRlcy5sZW5ndGgpKTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBkYXRlc18xID0gZGF0ZXM7IF9pIDwgZGF0ZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBkYXRlID0gZGF0ZXNfMVtfaV07XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHJlbmRlckRhdGVDZWxsKGRhdGUsIHByb3BzLmRhdGVQcm9maWxlLCBkYXRlc1JlcERpc3RpbmN0RGF5cywgZGF0ZXMubGVuZ3RoLCBjb2xIZWFkRm9ybWF0LCBjb250ZXh0KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbnRleHQuaXNSdGwpIHtcbiAgICAgICAgICAgIHBhcnRzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRoZWFkLmlubmVySFRNTCA9ICc8dHI+JyArIHBhcnRzLmpvaW4oJycpICsgJzwvdHI+JztcbiAgICB9O1xuICAgIERheUhlYWRlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMucmVuZGVyU2tlbGV0b24udW5yZW5kZXIoKTtcbiAgICB9O1xuICAgIERheUhlYWRlci5wcm90b3R5cGUuX3JlbmRlclNrZWxldG9uID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgdmFyIHRoZW1lID0gY29udGV4dC50aGVtZTtcbiAgICAgICAgdmFyIHBhcmVudEVsID0gdGhpcy5wYXJlbnRFbDtcbiAgICAgICAgcGFyZW50RWwuaW5uZXJIVE1MID0gJyc7IC8vIGJlY2F1c2UgbWlnaHQgYmUgbmJzcFxuICAgICAgICBwYXJlbnRFbC5hcHBlbmRDaGlsZCh0aGlzLmVsID0gaHRtbFRvRWxlbWVudCgnPGRpdiBjbGFzcz1cImZjLXJvdyAnICsgdGhlbWUuZ2V0Q2xhc3MoJ2hlYWRlclJvdycpICsgJ1wiPicgK1xuICAgICAgICAgICAgJzx0YWJsZSBjbGFzcz1cIicgKyB0aGVtZS5nZXRDbGFzcygndGFibGVHcmlkJykgKyAnXCI+JyArXG4gICAgICAgICAgICAnPHRoZWFkPjwvdGhlYWQ+JyArXG4gICAgICAgICAgICAnPC90YWJsZT4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nKSk7XG4gICAgICAgIHRoaXMudGhlYWQgPSB0aGlzLmVsLnF1ZXJ5U2VsZWN0b3IoJ3RoZWFkJyk7XG4gICAgfTtcbiAgICBEYXlIZWFkZXIucHJvdG90eXBlLl91bnJlbmRlclNrZWxldG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZW1vdmVFbGVtZW50KHRoaXMuZWwpO1xuICAgIH07XG4gICAgcmV0dXJuIERheUhlYWRlcjtcbn0oQ29tcG9uZW50KSk7XG5cbnZhciBEYXlTZXJpZXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRGF5U2VyaWVzKHJhbmdlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHJhbmdlLnN0YXJ0O1xuICAgICAgICB2YXIgZW5kID0gcmFuZ2UuZW5kO1xuICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuICAgICAgICB2YXIgZGF0ZXMgPSBbXTtcbiAgICAgICAgdmFyIGRheUluZGV4ID0gLTE7XG4gICAgICAgIHdoaWxlIChkYXRlIDwgZW5kKSB7IC8vIGxvb3AgZWFjaCBkYXkgZnJvbSBzdGFydCB0byBlbmRcbiAgICAgICAgICAgIGlmIChkYXRlUHJvZmlsZUdlbmVyYXRvci5pc0hpZGRlbkRheShkYXRlKSkge1xuICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChkYXlJbmRleCArIDAuNSk7IC8vIG1hcmsgdGhhdCBpdCdzIGJldHdlZW4gaW5kaWNlc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGF5SW5kZXgrKztcbiAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goZGF5SW5kZXgpO1xuICAgICAgICAgICAgICAgIGRhdGVzLnB1c2goZGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkYXRlID0gYWRkRGF5cyhkYXRlLCAxKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRhdGVzID0gZGF0ZXM7XG4gICAgICAgIHRoaXMuaW5kaWNlcyA9IGluZGljZXM7XG4gICAgICAgIHRoaXMuY250ID0gZGF0ZXMubGVuZ3RoO1xuICAgIH1cbiAgICBEYXlTZXJpZXMucHJvdG90eXBlLnNsaWNlUmFuZ2UgPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgICAgICAgdmFyIGZpcnN0SW5kZXggPSB0aGlzLmdldERhdGVEYXlJbmRleChyYW5nZS5zdGFydCk7IC8vIGluY2x1c2l2ZSBmaXJzdCBpbmRleFxuICAgICAgICB2YXIgbGFzdEluZGV4ID0gdGhpcy5nZXREYXRlRGF5SW5kZXgoYWRkRGF5cyhyYW5nZS5lbmQsIC0xKSk7IC8vIGluY2x1c2l2ZSBsYXN0IGluZGV4XG4gICAgICAgIHZhciBjbGlwcGVkRmlyc3RJbmRleCA9IE1hdGgubWF4KDAsIGZpcnN0SW5kZXgpO1xuICAgICAgICB2YXIgY2xpcHBlZExhc3RJbmRleCA9IE1hdGgubWluKHRoaXMuY250IC0gMSwgbGFzdEluZGV4KTtcbiAgICAgICAgLy8gZGVhbCB3aXRoIGluLWJldHdlZW4gaW5kaWNlc1xuICAgICAgICBjbGlwcGVkRmlyc3RJbmRleCA9IE1hdGguY2VpbChjbGlwcGVkRmlyc3RJbmRleCk7IC8vIGluLWJldHdlZW4gc3RhcnRzIHJvdW5kIHRvIG5leHQgY2VsbFxuICAgICAgICBjbGlwcGVkTGFzdEluZGV4ID0gTWF0aC5mbG9vcihjbGlwcGVkTGFzdEluZGV4KTsgLy8gaW4tYmV0d2VlbiBlbmRzIHJvdW5kIHRvIHByZXYgY2VsbFxuICAgICAgICBpZiAoY2xpcHBlZEZpcnN0SW5kZXggPD0gY2xpcHBlZExhc3RJbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmaXJzdEluZGV4OiBjbGlwcGVkRmlyc3RJbmRleCxcbiAgICAgICAgICAgICAgICBsYXN0SW5kZXg6IGNsaXBwZWRMYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgaXNTdGFydDogZmlyc3RJbmRleCA9PT0gY2xpcHBlZEZpcnN0SW5kZXgsXG4gICAgICAgICAgICAgICAgaXNFbmQ6IGxhc3RJbmRleCA9PT0gY2xpcHBlZExhc3RJbmRleFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBHaXZlbiBhIGRhdGUsIHJldHVybnMgaXRzIGNocm9ub2xvY2lhbCBjZWxsLWluZGV4IGZyb20gdGhlIGZpcnN0IGNlbGwgb2YgdGhlIGdyaWQuXG4gICAgLy8gSWYgdGhlIGRhdGUgbGllcyBiZXR3ZWVuIGNlbGxzIChiZWNhdXNlIG9mIGhpZGRlbkRheXMpLCByZXR1cm5zIGEgZmxvYXRpbmctcG9pbnQgdmFsdWUgYmV0d2VlbiBvZmZzZXRzLlxuICAgIC8vIElmIGJlZm9yZSB0aGUgZmlyc3Qgb2Zmc2V0LCByZXR1cm5zIGEgbmVnYXRpdmUgbnVtYmVyLlxuICAgIC8vIElmIGFmdGVyIHRoZSBsYXN0IG9mZnNldCwgcmV0dXJucyBhbiBvZmZzZXQgcGFzdCB0aGUgbGFzdCBjZWxsIG9mZnNldC5cbiAgICAvLyBPbmx5IHdvcmtzIGZvciAqc3RhcnQqIGRhdGVzIG9mIGNlbGxzLiBXaWxsIG5vdCB3b3JrIGZvciBleGNsdXNpdmUgZW5kIGRhdGVzIGZvciBjZWxscy5cbiAgICBEYXlTZXJpZXMucHJvdG90eXBlLmdldERhdGVEYXlJbmRleCA9IGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgIHZhciBpbmRpY2VzID0gdGhpcy5pbmRpY2VzO1xuICAgICAgICB2YXIgZGF5T2Zmc2V0ID0gTWF0aC5mbG9vcihkaWZmRGF5cyh0aGlzLmRhdGVzWzBdLCBkYXRlKSk7XG4gICAgICAgIGlmIChkYXlPZmZzZXQgPCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5kaWNlc1swXSAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZGF5T2Zmc2V0ID49IGluZGljZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5kaWNlc1tpbmRpY2VzLmxlbmd0aCAtIDFdICsgMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpbmRpY2VzW2RheU9mZnNldF07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBEYXlTZXJpZXM7XG59KCkpO1xuXG52YXIgRGF5VGFibGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRGF5VGFibGUoZGF5U2VyaWVzLCBicmVha09uV2Vla3MpIHtcbiAgICAgICAgdmFyIGRhdGVzID0gZGF5U2VyaWVzLmRhdGVzO1xuICAgICAgICB2YXIgZGF5c1BlclJvdztcbiAgICAgICAgdmFyIGZpcnN0RGF5O1xuICAgICAgICB2YXIgcm93Q250O1xuICAgICAgICBpZiAoYnJlYWtPbldlZWtzKSB7XG4gICAgICAgICAgICAvLyBjb3VudCBjb2x1bW5zIHVudGlsIHRoZSBkYXktb2Ytd2VlayByZXBlYXRzXG4gICAgICAgICAgICBmaXJzdERheSA9IGRhdGVzWzBdLmdldFVUQ0RheSgpO1xuICAgICAgICAgICAgZm9yIChkYXlzUGVyUm93ID0gMTsgZGF5c1BlclJvdyA8IGRhdGVzLmxlbmd0aDsgZGF5c1BlclJvdysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGVzW2RheXNQZXJSb3ddLmdldFVUQ0RheSgpID09PSBmaXJzdERheSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByb3dDbnQgPSBNYXRoLmNlaWwoZGF0ZXMubGVuZ3RoIC8gZGF5c1BlclJvdyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByb3dDbnQgPSAxO1xuICAgICAgICAgICAgZGF5c1BlclJvdyA9IGRhdGVzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd0NudCA9IHJvd0NudDtcbiAgICAgICAgdGhpcy5jb2xDbnQgPSBkYXlzUGVyUm93O1xuICAgICAgICB0aGlzLmRheVNlcmllcyA9IGRheVNlcmllcztcbiAgICAgICAgdGhpcy5jZWxscyA9IHRoaXMuYnVpbGRDZWxscygpO1xuICAgICAgICB0aGlzLmhlYWRlckRhdGVzID0gdGhpcy5idWlsZEhlYWRlckRhdGVzKCk7XG4gICAgfVxuICAgIERheVRhYmxlLnByb3RvdHlwZS5idWlsZENlbGxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciByb3cgPSAwOyByb3cgPCB0aGlzLnJvd0NudDsgcm93KyspIHtcbiAgICAgICAgICAgIHZhciBjZWxscyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgY29sID0gMDsgY29sIDwgdGhpcy5jb2xDbnQ7IGNvbCsrKSB7XG4gICAgICAgICAgICAgICAgY2VsbHMucHVzaCh0aGlzLmJ1aWxkQ2VsbChyb3csIGNvbCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcm93cy5wdXNoKGNlbGxzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcm93cztcbiAgICB9O1xuICAgIERheVRhYmxlLnByb3RvdHlwZS5idWlsZENlbGwgPSBmdW5jdGlvbiAocm93LCBjb2wpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRhdGU6IHRoaXMuZGF5U2VyaWVzLmRhdGVzW3JvdyAqIHRoaXMuY29sQ250ICsgY29sXVxuICAgICAgICB9O1xuICAgIH07XG4gICAgRGF5VGFibGUucHJvdG90eXBlLmJ1aWxkSGVhZGVyRGF0ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkYXRlcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBjb2wgPSAwOyBjb2wgPCB0aGlzLmNvbENudDsgY29sKyspIHtcbiAgICAgICAgICAgIGRhdGVzLnB1c2godGhpcy5jZWxsc1swXVtjb2xdLmRhdGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRlcztcbiAgICB9O1xuICAgIERheVRhYmxlLnByb3RvdHlwZS5zbGljZVJhbmdlID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gICAgICAgIHZhciBjb2xDbnQgPSB0aGlzLmNvbENudDtcbiAgICAgICAgdmFyIHNlcmllc1NlZyA9IHRoaXMuZGF5U2VyaWVzLnNsaWNlUmFuZ2UocmFuZ2UpO1xuICAgICAgICB2YXIgc2VncyA9IFtdO1xuICAgICAgICBpZiAoc2VyaWVzU2VnKSB7XG4gICAgICAgICAgICB2YXIgZmlyc3RJbmRleCA9IHNlcmllc1NlZy5maXJzdEluZGV4LCBsYXN0SW5kZXggPSBzZXJpZXNTZWcubGFzdEluZGV4O1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gZmlyc3RJbmRleDtcbiAgICAgICAgICAgIHdoaWxlIChpbmRleCA8PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcm93ID0gTWF0aC5mbG9vcihpbmRleCAvIGNvbENudCk7XG4gICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IE1hdGgubWluKChyb3cgKyAxKSAqIGNvbENudCwgbGFzdEluZGV4ICsgMSk7XG4gICAgICAgICAgICAgICAgc2Vncy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICAgICAgICAgIGZpcnN0Q29sOiBpbmRleCAlIGNvbENudCxcbiAgICAgICAgICAgICAgICAgICAgbGFzdENvbDogKG5leHRJbmRleCAtIDEpICUgY29sQ250LFxuICAgICAgICAgICAgICAgICAgICBpc1N0YXJ0OiBzZXJpZXNTZWcuaXNTdGFydCAmJiBpbmRleCA9PT0gZmlyc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgaXNFbmQ6IHNlcmllc1NlZy5pc0VuZCAmJiAobmV4dEluZGV4IC0gMSkgPT09IGxhc3RJbmRleFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH07XG4gICAgcmV0dXJuIERheVRhYmxlO1xufSgpKTtcblxudmFyIFNsaWNlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTbGljZXIoKSB7XG4gICAgICAgIHRoaXMuc2xpY2VCdXNpbmVzc0hvdXJzID0gbWVtb2l6ZSh0aGlzLl9zbGljZUJ1c2luZXNzSG91cnMpO1xuICAgICAgICB0aGlzLnNsaWNlRGF0ZVNlbGVjdGlvbiA9IG1lbW9pemUodGhpcy5fc2xpY2VEYXRlU3Bhbik7XG4gICAgICAgIHRoaXMuc2xpY2VFdmVudFN0b3JlID0gbWVtb2l6ZSh0aGlzLl9zbGljZUV2ZW50U3RvcmUpO1xuICAgICAgICB0aGlzLnNsaWNlRXZlbnREcmFnID0gbWVtb2l6ZSh0aGlzLl9zbGljZUludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5zbGljZUV2ZW50UmVzaXplID0gbWVtb2l6ZSh0aGlzLl9zbGljZUludGVyYWN0aW9uKTtcbiAgICB9XG4gICAgU2xpY2VyLnByb3RvdHlwZS5zbGljZVByb3BzID0gZnVuY3Rpb24gKHByb3BzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY2FsZW5kYXIsIGNvbXBvbmVudCkge1xuICAgICAgICB2YXIgZXh0cmFBcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gNTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBleHRyYUFyZ3NbX2kgLSA1XSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50VWlCYXNlcyA9IHByb3BzLmV2ZW50VWlCYXNlcztcbiAgICAgICAgdmFyIGV2ZW50U2VncyA9IHRoaXMuc2xpY2VFdmVudFN0b3JlLmFwcGx5KHRoaXMsIFtwcm9wcy5ldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRhdGVTZWxlY3Rpb25TZWdzOiB0aGlzLnNsaWNlRGF0ZVNlbGVjdGlvbi5hcHBseSh0aGlzLCBbcHJvcHMuZGF0ZVNlbGVjdGlvbiwgZXZlbnRVaUJhc2VzLCBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKSxcbiAgICAgICAgICAgIGJ1c2luZXNzSG91clNlZ3M6IHRoaXMuc2xpY2VCdXNpbmVzc0hvdXJzLmFwcGx5KHRoaXMsIFtwcm9wcy5idXNpbmVzc0hvdXJzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY2FsZW5kYXIsIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpLFxuICAgICAgICAgICAgZmdFdmVudFNlZ3M6IGV2ZW50U2Vncy5mZyxcbiAgICAgICAgICAgIGJnRXZlbnRTZWdzOiBldmVudFNlZ3MuYmcsXG4gICAgICAgICAgICBldmVudERyYWc6IHRoaXMuc2xpY2VFdmVudERyYWcuYXBwbHkodGhpcywgW3Byb3BzLmV2ZW50RHJhZywgZXZlbnRVaUJhc2VzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY29tcG9uZW50XS5jb25jYXQoZXh0cmFBcmdzKSksXG4gICAgICAgICAgICBldmVudFJlc2l6ZTogdGhpcy5zbGljZUV2ZW50UmVzaXplLmFwcGx5KHRoaXMsIFtwcm9wcy5ldmVudFJlc2l6ZSwgZXZlbnRVaUJhc2VzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY29tcG9uZW50XS5jb25jYXQoZXh0cmFBcmdzKSksXG4gICAgICAgICAgICBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb25cbiAgICAgICAgfTsgLy8gVE9ETzogZ2l2ZSBpbnRlcmFjdGlvblNlZ3M/XG4gICAgfTtcbiAgICBTbGljZXIucHJvdG90eXBlLnNsaWNlTm93RGF0ZSA9IGZ1bmN0aW9uICgvLyBkb2VzIG5vdCBtZW1vaXplXG4gICAgZGF0ZSwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAyOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDJdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fc2xpY2VEYXRlU3Bhbi5hcHBseSh0aGlzLCBbeyByYW5nZTogeyBzdGFydDogZGF0ZSwgZW5kOiBhZGRNcyhkYXRlLCAxKSB9LCBhbGxEYXk6IGZhbHNlIH0sXG4gICAgICAgICAgICB7fSxcbiAgICAgICAgICAgIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpO1xuICAgIH07XG4gICAgU2xpY2VyLnByb3RvdHlwZS5fc2xpY2VCdXNpbmVzc0hvdXJzID0gZnVuY3Rpb24gKGJ1c2luZXNzSG91cnMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjYWxlbmRhciwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSA1OyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDVdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWJ1c2luZXNzSG91cnMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fc2xpY2VFdmVudFN0b3JlLmFwcGx5KHRoaXMsIFtleHBhbmRSZWN1cnJpbmcoYnVzaW5lc3NIb3VycywgY29tcHV0ZUFjdGl2ZVJhbmdlKGRhdGVQcm9maWxlLCBCb29sZWFuKG5leHREYXlUaHJlc2hvbGQpKSwgY2FsZW5kYXIpLFxuICAgICAgICAgICAge30sXG4gICAgICAgICAgICBkYXRlUHJvZmlsZSxcbiAgICAgICAgICAgIG5leHREYXlUaHJlc2hvbGQsXG4gICAgICAgICAgICBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKS5iZztcbiAgICB9O1xuICAgIFNsaWNlci5wcm90b3R5cGUuX3NsaWNlRXZlbnRTdG9yZSA9IGZ1bmN0aW9uIChldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIGV4dHJhQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDU7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgZXh0cmFBcmdzW19pIC0gNV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudFN0b3JlKSB7XG4gICAgICAgICAgICB2YXIgcmFuZ2VSZXMgPSBzbGljZUV2ZW50U3RvcmUoZXZlbnRTdG9yZSwgZXZlbnRVaUJhc2VzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBuZXh0RGF5VGhyZXNob2xkKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgYmc6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5iZywgY29tcG9uZW50LCBleHRyYUFyZ3MpLFxuICAgICAgICAgICAgICAgIGZnOiB0aGlzLnNsaWNlRXZlbnRSYW5nZXMocmFuZ2VSZXMuZmcsIGNvbXBvbmVudCwgZXh0cmFBcmdzKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB7IGJnOiBbXSwgZmc6IFtdIH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNsaWNlci5wcm90b3R5cGUuX3NsaWNlSW50ZXJhY3Rpb24gPSBmdW5jdGlvbiAoaW50ZXJhY3Rpb24sIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbXBvbmVudCkge1xuICAgICAgICB2YXIgZXh0cmFBcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gNTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBleHRyYUFyZ3NbX2kgLSA1XSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpbnRlcmFjdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJhbmdlUmVzID0gc2xpY2VFdmVudFN0b3JlKGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMsIGV2ZW50VWlCYXNlcywgY29tcHV0ZUFjdGl2ZVJhbmdlKGRhdGVQcm9maWxlLCBCb29sZWFuKG5leHREYXlUaHJlc2hvbGQpKSwgbmV4dERheVRocmVzaG9sZCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzZWdzOiB0aGlzLnNsaWNlRXZlbnRSYW5nZXMocmFuZ2VSZXMuZmcsIGNvbXBvbmVudCwgZXh0cmFBcmdzKSxcbiAgICAgICAgICAgIGFmZmVjdGVkSW5zdGFuY2VzOiBpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cy5pbnN0YW5jZXMsXG4gICAgICAgICAgICBpc0V2ZW50OiBpbnRlcmFjdGlvbi5pc0V2ZW50LFxuICAgICAgICAgICAgc291cmNlU2VnOiBpbnRlcmFjdGlvbi5vcmlnU2VnXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBTbGljZXIucHJvdG90eXBlLl9zbGljZURhdGVTcGFuID0gZnVuY3Rpb24gKGRhdGVTcGFuLCBldmVudFVpQmFzZXMsIGNvbXBvbmVudCkge1xuICAgICAgICB2YXIgZXh0cmFBcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMzsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBleHRyYUFyZ3NbX2kgLSAzXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRlU3Bhbikge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBldmVudFJhbmdlID0gZmFicmljYXRlRXZlbnRSYW5nZShkYXRlU3BhbiwgZXZlbnRVaUJhc2VzLCBjb21wb25lbnQuY29udGV4dC5jYWxlbmRhcik7XG4gICAgICAgIHZhciBzZWdzID0gdGhpcy5zbGljZVJhbmdlLmFwcGx5KHRoaXMsIFtkYXRlU3Bhbi5yYW5nZV0uY29uY2F0KGV4dHJhQXJncykpO1xuICAgICAgICBmb3IgKHZhciBfYSA9IDAsIHNlZ3NfMSA9IHNlZ3M7IF9hIDwgc2Vnc18xLmxlbmd0aDsgX2ErKykge1xuICAgICAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMVtfYV07XG4gICAgICAgICAgICBzZWcuY29tcG9uZW50ID0gY29tcG9uZW50O1xuICAgICAgICAgICAgc2VnLmV2ZW50UmFuZ2UgPSBldmVudFJhbmdlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH07XG4gICAgLypcbiAgICBcImNvbXBsZXRlXCIgc2VnIG1lYW5zIGl0IGhhcyBjb21wb25lbnQgYW5kIGV2ZW50UmFuZ2VcbiAgICAqL1xuICAgIFNsaWNlci5wcm90b3R5cGUuc2xpY2VFdmVudFJhbmdlcyA9IGZ1bmN0aW9uIChldmVudFJhbmdlcywgY29tcG9uZW50LCAvLyBUT0RPOiBraWxsXG4gICAgZXh0cmFBcmdzKSB7XG4gICAgICAgIHZhciBzZWdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgZXZlbnRSYW5nZXNfMSA9IGV2ZW50UmFuZ2VzOyBfaSA8IGV2ZW50UmFuZ2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IGV2ZW50UmFuZ2VzXzFbX2ldO1xuICAgICAgICAgICAgc2Vncy5wdXNoLmFwcGx5KHNlZ3MsIHRoaXMuc2xpY2VFdmVudFJhbmdlKGV2ZW50UmFuZ2UsIGNvbXBvbmVudCwgZXh0cmFBcmdzKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICAvKlxuICAgIFwiY29tcGxldGVcIiBzZWcgbWVhbnMgaXQgaGFzIGNvbXBvbmVudCBhbmQgZXZlbnRSYW5nZVxuICAgICovXG4gICAgU2xpY2VyLnByb3RvdHlwZS5zbGljZUV2ZW50UmFuZ2UgPSBmdW5jdGlvbiAoZXZlbnRSYW5nZSwgY29tcG9uZW50LCAvLyBUT0RPOiBraWxsXG4gICAgZXh0cmFBcmdzKSB7XG4gICAgICAgIHZhciBzZWdzID0gdGhpcy5zbGljZVJhbmdlLmFwcGx5KHRoaXMsIFtldmVudFJhbmdlLnJhbmdlXS5jb25jYXQoZXh0cmFBcmdzKSk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18yID0gc2VnczsgX2kgPCBzZWdzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18yW19pXTtcbiAgICAgICAgICAgIHNlZy5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgICBzZWcuZXZlbnRSYW5nZSA9IGV2ZW50UmFuZ2U7XG4gICAgICAgICAgICBzZWcuaXNTdGFydCA9IGV2ZW50UmFuZ2UuaXNTdGFydCAmJiBzZWcuaXNTdGFydDtcbiAgICAgICAgICAgIHNlZy5pc0VuZCA9IGV2ZW50UmFuZ2UuaXNFbmQgJiYgc2VnLmlzRW5kO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH07XG4gICAgcmV0dXJuIFNsaWNlcjtcbn0oKSk7XG4vKlxuZm9yIGluY29ycG9yYXRpbmcgbWluVGltZS9tYXhUaW1lIGlmIGFwcHJvcHJpYXRlXG5UT0RPOiBzaG91bGQgYmUgcGFydCBvZiBEYXRlUHJvZmlsZSFcblRpbWVsaW5lRGF0ZVByb2ZpbGUgYWxyZWFkeSBkb2VzIHRoaXMgYnR3XG4qL1xuZnVuY3Rpb24gY29tcHV0ZUFjdGl2ZVJhbmdlKGRhdGVQcm9maWxlLCBpc0NvbXBvbmVudEFsbERheSkge1xuICAgIHZhciByYW5nZSA9IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlO1xuICAgIGlmIChpc0NvbXBvbmVudEFsbERheSkge1xuICAgICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiBhZGRNcyhyYW5nZS5zdGFydCwgZGF0ZVByb2ZpbGUubWluVGltZS5taWxsaXNlY29uZHMpLFxuICAgICAgICBlbmQ6IGFkZE1zKHJhbmdlLmVuZCwgZGF0ZVByb2ZpbGUubWF4VGltZS5taWxsaXNlY29uZHMgLSA4NjRlNSkgLy8gODY0ZTUgPSBtcyBpbiBhIGRheVxuICAgIH07XG59XG5cbi8vIGV4cG9ydHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG52YXIgdmVyc2lvbiA9ICc0LjQuMic7XG5cbmV4cG9ydCB7IENhbGVuZGFyLCBDb21wb25lbnQsIENvbXBvbmVudENvbnRleHQsIERhdGVDb21wb25lbnQsIERhdGVFbnYsIERhdGVQcm9maWxlR2VuZXJhdG9yLCBEYXlIZWFkZXIsIERheVNlcmllcywgRGF5VGFibGUsIEVsZW1lbnREcmFnZ2luZywgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIsIEVtaXR0ZXJNaXhpbiwgRXZlbnRBcGksIEZnRXZlbnRSZW5kZXJlciwgRmlsbFJlbmRlcmVyLCBJbnRlcmFjdGlvbiwgTWl4aW4sIE5hbWVkVGltZVpvbmVJbXBsLCBQb3NpdGlvbkNhY2hlLCBTY3JvbGxDb21wb25lbnQsIFNjcm9sbENvbnRyb2xsZXIsIFNsaWNlciwgU3BsaXR0ZXIsIFRoZW1lLCBWaWV3LCBXaW5kb3dTY3JvbGxDb250cm9sbGVyLCBhZGREYXlzLCBhZGREdXJhdGlvbnMsIGFkZE1zLCBhZGRXZWVrcywgYWxsb3dDb250ZXh0TWVudSwgYWxsb3dTZWxlY3Rpb24sIGFwcGVuZFRvRWxlbWVudCwgYXBwbHlBbGwsIGFwcGx5TXV0YXRpb25Ub0V2ZW50U3RvcmUsIGFwcGx5U3R5bGUsIGFwcGx5U3R5bGVQcm9wLCBhc1JvdWdoTWludXRlcywgYXNSb3VnaE1zLCBhc1JvdWdoU2Vjb25kcywgYnVpbGRHb3RvQW5jaG9ySHRtbCwgYnVpbGRTZWdDb21wYXJlT2JqLCBjYXBpdGFsaXNlRmlyc3RMZXR0ZXIsIGNvbWJpbmVFdmVudFVpcywgY29tcGFyZUJ5RmllbGRTcGVjLCBjb21wYXJlQnlGaWVsZFNwZWNzLCBjb21wYXJlTnVtYmVycywgY29tcGVuc2F0ZVNjcm9sbCwgY29tcHV0ZUNsaXBwaW5nUmVjdCwgY29tcHV0ZUVkZ2VzLCBjb21wdXRlRXZlbnREcmFnZ2FibGUsIGNvbXB1dGVFdmVudEVuZFJlc2l6YWJsZSwgY29tcHV0ZUV2ZW50U3RhcnRSZXNpemFibGUsIGNvbXB1dGVGYWxsYmFja0hlYWRlckZvcm1hdCwgY29tcHV0ZUhlaWdodEFuZE1hcmdpbnMsIGNvbXB1dGVJbm5lclJlY3QsIGNvbXB1dGVSZWN0LCBjb21wdXRlVmlzaWJsZURheVJhbmdlLCBjb25maWcsIGNvbnN0cmFpblBvaW50LCBjcmVhdGVEdXJhdGlvbiwgY3JlYXRlRWxlbWVudCwgY3JlYXRlRW1wdHlFdmVudFN0b3JlLCBjcmVhdGVFdmVudEluc3RhbmNlLCBjcmVhdGVGb3JtYXR0ZXIsIGNyZWF0ZVBsdWdpbiwgY3NzVG9TdHIsIGRlYm91bmNlLCBkaWZmRGF0ZXMsIGRpZmZEYXlBbmRUaW1lLCBkaWZmRGF5cywgZGlmZlBvaW50cywgZGlmZldlZWtzLCBkaWZmV2hvbGVEYXlzLCBkaWZmV2hvbGVXZWVrcywgZGlzYWJsZUN1cnNvciwgZGlzdHJpYnV0ZUhlaWdodCwgZWxlbWVudENsb3Nlc3QsIGVsZW1lbnRNYXRjaGVzLCBlbmFibGVDdXJzb3IsIGV2ZW50VHVwbGVUb1N0b3JlLCBmaWx0ZXJFdmVudFN0b3JlRGVmcywgZmlsdGVySGFzaCwgZmluZENoaWxkcmVuLCBmaW5kRWxlbWVudHMsIGZsZXhpYmxlQ29tcGFyZSwgZm9yY2VDbGFzc05hbWUsIGZvcm1hdERhdGUsIGZvcm1hdElzb1RpbWVTdHJpbmcsIGZvcm1hdFJhbmdlLCBnZXRBbGxEYXlIdG1sLCBnZXRDbGlwcGluZ1BhcmVudHMsIGdldERheUNsYXNzZXMsIGdldEVsU2VnLCBnZXRSZWN0Q2VudGVyLCBnZXRSZWxldmFudEV2ZW50cywgZ2xvYmFsRGVmYXVsdHMsIGdyZWF0ZXN0RHVyYXRpb25EZW5vbWluYXRvciwgaGFzQmdSZW5kZXJpbmcsIGh0bWxFc2NhcGUsIGh0bWxUb0VsZW1lbnQsIGluc2VydEFmdGVyRWxlbWVudCwgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZSwgaW50ZXJzZWN0UmFuZ2VzLCBpbnRlcnNlY3RSZWN0cywgaXNBcnJheXNFcXVhbCwgaXNEYXRlU3BhbnNFcXVhbCwgaXNJbnQsIGlzSW50ZXJhY3Rpb25WYWxpZCwgaXNNdWx0aURheVJhbmdlLCBpc1Byb3BzRXF1YWwsIGlzUHJvcHNWYWxpZCwgaXNTaW5nbGVEYXksIGlzVmFsaWREYXRlLCBsaXN0ZW5CeVNlbGVjdG9yLCBtYXBIYXNoLCBtYXRjaENlbGxXaWR0aHMsIG1lbW9pemUsIG1lbW9pemVPdXRwdXQsIG1lbW9pemVSZW5kZXJpbmcsIG1lcmdlRXZlbnRTdG9yZXMsIG11bHRpcGx5RHVyYXRpb24sIHBhZFN0YXJ0LCBwYXJzZUJ1c2luZXNzSG91cnMsIHBhcnNlRHJhZ01ldGEsIHBhcnNlRXZlbnREZWYsIHBhcnNlRmllbGRTcGVjcywgcGFyc2UgYXMgcGFyc2VNYXJrZXIsIHBvaW50SW5zaWRlUmVjdCwgcHJlcGVuZFRvRWxlbWVudCwgcHJldmVudENvbnRleHRNZW51LCBwcmV2ZW50RGVmYXVsdCwgcHJldmVudFNlbGVjdGlvbiwgcHJvY2Vzc1Njb3BlZFVpUHJvcHMsIHJhbmdlQ29udGFpbnNNYXJrZXIsIHJhbmdlQ29udGFpbnNSYW5nZSwgcmFuZ2VzRXF1YWwsIHJhbmdlc0ludGVyc2VjdCwgcmVmaW5lUHJvcHMsIHJlbW92ZUVsZW1lbnQsIHJlbW92ZUV4YWN0LCByZW5kZXJEYXRlQ2VsbCwgcmVxdWVzdEpzb24sIHNsaWNlRXZlbnRTdG9yZSwgc3RhcnRPZkRheSwgc3VidHJhY3RJbm5lckVsSGVpZ2h0LCB0cmFuc2xhdGVSZWN0LCB1bmNvbXBlbnNhdGVTY3JvbGwsIHVuZGlzdHJpYnV0ZUhlaWdodCwgdW5wcm9taXNpZnksIHZlcnNpb24sIHdoZW5UcmFuc2l0aW9uRG9uZSwgd2hvbGVEaXZpZGVEdXJhdGlvbnMgfTtcbiIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpbiIsIi8qIVxuRnVsbENhbGVuZGFyIERheSBHcmlkIFBsdWdpbiB2NC40LjJcbkRvY3MgJiBMaWNlbnNlOiBodHRwczovL2Z1bGxjYWxlbmRhci5pby9cbihjKSAyMDE5IEFkYW0gU2hhd1xuKi9cblxuaW1wb3J0IHsgYWRkV2Vla3MsIGRpZmZXZWVrcywgRGF0ZVByb2ZpbGVHZW5lcmF0b3IsIGNyZWF0ZUVsZW1lbnQsIGxpc3RlbkJ5U2VsZWN0b3IsIHJlbW92ZUVsZW1lbnQsIGNvbXB1dGVSZWN0LCBjb21wdXRlQ2xpcHBpbmdSZWN0LCBhcHBseVN0eWxlLCBjb21wdXRlRXZlbnREcmFnZ2FibGUsIGNvbXB1dGVFdmVudFN0YXJ0UmVzaXphYmxlLCBjb21wdXRlRXZlbnRFbmRSZXNpemFibGUsIGNzc1RvU3RyLCBodG1sRXNjYXBlLCBGZ0V2ZW50UmVuZGVyZXIsIGFwcGVuZFRvRWxlbWVudCwgcHJlcGVuZFRvRWxlbWVudCwgaHRtbFRvRWxlbWVudCwgRmlsbFJlbmRlcmVyLCBtZW1vaXplUmVuZGVyaW5nLCBjcmVhdGVGb3JtYXR0ZXIsIGFkZERheXMsIERhdGVDb21wb25lbnQsIHJhbmdlQ29udGFpbnNNYXJrZXIsIGdldERheUNsYXNzZXMsIGZpbmRFbGVtZW50cywgUG9zaXRpb25DYWNoZSwgYnVpbGRHb3RvQW5jaG9ySHRtbCwgZmluZENoaWxkcmVuLCBpbnNlcnRBZnRlckVsZW1lbnQsIGludGVyc2VjdFJhbmdlcywgbWVtb2l6ZSwgU2Nyb2xsQ29tcG9uZW50LCBtYXRjaENlbGxXaWR0aHMsIHVuY29tcGVuc2F0ZVNjcm9sbCwgY29tcGVuc2F0ZVNjcm9sbCwgc3VidHJhY3RJbm5lckVsSGVpZ2h0LCBkaXN0cmlidXRlSGVpZ2h0LCB1bmRpc3RyaWJ1dGVIZWlnaHQsIFZpZXcsIFNsaWNlciwgRGF5SGVhZGVyLCBEYXlTZXJpZXMsIERheVRhYmxlLCBjcmVhdGVQbHVnaW4gfSBmcm9tICdAZnVsbGNhbGVuZGFyL2NvcmUnO1xuXG4vKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5mdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG52YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfTtcclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59O1xuXG52YXIgRGF5R3JpZERhdGVQcm9maWxlR2VuZXJhdG9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3IsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5R3JpZERhdGVQcm9maWxlR2VuZXJhdG9yKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIC8vIENvbXB1dGVzIHRoZSBkYXRlIHJhbmdlIHRoYXQgd2lsbCBiZSByZW5kZXJlZC5cbiAgICBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkUmVuZGVyUmFuZ2UgPSBmdW5jdGlvbiAoY3VycmVudFJhbmdlLCBjdXJyZW50UmFuZ2VVbml0LCBpc1JhbmdlQWxsRGF5KSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgcmVuZGVyUmFuZ2UgPSBfc3VwZXIucHJvdG90eXBlLmJ1aWxkUmVuZGVyUmFuZ2UuY2FsbCh0aGlzLCBjdXJyZW50UmFuZ2UsIGN1cnJlbnRSYW5nZVVuaXQsIGlzUmFuZ2VBbGxEYXkpO1xuICAgICAgICB2YXIgc3RhcnQgPSByZW5kZXJSYW5nZS5zdGFydDtcbiAgICAgICAgdmFyIGVuZCA9IHJlbmRlclJhbmdlLmVuZDtcbiAgICAgICAgdmFyIGVuZE9mV2VlaztcbiAgICAgICAgLy8geWVhciBhbmQgbW9udGggdmlld3Mgc2hvdWxkIGJlIGFsaWduZWQgd2l0aCB3ZWVrcy4gdGhpcyBpcyBhbHJlYWR5IGRvbmUgZm9yIHdlZWtcbiAgICAgICAgaWYgKC9eKHllYXJ8bW9udGgpJC8udGVzdChjdXJyZW50UmFuZ2VVbml0KSkge1xuICAgICAgICAgICAgc3RhcnQgPSBkYXRlRW52LnN0YXJ0T2ZXZWVrKHN0YXJ0KTtcbiAgICAgICAgICAgIC8vIG1ha2UgZW5kLW9mLXdlZWsgaWYgbm90IGFscmVhZHlcbiAgICAgICAgICAgIGVuZE9mV2VlayA9IGRhdGVFbnYuc3RhcnRPZldlZWsoZW5kKTtcbiAgICAgICAgICAgIGlmIChlbmRPZldlZWsudmFsdWVPZigpICE9PSBlbmQudmFsdWVPZigpKSB7XG4gICAgICAgICAgICAgICAgZW5kID0gYWRkV2Vla3MoZW5kT2ZXZWVrLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBlbnN1cmUgNiB3ZWVrc1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLm1vbnRoTW9kZSAmJlxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmZpeGVkV2Vla0NvdW50KSB7XG4gICAgICAgICAgICB2YXIgcm93Q250ID0gTWF0aC5jZWlsKC8vIGNvdWxkIGJlIHBhcnRpYWwgd2Vla3MgZHVlIHRvIGhpZGRlbkRheXNcbiAgICAgICAgICAgIGRpZmZXZWVrcyhzdGFydCwgZW5kKSk7XG4gICAgICAgICAgICBlbmQgPSBhZGRXZWVrcyhlbmQsIDYgLSByb3dDbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfTtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3I7XG59KERhdGVQcm9maWxlR2VuZXJhdG9yKSk7XG5cbi8qIEEgcmVjdGFuZ3VsYXIgcGFuZWwgdGhhdCBpcyBhYnNvbHV0ZWx5IHBvc2l0aW9uZWQgb3ZlciBvdGhlciBjb250ZW50XG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbk9wdGlvbnM6XG4gIC0gY2xhc3NOYW1lIChzdHJpbmcpXG4gIC0gY29udGVudCAoSFRNTCBzdHJpbmcsIGVsZW1lbnQsIG9yIGVsZW1lbnQgYXJyYXkpXG4gIC0gcGFyZW50RWxcbiAgLSB0b3BcbiAgLSBsZWZ0XG4gIC0gcmlnaHQgKHRoZSB4IGNvb3JkIG9mIHdoZXJlIHRoZSByaWdodCBlZGdlIHNob3VsZCBiZS4gbm90IGEgXCJDU1NcIiByaWdodClcbiAgLSBhdXRvSGlkZSAoYm9vbGVhbilcbiAgLSBzaG93IChjYWxsYmFjaylcbiAgLSBoaWRlIChjYWxsYmFjaylcbiovXG52YXIgUG9wb3ZlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQb3BvdmVyKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5pc0hpZGRlbiA9IHRydWU7XG4gICAgICAgIHRoaXMubWFyZ2luID0gMTA7IC8vIHRoZSBzcGFjZSByZXF1aXJlZCBiZXR3ZWVuIHRoZSBwb3BvdmVyIGFuZCB0aGUgZWRnZXMgb2YgdGhlIHNjcm9sbCBjb250YWluZXJcbiAgICAgICAgLy8gVHJpZ2dlcmVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzICphbnl3aGVyZSogaW4gdGhlIGRvY3VtZW50LCBmb3IgdGhlIGF1dG9IaWRlIGZlYXR1cmVcbiAgICAgICAgdGhpcy5kb2N1bWVudE1vdXNlZG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgLy8gb25seSBoaWRlIHRoZSBwb3BvdmVyIGlmIHRoZSBjbGljayBoYXBwZW5lZCBvdXRzaWRlIHRoZSBwb3BvdmVyXG4gICAgICAgICAgICBpZiAoX3RoaXMuZWwgJiYgIV90aGlzLmVsLmNvbnRhaW5zKGV2LnRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfVxuICAgIC8vIFNob3dzIHRoZSBwb3BvdmVyIG9uIHRoZSBzcGVjaWZpZWQgcG9zaXRpb24uIFJlbmRlcnMgaXQgaWYgbm90IGFscmVhZHlcbiAgICBQb3BvdmVyLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc0hpZGRlbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWwuc3R5bGUuZGlzcGxheSA9ICcnO1xuICAgICAgICAgICAgdGhpcy5wb3NpdGlvbigpO1xuICAgICAgICAgICAgdGhpcy5pc0hpZGRlbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyKCdzaG93Jyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEhpZGVzIHRoZSBwb3BvdmVyLCB0aHJvdWdoIENTUywgYnV0IGRvZXMgbm90IHJlbW92ZSBpdCBmcm9tIHRoZSBET01cbiAgICBQb3BvdmVyLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNIaWRkZW4pIHtcbiAgICAgICAgICAgIHRoaXMuZWwuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIHRoaXMuaXNIaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyKCdoaWRlJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIENyZWF0ZXMgYHRoaXMuZWxgIGFuZCByZW5kZXJzIGNvbnRlbnQgaW5zaWRlIG9mIGl0XG4gICAgUG9wb3Zlci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgdmFyIGVsID0gdGhpcy5lbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZTogJ2ZjLXBvcG92ZXIgJyArIChvcHRpb25zLmNsYXNzTmFtZSB8fCAnJyksXG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICAgIHRvcDogJzAnLFxuICAgICAgICAgICAgICAgIGxlZnQ6ICcwJ1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmNvbnRlbnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuY29udGVudChlbCk7XG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucy5wYXJlbnRFbC5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIC8vIHdoZW4gYSBjbGljayBoYXBwZW5zIG9uIGFueXRoaW5nIGluc2lkZSB3aXRoIGEgJ2ZjLWNsb3NlJyBjbGFzc05hbWUsIGhpZGUgdGhlIHBvcG92ZXJcbiAgICAgICAgbGlzdGVuQnlTZWxlY3RvcihlbCwgJ2NsaWNrJywgJy5mYy1jbG9zZScsIGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuaGlkZSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG9wdGlvbnMuYXV0b0hpZGUpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuZG9jdW1lbnRNb3VzZWRvd24pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBIaWRlcyBhbmQgdW5yZWdpc3RlcnMgYW55IGhhbmRsZXJzXG4gICAgUG9wb3Zlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIGlmICh0aGlzLmVsKSB7XG4gICAgICAgICAgICByZW1vdmVFbGVtZW50KHRoaXMuZWwpO1xuICAgICAgICAgICAgdGhpcy5lbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5kb2N1bWVudE1vdXNlZG93bik7XG4gICAgfTtcbiAgICAvLyBQb3NpdGlvbnMgdGhlIHBvcG92ZXIgb3B0aW1hbGx5LCB1c2luZyB0aGUgdG9wL2xlZnQvcmlnaHQgb3B0aW9uc1xuICAgIFBvcG92ZXIucHJvdG90eXBlLnBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgdmFyIGVsID0gdGhpcy5lbDtcbiAgICAgICAgdmFyIGVsRGltcyA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyBvbmx5IHVzZWQgZm9yIHdpZHRoLGhlaWdodFxuICAgICAgICB2YXIgb3JpZ2luID0gY29tcHV0ZVJlY3QoZWwub2Zmc2V0UGFyZW50KTtcbiAgICAgICAgdmFyIGNsaXBwaW5nUmVjdCA9IGNvbXB1dGVDbGlwcGluZ1JlY3Qob3B0aW9ucy5wYXJlbnRFbCk7XG4gICAgICAgIHZhciB0b3A7IC8vIHRoZSBcInBvc2l0aW9uXCIgKG5vdCBcIm9mZnNldFwiKSB2YWx1ZXMgZm9yIHRoZSBwb3BvdmVyXG4gICAgICAgIHZhciBsZWZ0OyAvL1xuICAgICAgICAvLyBjb21wdXRlIHRvcCBhbmQgbGVmdFxuICAgICAgICB0b3AgPSBvcHRpb25zLnRvcCB8fCAwO1xuICAgICAgICBpZiAob3B0aW9ucy5sZWZ0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGxlZnQgPSBvcHRpb25zLmxlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3B0aW9ucy5yaWdodCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBsZWZ0ID0gb3B0aW9ucy5yaWdodCAtIGVsRGltcy53aWR0aDsgLy8gZGVyaXZlIHRoZSBsZWZ0IHZhbHVlIGZyb20gdGhlIHJpZ2h0IHZhbHVlXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZWZ0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb25zdHJhaW4gdG8gdGhlIHZpZXcgcG9ydC4gaWYgY29uc3RyYWluZWQgYnkgdHdvIGVkZ2VzLCBnaXZlIHByZWNlZGVuY2UgdG8gdG9wL2xlZnRcbiAgICAgICAgdG9wID0gTWF0aC5taW4odG9wLCBjbGlwcGluZ1JlY3QuYm90dG9tIC0gZWxEaW1zLmhlaWdodCAtIHRoaXMubWFyZ2luKTtcbiAgICAgICAgdG9wID0gTWF0aC5tYXgodG9wLCBjbGlwcGluZ1JlY3QudG9wICsgdGhpcy5tYXJnaW4pO1xuICAgICAgICBsZWZ0ID0gTWF0aC5taW4obGVmdCwgY2xpcHBpbmdSZWN0LnJpZ2h0IC0gZWxEaW1zLndpZHRoIC0gdGhpcy5tYXJnaW4pO1xuICAgICAgICBsZWZ0ID0gTWF0aC5tYXgobGVmdCwgY2xpcHBpbmdSZWN0LmxlZnQgKyB0aGlzLm1hcmdpbik7XG4gICAgICAgIGFwcGx5U3R5bGUoZWwsIHtcbiAgICAgICAgICAgIHRvcDogdG9wIC0gb3JpZ2luLnRvcCxcbiAgICAgICAgICAgIGxlZnQ6IGxlZnQgLSBvcmlnaW4ubGVmdFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIFRyaWdnZXJzIGEgY2FsbGJhY2suIENhbGxzIGEgZnVuY3Rpb24gaW4gdGhlIG9wdGlvbiBoYXNoIG9mIHRoZSBzYW1lIG5hbWUuXG4gICAgLy8gQXJndW1lbnRzIGJleW9uZCB0aGUgZmlyc3QgYG5hbWVgIGFyZSBmb3J3YXJkZWQgb24uXG4gICAgLy8gVE9ETzogYmV0dGVyIGNvZGUgcmV1c2UgZm9yIHRoaXMuIFJlcGVhdCBjb2RlXG4gICAgLy8gY2FuIGtpbGwgdGhpcz8/P1xuICAgIFBvcG92ZXIucHJvdG90eXBlLnRyaWdnZXIgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zW25hbWVdKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnNbbmFtZV0uYXBwbHkodGhpcywgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBQb3BvdmVyO1xufSgpKTtcblxuLyogRXZlbnQtcmVuZGVyaW5nIG1ldGhvZHMgZm9yIHRoZSBEYXlHcmlkIGNsYXNzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbi8vIFwiU2ltcGxlXCIgaXMgYmFkIGEgbmFtZS4gaGFzIG5vdGhpbmcgdG8gZG8gd2l0aCBTaW1wbGVEYXlHcmlkXG52YXIgU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIC8vIEJ1aWxkcyB0aGUgSFRNTCB0byBiZSB1c2VkIGZvciB0aGUgZGVmYXVsdCBlbGVtZW50IGZvciBhbiBpbmRpdmlkdWFsIHNlZ21lbnRcbiAgICBTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnSHRtbCA9IGZ1bmN0aW9uIChzZWcsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIGNvbnRleHQgPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgIHZhciBldmVudFJhbmdlID0gc2VnLmV2ZW50UmFuZ2U7XG4gICAgICAgIHZhciBldmVudERlZiA9IGV2ZW50UmFuZ2UuZGVmO1xuICAgICAgICB2YXIgZXZlbnRVaSA9IGV2ZW50UmFuZ2UudWk7XG4gICAgICAgIHZhciBhbGxEYXkgPSBldmVudERlZi5hbGxEYXk7XG4gICAgICAgIHZhciBpc0RyYWdnYWJsZSA9IGNvbXB1dGVFdmVudERyYWdnYWJsZShjb250ZXh0LCBldmVudERlZiwgZXZlbnRVaSk7XG4gICAgICAgIHZhciBpc1Jlc2l6YWJsZUZyb21TdGFydCA9IGFsbERheSAmJiBzZWcuaXNTdGFydCAmJiBjb21wdXRlRXZlbnRTdGFydFJlc2l6YWJsZShjb250ZXh0LCBldmVudERlZiwgZXZlbnRVaSk7XG4gICAgICAgIHZhciBpc1Jlc2l6YWJsZUZyb21FbmQgPSBhbGxEYXkgJiYgc2VnLmlzRW5kICYmIGNvbXB1dGVFdmVudEVuZFJlc2l6YWJsZShjb250ZXh0LCBldmVudERlZiwgZXZlbnRVaSk7XG4gICAgICAgIHZhciBjbGFzc2VzID0gdGhpcy5nZXRTZWdDbGFzc2VzKHNlZywgaXNEcmFnZ2FibGUsIGlzUmVzaXphYmxlRnJvbVN0YXJ0IHx8IGlzUmVzaXphYmxlRnJvbUVuZCwgbWlycm9ySW5mbyk7XG4gICAgICAgIHZhciBza2luQ3NzID0gY3NzVG9TdHIodGhpcy5nZXRTa2luQ3NzKGV2ZW50VWkpKTtcbiAgICAgICAgdmFyIHRpbWVIdG1sID0gJyc7XG4gICAgICAgIHZhciB0aW1lVGV4dDtcbiAgICAgICAgdmFyIHRpdGxlSHRtbDtcbiAgICAgICAgY2xhc3Nlcy51bnNoaWZ0KCdmYy1kYXktZ3JpZC1ldmVudCcsICdmYy1oLWV2ZW50Jyk7XG4gICAgICAgIC8vIE9ubHkgZGlzcGxheSBhIHRpbWVkIGV2ZW50cyB0aW1lIGlmIGl0IGlzIHRoZSBzdGFydGluZyBzZWdtZW50XG4gICAgICAgIGlmIChzZWcuaXNTdGFydCkge1xuICAgICAgICAgICAgdGltZVRleHQgPSB0aGlzLmdldFRpbWVUZXh0KGV2ZW50UmFuZ2UpO1xuICAgICAgICAgICAgaWYgKHRpbWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgdGltZUh0bWwgPSAnPHNwYW4gY2xhc3M9XCJmYy10aW1lXCI+JyArIGh0bWxFc2NhcGUodGltZVRleHQpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRpdGxlSHRtbCA9XG4gICAgICAgICAgICAnPHNwYW4gY2xhc3M9XCJmYy10aXRsZVwiPicgK1xuICAgICAgICAgICAgICAgIChodG1sRXNjYXBlKGV2ZW50RGVmLnRpdGxlIHx8ICcnKSB8fCAnJm5ic3A7JykgKyAvLyB3ZSBhbHdheXMgd2FudCBvbmUgbGluZSBvZiBoZWlnaHRcbiAgICAgICAgICAgICAgICAnPC9zcGFuPic7XG4gICAgICAgIHJldHVybiAnPGEgY2xhc3M9XCInICsgY2xhc3Nlcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgICAgIChldmVudERlZi51cmwgP1xuICAgICAgICAgICAgICAgICcgaHJlZj1cIicgKyBodG1sRXNjYXBlKGV2ZW50RGVmLnVybCkgKyAnXCInIDpcbiAgICAgICAgICAgICAgICAnJykgK1xuICAgICAgICAgICAgKHNraW5Dc3MgP1xuICAgICAgICAgICAgICAgICcgc3R5bGU9XCInICsgc2tpbkNzcyArICdcIicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAnPicgK1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1jb250ZW50XCI+JyArXG4gICAgICAgICAgICAoY29udGV4dC5vcHRpb25zLmRpciA9PT0gJ3J0bCcgP1xuICAgICAgICAgICAgICAgIHRpdGxlSHRtbCArICcgJyArIHRpbWVIdG1sIDogLy8gcHV0IGEgbmF0dXJhbCBzcGFjZSBpbiBiZXR3ZWVuXG4gICAgICAgICAgICAgICAgdGltZUh0bWwgKyAnICcgKyB0aXRsZUh0bWwgLy9cbiAgICAgICAgICAgICkgK1xuICAgICAgICAgICAgJzwvZGl2PicgK1xuICAgICAgICAgICAgKGlzUmVzaXphYmxlRnJvbVN0YXJ0ID9cbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLXJlc2l6ZXIgZmMtc3RhcnQtcmVzaXplclwiPjwvZGl2PicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAoaXNSZXNpemFibGVGcm9tRW5kID9cbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLXJlc2l6ZXIgZmMtZW5kLXJlc2l6ZXJcIj48L2Rpdj4nIDpcbiAgICAgICAgICAgICAgICAnJykgK1xuICAgICAgICAgICAgJzwvYT4nO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgYSBkZWZhdWx0IGV2ZW50IHRpbWUgZm9ybWF0dGluZyBzdHJpbmcgaWYgYGV2ZW50VGltZUZvcm1hdGAgaXMgbm90IGV4cGxpY2l0bHkgZGVmaW5lZFxuICAgIFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRXZlbnRUaW1lRm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG91cjogJ251bWVyaWMnLFxuICAgICAgICAgICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgICAgICAgICBvbWl0WmVyb01pbnV0ZTogdHJ1ZSxcbiAgICAgICAgICAgIG1lcmlkaWVtOiAnbmFycm93J1xuICAgICAgICB9O1xuICAgIH07XG4gICAgU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVEaXNwbGF5RXZlbnRFbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTsgLy8gVE9ETzogc29tZWhvdyBjb25zaWRlciB0aGUgb3JpZ2luYXRpbmcgRGF5R3JpZCdzIGNvbHVtbiBjb3VudFxuICAgIH07XG4gICAgcmV0dXJuIFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyO1xufShGZ0V2ZW50UmVuZGVyZXIpKTtcblxuLyogRXZlbnQtcmVuZGVyaW5nIG1ldGhvZHMgZm9yIHRoZSBEYXlHcmlkIGNsYXNzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbnZhciBEYXlHcmlkRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5R3JpZEV2ZW50UmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5R3JpZEV2ZW50UmVuZGVyZXIoZGF5R3JpZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5kYXlHcmlkID0gZGF5R3JpZDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICAvLyBSZW5kZXJzIHRoZSBnaXZlbiBmb3JlZ3JvdW5kIGV2ZW50IHNlZ21lbnRzIG9udG8gdGhlIGdyaWRcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuYXR0YWNoU2VncyA9IGZ1bmN0aW9uIChzZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHZhciByb3dTdHJ1Y3RzID0gdGhpcy5yb3dTdHJ1Y3RzID0gdGhpcy5yZW5kZXJTZWdSb3dzKHNlZ3MpO1xuICAgICAgICAvLyBhcHBlbmQgdG8gZWFjaCByb3cncyBjb250ZW50IHNrZWxldG9uXG4gICAgICAgIHRoaXMuZGF5R3JpZC5yb3dFbHMuZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSwgaSkge1xuICAgICAgICAgICAgcm93Tm9kZS5xdWVyeVNlbGVjdG9yKCcuZmMtY29udGVudC1za2VsZXRvbiA+IHRhYmxlJykuYXBwZW5kQ2hpbGQocm93U3RydWN0c1tpXS50Ym9keUVsKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHJlbW92ZXMgdGhlIFwibW9yZS4uXCIgZXZlbnRzIHBvcG92ZXJcbiAgICAgICAgaWYgKCFtaXJyb3JJbmZvKSB7XG4gICAgICAgICAgICB0aGlzLmRheUdyaWQucmVtb3ZlU2VnUG9wb3ZlcigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBVbnJlbmRlcnMgYWxsIGN1cnJlbnRseSByZW5kZXJlZCBmb3JlZ3JvdW5kIGV2ZW50IHNlZ21lbnRzXG4gICAgRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmRldGFjaFNlZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dTdHJ1Y3RzID0gdGhpcy5yb3dTdHJ1Y3RzIHx8IFtdO1xuICAgICAgICB2YXIgcm93U3RydWN0O1xuICAgICAgICB3aGlsZSAoKHJvd1N0cnVjdCA9IHJvd1N0cnVjdHMucG9wKCkpKSB7XG4gICAgICAgICAgICByZW1vdmVFbGVtZW50KHJvd1N0cnVjdC50Ym9keUVsKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd1N0cnVjdHMgPSBudWxsO1xuICAgIH07XG4gICAgLy8gVXNlcyB0aGUgZ2l2ZW4gZXZlbnRzIGFycmF5IHRvIGdlbmVyYXRlIDx0Ym9keT4gZWxlbWVudHMgdGhhdCBzaG91bGQgYmUgYXBwZW5kZWQgdG8gZWFjaCByb3cncyBjb250ZW50IHNrZWxldG9uLlxuICAgIC8vIFJldHVybnMgYW4gYXJyYXkgb2Ygcm93U3RydWN0IG9iamVjdHMgKHNlZSB0aGUgYm90dG9tIG9mIGByZW5kZXJTZWdSb3dgKS5cbiAgICAvLyBQUkVDT05ESVRJT046IGVhY2ggc2VnbWVudCBzaG91ZCBhbHJlYWR5IGhhdmUgYSByZW5kZXJlZCBhbmQgYXNzaWduZWQgYC5lbGBcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnUm93cyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIHZhciByb3dTdHJ1Y3RzID0gW107XG4gICAgICAgIHZhciBzZWdSb3dzO1xuICAgICAgICB2YXIgcm93O1xuICAgICAgICBzZWdSb3dzID0gdGhpcy5ncm91cFNlZ1Jvd3Moc2Vncyk7IC8vIGdyb3VwIGludG8gbmVzdGVkIGFycmF5c1xuICAgICAgICAvLyBpdGVyYXRlIGVhY2ggcm93IG9mIHNlZ21lbnQgZ3JvdXBpbmdzXG4gICAgICAgIGZvciAocm93ID0gMDsgcm93IDwgc2VnUm93cy5sZW5ndGg7IHJvdysrKSB7XG4gICAgICAgICAgICByb3dTdHJ1Y3RzLnB1c2godGhpcy5yZW5kZXJTZWdSb3cocm93LCBzZWdSb3dzW3Jvd10pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcm93U3RydWN0cztcbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgcm93ICMgYW5kIGFuIGFycmF5IG9mIHNlZ21lbnRzIGFsbCBpbiB0aGUgc2FtZSByb3csIHJlbmRlciBhIDx0Ym9keT4gZWxlbWVudCwgYSBza2VsZXRvbiB0aGF0IGNvbnRhaW5zXG4gICAgLy8gdGhlIHNlZ21lbnRzLiBSZXR1cm5zIG9iamVjdCB3aXRoIGEgYnVuY2ggb2YgaW50ZXJuYWwgZGF0YSBhYm91dCBob3cgdGhlIHJlbmRlciB3YXMgY2FsY3VsYXRlZC5cbiAgICAvLyBOT1RFOiBtb2RpZmllcyByb3dTZWdzXG4gICAgRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLnJlbmRlclNlZ1JvdyA9IGZ1bmN0aW9uIChyb3csIHJvd1NlZ3MpIHtcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5jb250ZXh0LmlzUnRsO1xuICAgICAgICB2YXIgZGF5R3JpZCA9IHRoaXMuZGF5R3JpZDtcbiAgICAgICAgdmFyIGNvbENudCA9IGRheUdyaWQuY29sQ250O1xuICAgICAgICB2YXIgc2VnTGV2ZWxzID0gdGhpcy5idWlsZFNlZ0xldmVscyhyb3dTZWdzKTsgLy8gZ3JvdXAgaW50byBzdWItYXJyYXlzIG9mIGxldmVsc1xuICAgICAgICB2YXIgbGV2ZWxDbnQgPSBNYXRoLm1heCgxLCBzZWdMZXZlbHMubGVuZ3RoKTsgLy8gZW5zdXJlIGF0IGxlYXN0IG9uZSBsZXZlbFxuICAgICAgICB2YXIgdGJvZHkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0Ym9keScpO1xuICAgICAgICB2YXIgc2VnTWF0cml4ID0gW107IC8vIGxvb2t1cCBmb3Igd2hpY2ggc2VnbWVudHMgYXJlIHJlbmRlcmVkIGludG8gd2hpY2ggbGV2ZWwrY29sIGNlbGxzXG4gICAgICAgIHZhciBjZWxsTWF0cml4ID0gW107IC8vIGxvb2t1cCBmb3IgYWxsIDx0ZD4gZWxlbWVudHMgb2YgdGhlIGxldmVsK2NvbCBtYXRyaXhcbiAgICAgICAgdmFyIGxvbmVDZWxsTWF0cml4ID0gW107IC8vIGxvb2t1cCBmb3IgPHRkPiBlbGVtZW50cyB0aGF0IG9ubHkgdGFrZSB1cCBhIHNpbmdsZSBjb2x1bW5cbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBsZXZlbFNlZ3M7XG4gICAgICAgIHZhciBjb2w7XG4gICAgICAgIHZhciB0cjtcbiAgICAgICAgdmFyIGo7XG4gICAgICAgIHZhciBzZWc7XG4gICAgICAgIHZhciB0ZDtcbiAgICAgICAgLy8gcG9wdWxhdGVzIGVtcHR5IGNlbGxzIGZyb20gdGhlIGN1cnJlbnQgY29sdW1uIChgY29sYCkgdG8gYGVuZENvbGBcbiAgICAgICAgZnVuY3Rpb24gZW1wdHlDZWxsc1VudGlsKGVuZENvbCkge1xuICAgICAgICAgICAgd2hpbGUgKGNvbCA8IGVuZENvbCkge1xuICAgICAgICAgICAgICAgIC8vIHRyeSB0byBncmFiIGEgY2VsbCBmcm9tIHRoZSBsZXZlbCBhYm92ZSBhbmQgZXh0ZW5kIGl0cyByb3dzcGFuLiBvdGhlcndpc2UsIGNyZWF0ZSBhIGZyZXNoIGNlbGxcbiAgICAgICAgICAgICAgICB0ZCA9IChsb25lQ2VsbE1hdHJpeFtpIC0gMV0gfHwgW10pW2NvbF07XG4gICAgICAgICAgICAgICAgaWYgKHRkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRkLnJvd1NwYW4gPSAodGQucm93U3BhbiB8fCAxKSArIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0ZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RkJyk7XG4gICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2VsbE1hdHJpeFtpXVtjb2xdID0gdGQ7XG4gICAgICAgICAgICAgICAgbG9uZUNlbGxNYXRyaXhbaV1bY29sXSA9IHRkO1xuICAgICAgICAgICAgICAgIGNvbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZXZlbENudDsgaSsrKSB7IC8vIGl0ZXJhdGUgdGhyb3VnaCBhbGwgbGV2ZWxzXG4gICAgICAgICAgICBsZXZlbFNlZ3MgPSBzZWdMZXZlbHNbaV07XG4gICAgICAgICAgICBjb2wgPSAwO1xuICAgICAgICAgICAgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0cicpO1xuICAgICAgICAgICAgc2VnTWF0cml4LnB1c2goW10pO1xuICAgICAgICAgICAgY2VsbE1hdHJpeC5wdXNoKFtdKTtcbiAgICAgICAgICAgIGxvbmVDZWxsTWF0cml4LnB1c2goW10pO1xuICAgICAgICAgICAgLy8gbGV2ZWxDbnQgbWlnaHQgYmUgMSBldmVuIHRob3VnaCB0aGVyZSBhcmUgbm8gYWN0dWFsIGxldmVscy4gcHJvdGVjdCBhZ2FpbnN0IHRoaXMuXG4gICAgICAgICAgICAvLyB0aGlzIHNpbmdsZSBlbXB0eSByb3cgaXMgdXNlZnVsIGZvciBzdHlsaW5nLlxuICAgICAgICAgICAgaWYgKGxldmVsU2Vncykge1xuICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBsZXZlbFNlZ3MubGVuZ3RoOyBqKyspIHsgLy8gaXRlcmF0ZSB0aHJvdWdoIHNlZ21lbnRzIGluIGxldmVsXG4gICAgICAgICAgICAgICAgICAgIHNlZyA9IGxldmVsU2Vnc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmxhc3RDb2wpIDogc2VnLmZpcnN0Q29sO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmZpcnN0Q29sKSA6IHNlZy5sYXN0Q29sO1xuICAgICAgICAgICAgICAgICAgICBlbXB0eUNlbGxzVW50aWwobGVmdENvbCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNyZWF0ZSBhIGNvbnRhaW5lciB0aGF0IG9jY3VwaWVzIG9yIG1vcmUgY29sdW1ucy4gYXBwZW5kIHRoZSBldmVudCBlbGVtZW50LlxuICAgICAgICAgICAgICAgICAgICB0ZCA9IGNyZWF0ZUVsZW1lbnQoJ3RkJywgeyBjbGFzc05hbWU6ICdmYy1ldmVudC1jb250YWluZXInIH0sIHNlZy5lbCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZWZ0Q29sICE9PSByaWdodENvbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGQuY29sU3BhbiA9IHJpZ2h0Q29sIC0gbGVmdENvbCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7IC8vIGEgc2luZ2xlLWNvbHVtbiBzZWdtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICBsb25lQ2VsbE1hdHJpeFtpXVtjb2xdID0gdGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGNvbCA8PSByaWdodENvbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2VsbE1hdHJpeFtpXVtjb2xdID0gdGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWdNYXRyaXhbaV1bY29sXSA9IHNlZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbXB0eUNlbGxzVW50aWwoY29sQ250KTsgLy8gZmluaXNoIG9mZiB0aGUgcm93XG4gICAgICAgICAgICB2YXIgaW50cm9IdG1sID0gZGF5R3JpZC5yZW5kZXJQcm9wcy5yZW5kZXJJbnRyb0h0bWwoKTtcbiAgICAgICAgICAgIGlmIChpbnRyb0h0bWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYXBwZW5kVG9FbGVtZW50KHRyLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlcGVuZFRvRWxlbWVudCh0ciwgaW50cm9IdG1sKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0Ym9keS5hcHBlbmRDaGlsZCh0cik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvdzogcm93LFxuICAgICAgICAgICAgdGJvZHlFbDogdGJvZHksXG4gICAgICAgICAgICBjZWxsTWF0cml4OiBjZWxsTWF0cml4LFxuICAgICAgICAgICAgc2VnTWF0cml4OiBzZWdNYXRyaXgsXG4gICAgICAgICAgICBzZWdMZXZlbHM6IHNlZ0xldmVscyxcbiAgICAgICAgICAgIHNlZ3M6IHJvd1NlZ3NcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIC8vIFN0YWNrcyBhIGZsYXQgYXJyYXkgb2Ygc2VnbWVudHMsIHdoaWNoIGFyZSBhbGwgYXNzdW1lZCB0byBiZSBpbiB0aGUgc2FtZSByb3csIGludG8gc3ViYXJyYXlzIG9mIHZlcnRpY2FsIGxldmVscy5cbiAgICAvLyBOT1RFOiBtb2RpZmllcyBzZWdzXG4gICAgRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmJ1aWxkU2VnTGV2ZWxzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5jb250ZXh0LmlzUnRsO1xuICAgICAgICB2YXIgY29sQ250ID0gdGhpcy5kYXlHcmlkLmNvbENudDtcbiAgICAgICAgdmFyIGxldmVscyA9IFtdO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHNlZztcbiAgICAgICAgdmFyIGo7XG4gICAgICAgIC8vIEdpdmUgcHJlZmVyZW5jZSB0byBlbGVtZW50cyB3aXRoIGNlcnRhaW4gY3JpdGVyaWEsIHNvIHRoZXkgaGF2ZVxuICAgICAgICAvLyBhIGNoYW5jZSB0byBiZSBjbG9zZXIgdG8gdGhlIHRvcC5cbiAgICAgICAgc2VncyA9IHRoaXMuc29ydEV2ZW50U2VncyhzZWdzKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNlZyA9IHNlZ3NbaV07XG4gICAgICAgICAgICAvLyBsb29wIHRocm91Z2ggbGV2ZWxzLCBzdGFydGluZyB3aXRoIHRoZSB0b3Btb3N0LCB1bnRpbCB0aGUgc2VnbWVudCBkb2Vzbid0IGNvbGxpZGUgd2l0aCBvdGhlciBzZWdtZW50c1xuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGxldmVscy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGlmICghaXNEYXlTZWdDb2xsaXNpb24oc2VnLCBsZXZlbHNbal0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGBqYCBub3cgaG9sZHMgdGhlIGRlc2lyZWQgc3Vicm93IGluZGV4XG4gICAgICAgICAgICBzZWcubGV2ZWwgPSBqO1xuICAgICAgICAgICAgc2VnLmxlZnRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmxhc3RDb2wpIDogc2VnLmZpcnN0Q29sOyAvLyBmb3Igc29ydGluZyBvbmx5XG4gICAgICAgICAgICBzZWcucmlnaHRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmZpcnN0Q29sKSA6IHNlZy5sYXN0Q29sIC8vIGZvciBzb3J0aW5nIG9ubHlcbiAgICAgICAgICAgIDtcbiAgICAgICAgICAgIChsZXZlbHNbal0gfHwgKGxldmVsc1tqXSA9IFtdKSkucHVzaChzZWcpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG9yZGVyIHNlZ21lbnRzIGxlZnQtdG8tcmlnaHQuIHZlcnkgaW1wb3J0YW50IGlmIGNhbGVuZGFyIGlzIFJUTFxuICAgICAgICBmb3IgKGogPSAwOyBqIDwgbGV2ZWxzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBsZXZlbHNbal0uc29ydChjb21wYXJlRGF5U2VnQ29scyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxldmVscztcbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgZmxhdCBhcnJheSBvZiBzZWdtZW50cywgcmV0dXJuIGFuIGFycmF5IG9mIHN1Yi1hcnJheXMsIGdyb3VwZWQgYnkgZWFjaCBzZWdtZW50J3Mgcm93XG4gICAgRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmdyb3VwU2VnUm93cyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIHZhciBzZWdSb3dzID0gW107XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5kYXlHcmlkLnJvd0NudDsgaSsrKSB7XG4gICAgICAgICAgICBzZWdSb3dzLnB1c2goW10pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzZWdSb3dzW3NlZ3NbaV0ucm93XS5wdXNoKHNlZ3NbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdSb3dzO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgYSBkZWZhdWx0IGBkaXNwbGF5RXZlbnRFbmRgIHZhbHVlIGlmIG9uZSBpcyBub3QgZXhwbGljbHR5IGRlZmluZWRcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZURpc3BsYXlFdmVudEVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5R3JpZC5jb2xDbnQgPT09IDE7IC8vIHdlJ2xsIGxpa2VseSBoYXZlIHNwYWNlIGlmIHRoZXJlJ3Mgb25seSBvbmUgZGF5XG4gICAgfTtcbiAgICByZXR1cm4gRGF5R3JpZEV2ZW50UmVuZGVyZXI7XG59KFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyKSk7XG4vLyBDb21wdXRlcyB3aGV0aGVyIHR3byBzZWdtZW50cycgY29sdW1ucyBjb2xsaWRlLiBUaGV5IGFyZSBhc3N1bWVkIHRvIGJlIGluIHRoZSBzYW1lIHJvdy5cbmZ1bmN0aW9uIGlzRGF5U2VnQ29sbGlzaW9uKHNlZywgb3RoZXJTZWdzKSB7XG4gICAgdmFyIGk7XG4gICAgdmFyIG90aGVyU2VnO1xuICAgIGZvciAoaSA9IDA7IGkgPCBvdGhlclNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb3RoZXJTZWcgPSBvdGhlclNlZ3NbaV07XG4gICAgICAgIGlmIChvdGhlclNlZy5maXJzdENvbCA8PSBzZWcubGFzdENvbCAmJlxuICAgICAgICAgICAgb3RoZXJTZWcubGFzdENvbCA+PSBzZWcuZmlyc3RDb2wpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8vIEEgY21wIGZ1bmN0aW9uIGZvciBkZXRlcm1pbmluZyB0aGUgbGVmdG1vc3QgZXZlbnRcbmZ1bmN0aW9uIGNvbXBhcmVEYXlTZWdDb2xzKGEsIGIpIHtcbiAgICByZXR1cm4gYS5sZWZ0Q29sIC0gYi5sZWZ0Q29sO1xufVxuXG52YXIgRGF5R3JpZE1pcnJvclJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkTWlycm9yUmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5R3JpZE1pcnJvclJlbmRlcmVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIERheUdyaWRNaXJyb3JSZW5kZXJlci5wcm90b3R5cGUuYXR0YWNoU2VncyA9IGZ1bmN0aW9uIChzZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHZhciBzb3VyY2VTZWcgPSBtaXJyb3JJbmZvLnNvdXJjZVNlZztcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSB0aGlzLnJvd1N0cnVjdHMgPSB0aGlzLnJlbmRlclNlZ1Jvd3Moc2Vncyk7XG4gICAgICAgIC8vIGluamVjdCBlYWNoIG5ldyBldmVudCBza2VsZXRvbiBpbnRvIGVhY2ggYXNzb2NpYXRlZCByb3dcbiAgICAgICAgdGhpcy5kYXlHcmlkLnJvd0Vscy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlLCByb3cpIHtcbiAgICAgICAgICAgIHZhciBza2VsZXRvbkVsID0gaHRtbFRvRWxlbWVudCgnPGRpdiBjbGFzcz1cImZjLW1pcnJvci1za2VsZXRvblwiPjx0YWJsZT48L3RhYmxlPjwvZGl2PicpOyAvLyB3aWxsIGJlIGFic29sdXRlbHkgcG9zaXRpb25lZFxuICAgICAgICAgICAgdmFyIHNrZWxldG9uVG9wRWw7XG4gICAgICAgICAgICB2YXIgc2tlbGV0b25Ub3A7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBhbiBvcmlnaW5hbCBzZWdtZW50LCBtYXRjaCB0aGUgdG9wIHBvc2l0aW9uLiBPdGhlcndpc2UsIHB1dCBpdCBhdCB0aGUgcm93J3MgdG9wIGxldmVsXG4gICAgICAgICAgICBpZiAoc291cmNlU2VnICYmIHNvdXJjZVNlZy5yb3cgPT09IHJvdykge1xuICAgICAgICAgICAgICAgIHNrZWxldG9uVG9wRWwgPSBzb3VyY2VTZWcuZWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBza2VsZXRvblRvcEVsID0gcm93Tm9kZS5xdWVyeVNlbGVjdG9yKCcuZmMtY29udGVudC1za2VsZXRvbiB0Ym9keScpO1xuICAgICAgICAgICAgICAgIGlmICghc2tlbGV0b25Ub3BFbCkgeyAvLyB3aGVuIG5vIGV2ZW50c1xuICAgICAgICAgICAgICAgICAgICBza2VsZXRvblRvcEVsID0gcm93Tm9kZS5xdWVyeVNlbGVjdG9yKCcuZmMtY29udGVudC1za2VsZXRvbiB0YWJsZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNrZWxldG9uVG9wID0gc2tlbGV0b25Ub3BFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLVxuICAgICAgICAgICAgICAgIHJvd05vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wOyAvLyB0aGUgb2Zmc2V0UGFyZW50IG9yaWdpblxuICAgICAgICAgICAgc2tlbGV0b25FbC5zdHlsZS50b3AgPSBza2VsZXRvblRvcCArICdweCc7XG4gICAgICAgICAgICBza2VsZXRvbkVsLnF1ZXJ5U2VsZWN0b3IoJ3RhYmxlJykuYXBwZW5kQ2hpbGQocm93U3RydWN0c1tyb3ddLnRib2R5RWwpO1xuICAgICAgICAgICAgcm93Tm9kZS5hcHBlbmRDaGlsZChza2VsZXRvbkVsKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5R3JpZE1pcnJvclJlbmRlcmVyO1xufShEYXlHcmlkRXZlbnRSZW5kZXJlcikpO1xuXG52YXIgRU1QVFlfQ0VMTF9IVE1MID0gJzx0ZCBzdHlsZT1cInBvaW50ZXItZXZlbnRzOm5vbmVcIj48L3RkPic7XG52YXIgRGF5R3JpZEZpbGxSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5R3JpZEZpbGxSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkRmlsbFJlbmRlcmVyKGRheUdyaWQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZmlsbFNlZ1RhZyA9ICd0ZCc7IC8vIG92ZXJyaWRlIHRoZSBkZWZhdWx0IHRhZyBuYW1lXG4gICAgICAgIF90aGlzLmRheUdyaWQgPSBkYXlHcmlkO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERheUdyaWRGaWxsUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlclNlZ3MgPSBmdW5jdGlvbiAodHlwZSwgY29udGV4dCwgc2Vncykge1xuICAgICAgICAvLyBkb24ndCByZW5kZXIgdGltZWQgYmFja2dyb3VuZCBldmVudHNcbiAgICAgICAgaWYgKHR5cGUgPT09ICdiZ0V2ZW50Jykge1xuICAgICAgICAgICAgc2VncyA9IHNlZ3MuZmlsdGVyKGZ1bmN0aW9uIChzZWcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2VnLmV2ZW50UmFuZ2UuZGVmLmFsbERheTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucmVuZGVyU2Vncy5jYWxsKHRoaXMsIHR5cGUsIGNvbnRleHQsIHNlZ3MpO1xuICAgIH07XG4gICAgRGF5R3JpZEZpbGxSZW5kZXJlci5wcm90b3R5cGUuYXR0YWNoU2VncyA9IGZ1bmN0aW9uICh0eXBlLCBzZWdzKSB7XG4gICAgICAgIHZhciBlbHMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBzZWc7XG4gICAgICAgIHZhciBza2VsZXRvbkVsO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgIHNrZWxldG9uRWwgPSB0aGlzLnJlbmRlckZpbGxSb3codHlwZSwgc2VnKTtcbiAgICAgICAgICAgIHRoaXMuZGF5R3JpZC5yb3dFbHNbc2VnLnJvd10uYXBwZW5kQ2hpbGQoc2tlbGV0b25FbCk7XG4gICAgICAgICAgICBlbHMucHVzaChza2VsZXRvbkVsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxzO1xuICAgIH07XG4gICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIG5lZWRlZCBmb3Igb25lIHJvdyBvZiBhIGZpbGwuIFJlcXVpcmVzIHRoZSBzZWcncyBlbCB0byBiZSByZW5kZXJlZC5cbiAgICBEYXlHcmlkRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJGaWxsUm93ID0gZnVuY3Rpb24gKHR5cGUsIHNlZykge1xuICAgICAgICB2YXIgZGF5R3JpZCA9IHRoaXMuZGF5R3JpZDtcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5jb250ZXh0LmlzUnRsO1xuICAgICAgICB2YXIgY29sQ250ID0gZGF5R3JpZC5jb2xDbnQ7XG4gICAgICAgIHZhciBsZWZ0Q29sID0gaXNSdGwgPyAoY29sQ250IC0gMSAtIHNlZy5sYXN0Q29sKSA6IHNlZy5maXJzdENvbDtcbiAgICAgICAgdmFyIHJpZ2h0Q29sID0gaXNSdGwgPyAoY29sQ250IC0gMSAtIHNlZy5maXJzdENvbCkgOiBzZWcubGFzdENvbDtcbiAgICAgICAgdmFyIHN0YXJ0Q29sID0gbGVmdENvbDtcbiAgICAgICAgdmFyIGVuZENvbCA9IHJpZ2h0Q29sICsgMTtcbiAgICAgICAgdmFyIGNsYXNzTmFtZTtcbiAgICAgICAgdmFyIHNrZWxldG9uRWw7XG4gICAgICAgIHZhciB0ckVsO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2J1c2luZXNzSG91cnMnKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSAnYmdldmVudCc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSB0eXBlLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgc2tlbGV0b25FbCA9IGh0bWxUb0VsZW1lbnQoJzxkaXYgY2xhc3M9XCJmYy0nICsgY2xhc3NOYW1lICsgJy1za2VsZXRvblwiPicgK1xuICAgICAgICAgICAgJzx0YWJsZT48dHI+PC90cj48L3RhYmxlPicgK1xuICAgICAgICAgICAgJzwvZGl2PicpO1xuICAgICAgICB0ckVsID0gc2tlbGV0b25FbC5nZXRFbGVtZW50c0J5VGFnTmFtZSgndHInKVswXTtcbiAgICAgICAgaWYgKHN0YXJ0Q29sID4gMCkge1xuICAgICAgICAgICAgYXBwZW5kVG9FbGVtZW50KHRyRWwsIFxuICAgICAgICAgICAgLy8gd2lsbCBjcmVhdGUgKHN0YXJ0Q29sICsgMSkgdGQnc1xuICAgICAgICAgICAgbmV3IEFycmF5KHN0YXJ0Q29sICsgMSkuam9pbihFTVBUWV9DRUxMX0hUTUwpKTtcbiAgICAgICAgfVxuICAgICAgICBzZWcuZWwuY29sU3BhbiA9IGVuZENvbCAtIHN0YXJ0Q29sO1xuICAgICAgICB0ckVsLmFwcGVuZENoaWxkKHNlZy5lbCk7XG4gICAgICAgIGlmIChlbmRDb2wgPCBjb2xDbnQpIHtcbiAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudCh0ckVsLCBcbiAgICAgICAgICAgIC8vIHdpbGwgY3JlYXRlIChjb2xDbnQgLSBlbmRDb2wpIHRkJ3NcbiAgICAgICAgICAgIG5ldyBBcnJheShjb2xDbnQgLSBlbmRDb2wgKyAxKS5qb2luKEVNUFRZX0NFTExfSFRNTCkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbnRyb0h0bWwgPSBkYXlHcmlkLnJlbmRlclByb3BzLnJlbmRlckludHJvSHRtbCgpO1xuICAgICAgICBpZiAoaW50cm9IdG1sKSB7XG4gICAgICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQodHJFbCwgaW50cm9IdG1sKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHByZXBlbmRUb0VsZW1lbnQodHJFbCwgaW50cm9IdG1sKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2tlbGV0b25FbDtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkRmlsbFJlbmRlcmVyO1xufShGaWxsUmVuZGVyZXIpKTtcblxudmFyIERheVRpbGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheVRpbGUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5VGlsZShlbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBlbCkgfHwgdGhpcztcbiAgICAgICAgdmFyIGV2ZW50UmVuZGVyZXIgPSBfdGhpcy5ldmVudFJlbmRlcmVyID0gbmV3IERheVRpbGVFdmVudFJlbmRlcmVyKF90aGlzKTtcbiAgICAgICAgdmFyIHJlbmRlckZyYW1lID0gX3RoaXMucmVuZGVyRnJhbWUgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLl9yZW5kZXJGcmFtZSk7XG4gICAgICAgIF90aGlzLnJlbmRlckZnRXZlbnRzID0gbWVtb2l6ZVJlbmRlcmluZyhldmVudFJlbmRlcmVyLnJlbmRlclNlZ3MuYmluZChldmVudFJlbmRlcmVyKSwgZXZlbnRSZW5kZXJlci51bnJlbmRlci5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbcmVuZGVyRnJhbWVdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRTZWxlY3Rpb24gPSBtZW1vaXplUmVuZGVyaW5nKGV2ZW50UmVuZGVyZXIuc2VsZWN0QnlJbnN0YW5jZUlkLmJpbmQoZXZlbnRSZW5kZXJlciksIGV2ZW50UmVuZGVyZXIudW5zZWxlY3RCeUluc3RhbmNlSWQuYmluZChldmVudFJlbmRlcmVyKSwgW190aGlzLnJlbmRlckZnRXZlbnRzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50RHJhZyA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5oaWRlQnlIYXNoLmJpbmQoZXZlbnRSZW5kZXJlciksIGV2ZW50UmVuZGVyZXIuc2hvd0J5SGFzaC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbcmVuZGVyRnJhbWVdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRSZXNpemUgPSBtZW1vaXplUmVuZGVyaW5nKGV2ZW50UmVuZGVyZXIuaGlkZUJ5SGFzaC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBldmVudFJlbmRlcmVyLnNob3dCeUhhc2guYmluZChldmVudFJlbmRlcmVyKSwgW3JlbmRlckZyYW1lXSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5VGlsZS5wcm90b3R5cGUuZmlyc3RDb250ZXh0ID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgY29udGV4dC5jYWxlbmRhci5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KHRoaXMsIHtcbiAgICAgICAgICAgIGVsOiB0aGlzLmVsLFxuICAgICAgICAgICAgdXNlRXZlbnRDZW50ZXI6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRGF5VGlsZS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzLCBjb250ZXh0KSB7XG4gICAgICAgIHRoaXMucmVuZGVyRnJhbWUocHJvcHMuZGF0ZSk7XG4gICAgICAgIHRoaXMucmVuZGVyRmdFdmVudHMoY29udGV4dCwgcHJvcHMuZmdTZWdzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbihwcm9wcy5ldmVudFNlbGVjdGlvbik7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnREcmFnKHByb3BzLmV2ZW50RHJhZ0luc3RhbmNlcyk7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnRSZXNpemUocHJvcHMuZXZlbnRSZXNpemVJbnN0YW5jZXMpO1xuICAgIH07XG4gICAgRGF5VGlsZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMucmVuZGVyRnJhbWUudW5yZW5kZXIoKTsgLy8gc2hvdWxkIHVucmVuZGVyIGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICB0aGlzLmNvbnRleHQuY2FsZW5kYXIudW5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KHRoaXMpO1xuICAgIH07XG4gICAgRGF5VGlsZS5wcm90b3R5cGUuX3JlbmRlckZyYW1lID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCB0aGVtZSA9IF9hLnRoZW1lLCBkYXRlRW52ID0gX2EuZGF0ZUVudiwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgIHZhciB0aXRsZSA9IGRhdGVFbnYuZm9ybWF0KGRhdGUsIGNyZWF0ZUZvcm1hdHRlcihvcHRpb25zLmRheVBvcG92ZXJGb3JtYXQpIC8vIFRPRE86IGNhY2hlXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID1cbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtaGVhZGVyICcgKyB0aGVtZS5nZXRDbGFzcygncG9wb3ZlckhlYWRlcicpICsgJ1wiPicgK1xuICAgICAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cImZjLXRpdGxlXCI+JyArXG4gICAgICAgICAgICAgICAgaHRtbEVzY2FwZSh0aXRsZSkgK1xuICAgICAgICAgICAgICAgICc8L3NwYW4+JyArXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiZmMtY2xvc2UgJyArIHRoZW1lLmdldEljb25DbGFzcygnY2xvc2UnKSArICdcIj48L3NwYW4+JyArXG4gICAgICAgICAgICAgICAgJzwvZGl2PicgK1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtYm9keSAnICsgdGhlbWUuZ2V0Q2xhc3MoJ3BvcG92ZXJDb250ZW50JykgKyAnXCI+JyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1ldmVudC1jb250YWluZXJcIj48L2Rpdj4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgdGhpcy5zZWdDb250YWluZXJFbCA9IHRoaXMuZWwucXVlcnlTZWxlY3RvcignLmZjLWV2ZW50LWNvbnRhaW5lcicpO1xuICAgIH07XG4gICAgRGF5VGlsZS5wcm90b3R5cGUucXVlcnlIaXQgPSBmdW5jdGlvbiAocG9zaXRpb25MZWZ0LCBwb3NpdGlvblRvcCwgZWxXaWR0aCwgZWxIZWlnaHQpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLnByb3BzLmRhdGU7IC8vIEhBQ0tcbiAgICAgICAgaWYgKHBvc2l0aW9uTGVmdCA8IGVsV2lkdGggJiYgcG9zaXRpb25Ub3AgPCBlbEhlaWdodCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQ6IHRoaXMsXG4gICAgICAgICAgICAgICAgZGF0ZVNwYW46IHtcbiAgICAgICAgICAgICAgICAgICAgYWxsRGF5OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICByYW5nZTogeyBzdGFydDogZGF0ZSwgZW5kOiBhZGREYXlzKGRhdGUsIDEpIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGRheUVsOiB0aGlzLmVsLFxuICAgICAgICAgICAgICAgIHJlY3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAwLFxuICAgICAgICAgICAgICAgICAgICByaWdodDogZWxXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiBlbEhlaWdodFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbGF5ZXI6IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBEYXlUaWxlO1xufShEYXRlQ29tcG9uZW50KSk7XG52YXIgRGF5VGlsZUV2ZW50UmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheVRpbGVFdmVudFJlbmRlcmVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheVRpbGVFdmVudFJlbmRlcmVyKGRheVRpbGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZGF5VGlsZSA9IGRheVRpbGU7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5VGlsZUV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmF0dGFjaFNlZ3MgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHNlZ3NfMSA9IHNlZ3M7IF9pIDwgc2Vnc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMVtfaV07XG4gICAgICAgICAgICB0aGlzLmRheVRpbGUuc2VnQ29udGFpbmVyRWwuYXBwZW5kQ2hpbGQoc2VnLmVsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGF5VGlsZUV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmRldGFjaFNlZ3MgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHNlZ3NfMiA9IHNlZ3M7IF9pIDwgc2Vnc18yLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMltfaV07XG4gICAgICAgICAgICByZW1vdmVFbGVtZW50KHNlZy5lbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBEYXlUaWxlRXZlbnRSZW5kZXJlcjtcbn0oU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIpKTtcblxudmFyIERheUJnUm93ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIERheUJnUm93KGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICB9XG4gICAgRGF5QmdSb3cucHJvdG90eXBlLnJlbmRlckh0bWwgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgICAgICAgdmFyIHBhcnRzID0gW107XG4gICAgICAgIGlmIChwcm9wcy5yZW5kZXJJbnRyb0h0bWwpIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocHJvcHMucmVuZGVySW50cm9IdG1sKCkpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBwcm9wcy5jZWxsczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBjZWxsID0gX2FbX2ldO1xuICAgICAgICAgICAgcGFydHMucHVzaChyZW5kZXJDZWxsSHRtbChjZWxsLmRhdGUsIHByb3BzLmRhdGVQcm9maWxlLCB0aGlzLmNvbnRleHQsIGNlbGwuaHRtbEF0dHJzKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFwcm9wcy5jZWxscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2goJzx0ZCBjbGFzcz1cImZjLWRheSAnICsgdGhpcy5jb250ZXh0LnRoZW1lLmdldENsYXNzKCd3aWRnZXRDb250ZW50JykgKyAnXCI+PC90ZD4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5jb250ZXh0Lm9wdGlvbnMuZGlyID09PSAncnRsJykge1xuICAgICAgICAgICAgcGFydHMucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnPHRyPicgKyBwYXJ0cy5qb2luKCcnKSArICc8L3RyPic7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5QmdSb3c7XG59KCkpO1xuZnVuY3Rpb24gcmVuZGVyQ2VsbEh0bWwoZGF0ZSwgZGF0ZVByb2ZpbGUsIGNvbnRleHQsIG90aGVyQXR0cnMpIHtcbiAgICB2YXIgZGF0ZUVudiA9IGNvbnRleHQuZGF0ZUVudiwgdGhlbWUgPSBjb250ZXh0LnRoZW1lO1xuICAgIHZhciBpc0RhdGVWYWxpZCA9IHJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGRhdGUpOyAvLyBUT0RPOiBjYWxsZWQgdG9vIGZyZXF1ZW50bHkuIGNhY2hlIHNvbWVob3cuXG4gICAgdmFyIGNsYXNzZXMgPSBnZXREYXlDbGFzc2VzKGRhdGUsIGRhdGVQcm9maWxlLCBjb250ZXh0KTtcbiAgICBjbGFzc2VzLnVuc2hpZnQoJ2ZjLWRheScsIHRoZW1lLmdldENsYXNzKCd3aWRnZXRDb250ZW50JykpO1xuICAgIHJldHVybiAnPHRkIGNsYXNzPVwiJyArIGNsYXNzZXMuam9pbignICcpICsgJ1wiJyArXG4gICAgICAgIChpc0RhdGVWYWxpZCA/XG4gICAgICAgICAgICAnIGRhdGEtZGF0ZT1cIicgKyBkYXRlRW52LmZvcm1hdElzbyhkYXRlLCB7IG9taXRUaW1lOiB0cnVlIH0pICsgJ1wiJyA6XG4gICAgICAgICAgICAnJykgK1xuICAgICAgICAob3RoZXJBdHRycyA/XG4gICAgICAgICAgICAnICcgKyBvdGhlckF0dHJzIDpcbiAgICAgICAgICAgICcnKSArXG4gICAgICAgICc+PC90ZD4nO1xufVxuXG52YXIgREFZX05VTV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoeyBkYXk6ICdudW1lcmljJyB9KTtcbnZhciBXRUVLX05VTV9GT1JNQVQgPSBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrOiAnbnVtZXJpYycgfSk7XG52YXIgRGF5R3JpZCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5R3JpZCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkKGVsLCByZW5kZXJQcm9wcykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBlbCkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuYm90dG9tQ29vcmRQYWRkaW5nID0gMDsgLy8gaGFjayBmb3IgZXh0ZW5kaW5nIHRoZSBoaXQgYXJlYSBmb3IgdGhlIGxhc3Qgcm93IG9mIHRoZSBjb29yZGluYXRlIGdyaWRcbiAgICAgICAgX3RoaXMuaXNDZWxsU2l6ZXNEaXJ0eSA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5yZW5kZXJQcm9wcyA9IHJlbmRlclByb3BzO1xuICAgICAgICB2YXIgZXZlbnRSZW5kZXJlciA9IF90aGlzLmV2ZW50UmVuZGVyZXIgPSBuZXcgRGF5R3JpZEV2ZW50UmVuZGVyZXIoX3RoaXMpO1xuICAgICAgICB2YXIgZmlsbFJlbmRlcmVyID0gX3RoaXMuZmlsbFJlbmRlcmVyID0gbmV3IERheUdyaWRGaWxsUmVuZGVyZXIoX3RoaXMpO1xuICAgICAgICBfdGhpcy5taXJyb3JSZW5kZXJlciA9IG5ldyBEYXlHcmlkTWlycm9yUmVuZGVyZXIoX3RoaXMpO1xuICAgICAgICB2YXIgcmVuZGVyQ2VsbHMgPSBfdGhpcy5yZW5kZXJDZWxscyA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlckNlbGxzLCBfdGhpcy5fdW5yZW5kZXJDZWxscyk7XG4gICAgICAgIF90aGlzLnJlbmRlckJ1c2luZXNzSG91cnMgPSBtZW1vaXplUmVuZGVyaW5nKGZpbGxSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZmlsbFJlbmRlcmVyLCAnYnVzaW5lc3NIb3VycycpLCBmaWxsUmVuZGVyZXIudW5yZW5kZXIuYmluZChmaWxsUmVuZGVyZXIsICdidXNpbmVzc0hvdXJzJyksIFtyZW5kZXJDZWxsc10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uID0gbWVtb2l6ZVJlbmRlcmluZyhmaWxsUmVuZGVyZXIucmVuZGVyU2Vncy5iaW5kKGZpbGxSZW5kZXJlciwgJ2hpZ2hsaWdodCcpLCBmaWxsUmVuZGVyZXIudW5yZW5kZXIuYmluZChmaWxsUmVuZGVyZXIsICdoaWdobGlnaHQnKSwgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckJnRXZlbnRzID0gbWVtb2l6ZVJlbmRlcmluZyhmaWxsUmVuZGVyZXIucmVuZGVyU2Vncy5iaW5kKGZpbGxSZW5kZXJlciwgJ2JnRXZlbnQnKSwgZmlsbFJlbmRlcmVyLnVucmVuZGVyLmJpbmQoZmlsbFJlbmRlcmVyLCAnYmdFdmVudCcpLCBbcmVuZGVyQ2VsbHNdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRmdFdmVudHMgPSBtZW1vaXplUmVuZGVyaW5nKGV2ZW50UmVuZGVyZXIucmVuZGVyU2Vncy5iaW5kKGV2ZW50UmVuZGVyZXIpLCBldmVudFJlbmRlcmVyLnVucmVuZGVyLmJpbmQoZXZlbnRSZW5kZXJlciksIFtyZW5kZXJDZWxsc10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5zZWxlY3RCeUluc3RhbmNlSWQuYmluZChldmVudFJlbmRlcmVyKSwgZXZlbnRSZW5kZXJlci51bnNlbGVjdEJ5SW5zdGFuY2VJZC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbX3RoaXMucmVuZGVyRmdFdmVudHNdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnREcmFnID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyRXZlbnREcmFnLCBfdGhpcy5fdW5yZW5kZXJFdmVudERyYWcsIFtyZW5kZXJDZWxsc10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFJlc2l6ZSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlckV2ZW50UmVzaXplLCBfdGhpcy5fdW5yZW5kZXJFdmVudFJlc2l6ZSwgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5R3JpZC5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBjZWxscyA9IHByb3BzLmNlbGxzO1xuICAgICAgICB0aGlzLnJvd0NudCA9IGNlbGxzLmxlbmd0aDtcbiAgICAgICAgdGhpcy5jb2xDbnQgPSBjZWxsc1swXS5sZW5ndGg7XG4gICAgICAgIHRoaXMucmVuZGVyQ2VsbHMoY2VsbHMsIHByb3BzLmlzUmlnaWQpO1xuICAgICAgICB0aGlzLnJlbmRlckJ1c2luZXNzSG91cnMoY29udGV4dCwgcHJvcHMuYnVzaW5lc3NIb3VyU2Vncyk7XG4gICAgICAgIHRoaXMucmVuZGVyRGF0ZVNlbGVjdGlvbihjb250ZXh0LCBwcm9wcy5kYXRlU2VsZWN0aW9uU2Vncyk7XG4gICAgICAgIHRoaXMucmVuZGVyQmdFdmVudHMoY29udGV4dCwgcHJvcHMuYmdFdmVudFNlZ3MpO1xuICAgICAgICB0aGlzLnJlbmRlckZnRXZlbnRzKGNvbnRleHQsIHByb3BzLmZnRXZlbnRTZWdzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbihwcm9wcy5ldmVudFNlbGVjdGlvbik7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnREcmFnKHByb3BzLmV2ZW50RHJhZyk7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnRSZXNpemUocHJvcHMuZXZlbnRSZXNpemUpO1xuICAgICAgICBpZiAodGhpcy5zZWdQb3BvdmVyVGlsZSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVTZWdQb3BvdmVyVGlsZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJDZWxscy51bnJlbmRlcigpOyAvLyB3aWxsIHVucmVuZGVyIGV2ZXJ5dGhpbmcgZWxzZVxuICAgIH07XG4gICAgRGF5R3JpZC5wcm90b3R5cGUuZ2V0Q2VsbFJhbmdlID0gZnVuY3Rpb24gKHJvdywgY29sKSB7XG4gICAgICAgIHZhciBzdGFydCA9IHRoaXMucHJvcHMuY2VsbHNbcm93XVtjb2xdLmRhdGU7XG4gICAgICAgIHZhciBlbmQgPSBhZGREYXlzKHN0YXJ0LCAxKTtcbiAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgIH07XG4gICAgRGF5R3JpZC5wcm90b3R5cGUudXBkYXRlU2VnUG9wb3ZlclRpbGUgPSBmdW5jdGlvbiAoZGF0ZSwgc2Vncykge1xuICAgICAgICB2YXIgb3duUHJvcHMgPSB0aGlzLnByb3BzO1xuICAgICAgICB0aGlzLnNlZ1BvcG92ZXJUaWxlLnJlY2VpdmVQcm9wcyh7XG4gICAgICAgICAgICBkYXRlOiBkYXRlIHx8IHRoaXMuc2VnUG9wb3ZlclRpbGUucHJvcHMuZGF0ZSxcbiAgICAgICAgICAgIGZnU2Vnczogc2VncyB8fCB0aGlzLnNlZ1BvcG92ZXJUaWxlLnByb3BzLmZnU2VncyxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBvd25Qcm9wcy5ldmVudFNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50RHJhZ0luc3RhbmNlczogb3duUHJvcHMuZXZlbnREcmFnID8gb3duUHJvcHMuZXZlbnREcmFnLmFmZmVjdGVkSW5zdGFuY2VzIDogbnVsbCxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplSW5zdGFuY2VzOiBvd25Qcm9wcy5ldmVudFJlc2l6ZSA/IG93blByb3BzLmV2ZW50UmVzaXplLmFmZmVjdGVkSW5zdGFuY2VzIDogbnVsbFxuICAgICAgICB9LCB0aGlzLmNvbnRleHQpO1xuICAgIH07XG4gICAgLyogRGF0ZSBSZW5kZXJpbmdcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLl9yZW5kZXJDZWxscyA9IGZ1bmN0aW9uIChjZWxscywgaXNSaWdpZCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3LCBpc1J0bCA9IF9hLmlzUnRsLCBkYXRlRW52ID0gX2EuZGF0ZUVudjtcbiAgICAgICAgdmFyIF9iID0gdGhpcywgcm93Q250ID0gX2Iucm93Q250LCBjb2xDbnQgPSBfYi5jb2xDbnQ7XG4gICAgICAgIHZhciBodG1sID0gJyc7XG4gICAgICAgIHZhciByb3c7XG4gICAgICAgIHZhciBjb2w7XG4gICAgICAgIGZvciAocm93ID0gMDsgcm93IDwgcm93Q250OyByb3crKykge1xuICAgICAgICAgICAgaHRtbCArPSB0aGlzLnJlbmRlckRheVJvd0h0bWwocm93LCBpc1JpZ2lkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVsLmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIHRoaXMucm93RWxzID0gZmluZEVsZW1lbnRzKHRoaXMuZWwsICcuZmMtcm93Jyk7XG4gICAgICAgIHRoaXMuY2VsbEVscyA9IGZpbmRFbGVtZW50cyh0aGlzLmVsLCAnLmZjLWRheSwgLmZjLWRpc2FibGVkLWRheScpO1xuICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbEVscy5yZXZlcnNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yb3dQb3NpdGlvbnMgPSBuZXcgUG9zaXRpb25DYWNoZSh0aGlzLmVsLCB0aGlzLnJvd0VscywgZmFsc2UsIHRydWUgLy8gdmVydGljYWxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5jb2xQb3NpdGlvbnMgPSBuZXcgUG9zaXRpb25DYWNoZSh0aGlzLmVsLCB0aGlzLmNlbGxFbHMuc2xpY2UoMCwgY29sQ250KSwgLy8gb25seSB0aGUgZmlyc3Qgcm93XG4gICAgICAgIHRydWUsIGZhbHNlIC8vIGhvcml6b250YWxcbiAgICAgICAgKTtcbiAgICAgICAgLy8gdHJpZ2dlciBkYXlSZW5kZXIgd2l0aCBlYWNoIGNlbGwncyBlbGVtZW50XG4gICAgICAgIGZvciAocm93ID0gMDsgcm93IDwgcm93Q250OyByb3crKykge1xuICAgICAgICAgICAgZm9yIChjb2wgPSAwOyBjb2wgPCBjb2xDbnQ7IGNvbCsrKSB7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdkYXlSZW5kZXInLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IGRhdGVFbnYudG9EYXRlKGNlbGxzW3Jvd11bY29sXS5kYXRlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiB0aGlzLmdldENlbGxFbChyb3csIGNvbCksXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmlzQ2VsbFNpemVzRGlydHkgPSB0cnVlO1xuICAgIH07XG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3VucmVuZGVyQ2VsbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlU2VnUG9wb3ZlcigpO1xuICAgIH07XG4gICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIGZvciBhIHNpbmdsZSByb3csIHdoaWNoIGlzIGEgZGl2IHRoYXQgd3JhcHMgYSB0YWJsZS5cbiAgICAvLyBgcm93YCBpcyB0aGUgcm93IG51bWJlci5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXJEYXlSb3dIdG1sID0gZnVuY3Rpb24gKHJvdywgaXNSaWdpZCkge1xuICAgICAgICB2YXIgdGhlbWUgPSB0aGlzLmNvbnRleHQudGhlbWU7XG4gICAgICAgIHZhciBjbGFzc2VzID0gWydmYy1yb3cnLCAnZmMtd2VlaycsIHRoZW1lLmdldENsYXNzKCdkYXlSb3cnKV07XG4gICAgICAgIGlmIChpc1JpZ2lkKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLXJpZ2lkJyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJnUm93ID0gbmV3IERheUJnUm93KHRoaXMuY29udGV4dCk7XG4gICAgICAgIHJldHVybiAnJyArXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cIicgKyBjbGFzc2VzLmpvaW4oJyAnKSArICdcIj4nICtcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtYmdcIj4nICtcbiAgICAgICAgICAgICc8dGFibGUgY2xhc3M9XCInICsgdGhlbWUuZ2V0Q2xhc3MoJ3RhYmxlR3JpZCcpICsgJ1wiPicgK1xuICAgICAgICAgICAgYmdSb3cucmVuZGVySHRtbCh7XG4gICAgICAgICAgICAgICAgY2VsbHM6IHRoaXMucHJvcHMuY2VsbHNbcm93XSxcbiAgICAgICAgICAgICAgICBkYXRlUHJvZmlsZTogdGhpcy5wcm9wcy5kYXRlUHJvZmlsZSxcbiAgICAgICAgICAgICAgICByZW5kZXJJbnRyb0h0bWw6IHRoaXMucmVuZGVyUHJvcHMucmVuZGVyQmdJbnRyb0h0bWxcbiAgICAgICAgICAgIH0pICtcbiAgICAgICAgICAgICc8L3RhYmxlPicgK1xuICAgICAgICAgICAgJzwvZGl2PicgK1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1jb250ZW50LXNrZWxldG9uXCI+JyArXG4gICAgICAgICAgICAnPHRhYmxlPicgK1xuICAgICAgICAgICAgKHRoaXMuZ2V0SXNOdW1iZXJzVmlzaWJsZSgpID9cbiAgICAgICAgICAgICAgICAnPHRoZWFkPicgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlck51bWJlclRySHRtbChyb3cpICtcbiAgICAgICAgICAgICAgICAgICAgJzwvdGhlYWQ+JyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgICc8L3RhYmxlPicgK1xuICAgICAgICAgICAgJzwvZGl2PicgK1xuICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRJc051bWJlcnNWaXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRJc0RheU51bWJlcnNWaXNpYmxlKCkgfHxcbiAgICAgICAgICAgIHRoaXMucmVuZGVyUHJvcHMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSB8fFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJQcm9wcy5jb2xXZWVrTnVtYmVyc1Zpc2libGU7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRJc0RheU51bWJlcnNWaXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dDbnQgPiAxO1xuICAgIH07XG4gICAgLyogR3JpZCBOdW1iZXIgUmVuZGVyaW5nXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXJOdW1iZXJUckh0bWwgPSBmdW5jdGlvbiAocm93KSB7XG4gICAgICAgIHZhciBpc1J0bCA9IHRoaXMuY29udGV4dC5pc1J0bDtcbiAgICAgICAgdmFyIGludHJvID0gdGhpcy5yZW5kZXJQcm9wcy5yZW5kZXJOdW1iZXJJbnRyb0h0bWwocm93LCB0aGlzKTtcbiAgICAgICAgcmV0dXJuICcnICtcbiAgICAgICAgICAgICc8dHI+JyArXG4gICAgICAgICAgICAoaXNSdGwgPyAnJyA6IGludHJvKSArXG4gICAgICAgICAgICB0aGlzLnJlbmRlck51bWJlckNlbGxzSHRtbChyb3cpICtcbiAgICAgICAgICAgIChpc1J0bCA/IGludHJvIDogJycpICtcbiAgICAgICAgICAgICc8L3RyPic7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXJOdW1iZXJDZWxsc0h0bWwgPSBmdW5jdGlvbiAocm93KSB7XG4gICAgICAgIHZhciBodG1scyA9IFtdO1xuICAgICAgICB2YXIgY29sO1xuICAgICAgICB2YXIgZGF0ZTtcbiAgICAgICAgZm9yIChjb2wgPSAwOyBjb2wgPCB0aGlzLmNvbENudDsgY29sKyspIHtcbiAgICAgICAgICAgIGRhdGUgPSB0aGlzLnByb3BzLmNlbGxzW3Jvd11bY29sXS5kYXRlO1xuICAgICAgICAgICAgaHRtbHMucHVzaCh0aGlzLnJlbmRlck51bWJlckNlbGxIdG1sKGRhdGUpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5jb250ZXh0LmlzUnRsKSB7XG4gICAgICAgICAgICBodG1scy5yZXZlcnNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGh0bWxzLmpvaW4oJycpO1xuICAgIH07XG4gICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIGZvciB0aGUgPHRkPnMgb2YgdGhlIFwibnVtYmVyXCIgcm93IGluIHRoZSBEYXlHcmlkJ3MgY29udGVudCBza2VsZXRvbi5cbiAgICAvLyBUaGUgbnVtYmVyIHJvdyB3aWxsIG9ubHkgZXhpc3QgaWYgZWl0aGVyIGRheSBudW1iZXJzIG9yIHdlZWsgbnVtYmVycyBhcmUgdHVybmVkIG9uLlxuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlck51bWJlckNlbGxIdG1sID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCBkYXRlRW52ID0gX2EuZGF0ZUVudiwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgIHZhciBodG1sID0gJyc7XG4gICAgICAgIHZhciBpc0RhdGVWYWxpZCA9IHJhbmdlQ29udGFpbnNNYXJrZXIodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgZGF0ZSk7IC8vIFRPRE86IGNhbGxlZCB0b28gZnJlcXVlbnRseS4gY2FjaGUgc29tZWhvdy5cbiAgICAgICAgdmFyIGlzRGF5TnVtYmVyVmlzaWJsZSA9IHRoaXMuZ2V0SXNEYXlOdW1iZXJzVmlzaWJsZSgpICYmIGlzRGF0ZVZhbGlkO1xuICAgICAgICB2YXIgY2xhc3NlcztcbiAgICAgICAgdmFyIHdlZWtDYWxjRmlyc3REb3c7XG4gICAgICAgIGlmICghaXNEYXlOdW1iZXJWaXNpYmxlICYmICF0aGlzLnJlbmRlclByb3BzLmNlbGxXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgIC8vIG5vIG51bWJlcnMgaW4gZGF5IGNlbGwgKHdlZWsgbnVtYmVyIG11c3QgYmUgYWxvbmcgdGhlIHNpZGUpXG4gICAgICAgICAgICByZXR1cm4gJzx0ZD48L3RkPic7IC8vICB3aWxsIGNyZWF0ZSBhbiBlbXB0eSBzcGFjZSBhYm92ZSBldmVudHMgOihcbiAgICAgICAgfVxuICAgICAgICBjbGFzc2VzID0gZ2V0RGF5Q2xhc3NlcyhkYXRlLCB0aGlzLnByb3BzLmRhdGVQcm9maWxlLCB0aGlzLmNvbnRleHQpO1xuICAgICAgICBjbGFzc2VzLnVuc2hpZnQoJ2ZjLWRheS10b3AnKTtcbiAgICAgICAgaWYgKHRoaXMucmVuZGVyUHJvcHMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSkge1xuICAgICAgICAgICAgd2Vla0NhbGNGaXJzdERvdyA9IGRhdGVFbnYud2Vla0RvdztcbiAgICAgICAgfVxuICAgICAgICBodG1sICs9ICc8dGQgY2xhc3M9XCInICsgY2xhc3Nlcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgICAgIChpc0RhdGVWYWxpZCA/XG4gICAgICAgICAgICAgICAgJyBkYXRhLWRhdGU9XCInICsgZGF0ZUVudi5mb3JtYXRJc28oZGF0ZSwgeyBvbWl0VGltZTogdHJ1ZSB9KSArICdcIicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAnPic7XG4gICAgICAgIGlmICh0aGlzLnJlbmRlclByb3BzLmNlbGxXZWVrTnVtYmVyc1Zpc2libGUgJiYgKGRhdGUuZ2V0VVRDRGF5KCkgPT09IHdlZWtDYWxjRmlyc3REb3cpKSB7XG4gICAgICAgICAgICBodG1sICs9IGJ1aWxkR290b0FuY2hvckh0bWwob3B0aW9ucywgZGF0ZUVudiwgeyBkYXRlOiBkYXRlLCB0eXBlOiAnd2VlaycgfSwgeyAnY2xhc3MnOiAnZmMtd2Vlay1udW1iZXInIH0sIGRhdGVFbnYuZm9ybWF0KGRhdGUsIFdFRUtfTlVNX0ZPUk1BVCkgLy8gaW5uZXIgSFRNTFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNEYXlOdW1iZXJWaXNpYmxlKSB7XG4gICAgICAgICAgICBodG1sICs9IGJ1aWxkR290b0FuY2hvckh0bWwob3B0aW9ucywgZGF0ZUVudiwgZGF0ZSwgeyAnY2xhc3MnOiAnZmMtZGF5LW51bWJlcicgfSwgZGF0ZUVudi5mb3JtYXQoZGF0ZSwgREFZX05VTV9GT1JNQVQpIC8vIGlubmVyIEhUTUxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaHRtbCArPSAnPC90ZD4nO1xuICAgICAgICByZXR1cm4gaHRtbDtcbiAgICB9O1xuICAgIC8qIFNpemluZ1xuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUudXBkYXRlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSkge1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzLmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBfYSA9IHRoaXMsIGZpbGxSZW5kZXJlciA9IF9hLmZpbGxSZW5kZXJlciwgZXZlbnRSZW5kZXJlciA9IF9hLmV2ZW50UmVuZGVyZXIsIG1pcnJvclJlbmRlcmVyID0gX2EubWlycm9yUmVuZGVyZXI7XG4gICAgICAgIGlmIChpc1Jlc2l6ZSB8fFxuICAgICAgICAgICAgdGhpcy5pc0NlbGxTaXplc0RpcnR5IHx8XG4gICAgICAgICAgICBjYWxlbmRhci5pc0V2ZW50c1VwZGF0ZWQgLy8gaGFja1xuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuYnVpbGRQb3NpdGlvbkNhY2hlcygpO1xuICAgICAgICAgICAgdGhpcy5pc0NlbGxTaXplc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZmlsbFJlbmRlcmVyLmNvbXB1dGVTaXplcyhpc1Jlc2l6ZSk7XG4gICAgICAgIGV2ZW50UmVuZGVyZXIuY29tcHV0ZVNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgbWlycm9yUmVuZGVyZXIuY29tcHV0ZVNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgZmlsbFJlbmRlcmVyLmFzc2lnblNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgZXZlbnRSZW5kZXJlci5hc3NpZ25TaXplcyhpc1Jlc2l6ZSk7XG4gICAgICAgIG1pcnJvclJlbmRlcmVyLmFzc2lnblNpemVzKGlzUmVzaXplKTtcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmJ1aWxkUG9zaXRpb25DYWNoZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYnVpbGRDb2xQb3NpdGlvbnMoKTtcbiAgICAgICAgdGhpcy5idWlsZFJvd1Bvc2l0aW9ucygpO1xuICAgIH07XG4gICAgRGF5R3JpZC5wcm90b3R5cGUuYnVpbGRDb2xQb3NpdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY29sUG9zaXRpb25zLmJ1aWxkKCk7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5idWlsZFJvd1Bvc2l0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yb3dQb3NpdGlvbnMuYnVpbGQoKTtcbiAgICAgICAgdGhpcy5yb3dQb3NpdGlvbnMuYm90dG9tc1t0aGlzLnJvd0NudCAtIDFdICs9IHRoaXMuYm90dG9tQ29vcmRQYWRkaW5nOyAvLyBoYWNrXG4gICAgfTtcbiAgICAvKiBIaXQgU3lzdGVtXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5wb3NpdGlvblRvSGl0ID0gZnVuY3Rpb24gKGxlZnRQb3NpdGlvbiwgdG9wUG9zaXRpb24pIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgY29sUG9zaXRpb25zID0gX2EuY29sUG9zaXRpb25zLCByb3dQb3NpdGlvbnMgPSBfYS5yb3dQb3NpdGlvbnM7XG4gICAgICAgIHZhciBjb2wgPSBjb2xQb3NpdGlvbnMubGVmdFRvSW5kZXgobGVmdFBvc2l0aW9uKTtcbiAgICAgICAgdmFyIHJvdyA9IHJvd1Bvc2l0aW9ucy50b3BUb0luZGV4KHRvcFBvc2l0aW9uKTtcbiAgICAgICAgaWYgKHJvdyAhPSBudWxsICYmIGNvbCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHJvdzogcm93LFxuICAgICAgICAgICAgICAgIGNvbDogY29sLFxuICAgICAgICAgICAgICAgIGRhdGVTcGFuOiB7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlOiB0aGlzLmdldENlbGxSYW5nZShyb3csIGNvbCksXG4gICAgICAgICAgICAgICAgICAgIGFsbERheTogdHJ1ZVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGF5RWw6IHRoaXMuZ2V0Q2VsbEVsKHJvdywgY29sKSxcbiAgICAgICAgICAgICAgICByZWxhdGl2ZVJlY3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogY29sUG9zaXRpb25zLmxlZnRzW2NvbF0sXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBjb2xQb3NpdGlvbnMucmlnaHRzW2NvbF0sXG4gICAgICAgICAgICAgICAgICAgIHRvcDogcm93UG9zaXRpb25zLnRvcHNbcm93XSxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiByb3dQb3NpdGlvbnMuYm90dG9tc1tyb3ddXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyogQ2VsbCBTeXN0ZW1cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIC8vIEZZSTogdGhlIGZpcnN0IGNvbHVtbiBpcyB0aGUgbGVmdG1vc3QgY29sdW1uLCByZWdhcmRsZXNzIG9mIGRhdGVcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRDZWxsRWwgPSBmdW5jdGlvbiAocm93LCBjb2wpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbEVsc1tyb3cgKiB0aGlzLmNvbENudCArIGNvbF07XG4gICAgfTtcbiAgICAvKiBFdmVudCBEcmFnIFZpc3VhbGl6YXRpb25cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLl9yZW5kZXJFdmVudERyYWcgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50UmVuZGVyZXIuaGlkZUJ5SGFzaChzdGF0ZS5hZmZlY3RlZEluc3RhbmNlcyk7XG4gICAgICAgICAgICB0aGlzLmZpbGxSZW5kZXJlci5yZW5kZXJTZWdzKCdoaWdobGlnaHQnLCB0aGlzLmNvbnRleHQsIHN0YXRlLnNlZ3MpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5fdW5yZW5kZXJFdmVudERyYWcgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50UmVuZGVyZXIuc2hvd0J5SGFzaChzdGF0ZS5hZmZlY3RlZEluc3RhbmNlcyk7XG4gICAgICAgICAgICB0aGlzLmZpbGxSZW5kZXJlci51bnJlbmRlcignaGlnaGxpZ2h0JywgdGhpcy5jb250ZXh0KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyogRXZlbnQgUmVzaXplIFZpc3VhbGl6YXRpb25cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLl9yZW5kZXJFdmVudFJlc2l6ZSA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlci5oaWRlQnlIYXNoKHN0YXRlLmFmZmVjdGVkSW5zdGFuY2VzKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbFJlbmRlcmVyLnJlbmRlclNlZ3MoJ2hpZ2hsaWdodCcsIHRoaXMuY29udGV4dCwgc3RhdGUuc2Vncyk7XG4gICAgICAgICAgICB0aGlzLm1pcnJvclJlbmRlcmVyLnJlbmRlclNlZ3ModGhpcy5jb250ZXh0LCBzdGF0ZS5zZWdzLCB7IGlzUmVzaXppbmc6IHRydWUsIHNvdXJjZVNlZzogc3RhdGUuc291cmNlU2VnIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5fdW5yZW5kZXJFdmVudFJlc2l6ZSA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlci5zaG93QnlIYXNoKHN0YXRlLmFmZmVjdGVkSW5zdGFuY2VzKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbFJlbmRlcmVyLnVucmVuZGVyKCdoaWdobGlnaHQnLCB0aGlzLmNvbnRleHQpO1xuICAgICAgICAgICAgdGhpcy5taXJyb3JSZW5kZXJlci51bnJlbmRlcih0aGlzLmNvbnRleHQsIHN0YXRlLnNlZ3MsIHsgaXNSZXNpemluZzogdHJ1ZSwgc291cmNlU2VnOiBzdGF0ZS5zb3VyY2VTZWcgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qIE1vcmUrIExpbmsgUG9wb3ZlclxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUucmVtb3ZlU2VnUG9wb3ZlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2VnUG9wb3Zlcikge1xuICAgICAgICAgICAgdGhpcy5zZWdQb3BvdmVyLmhpZGUoKTsgLy8gaW4gaGFuZGxlciwgd2lsbCBjYWxsIHNlZ1BvcG92ZXIncyByZW1vdmVFbGVtZW50XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIExpbWl0cyB0aGUgbnVtYmVyIG9mIFwibGV2ZWxzXCIgKHZlcnRpY2FsbHkgc3RhY2tpbmcgbGF5ZXJzIG9mIGV2ZW50cykgZm9yIGVhY2ggcm93IG9mIHRoZSBncmlkLlxuICAgIC8vIGBsZXZlbExpbWl0YCBjYW4gYmUgZmFsc2UgKGRvbid0IGxpbWl0KSwgYSBudW1iZXIsIG9yIHRydWUgKHNob3VsZCBiZSBjb21wdXRlZCkuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUubGltaXRSb3dzID0gZnVuY3Rpb24gKGxldmVsTGltaXQpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSB0aGlzLmV2ZW50UmVuZGVyZXIucm93U3RydWN0cyB8fCBbXTtcbiAgICAgICAgdmFyIHJvdzsgLy8gcm93ICNcbiAgICAgICAgdmFyIHJvd0xldmVsTGltaXQ7XG4gICAgICAgIGZvciAocm93ID0gMDsgcm93IDwgcm93U3RydWN0cy5sZW5ndGg7IHJvdysrKSB7XG4gICAgICAgICAgICB0aGlzLnVubGltaXRSb3cocm93KTtcbiAgICAgICAgICAgIGlmICghbGV2ZWxMaW1pdCkge1xuICAgICAgICAgICAgICAgIHJvd0xldmVsTGltaXQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBsZXZlbExpbWl0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIHJvd0xldmVsTGltaXQgPSBsZXZlbExpbWl0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcm93TGV2ZWxMaW1pdCA9IHRoaXMuY29tcHV0ZVJvd0xldmVsTGltaXQocm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyb3dMZXZlbExpbWl0ICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubGltaXRSb3cocm93LCByb3dMZXZlbExpbWl0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgdGhlIG51bWJlciBvZiBsZXZlbHMgYSByb3cgd2lsbCBhY2NvbW9kYXRlIHdpdGhvdXQgZ29pbmcgb3V0c2lkZSBpdHMgYm91bmRzLlxuICAgIC8vIEFzc3VtZXMgdGhlIHJvdyBpcyBcInJpZ2lkXCIgKG1haW50YWlucyBhIGNvbnN0YW50IGhlaWdodCByZWdhcmRsZXNzIG9mIHdoYXQgaXMgaW5zaWRlKS5cbiAgICAvLyBgcm93YCBpcyB0aGUgcm93IG51bWJlci5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5jb21wdXRlUm93TGV2ZWxMaW1pdCA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIHJvd0VsID0gdGhpcy5yb3dFbHNbcm93XTsgLy8gdGhlIGNvbnRhaW5pbmcgXCJmYWtlXCIgcm93IGRpdlxuICAgICAgICB2YXIgcm93Qm90dG9tID0gcm93RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuYm90dG9tOyAvLyByZWxhdGl2ZSB0byB2aWV3cG9ydCFcbiAgICAgICAgdmFyIHRyRWxzID0gZmluZENoaWxkcmVuKHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzW3Jvd10udGJvZHlFbCk7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdHJFbDtcbiAgICAgICAgLy8gUmV2ZWFsIG9uZSBsZXZlbCA8dHI+IGF0IGEgdGltZSBhbmQgc3RvcCB3aGVuIHdlIGZpbmQgb25lIG91dCBvZiBib3VuZHNcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRyRWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0ckVsID0gdHJFbHNbaV07XG4gICAgICAgICAgICB0ckVsLmNsYXNzTGlzdC5yZW1vdmUoJ2ZjLWxpbWl0ZWQnKTsgLy8gcmVzZXQgdG8gb3JpZ2luYWwgc3RhdGUgKHJldmVhbClcbiAgICAgICAgICAgIGlmICh0ckVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmJvdHRvbSA+IHJvd0JvdHRvbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTsgLy8gc2hvdWxkIG5vdCBsaW1pdCBhdCBhbGxcbiAgICB9O1xuICAgIC8vIExpbWl0cyB0aGUgZ2l2ZW4gZ3JpZCByb3cgdG8gdGhlIG1heGltdW0gbnVtYmVyIG9mIGxldmVscyBhbmQgaW5qZWN0cyBcIm1vcmVcIiBsaW5rcyBpZiBuZWNlc3NhcnkuXG4gICAgLy8gYHJvd2AgaXMgdGhlIHJvdyBudW1iZXIuXG4gICAgLy8gYGxldmVsTGltaXRgIGlzIGEgbnVtYmVyIGZvciB0aGUgbWF4aW11bSAoaW5jbHVzaXZlKSBudW1iZXIgb2YgbGV2ZWxzIGFsbG93ZWQuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUubGltaXRSb3cgPSBmdW5jdGlvbiAocm93LCBsZXZlbExpbWl0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb2xDbnQgPSB0aGlzLmNvbENudDtcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5jb250ZXh0LmlzUnRsO1xuICAgICAgICB2YXIgcm93U3RydWN0ID0gdGhpcy5ldmVudFJlbmRlcmVyLnJvd1N0cnVjdHNbcm93XTtcbiAgICAgICAgdmFyIG1vcmVOb2RlcyA9IFtdOyAvLyBhcnJheSBvZiBcIm1vcmVcIiA8YT4gbGlua3MgYW5kIDx0ZD4gRE9NIG5vZGVzXG4gICAgICAgIHZhciBjb2wgPSAwOyAvLyBjb2wgIywgbGVmdC10by1yaWdodCAobm90IGNocm9ub2xvZ2ljYWxseSlcbiAgICAgICAgdmFyIGxldmVsU2VnczsgLy8gYXJyYXkgb2Ygc2VnbWVudCBvYmplY3RzIGluIHRoZSBsYXN0IGFsbG93YWJsZSBsZXZlbCwgb3JkZXJlZCBsZWZ0LXRvLXJpZ2h0XG4gICAgICAgIHZhciBjZWxsTWF0cml4OyAvLyBhIG1hdHJpeCAoYnkgbGV2ZWwsIHRoZW4gY29sdW1uKSBvZiBhbGwgPHRkPiBlbGVtZW50cyBpbiB0aGUgcm93XG4gICAgICAgIHZhciBsaW1pdGVkTm9kZXM7IC8vIGFycmF5IG9mIHRlbXBvcmFyaWx5IGhpZGRlbiBsZXZlbCA8dHI+IGFuZCBzZWdtZW50IDx0ZD4gRE9NIG5vZGVzXG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgc2VnO1xuICAgICAgICB2YXIgc2Vnc0JlbG93OyAvLyBhcnJheSBvZiBzZWdtZW50IG9iamVjdHMgYmVsb3cgYHNlZ2AgaW4gdGhlIGN1cnJlbnQgYGNvbGBcbiAgICAgICAgdmFyIHRvdGFsU2Vnc0JlbG93OyAvLyB0b3RhbCBudW1iZXIgb2Ygc2VnbWVudHMgYmVsb3cgYHNlZ2AgaW4gYW55IG9mIHRoZSBjb2x1bW5zIGBzZWdgIG9jY3VwaWVzXG4gICAgICAgIHZhciBjb2xTZWdzQmVsb3c7IC8vIGFycmF5IG9mIHNlZ21lbnQgYXJyYXlzLCBiZWxvdyBzZWcsIG9uZSBmb3IgZWFjaCBjb2x1bW4gKG9mZnNldCBmcm9tIHNlZ3MncyBmaXJzdCBjb2x1bW4pXG4gICAgICAgIHZhciB0ZDtcbiAgICAgICAgdmFyIHJvd1NwYW47XG4gICAgICAgIHZhciBzZWdNb3JlTm9kZXM7IC8vIGFycmF5IG9mIFwibW9yZVwiIDx0ZD4gY2VsbHMgdGhhdCB3aWxsIHN0YW5kLWluIGZvciB0aGUgY3VycmVudCBzZWcncyBjZWxsXG4gICAgICAgIHZhciBqO1xuICAgICAgICB2YXIgbW9yZVRkO1xuICAgICAgICB2YXIgbW9yZVdyYXA7XG4gICAgICAgIHZhciBtb3JlTGluaztcbiAgICAgICAgLy8gSXRlcmF0ZXMgdGhyb3VnaCBlbXB0eSBsZXZlbCBjZWxscyBhbmQgcGxhY2VzIFwibW9yZVwiIGxpbmtzIGluc2lkZSBpZiBuZWVkIGJlXG4gICAgICAgIHZhciBlbXB0eUNlbGxzVW50aWwgPSBmdW5jdGlvbiAoZW5kQ29sKSB7XG4gICAgICAgICAgICB3aGlsZSAoY29sIDwgZW5kQ29sKSB7XG4gICAgICAgICAgICAgICAgc2Vnc0JlbG93ID0gX3RoaXMuZ2V0Q2VsbFNlZ3Mocm93LCBjb2wsIGxldmVsTGltaXQpO1xuICAgICAgICAgICAgICAgIGlmIChzZWdzQmVsb3cubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRkID0gY2VsbE1hdHJpeFtsZXZlbExpbWl0IC0gMV1bY29sXTtcbiAgICAgICAgICAgICAgICAgICAgbW9yZUxpbmsgPSBfdGhpcy5yZW5kZXJNb3JlTGluayhyb3csIGNvbCwgc2Vnc0JlbG93KTtcbiAgICAgICAgICAgICAgICAgICAgbW9yZVdyYXAgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCBudWxsLCBtb3JlTGluayk7XG4gICAgICAgICAgICAgICAgICAgIHRkLmFwcGVuZENoaWxkKG1vcmVXcmFwKTtcbiAgICAgICAgICAgICAgICAgICAgbW9yZU5vZGVzLnB1c2gobW9yZVdyYXApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb2wrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGxldmVsTGltaXQgJiYgbGV2ZWxMaW1pdCA8IHJvd1N0cnVjdC5zZWdMZXZlbHMubGVuZ3RoKSB7IC8vIGlzIGl0IGFjdHVhbGx5IG92ZXIgdGhlIGxpbWl0P1xuICAgICAgICAgICAgbGV2ZWxTZWdzID0gcm93U3RydWN0LnNlZ0xldmVsc1tsZXZlbExpbWl0IC0gMV07XG4gICAgICAgICAgICBjZWxsTWF0cml4ID0gcm93U3RydWN0LmNlbGxNYXRyaXg7XG4gICAgICAgICAgICBsaW1pdGVkTm9kZXMgPSBmaW5kQ2hpbGRyZW4ocm93U3RydWN0LnRib2R5RWwpLnNsaWNlKGxldmVsTGltaXQpOyAvLyBnZXQgbGV2ZWwgPHRyPiBlbGVtZW50cyBwYXN0IHRoZSBsaW1pdFxuICAgICAgICAgICAgbGltaXRlZE5vZGVzLmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgICAgICBub2RlLmNsYXNzTGlzdC5hZGQoJ2ZjLWxpbWl0ZWQnKTsgLy8gaGlkZSBlbGVtZW50cyBhbmQgZ2V0IGEgc2ltcGxlIERPTS1ub2RlcyBhcnJheVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBpdGVyYXRlIHRob3VnaCBzZWdtZW50cyBpbiB0aGUgbGFzdCBhbGxvd2FibGUgbGV2ZWxcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZXZlbFNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzZWcgPSBsZXZlbFNlZ3NbaV07XG4gICAgICAgICAgICAgICAgdmFyIGxlZnRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmxhc3RDb2wpIDogc2VnLmZpcnN0Q29sO1xuICAgICAgICAgICAgICAgIHZhciByaWdodENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcuZmlyc3RDb2wpIDogc2VnLmxhc3RDb2w7XG4gICAgICAgICAgICAgICAgZW1wdHlDZWxsc1VudGlsKGxlZnRDb2wpOyAvLyBwcm9jZXNzIGVtcHR5IGNlbGxzIGJlZm9yZSB0aGUgc2VnbWVudFxuICAgICAgICAgICAgICAgIC8vIGRldGVybWluZSAqYWxsKiBzZWdtZW50cyBiZWxvdyBgc2VnYCB0aGF0IG9jY3VweSB0aGUgc2FtZSBjb2x1bW5zXG4gICAgICAgICAgICAgICAgY29sU2Vnc0JlbG93ID0gW107XG4gICAgICAgICAgICAgICAgdG90YWxTZWdzQmVsb3cgPSAwO1xuICAgICAgICAgICAgICAgIHdoaWxlIChjb2wgPD0gcmlnaHRDb2wpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vnc0JlbG93ID0gdGhpcy5nZXRDZWxsU2Vncyhyb3csIGNvbCwgbGV2ZWxMaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbFNlZ3NCZWxvdy5wdXNoKHNlZ3NCZWxvdyk7XG4gICAgICAgICAgICAgICAgICAgIHRvdGFsU2Vnc0JlbG93ICs9IHNlZ3NCZWxvdy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGNvbCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodG90YWxTZWdzQmVsb3cpIHsgLy8gZG8gd2UgbmVlZCB0byByZXBsYWNlIHRoaXMgc2VnbWVudCB3aXRoIG9uZSBvciBtYW55IFwibW9yZVwiIGxpbmtzP1xuICAgICAgICAgICAgICAgICAgICB0ZCA9IGNlbGxNYXRyaXhbbGV2ZWxMaW1pdCAtIDFdW2xlZnRDb2xdOyAvLyB0aGUgc2VnbWVudCdzIHBhcmVudCBjZWxsXG4gICAgICAgICAgICAgICAgICAgIHJvd1NwYW4gPSB0ZC5yb3dTcGFuIHx8IDE7XG4gICAgICAgICAgICAgICAgICAgIHNlZ01vcmVOb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAvLyBtYWtlIGEgcmVwbGFjZW1lbnQgPHRkPiBmb3IgZWFjaCBjb2x1bW4gdGhlIHNlZ21lbnQgb2NjdXBpZXMuIHdpbGwgYmUgb25lIGZvciBlYWNoIGNvbHNwYW5cbiAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGNvbFNlZ3NCZWxvdy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbW9yZVRkID0gY3JlYXRlRWxlbWVudCgndGQnLCB7IGNsYXNzTmFtZTogJ2ZjLW1vcmUtY2VsbCcsIHJvd1NwYW46IHJvd1NwYW4gfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWdzQmVsb3cgPSBjb2xTZWdzQmVsb3dbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBtb3JlTGluayA9IHRoaXMucmVuZGVyTW9yZUxpbmsocm93LCBsZWZ0Q29sICsgaiwgW3NlZ10uY29uY2F0KHNlZ3NCZWxvdykgLy8gY291bnQgc2VnIGFzIGhpZGRlbiB0b29cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb3JlV3JhcCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIG51bGwsIG1vcmVMaW5rKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vcmVUZC5hcHBlbmRDaGlsZChtb3JlV3JhcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWdNb3JlTm9kZXMucHVzaChtb3JlVGQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW9yZU5vZGVzLnB1c2gobW9yZVRkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0ZC5jbGFzc0xpc3QuYWRkKCdmYy1saW1pdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydEFmdGVyRWxlbWVudCh0ZCwgc2VnTW9yZU5vZGVzKTtcbiAgICAgICAgICAgICAgICAgICAgbGltaXRlZE5vZGVzLnB1c2godGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVtcHR5Q2VsbHNVbnRpbCh0aGlzLmNvbENudCk7IC8vIGZpbmlzaCBvZmYgdGhlIGxldmVsXG4gICAgICAgICAgICByb3dTdHJ1Y3QubW9yZUVscyA9IG1vcmVOb2RlczsgLy8gZm9yIGVhc3kgdW5kb2luZyBsYXRlclxuICAgICAgICAgICAgcm93U3RydWN0LmxpbWl0ZWRFbHMgPSBsaW1pdGVkTm9kZXM7IC8vIGZvciBlYXN5IHVuZG9pbmcgbGF0ZXJcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gUmV2ZWFscyBhbGwgbGV2ZWxzIGFuZCByZW1vdmVzIGFsbCBcIm1vcmVcIi1yZWxhdGVkIGVsZW1lbnRzIGZvciBhIGdyaWQncyByb3cuXG4gICAgLy8gYHJvd2AgaXMgYSByb3cgbnVtYmVyLlxuICAgIERheUdyaWQucHJvdG90eXBlLnVubGltaXRSb3cgPSBmdW5jdGlvbiAocm93KSB7XG4gICAgICAgIHZhciByb3dTdHJ1Y3QgPSB0aGlzLmV2ZW50UmVuZGVyZXIucm93U3RydWN0c1tyb3ddO1xuICAgICAgICBpZiAocm93U3RydWN0Lm1vcmVFbHMpIHtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5tb3JlRWxzLmZvckVhY2gocmVtb3ZlRWxlbWVudCk7XG4gICAgICAgICAgICByb3dTdHJ1Y3QubW9yZUVscyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJvd1N0cnVjdC5saW1pdGVkRWxzKSB7XG4gICAgICAgICAgICByb3dTdHJ1Y3QubGltaXRlZEVscy5mb3JFYWNoKGZ1bmN0aW9uIChsaW1pdGVkRWwpIHtcbiAgICAgICAgICAgICAgICBsaW1pdGVkRWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtbGltaXRlZCcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByb3dTdHJ1Y3QubGltaXRlZEVscyA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJlbmRlcnMgYW4gPGE+IGVsZW1lbnQgdGhhdCByZXByZXNlbnRzIGhpZGRlbiBldmVudCBlbGVtZW50IGZvciBhIGNlbGwuXG4gICAgLy8gUmVzcG9uc2libGUgZm9yIGF0dGFjaGluZyBjbGljayBoYW5kbGVyIGFzIHdlbGwuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUucmVuZGVyTW9yZUxpbmsgPSBmdW5jdGlvbiAocm93LCBjb2wsIGhpZGRlblNlZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldywgZGF0ZUVudiA9IF9hLmRhdGVFbnYsIG9wdGlvbnMgPSBfYS5vcHRpb25zLCBpc1J0bCA9IF9hLmlzUnRsO1xuICAgICAgICB2YXIgYSA9IGNyZWF0ZUVsZW1lbnQoJ2EnLCB7IGNsYXNzTmFtZTogJ2ZjLW1vcmUnIH0pO1xuICAgICAgICBhLmlubmVyVGV4dCA9IHRoaXMuZ2V0TW9yZUxpbmtUZXh0KGhpZGRlblNlZ3MubGVuZ3RoKTtcbiAgICAgICAgYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGNsaWNrT3B0aW9uID0gb3B0aW9ucy5ldmVudExpbWl0Q2xpY2s7XG4gICAgICAgICAgICB2YXIgX2NvbCA9IGlzUnRsID8gX3RoaXMuY29sQ250IC0gY29sIC0gMSA6IGNvbDsgLy8gSEFDSzogcHJvcHMuY2VsbHMgaGFzIGRpZmZlcmVudCBkaXIgc3lzdGVtP1xuICAgICAgICAgICAgdmFyIGRhdGUgPSBfdGhpcy5wcm9wcy5jZWxsc1tyb3ddW19jb2xdLmRhdGU7XG4gICAgICAgICAgICB2YXIgbW9yZUVsID0gZXYuY3VycmVudFRhcmdldDtcbiAgICAgICAgICAgIHZhciBkYXlFbCA9IF90aGlzLmdldENlbGxFbChyb3csIGNvbCk7XG4gICAgICAgICAgICB2YXIgYWxsU2VncyA9IF90aGlzLmdldENlbGxTZWdzKHJvdywgY29sKTtcbiAgICAgICAgICAgIC8vIHJlc2NvcGUgdGhlIHNlZ21lbnRzIHRvIGJlIHdpdGhpbiB0aGUgY2VsbCdzIGRhdGVcbiAgICAgICAgICAgIHZhciByZXNsaWNlZEFsbFNlZ3MgPSBfdGhpcy5yZXNsaWNlRGF5U2VncyhhbGxTZWdzLCBkYXRlKTtcbiAgICAgICAgICAgIHZhciByZXNsaWNlZEhpZGRlblNlZ3MgPSBfdGhpcy5yZXNsaWNlRGF5U2VncyhoaWRkZW5TZWdzLCBkYXRlKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2xpY2tPcHRpb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgcmV0dXJuZWQgdmFsdWUgY2FuIGJlIGFuIGF0b21pYyBvcHRpb25cbiAgICAgICAgICAgICAgICBjbGlja09wdGlvbiA9IGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRMaW1pdENsaWNrJywgW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiBkYXRlRW52LnRvRGF0ZShkYXRlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbERheTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRheUVsOiBkYXlFbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vcmVFbDogbW9yZUVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VnczogcmVzbGljZWRBbGxTZWdzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGlkZGVuU2VnczogcmVzbGljZWRIaWRkZW5TZWdzLFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjbGlja09wdGlvbiA9PT0gJ3BvcG92ZXInKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2hvd1NlZ1BvcG92ZXIocm93LCBjb2wsIG1vcmVFbCwgcmVzbGljZWRBbGxTZWdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBjbGlja09wdGlvbiA9PT0gJ3N0cmluZycpIHsgLy8gYSB2aWV3IG5hbWVcbiAgICAgICAgICAgICAgICBjYWxlbmRhci56b29tVG8oZGF0ZSwgY2xpY2tPcHRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfTtcbiAgICAvLyBSZXZlYWxzIHRoZSBwb3BvdmVyIHRoYXQgZGlzcGxheXMgYWxsIGV2ZW50cyB3aXRoaW4gYSBjZWxsXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuc2hvd1NlZ1BvcG92ZXIgPSBmdW5jdGlvbiAocm93LCBjb2wsIG1vcmVMaW5rLCBzZWdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29udGV4dCwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhciwgdmlldyA9IF9hLnZpZXcsIHRoZW1lID0gX2EudGhlbWUsIGlzUnRsID0gX2EuaXNSdGw7XG4gICAgICAgIHZhciBfY29sID0gaXNSdGwgPyB0aGlzLmNvbENudCAtIGNvbCAtIDEgOiBjb2w7IC8vIEhBQ0s6IHByb3BzLmNlbGxzIGhhcyBkaWZmZXJlbnQgZGlyIHN5c3RlbT9cbiAgICAgICAgdmFyIG1vcmVXcmFwID0gbW9yZUxpbmsucGFyZW50Tm9kZTsgLy8gdGhlIDxkaXY+IHdyYXBwZXIgYXJvdW5kIHRoZSA8YT5cbiAgICAgICAgdmFyIHRvcEVsOyAvLyB0aGUgZWxlbWVudCB3ZSB3YW50IHRvIG1hdGNoIHRoZSB0b3AgY29vcmRpbmF0ZSBvZlxuICAgICAgICB2YXIgb3B0aW9ucztcbiAgICAgICAgaWYgKHRoaXMucm93Q250ID09PSAxKSB7XG4gICAgICAgICAgICB0b3BFbCA9IHZpZXcuZWw7IC8vIHdpbGwgY2F1c2UgdGhlIHBvcG92ZXIgdG8gY292ZXIgYW55IHNvcnQgb2YgaGVhZGVyXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0b3BFbCA9IHRoaXMucm93RWxzW3Jvd107IC8vIHdpbGwgYWxpZ24gd2l0aCB0b3Agb2Ygcm93XG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGNsYXNzTmFtZTogJ2ZjLW1vcmUtcG9wb3ZlciAnICsgdGhlbWUuZ2V0Q2xhc3MoJ3BvcG92ZXInKSxcbiAgICAgICAgICAgIHBhcmVudEVsOiB2aWV3LmVsLFxuICAgICAgICAgICAgdG9wOiBjb21wdXRlUmVjdCh0b3BFbCkudG9wLFxuICAgICAgICAgICAgYXV0b0hpZGU6IHRydWUsXG4gICAgICAgICAgICBjb250ZW50OiBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZWdQb3BvdmVyVGlsZSA9IG5ldyBEYXlUaWxlKGVsKTtcbiAgICAgICAgICAgICAgICBfdGhpcy51cGRhdGVTZWdQb3BvdmVyVGlsZShfdGhpcy5wcm9wcy5jZWxsc1tyb3ddW19jb2xdLmRhdGUsIHNlZ3MpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGhpZGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZWdQb3BvdmVyVGlsZS5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2VnUG9wb3ZlclRpbGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIF90aGlzLnNlZ1BvcG92ZXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIF90aGlzLnNlZ1BvcG92ZXIgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvLyBEZXRlcm1pbmUgaG9yaXpvbnRhbCBjb29yZGluYXRlLlxuICAgICAgICAvLyBXZSB1c2UgdGhlIG1vcmVXcmFwIGluc3RlYWQgb2YgdGhlIDx0ZD4gdG8gYXZvaWQgYm9yZGVyIGNvbmZ1c2lvbi5cbiAgICAgICAgaWYgKGlzUnRsKSB7XG4gICAgICAgICAgICBvcHRpb25zLnJpZ2h0ID0gY29tcHV0ZVJlY3QobW9yZVdyYXApLnJpZ2h0ICsgMTsgLy8gKzEgdG8gYmUgb3ZlciBjZWxsIGJvcmRlclxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgb3B0aW9ucy5sZWZ0ID0gY29tcHV0ZVJlY3QobW9yZVdyYXApLmxlZnQgLSAxOyAvLyAtMSB0byBiZSBvdmVyIGNlbGwgYm9yZGVyXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWdQb3BvdmVyID0gbmV3IFBvcG92ZXIob3B0aW9ucyk7XG4gICAgICAgIHRoaXMuc2VnUG9wb3Zlci5zaG93KCk7XG4gICAgICAgIGNhbGVuZGFyLnJlbGVhc2VBZnRlclNpemluZ1RyaWdnZXJzKCk7IC8vIGhhY2sgZm9yIGV2ZW50UG9zaXRpb25lZFxuICAgIH07XG4gICAgLy8gR2l2ZW4gdGhlIGV2ZW50cyB3aXRoaW4gYW4gYXJyYXkgb2Ygc2VnbWVudCBvYmplY3RzLCByZXNsaWNlIHRoZW0gdG8gYmUgaW4gYSBzaW5nbGUgZGF5XG4gICAgRGF5R3JpZC5wcm90b3R5cGUucmVzbGljZURheVNlZ3MgPSBmdW5jdGlvbiAoc2VncywgZGF5RGF0ZSkge1xuICAgICAgICB2YXIgZGF5U3RhcnQgPSBkYXlEYXRlO1xuICAgICAgICB2YXIgZGF5RW5kID0gYWRkRGF5cyhkYXlTdGFydCwgMSk7XG4gICAgICAgIHZhciBkYXlSYW5nZSA9IHsgc3RhcnQ6IGRheVN0YXJ0LCBlbmQ6IGRheUVuZCB9O1xuICAgICAgICB2YXIgbmV3U2VncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHNlZ3NfMSA9IHNlZ3M7IF9pIDwgc2Vnc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMVtfaV07XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IHNlZy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgdmFyIG9yaWdSYW5nZSA9IGV2ZW50UmFuZ2UucmFuZ2U7XG4gICAgICAgICAgICB2YXIgc2xpY2VkUmFuZ2UgPSBpbnRlcnNlY3RSYW5nZXMob3JpZ1JhbmdlLCBkYXlSYW5nZSk7XG4gICAgICAgICAgICBpZiAoc2xpY2VkUmFuZ2UpIHtcbiAgICAgICAgICAgICAgICBuZXdTZWdzLnB1c2goX19hc3NpZ24oe30sIHNlZywgeyBldmVudFJhbmdlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWY6IGV2ZW50UmFuZ2UuZGVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgdWk6IF9fYXNzaWduKHt9LCBldmVudFJhbmdlLnVpLCB7IGR1cmF0aW9uRWRpdGFibGU6IGZhbHNlIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2U6IGV2ZW50UmFuZ2UuaW5zdGFuY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICByYW5nZTogc2xpY2VkUmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgfSwgaXNTdGFydDogc2VnLmlzU3RhcnQgJiYgc2xpY2VkUmFuZ2Uuc3RhcnQudmFsdWVPZigpID09PSBvcmlnUmFuZ2Uuc3RhcnQudmFsdWVPZigpLCBpc0VuZDogc2VnLmlzRW5kICYmIHNsaWNlZFJhbmdlLmVuZC52YWx1ZU9mKCkgPT09IG9yaWdSYW5nZS5lbmQudmFsdWVPZigpIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3U2VncztcbiAgICB9O1xuICAgIC8vIEdlbmVyYXRlcyB0aGUgdGV4dCB0aGF0IHNob3VsZCBiZSBpbnNpZGUgYSBcIm1vcmVcIiBsaW5rLCBnaXZlbiB0aGUgbnVtYmVyIG9mIGV2ZW50cyBpdCByZXByZXNlbnRzXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuZ2V0TW9yZUxpbmtUZXh0ID0gZnVuY3Rpb24gKG51bSkge1xuICAgICAgICB2YXIgb3B0ID0gdGhpcy5jb250ZXh0Lm9wdGlvbnMuZXZlbnRMaW1pdFRleHQ7XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gb3B0KG51bSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJysnICsgbnVtICsgJyAnICsgb3B0O1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBSZXR1cm5zIHNlZ21lbnRzIHdpdGhpbiBhIGdpdmVuIGNlbGwuXG4gICAgLy8gSWYgYHN0YXJ0TGV2ZWxgIGlzIHNwZWNpZmllZCwgcmV0dXJucyBvbmx5IGV2ZW50cyBpbmNsdWRpbmcgYW5kIGJlbG93IHRoYXQgbGV2ZWwuIE90aGVyd2lzZSByZXR1cm5zIGFsbCBzZWdzLlxuICAgIERheUdyaWQucHJvdG90eXBlLmdldENlbGxTZWdzID0gZnVuY3Rpb24gKHJvdywgY29sLCBzdGFydExldmVsKSB7XG4gICAgICAgIHZhciBzZWdNYXRyaXggPSB0aGlzLmV2ZW50UmVuZGVyZXIucm93U3RydWN0c1tyb3ddLnNlZ01hdHJpeDtcbiAgICAgICAgdmFyIGxldmVsID0gc3RhcnRMZXZlbCB8fCAwO1xuICAgICAgICB2YXIgc2VncyA9IFtdO1xuICAgICAgICB2YXIgc2VnO1xuICAgICAgICB3aGlsZSAobGV2ZWwgPCBzZWdNYXRyaXgubGVuZ3RoKSB7XG4gICAgICAgICAgICBzZWcgPSBzZWdNYXRyaXhbbGV2ZWxdW2NvbF07XG4gICAgICAgICAgICBpZiAoc2VnKSB7XG4gICAgICAgICAgICAgICAgc2Vncy5wdXNoKHNlZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXZlbCsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWdzO1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWQ7XG59KERhdGVDb21wb25lbnQpKTtcblxudmFyIFdFRUtfTlVNX0ZPUk1BVCQxID0gY3JlYXRlRm9ybWF0dGVyKHsgd2VlazogJ251bWVyaWMnIH0pO1xuLyogQW4gYWJzdHJhY3QgY2xhc3MgZm9yIHRoZSBkYXlncmlkIHZpZXdzLCBhcyB3ZWxsIGFzIG1vbnRoIHZpZXcuIFJlbmRlcnMgb25lIG9yIG1vcmUgcm93cyBvZiBkYXkgY2VsbHMuXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbi8vIEl0IGlzIGEgbWFuYWdlciBmb3IgYSBEYXlHcmlkIHN1YmNvbXBvbmVudCwgd2hpY2ggZG9lcyBtb3N0IG9mIHRoZSBoZWF2eSBsaWZ0aW5nLlxuLy8gSXQgaXMgcmVzcG9uc2libGUgZm9yIG1hbmFnaW5nIHdpZHRoL2hlaWdodC5cbnZhciBBYnN0cmFjdERheUdyaWRWaWV3ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhBYnN0cmFjdERheUdyaWRWaWV3LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFic3RyYWN0RGF5R3JpZFZpZXcoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wcm9jZXNzT3B0aW9ucyA9IG1lbW9pemUoX3RoaXMuX3Byb2Nlc3NPcHRpb25zKTtcbiAgICAgICAgX3RoaXMucmVuZGVyU2tlbGV0b24gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLl9yZW5kZXJTa2VsZXRvbiwgX3RoaXMuX3VucmVuZGVyU2tlbGV0b24pO1xuICAgICAgICAvKiBIZWFkZXIgUmVuZGVyaW5nXG4gICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgICAgIC8vIEdlbmVyYXRlcyB0aGUgSFRNTCB0aGF0IHdpbGwgZ28gYmVmb3JlIHRoZSBkYXktb2Ygd2VlayBoZWFkZXIgY2VsbHNcbiAgICAgICAgX3RoaXMucmVuZGVySGVhZEludHJvSHRtbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLmNvbnRleHQsIHRoZW1lID0gX2EudGhlbWUsIG9wdGlvbnMgPSBfYS5vcHRpb25zO1xuICAgICAgICAgICAgaWYgKF90aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnJyArXG4gICAgICAgICAgICAgICAgICAgICc8dGggY2xhc3M9XCJmYy13ZWVrLW51bWJlciAnICsgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldEhlYWRlcicpICsgJ1wiICcgKyBfdGhpcy53ZWVrTnVtYmVyU3R5bGVBdHRyKCkgKyAnPicgK1xuICAgICAgICAgICAgICAgICAgICAnPHNwYW4+JyArIC8vIG5lZWRlZCBmb3IgbWF0Y2hDZWxsV2lkdGhzXG4gICAgICAgICAgICAgICAgICAgIGh0bWxFc2NhcGUob3B0aW9ucy53ZWVrTGFiZWwpICtcbiAgICAgICAgICAgICAgICAgICAgJzwvc3Bhbj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzwvdGg+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfTtcbiAgICAgICAgLyogRGF5IEdyaWQgUmVuZGVyaW5nXG4gICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgICAgIC8vIEdlbmVyYXRlcyB0aGUgSFRNTCB0aGF0IHdpbGwgZ28gYmVmb3JlIGNvbnRlbnQtc2tlbGV0b24gY2VsbHMgdGhhdCBkaXNwbGF5IHRoZSBkYXkvd2VlayBudW1iZXJzXG4gICAgICAgIF90aGlzLnJlbmRlckRheUdyaWROdW1iZXJJbnRyb0h0bWwgPSBmdW5jdGlvbiAocm93LCBkYXlHcmlkKSB7XG4gICAgICAgICAgICB2YXIgX2EgPSBfdGhpcy5jb250ZXh0LCBvcHRpb25zID0gX2Eub3B0aW9ucywgZGF0ZUVudiA9IF9hLmRhdGVFbnY7XG4gICAgICAgICAgICB2YXIgd2Vla1N0YXJ0ID0gZGF5R3JpZC5wcm9wcy5jZWxsc1tyb3ddWzBdLmRhdGU7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcnICtcbiAgICAgICAgICAgICAgICAgICAgJzx0ZCBjbGFzcz1cImZjLXdlZWstbnVtYmVyXCIgJyArIF90aGlzLndlZWtOdW1iZXJTdHlsZUF0dHIoKSArICc+JyArXG4gICAgICAgICAgICAgICAgICAgIGJ1aWxkR290b0FuY2hvckh0bWwoLy8gYXNpZGUgZnJvbSBsaW5rLCBpbXBvcnRhbnQgZm9yIG1hdGNoQ2VsbFdpZHRoc1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLCBkYXRlRW52LCB7IGRhdGU6IHdlZWtTdGFydCwgdHlwZTogJ3dlZWsnLCBmb3JjZU9mZjogZGF5R3JpZC5jb2xDbnQgPT09IDEgfSwgZGF0ZUVudi5mb3JtYXQod2Vla1N0YXJ0LCBXRUVLX05VTV9GT1JNQVQkMSkgLy8gaW5uZXIgSFRNTFxuICAgICAgICAgICAgICAgICAgICApICtcbiAgICAgICAgICAgICAgICAgICAgJzwvdGQ+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfTtcbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgZ29lcyBiZWZvcmUgdGhlIGRheSBiZyBjZWxscyBmb3IgZWFjaCBkYXktcm93XG4gICAgICAgIF90aGlzLnJlbmRlckRheUdyaWRCZ0ludHJvSHRtbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciB0aGVtZSA9IF90aGlzLmNvbnRleHQudGhlbWU7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICc8dGQgY2xhc3M9XCJmYy13ZWVrLW51bWJlciAnICsgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSArICdcIiAnICsgX3RoaXMud2Vla051bWJlclN0eWxlQXR0cigpICsgJz48L3RkPic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEdlbmVyYXRlcyB0aGUgSFRNTCB0aGF0IGdvZXMgYmVmb3JlIGV2ZXJ5IG90aGVyIHR5cGUgb2Ygcm93IGdlbmVyYXRlZCBieSBEYXlHcmlkLlxuICAgICAgICAvLyBBZmZlY3RzIG1pcnJvci1za2VsZXRvbiBhbmQgaGlnaGxpZ2h0LXNrZWxldG9uIHJvd3MuXG4gICAgICAgIF90aGlzLnJlbmRlckRheUdyaWRJbnRyb0h0bWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICc8dGQgY2xhc3M9XCJmYy13ZWVrLW51bWJlclwiICcgKyBfdGhpcy53ZWVrTnVtYmVyU3R5bGVBdHRyKCkgKyAnPjwvdGQ+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5fcHJvY2Vzc09wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucy53ZWVrTnVtYmVycykge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMud2Vla051bWJlcnNXaXRoaW5EYXlzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZW5kZXIuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCk7XG4gICAgICAgIHRoaXMucHJvY2Vzc09wdGlvbnMoY29udGV4dC5vcHRpb25zKTtcbiAgICAgICAgdGhpcy5yZW5kZXJTa2VsZXRvbihjb250ZXh0KTtcbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uLnVucmVuZGVyKCk7XG4gICAgfTtcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5fcmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ2ZjLWRheUdyaWQtdmlldycpO1xuICAgICAgICB0aGlzLmVsLmlubmVySFRNTCA9IHRoaXMucmVuZGVyU2tlbGV0b25IdG1sKCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsZXIgPSBuZXcgU2Nyb2xsQ29tcG9uZW50KCdoaWRkZW4nLCAvLyBvdmVyZmxvdyB4XG4gICAgICAgICdhdXRvJyAvLyBvdmVyZmxvdyB5XG4gICAgICAgICk7XG4gICAgICAgIHZhciBkYXlHcmlkQ29udGFpbmVyRWwgPSB0aGlzLnNjcm9sbGVyLmVsO1xuICAgICAgICB0aGlzLmVsLnF1ZXJ5U2VsZWN0b3IoJy5mYy1ib2R5ID4gdHIgPiB0ZCcpLmFwcGVuZENoaWxkKGRheUdyaWRDb250YWluZXJFbCk7XG4gICAgICAgIGRheUdyaWRDb250YWluZXJFbC5jbGFzc0xpc3QuYWRkKCdmYy1kYXktZ3JpZC1jb250YWluZXInKTtcbiAgICAgICAgdmFyIGRheUdyaWRFbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHsgY2xhc3NOYW1lOiAnZmMtZGF5LWdyaWQnIH0pO1xuICAgICAgICBkYXlHcmlkQ29udGFpbmVyRWwuYXBwZW5kQ2hpbGQoZGF5R3JpZEVsKTtcbiAgICAgICAgdGhpcy5kYXlHcmlkID0gbmV3IERheUdyaWQoZGF5R3JpZEVsLCB7XG4gICAgICAgICAgICByZW5kZXJOdW1iZXJJbnRyb0h0bWw6IHRoaXMucmVuZGVyRGF5R3JpZE51bWJlckludHJvSHRtbCxcbiAgICAgICAgICAgIHJlbmRlckJnSW50cm9IdG1sOiB0aGlzLnJlbmRlckRheUdyaWRCZ0ludHJvSHRtbCxcbiAgICAgICAgICAgIHJlbmRlckludHJvSHRtbDogdGhpcy5yZW5kZXJEYXlHcmlkSW50cm9IdG1sLFxuICAgICAgICAgICAgY29sV2Vla051bWJlcnNWaXNpYmxlOiB0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSxcbiAgICAgICAgICAgIGNlbGxXZWVrTnVtYmVyc1Zpc2libGU6IHRoaXMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLl91bnJlbmRlclNrZWxldG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoJ2ZjLWRheUdyaWQtdmlldycpO1xuICAgICAgICB0aGlzLmRheUdyaWQuZGVzdHJveSgpO1xuICAgICAgICB0aGlzLnNjcm9sbGVyLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIC8vIEJ1aWxkcyB0aGUgSFRNTCBza2VsZXRvbiBmb3IgdGhlIHZpZXcuXG4gICAgLy8gVGhlIGRheS1ncmlkIGNvbXBvbmVudCB3aWxsIHJlbmRlciBpbnNpZGUgb2YgYSBjb250YWluZXIgZGVmaW5lZCBieSB0aGlzIEhUTUwuXG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUucmVuZGVyU2tlbGV0b25IdG1sID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIHRoZW1lID0gX2EudGhlbWUsIG9wdGlvbnMgPSBfYS5vcHRpb25zO1xuICAgICAgICByZXR1cm4gJycgK1xuICAgICAgICAgICAgJzx0YWJsZSBjbGFzcz1cIicgKyB0aGVtZS5nZXRDbGFzcygndGFibGVHcmlkJykgKyAnXCI+JyArXG4gICAgICAgICAgICAob3B0aW9ucy5jb2x1bW5IZWFkZXIgP1xuICAgICAgICAgICAgICAgICc8dGhlYWQgY2xhc3M9XCJmYy1oZWFkXCI+JyArXG4gICAgICAgICAgICAgICAgICAgICc8dHI+JyArXG4gICAgICAgICAgICAgICAgICAgICc8dGQgY2xhc3M9XCJmYy1oZWFkLWNvbnRhaW5lciAnICsgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldEhlYWRlcicpICsgJ1wiPiZuYnNwOzwvdGQ+JyArXG4gICAgICAgICAgICAgICAgICAgICc8L3RyPicgK1xuICAgICAgICAgICAgICAgICAgICAnPC90aGVhZD4nIDpcbiAgICAgICAgICAgICAgICAnJykgK1xuICAgICAgICAgICAgJzx0Ym9keSBjbGFzcz1cImZjLWJvZHlcIj4nICtcbiAgICAgICAgICAgICc8dHI+JyArXG4gICAgICAgICAgICAnPHRkIGNsYXNzPVwiJyArIHRoZW1lLmdldENsYXNzKCd3aWRnZXRDb250ZW50JykgKyAnXCI+PC90ZD4nICtcbiAgICAgICAgICAgICc8L3RyPicgK1xuICAgICAgICAgICAgJzwvdGJvZHk+JyArXG4gICAgICAgICAgICAnPC90YWJsZT4nO1xuICAgIH07XG4gICAgLy8gR2VuZXJhdGVzIGFuIEhUTUwgYXR0cmlidXRlIHN0cmluZyBmb3Igc2V0dGluZyB0aGUgd2lkdGggb2YgdGhlIHdlZWsgbnVtYmVyIGNvbHVtbiwgaWYgaXQgaXMga25vd25cbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS53ZWVrTnVtYmVyU3R5bGVBdHRyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy53ZWVrTnVtYmVyV2lkdGggIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuICdzdHlsZT1cIndpZHRoOicgKyB0aGlzLndlZWtOdW1iZXJXaWR0aCArICdweFwiJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfTtcbiAgICAvLyBEZXRlcm1pbmVzIHdoZXRoZXIgZWFjaCByb3cgc2hvdWxkIGhhdmUgYSBjb25zdGFudCBoZWlnaHRcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5oYXNSaWdpZFJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudExpbWl0ID0gdGhpcy5jb250ZXh0Lm9wdGlvbnMuZXZlbnRMaW1pdDtcbiAgICAgICAgcmV0dXJuIGV2ZW50TGltaXQgJiYgdHlwZW9mIGV2ZW50TGltaXQgIT09ICdudW1iZXInO1xuICAgIH07XG4gICAgLyogRGltZW5zaW9uc1xuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUudXBkYXRlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUudXBkYXRlU2l6ZS5jYWxsKHRoaXMsIGlzUmVzaXplLCB2aWV3SGVpZ2h0LCBpc0F1dG8pOyAvLyB3aWxsIGNhbGwgdXBkYXRlQmFzZVNpemUuIGltcG9ydGFudCB0aGF0IGV4ZWN1dGVzIGZpcnN0XG4gICAgICAgIHRoaXMuZGF5R3JpZC51cGRhdGVTaXplKGlzUmVzaXplKTtcbiAgICB9O1xuICAgIC8vIFJlZnJlc2hlcyB0aGUgaG9yaXpvbnRhbCBkaW1lbnNpb25zIG9mIHRoZSB2aWV3XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUudXBkYXRlQmFzZVNpemUgPSBmdW5jdGlvbiAoaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0bykge1xuICAgICAgICB2YXIgZGF5R3JpZCA9IHRoaXMuZGF5R3JpZDtcbiAgICAgICAgdmFyIGV2ZW50TGltaXQgPSB0aGlzLmNvbnRleHQub3B0aW9ucy5ldmVudExpbWl0O1xuICAgICAgICB2YXIgaGVhZFJvd0VsID0gdGhpcy5oZWFkZXIgPyB0aGlzLmhlYWRlci5lbCA6IG51bGw7IC8vIEhBQ0tcbiAgICAgICAgdmFyIHNjcm9sbGVySGVpZ2h0O1xuICAgICAgICB2YXIgc2Nyb2xsYmFyV2lkdGhzO1xuICAgICAgICAvLyBoYWNrIHRvIGdpdmUgdGhlIHZpZXcgc29tZSBoZWlnaHQgcHJpb3IgdG8gZGF5R3JpZCdzIGNvbHVtbnMgYmVpbmcgcmVuZGVyZWRcbiAgICAgICAgLy8gVE9ETzogc2VwYXJhdGUgc2V0dGluZyBoZWlnaHQgZnJvbSBzY3JvbGxlciBWUyBkYXlHcmlkLlxuICAgICAgICBpZiAoIWRheUdyaWQucm93RWxzKSB7XG4gICAgICAgICAgICBpZiAoIWlzQXV0bykge1xuICAgICAgICAgICAgICAgIHNjcm9sbGVySGVpZ2h0ID0gdGhpcy5jb21wdXRlU2Nyb2xsZXJIZWlnaHQodmlld0hlaWdodCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxlci5zZXRIZWlnaHQoc2Nyb2xsZXJIZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGFsbCB3ZWVrIG51bWJlciBjZWxscyBydW5uaW5nIGRvd24gdGhlIHNpZGUgaGF2ZSB0aGUgc2FtZSB3aWR0aC5cbiAgICAgICAgICAgIHRoaXMud2Vla051bWJlcldpZHRoID0gbWF0Y2hDZWxsV2lkdGhzKGZpbmRFbGVtZW50cyh0aGlzLmVsLCAnLmZjLXdlZWstbnVtYmVyJykpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHJlc2V0IGFsbCBoZWlnaHRzIHRvIGJlIG5hdHVyYWxcbiAgICAgICAgdGhpcy5zY3JvbGxlci5jbGVhcigpO1xuICAgICAgICBpZiAoaGVhZFJvd0VsKSB7XG4gICAgICAgICAgICB1bmNvbXBlbnNhdGVTY3JvbGwoaGVhZFJvd0VsKTtcbiAgICAgICAgfVxuICAgICAgICBkYXlHcmlkLnJlbW92ZVNlZ1BvcG92ZXIoKTsgLy8ga2lsbCB0aGUgXCJtb3JlXCIgcG9wb3ZlciBpZiBkaXNwbGF5ZWRcbiAgICAgICAgLy8gaXMgdGhlIGV2ZW50IGxpbWl0IGEgY29uc3RhbnQgbGV2ZWwgbnVtYmVyP1xuICAgICAgICBpZiAoZXZlbnRMaW1pdCAmJiB0eXBlb2YgZXZlbnRMaW1pdCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGRheUdyaWQubGltaXRSb3dzKGV2ZW50TGltaXQpOyAvLyBsaW1pdCB0aGUgbGV2ZWxzIGZpcnN0IHNvIHRoZSBoZWlnaHQgY2FuIHJlZGlzdHJpYnV0ZSBhZnRlclxuICAgICAgICB9XG4gICAgICAgIC8vIGRpc3RyaWJ1dGUgdGhlIGhlaWdodCB0byB0aGUgcm93c1xuICAgICAgICAvLyAodmlld0hlaWdodCBpcyBhIFwicmVjb21tZW5kZWRcIiB2YWx1ZSBpZiBpc0F1dG8pXG4gICAgICAgIHNjcm9sbGVySGVpZ2h0ID0gdGhpcy5jb21wdXRlU2Nyb2xsZXJIZWlnaHQodmlld0hlaWdodCk7XG4gICAgICAgIHRoaXMuc2V0R3JpZEhlaWdodChzY3JvbGxlckhlaWdodCwgaXNBdXRvKTtcbiAgICAgICAgLy8gaXMgdGhlIGV2ZW50IGxpbWl0IGR5bmFtaWNhbGx5IGNhbGN1bGF0ZWQ/XG4gICAgICAgIGlmIChldmVudExpbWl0ICYmIHR5cGVvZiBldmVudExpbWl0ICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgZGF5R3JpZC5saW1pdFJvd3MoZXZlbnRMaW1pdCk7IC8vIGxpbWl0IHRoZSBsZXZlbHMgYWZ0ZXIgdGhlIGdyaWQncyByb3cgaGVpZ2h0cyBoYXZlIGJlZW4gc2V0XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0F1dG8pIHsgLy8gc2hvdWxkIHdlIGZvcmNlIGRpbWVuc2lvbnMgb2YgdGhlIHNjcm9sbCBjb250YWluZXI/XG4gICAgICAgICAgICB0aGlzLnNjcm9sbGVyLnNldEhlaWdodChzY3JvbGxlckhlaWdodCk7XG4gICAgICAgICAgICBzY3JvbGxiYXJXaWR0aHMgPSB0aGlzLnNjcm9sbGVyLmdldFNjcm9sbGJhcldpZHRocygpO1xuICAgICAgICAgICAgaWYgKHNjcm9sbGJhcldpZHRocy5sZWZ0IHx8IHNjcm9sbGJhcldpZHRocy5yaWdodCkgeyAvLyB1c2luZyBzY3JvbGxiYXJzP1xuICAgICAgICAgICAgICAgIGlmIChoZWFkUm93RWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGVuc2F0ZVNjcm9sbChoZWFkUm93RWwsIHNjcm9sbGJhcldpZHRocyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGRvaW5nIHRoZSBzY3JvbGxiYXIgY29tcGVuc2F0aW9uIG1pZ2h0IGhhdmUgY3JlYXRlZCB0ZXh0IG92ZXJmbG93IHdoaWNoIGNyZWF0ZWQgbW9yZSBoZWlnaHQuIHJlZG9cbiAgICAgICAgICAgICAgICBzY3JvbGxlckhlaWdodCA9IHRoaXMuY29tcHV0ZVNjcm9sbGVySGVpZ2h0KHZpZXdIZWlnaHQpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsZXIuc2V0SGVpZ2h0KHNjcm9sbGVySGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGd1YXJhbnRlZXMgdGhlIHNhbWUgc2Nyb2xsYmFyIHdpZHRoc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxlci5sb2NrT3ZlcmZsb3coc2Nyb2xsYmFyV2lkdGhzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZ2l2ZW4gYSBkZXNpcmVkIHRvdGFsIGhlaWdodCBvZiB0aGUgdmlldywgcmV0dXJucyB3aGF0IHRoZSBoZWlnaHQgb2YgdGhlIHNjcm9sbGVyIHNob3VsZCBiZVxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmNvbXB1dGVTY3JvbGxlckhlaWdodCA9IGZ1bmN0aW9uICh2aWV3SGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiB2aWV3SGVpZ2h0IC1cbiAgICAgICAgICAgIHN1YnRyYWN0SW5uZXJFbEhlaWdodCh0aGlzLmVsLCB0aGlzLnNjcm9sbGVyLmVsKTsgLy8gZXZlcnl0aGluZyB0aGF0J3MgTk9UIHRoZSBzY3JvbGxlclxuICAgIH07XG4gICAgLy8gU2V0cyB0aGUgaGVpZ2h0IG9mIGp1c3QgdGhlIERheUdyaWQgY29tcG9uZW50IGluIHRoaXMgdmlld1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLnNldEdyaWRIZWlnaHQgPSBmdW5jdGlvbiAoaGVpZ2h0LCBpc0F1dG8pIHtcbiAgICAgICAgaWYgKHRoaXMuY29udGV4dC5vcHRpb25zLm1vbnRoTW9kZSkge1xuICAgICAgICAgICAgLy8gaWYgYXV0bywgbWFrZSB0aGUgaGVpZ2h0IG9mIGVhY2ggcm93IHRoZSBoZWlnaHQgdGhhdCBpdCB3b3VsZCBiZSBpZiB0aGVyZSB3ZXJlIDYgd2Vla3NcbiAgICAgICAgICAgIGlmIChpc0F1dG8pIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgKj0gdGhpcy5kYXlHcmlkLnJvd0NudCAvIDY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXN0cmlidXRlSGVpZ2h0KHRoaXMuZGF5R3JpZC5yb3dFbHMsIGhlaWdodCwgIWlzQXV0byk7IC8vIGlmIGF1dG8sIGRvbid0IGNvbXBlbnNhdGUgZm9yIGhlaWdodC1ob2dnaW5nIHJvd3NcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChpc0F1dG8pIHtcbiAgICAgICAgICAgICAgICB1bmRpc3RyaWJ1dGVIZWlnaHQodGhpcy5kYXlHcmlkLnJvd0Vscyk7IC8vIGxldCB0aGUgcm93cyBiZSB0aGVpciBuYXR1cmFsIGhlaWdodCB3aXRoIG5vIGV4cGFuZGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzdHJpYnV0ZUhlaWdodCh0aGlzLmRheUdyaWQucm93RWxzLCBoZWlnaHQsIHRydWUpOyAvLyB0cnVlID0gY29tcGVuc2F0ZSBmb3IgaGVpZ2h0LWhvZ2dpbmcgcm93c1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiBTY3JvbGxcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmNvbXB1dGVEYXRlU2Nyb2xsID0gZnVuY3Rpb24gKGR1cmF0aW9uKSB7XG4gICAgICAgIHJldHVybiB7IHRvcDogMCB9O1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUucXVlcnlEYXRlU2Nyb2xsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyB0b3A6IHRoaXMuc2Nyb2xsZXIuZ2V0U2Nyb2xsVG9wKCkgfTtcbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmFwcGx5RGF0ZVNjcm9sbCA9IGZ1bmN0aW9uIChzY3JvbGwpIHtcbiAgICAgICAgaWYgKHNjcm9sbC50b3AgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxlci5zZXRTY3JvbGxUb3Aoc2Nyb2xsLnRvcCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBBYnN0cmFjdERheUdyaWRWaWV3O1xufShWaWV3KSk7XG5BYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5kYXRlUHJvZmlsZUdlbmVyYXRvckNsYXNzID0gRGF5R3JpZERhdGVQcm9maWxlR2VuZXJhdG9yO1xuXG52YXIgU2ltcGxlRGF5R3JpZCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU2ltcGxlRGF5R3JpZCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTaW1wbGVEYXlHcmlkKGRheUdyaWQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgZGF5R3JpZC5lbCkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc2xpY2VyID0gbmV3IERheUdyaWRTbGljZXIoKTtcbiAgICAgICAgX3RoaXMuZGF5R3JpZCA9IGRheUdyaWQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU2ltcGxlRGF5R3JpZC5wcm90b3R5cGUuZmlyc3RDb250ZXh0ID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgY29udGV4dC5jYWxlbmRhci5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KHRoaXMsIHsgZWw6IHRoaXMuZGF5R3JpZC5lbCB9KTtcbiAgICB9O1xuICAgIFNpbXBsZURheUdyaWQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLmNvbnRleHQuY2FsZW5kYXIudW5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50KHRoaXMpO1xuICAgIH07XG4gICAgU2ltcGxlRGF5R3JpZC5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgZGF0ZVByb2ZpbGUgPSBwcm9wcy5kYXRlUHJvZmlsZSwgZGF5VGFibGUgPSBwcm9wcy5kYXlUYWJsZTtcbiAgICAgICAgZGF5R3JpZC5yZWNlaXZlQ29udGV4dChjb250ZXh0KTsgLy8gaGFjayBiZWNhdXNlIGNvbnRleHQgaXMgdXNlZCBpbiBzbGljZVByb3BzXG4gICAgICAgIGRheUdyaWQucmVjZWl2ZVByb3BzKF9fYXNzaWduKHt9LCB0aGlzLnNsaWNlci5zbGljZVByb3BzKHByb3BzLCBkYXRlUHJvZmlsZSwgcHJvcHMubmV4dERheVRocmVzaG9sZCwgY29udGV4dC5jYWxlbmRhciwgZGF5R3JpZCwgZGF5VGFibGUpLCB7IGRhdGVQcm9maWxlOiBkYXRlUHJvZmlsZSwgY2VsbHM6IGRheVRhYmxlLmNlbGxzLCBpc1JpZ2lkOiBwcm9wcy5pc1JpZ2lkIH0pLCBjb250ZXh0KTtcbiAgICB9O1xuICAgIFNpbXBsZURheUdyaWQucHJvdG90eXBlLmJ1aWxkUG9zaXRpb25DYWNoZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF5R3JpZC5idWlsZFBvc2l0aW9uQ2FjaGVzKCk7XG4gICAgfTtcbiAgICBTaW1wbGVEYXlHcmlkLnByb3RvdHlwZS5xdWVyeUhpdCA9IGZ1bmN0aW9uIChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wKSB7XG4gICAgICAgIHZhciByYXdIaXQgPSB0aGlzLmRheUdyaWQucG9zaXRpb25Ub0hpdChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wKTtcbiAgICAgICAgaWYgKHJhd0hpdCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQ6IHRoaXMuZGF5R3JpZCxcbiAgICAgICAgICAgICAgICBkYXRlU3BhbjogcmF3SGl0LmRhdGVTcGFuLFxuICAgICAgICAgICAgICAgIGRheUVsOiByYXdIaXQuZGF5RWwsXG4gICAgICAgICAgICAgICAgcmVjdDoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiByYXdIaXQucmVsYXRpdmVSZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiByYXdIaXQucmVsYXRpdmVSZWN0LnJpZ2h0LFxuICAgICAgICAgICAgICAgICAgICB0b3A6IHJhd0hpdC5yZWxhdGl2ZVJlY3QudG9wLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IHJhd0hpdC5yZWxhdGl2ZVJlY3QuYm90dG9tXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsYXllcjogMFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFNpbXBsZURheUdyaWQ7XG59KERhdGVDb21wb25lbnQpKTtcbnZhciBEYXlHcmlkU2xpY2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkU2xpY2VyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUdyaWRTbGljZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgRGF5R3JpZFNsaWNlci5wcm90b3R5cGUuc2xpY2VSYW5nZSA9IGZ1bmN0aW9uIChkYXRlUmFuZ2UsIGRheVRhYmxlKSB7XG4gICAgICAgIHJldHVybiBkYXlUYWJsZS5zbGljZVJhbmdlKGRhdGVSYW5nZSk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5R3JpZFNsaWNlcjtcbn0oU2xpY2VyKSk7XG5cbnZhciBEYXlHcmlkVmlldyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5R3JpZFZpZXcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5R3JpZFZpZXcoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5idWlsZERheVRhYmxlID0gbWVtb2l6ZShidWlsZERheVRhYmxlKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlHcmlkVmlldy5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzLCBjb250ZXh0KSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucmVuZGVyLmNhbGwodGhpcywgcHJvcHMsIGNvbnRleHQpOyAvLyB3aWxsIGNhbGwgX3JlbmRlclNrZWxldG9uL191bnJlbmRlclNrZWxldG9uXG4gICAgICAgIHZhciBkYXRlUHJvZmlsZSA9IHRoaXMucHJvcHMuZGF0ZVByb2ZpbGU7XG4gICAgICAgIHZhciBkYXlUYWJsZSA9IHRoaXMuZGF5VGFibGUgPVxuICAgICAgICAgICAgdGhpcy5idWlsZERheVRhYmxlKGRhdGVQcm9maWxlLCBwcm9wcy5kYXRlUHJvZmlsZUdlbmVyYXRvcik7XG4gICAgICAgIGlmICh0aGlzLmhlYWRlcikge1xuICAgICAgICAgICAgdGhpcy5oZWFkZXIucmVjZWl2ZVByb3BzKHtcbiAgICAgICAgICAgICAgICBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICAgICAgZGF0ZXM6IGRheVRhYmxlLmhlYWRlckRhdGVzLFxuICAgICAgICAgICAgICAgIGRhdGVzUmVwRGlzdGluY3REYXlzOiBkYXlUYWJsZS5yb3dDbnQgPT09IDEsXG4gICAgICAgICAgICAgICAgcmVuZGVySW50cm9IdG1sOiB0aGlzLnJlbmRlckhlYWRJbnRyb0h0bWxcbiAgICAgICAgICAgIH0sIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2ltcGxlRGF5R3JpZC5yZWNlaXZlUHJvcHMoe1xuICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IGRhdGVQcm9maWxlLFxuICAgICAgICAgICAgZGF5VGFibGU6IGRheVRhYmxlLFxuICAgICAgICAgICAgYnVzaW5lc3NIb3VyczogcHJvcHMuYnVzaW5lc3NIb3VycyxcbiAgICAgICAgICAgIGRhdGVTZWxlY3Rpb246IHByb3BzLmRhdGVTZWxlY3Rpb24sXG4gICAgICAgICAgICBldmVudFN0b3JlOiBwcm9wcy5ldmVudFN0b3JlLFxuICAgICAgICAgICAgZXZlbnRVaUJhc2VzOiBwcm9wcy5ldmVudFVpQmFzZXMsXG4gICAgICAgICAgICBldmVudFNlbGVjdGlvbjogcHJvcHMuZXZlbnRTZWxlY3Rpb24sXG4gICAgICAgICAgICBldmVudERyYWc6IHByb3BzLmV2ZW50RHJhZyxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplOiBwcm9wcy5ldmVudFJlc2l6ZSxcbiAgICAgICAgICAgIGlzUmlnaWQ6IHRoaXMuaGFzUmlnaWRSb3dzKCksXG4gICAgICAgICAgICBuZXh0RGF5VGhyZXNob2xkOiB0aGlzLmNvbnRleHQubmV4dERheVRocmVzaG9sZFxuICAgICAgICB9LCBjb250ZXh0KTtcbiAgICB9O1xuICAgIERheUdyaWRWaWV3LnByb3RvdHlwZS5fcmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLl9yZW5kZXJTa2VsZXRvbi5jYWxsKHRoaXMsIGNvbnRleHQpO1xuICAgICAgICBpZiAoY29udGV4dC5vcHRpb25zLmNvbHVtbkhlYWRlcikge1xuICAgICAgICAgICAgdGhpcy5oZWFkZXIgPSBuZXcgRGF5SGVhZGVyKHRoaXMuZWwucXVlcnlTZWxlY3RvcignLmZjLWhlYWQtY29udGFpbmVyJykpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2ltcGxlRGF5R3JpZCA9IG5ldyBTaW1wbGVEYXlHcmlkKHRoaXMuZGF5R3JpZCk7XG4gICAgfTtcbiAgICBEYXlHcmlkVmlldy5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24uY2FsbCh0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zaW1wbGVEYXlHcmlkLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkVmlldztcbn0oQWJzdHJhY3REYXlHcmlkVmlldykpO1xuZnVuY3Rpb24gYnVpbGREYXlUYWJsZShkYXRlUHJvZmlsZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpIHtcbiAgICB2YXIgZGF5U2VyaWVzID0gbmV3IERheVNlcmllcyhkYXRlUHJvZmlsZS5yZW5kZXJSYW5nZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpO1xuICAgIHJldHVybiBuZXcgRGF5VGFibGUoZGF5U2VyaWVzLCAveWVhcnxtb250aHx3ZWVrLy50ZXN0KGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpKTtcbn1cblxudmFyIG1haW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIGRlZmF1bHRWaWV3OiAnZGF5R3JpZE1vbnRoJyxcbiAgICB2aWV3czoge1xuICAgICAgICBkYXlHcmlkOiBEYXlHcmlkVmlldyxcbiAgICAgICAgZGF5R3JpZERheToge1xuICAgICAgICAgICAgdHlwZTogJ2RheUdyaWQnLFxuICAgICAgICAgICAgZHVyYXRpb246IHsgZGF5czogMSB9XG4gICAgICAgIH0sXG4gICAgICAgIGRheUdyaWRXZWVrOiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyB3ZWVrczogMSB9XG4gICAgICAgIH0sXG4gICAgICAgIGRheUdyaWRNb250aDoge1xuICAgICAgICAgICAgdHlwZTogJ2RheUdyaWQnLFxuICAgICAgICAgICAgZHVyYXRpb246IHsgbW9udGhzOiAxIH0sXG4gICAgICAgICAgICBtb250aE1vZGU6IHRydWUsXG4gICAgICAgICAgICBmaXhlZFdlZWtDb3VudDogdHJ1ZVxuICAgICAgICB9XG4gICAgfVxufSk7XG5cbmV4cG9ydCBkZWZhdWx0IG1haW47XG5leHBvcnQgeyBBYnN0cmFjdERheUdyaWRWaWV3LCBEYXlCZ1JvdywgRGF5R3JpZCwgRGF5R3JpZFNsaWNlciwgRGF5R3JpZFZpZXcsIFNpbXBsZURheUdyaWQsIGJ1aWxkRGF5VGFibGUgYXMgYnVpbGRCYXNpY0RheVRhYmxlIH07XG4iLCIvKiFcbkZ1bGxDYWxlbmRhciBJbnRlcmFjdGlvbiBQbHVnaW4gdjQuNC4yXG5Eb2NzICYgTGljZW5zZTogaHR0cHM6Ly9mdWxsY2FsZW5kYXIuaW8vXG4oYykgMjAxOSBBZGFtIFNoYXdcbiovXG5cbmltcG9ydCB7IGNvbmZpZywgZWxlbWVudENsb3Nlc3QsIEVtaXR0ZXJNaXhpbiwgYXBwbHlTdHlsZSwgd2hlblRyYW5zaXRpb25Eb25lLCByZW1vdmVFbGVtZW50LCBTY3JvbGxDb250cm9sbGVyLCBFbGVtZW50U2Nyb2xsQ29udHJvbGxlciwgY29tcHV0ZUlubmVyUmVjdCwgV2luZG93U2Nyb2xsQ29udHJvbGxlciwgcHJldmVudFNlbGVjdGlvbiwgcHJldmVudENvbnRleHRNZW51LCBhbGxvd1NlbGVjdGlvbiwgYWxsb3dDb250ZXh0TWVudSwgRWxlbWVudERyYWdnaW5nLCBjb21wdXRlUmVjdCwgZ2V0Q2xpcHBpbmdQYXJlbnRzLCBwb2ludEluc2lkZVJlY3QsIGlzRGF0ZVNwYW5zRXF1YWwsIGNvbnN0cmFpblBvaW50LCBpbnRlcnNlY3RSZWN0cywgZ2V0UmVjdENlbnRlciwgZGlmZlBvaW50cywgbWFwSGFzaCwgcmFuZ2VDb250YWluc1JhbmdlLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZSwgSW50ZXJhY3Rpb24sIGVuYWJsZUN1cnNvciwgZGlzYWJsZUN1cnNvciwgY29tcGFyZU51bWJlcnMsIGdldEVsU2VnLCBnZXRSZWxldmFudEV2ZW50cywgRXZlbnRBcGksIGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSwgYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZSwgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlLCBzdGFydE9mRGF5LCBkaWZmRGF0ZXMsIGNyZWF0ZUR1cmF0aW9uLCBldmVudFR1cGxlVG9TdG9yZSwgaXNJbnRlcmFjdGlvblZhbGlkLCBwYXJzZURyYWdNZXRhLCBlbGVtZW50TWF0Y2hlcywgcGFyc2VFdmVudERlZiwgY3JlYXRlRXZlbnRJbnN0YW5jZSwgZ2xvYmFsRGVmYXVsdHMsIGNyZWF0ZVBsdWdpbiB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZSc7XG5cbi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbnZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn07XG5cbmNvbmZpZy50b3VjaE1vdXNlSWdub3JlV2FpdCA9IDUwMDtcbnZhciBpZ25vcmVNb3VzZURlcHRoID0gMDtcbnZhciBsaXN0ZW5lckNudCA9IDA7XG52YXIgaXNXaW5kb3dUb3VjaE1vdmVDYW5jZWxsZWQgPSBmYWxzZTtcbi8qXG5Vc2VzIGEgXCJwb2ludGVyXCIgYWJzdHJhY3Rpb24sIHdoaWNoIG1vbml0b3JzIFVJIGV2ZW50cyBmb3IgYm90aCBtb3VzZSBhbmQgdG91Y2guXG5UcmFja3Mgd2hlbiB0aGUgcG9pbnRlciBcImRyYWdzXCIgb24gYSBjZXJ0YWluIGVsZW1lbnQsIG1lYW5pbmcgZG93bittb3ZlK3VwLlxuXG5BbHNvLCB0cmFja3MgaWYgdGhlcmUgd2FzIHRvdWNoLXNjcm9sbGluZy5cbkFsc28sIGNhbiBwcmV2ZW50IHRvdWNoLXNjcm9sbGluZyBmcm9tIGhhcHBlbmluZy5cbkFsc28sIGNhbiBmaXJlIHBvaW50ZXJtb3ZlIGV2ZW50cyB3aGVuIHNjcm9sbGluZyBoYXBwZW5zIHVuZGVybmVhdGgsIGV2ZW4gd2hlbiBubyByZWFsIHBvaW50ZXIgbW92ZW1lbnQuXG5cbmVtaXRzOlxuLSBwb2ludGVyZG93blxuLSBwb2ludGVybW92ZVxuLSBwb2ludGVydXBcbiovXG52YXIgUG9pbnRlckRyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBvaW50ZXJEcmFnZ2luZyhjb250YWluZXJFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnN1YmplY3RFbCA9IG51bGw7XG4gICAgICAgIHRoaXMuZG93bkVsID0gbnVsbDtcbiAgICAgICAgLy8gb3B0aW9ucyB0aGF0IGNhbiBiZSBkaXJlY3RseSBhc3NpZ25lZCBieSBjYWxsZXJcbiAgICAgICAgdGhpcy5zZWxlY3RvciA9ICcnOyAvLyB3aWxsIGNhdXNlIHN1YmplY3RFbCBpbiBhbGwgZW1pdHRlZCBldmVudHMgdG8gYmUgdGhpcyBlbGVtZW50XG4gICAgICAgIHRoaXMuaGFuZGxlU2VsZWN0b3IgPSAnJztcbiAgICAgICAgdGhpcy5zaG91bGRJZ25vcmVNb3ZlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2hvdWxkV2F0Y2hTY3JvbGwgPSB0cnVlOyAvLyBmb3Igc2ltdWxhdGluZyBwb2ludGVybW92ZSBvbiBzY3JvbGxcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVzXG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzVG91Y2hEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLndhc1RvdWNoU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgIC8vIE1vdXNlXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgdGhpcy5oYW5kbGVNb3VzZURvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuc2hvdWxkSWdub3JlTW91c2UoKSAmJlxuICAgICAgICAgICAgICAgIGlzUHJpbWFyeU1vdXNlQnV0dG9uKGV2KSAmJlxuICAgICAgICAgICAgICAgIF90aGlzLnRyeVN0YXJ0KGV2KSkge1xuICAgICAgICAgICAgICAgIHZhciBwZXYgPSBfdGhpcy5jcmVhdGVFdmVudEZyb21Nb3VzZShldiwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIHBldik7XG4gICAgICAgICAgICAgICAgX3RoaXMuaW5pdFNjcm9sbFdhdGNoKHBldik7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIF90aGlzLmhhbmRsZU1vdXNlTW92ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBfdGhpcy5oYW5kbGVNb3VzZVVwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVNb3VzZU1vdmUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBwZXYgPSBfdGhpcy5jcmVhdGVFdmVudEZyb21Nb3VzZShldik7XG4gICAgICAgICAgICBfdGhpcy5yZWNvcmRDb29yZHMocGV2KTtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcm1vdmUnLCBwZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlVXAgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIF90aGlzLmhhbmRsZU1vdXNlTW92ZSk7XG4gICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgX3RoaXMuaGFuZGxlTW91c2VVcCk7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJ1cCcsIF90aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2KSk7XG4gICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7IC8vIGNhbGwgbGFzdCBzbyB0aGF0IHBvaW50ZXJ1cCBoYXMgYWNjZXNzIHRvIHByb3BzXG4gICAgICAgIH07XG4gICAgICAgIC8vIFRvdWNoXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgdGhpcy5oYW5kbGVUb3VjaFN0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMudHJ5U3RhcnQoZXYpKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNUb3VjaERyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgcGV2ID0gX3RoaXMuY3JlYXRlRXZlbnRGcm9tVG91Y2goZXYsIHRydWUpO1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcmRvd24nLCBwZXYpO1xuICAgICAgICAgICAgICAgIF90aGlzLmluaXRTY3JvbGxXYXRjaChwZXYpO1xuICAgICAgICAgICAgICAgIC8vIHVubGlrZSBtb3VzZSwgbmVlZCB0byBhdHRhY2ggdG8gdGFyZ2V0LCBub3QgZG9jdW1lbnRcbiAgICAgICAgICAgICAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNDU3NjAwMTRcbiAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZXYudGFyZ2V0O1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuc2hvdWxkSWdub3JlTW92ZSkge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgX3RoaXMuaGFuZGxlVG91Y2hNb3ZlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgX3RoaXMuaGFuZGxlVG91Y2hFbmQpO1xuICAgICAgICAgICAgICAgIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIF90aGlzLmhhbmRsZVRvdWNoRW5kKTsgLy8gdHJlYXQgaXQgYXMgYSB0b3VjaCBlbmRcbiAgICAgICAgICAgICAgICAvLyBhdHRhY2ggYSBoYW5kbGVyIHRvIGdldCBjYWxsZWQgd2hlbiBBTlkgc2Nyb2xsIGFjdGlvbiBoYXBwZW5zIG9uIHRoZSBwYWdlLlxuICAgICAgICAgICAgICAgIC8vIHRoaXMgd2FzIGltcG9zc2libGUgdG8gZG8gd2l0aCBub3JtYWwgb24vb2ZmIGJlY2F1c2UgJ3Njcm9sbCcgZG9lc24ndCBidWJibGUuXG4gICAgICAgICAgICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzI5NTQ1NjUvOTYzNDJcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgX3RoaXMuaGFuZGxlVG91Y2hTY3JvbGwsIHRydWUgLy8gdXNlQ2FwdHVyZVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlVG91Y2hNb3ZlID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgcGV2ID0gX3RoaXMuY3JlYXRlRXZlbnRGcm9tVG91Y2goZXYpO1xuICAgICAgICAgICAgX3RoaXMucmVjb3JkQ29vcmRzKHBldik7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJtb3ZlJywgcGV2KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVUb3VjaEVuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJhZ2dpbmcpIHsgLy8gZG9uZSB0byBndWFyZCBhZ2FpbnN0IHRvdWNoZW5kIGZvbGxvd2VkIGJ5IHRvdWNoY2FuY2VsXG4gICAgICAgICAgICAgICAgdmFyIHRhcmdldCA9IGV2LnRhcmdldDtcbiAgICAgICAgICAgICAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgX3RoaXMuaGFuZGxlVG91Y2hNb3ZlKTtcbiAgICAgICAgICAgICAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBfdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoY2FuY2VsJywgX3RoaXMuaGFuZGxlVG91Y2hFbmQpO1xuICAgICAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBfdGhpcy5oYW5kbGVUb3VjaFNjcm9sbCwgdHJ1ZSk7IC8vIHVzZUNhcHR1cmVkPXRydWVcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJ1cCcsIF90aGlzLmNyZWF0ZUV2ZW50RnJvbVRvdWNoKGV2KSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2xlYW51cCgpOyAvLyBjYWxsIGxhc3Qgc28gdGhhdCBwb2ludGVydXAgaGFzIGFjY2VzcyB0byBwcm9wc1xuICAgICAgICAgICAgICAgIF90aGlzLmlzVG91Y2hEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHN0YXJ0SWdub3JpbmdNb3VzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVRvdWNoU2Nyb2xsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMud2FzVG91Y2hTY3JvbGwgPSB0cnVlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVNjcm9sbCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhZ2VYID0gKHdpbmRvdy5wYWdlWE9mZnNldCAtIF90aGlzLnByZXZTY3JvbGxYKSArIF90aGlzLnByZXZQYWdlWDtcbiAgICAgICAgICAgICAgICB2YXIgcGFnZVkgPSAod2luZG93LnBhZ2VZT2Zmc2V0IC0gX3RoaXMucHJldlNjcm9sbFkpICsgX3RoaXMucHJldlBhZ2VZO1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcm1vdmUnLCB7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdFdmVudDogZXYsXG4gICAgICAgICAgICAgICAgICAgIGlzVG91Y2g6IF90aGlzLmlzVG91Y2hEcmFnZ2luZyxcbiAgICAgICAgICAgICAgICAgICAgc3ViamVjdEVsOiBfdGhpcy5zdWJqZWN0RWwsXG4gICAgICAgICAgICAgICAgICAgIHBhZ2VYOiBwYWdlWCxcbiAgICAgICAgICAgICAgICAgICAgcGFnZVk6IHBhZ2VZLFxuICAgICAgICAgICAgICAgICAgICBkZWx0YVg6IHBhZ2VYIC0gX3RoaXMub3JpZ1BhZ2VYLFxuICAgICAgICAgICAgICAgICAgICBkZWx0YVk6IHBhZ2VZIC0gX3RoaXMub3JpZ1BhZ2VZXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwgPSBjb250YWluZXJFbDtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXJNaXhpbigpO1xuICAgICAgICBjb250YWluZXJFbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmhhbmRsZU1vdXNlRG93bik7XG4gICAgICAgIGNvbnRhaW5lckVsLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLmhhbmRsZVRvdWNoU3RhcnQsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgbGlzdGVuZXJDcmVhdGVkKCk7XG4gICAgfVxuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmhhbmRsZU1vdXNlRG93bik7XG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuaGFuZGxlVG91Y2hTdGFydCwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgICBsaXN0ZW5lckRlc3Ryb3llZCgpO1xuICAgIH07XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS50cnlTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICB2YXIgc3ViamVjdEVsID0gdGhpcy5xdWVyeVN1YmplY3RFbChldik7XG4gICAgICAgIHZhciBkb3duRWwgPSBldi50YXJnZXQ7XG4gICAgICAgIGlmIChzdWJqZWN0RWwgJiZcbiAgICAgICAgICAgICghdGhpcy5oYW5kbGVTZWxlY3RvciB8fCBlbGVtZW50Q2xvc2VzdChkb3duRWwsIHRoaXMuaGFuZGxlU2VsZWN0b3IpKSkge1xuICAgICAgICAgICAgdGhpcy5zdWJqZWN0RWwgPSBzdWJqZWN0RWw7XG4gICAgICAgICAgICB0aGlzLmRvd25FbCA9IGRvd25FbDtcbiAgICAgICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7IC8vIGRvIHRoaXMgZmlyc3Qgc28gY2FuY2VsVG91Y2hTY3JvbGwgd2lsbCB3b3JrXG4gICAgICAgICAgICB0aGlzLndhc1RvdWNoU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLmNsZWFudXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlzV2luZG93VG91Y2hNb3ZlQ2FuY2VsbGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnN1YmplY3RFbCA9IG51bGw7XG4gICAgICAgIHRoaXMuZG93bkVsID0gbnVsbDtcbiAgICAgICAgLy8ga2VlcCB3YXNUb3VjaFNjcm9sbCBhcm91bmQgZm9yIGxhdGVyIGFjY2Vzc1xuICAgICAgICB0aGlzLmRlc3Ryb3lTY3JvbGxXYXRjaCgpO1xuICAgIH07XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5xdWVyeVN1YmplY3RFbCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICBpZiAodGhpcy5zZWxlY3Rvcikge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnRDbG9zZXN0KGV2LnRhcmdldCwgdGhpcy5zZWxlY3Rvcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXJFbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5zaG91bGRJZ25vcmVNb3VzZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlnbm9yZU1vdXNlRGVwdGggfHwgdGhpcy5pc1RvdWNoRHJhZ2dpbmc7XG4gICAgfTtcbiAgICAvLyBjYW4gYmUgY2FsbGVkIGJ5IHVzZXIgb2YgdGhpcyBjbGFzcywgdG8gY2FuY2VsIHRvdWNoLWJhc2VkIHNjcm9sbGluZyBmb3IgdGhlIGN1cnJlbnQgZHJhZ1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY2FuY2VsVG91Y2hTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIGlzV2luZG93VG91Y2hNb3ZlQ2FuY2VsbGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gU2Nyb2xsaW5nIHRoYXQgc2ltdWxhdGVzIHBvaW50ZXJtb3Zlc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLmluaXRTY3JvbGxXYXRjaCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICBpZiAodGhpcy5zaG91bGRXYXRjaFNjcm9sbCkge1xuICAgICAgICAgICAgdGhpcy5yZWNvcmRDb29yZHMoZXYpO1xuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsLCB0cnVlKTsgLy8gdXNlQ2FwdHVyZT10cnVlXG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUucmVjb3JkQ29vcmRzID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZFdhdGNoU2Nyb2xsKSB7XG4gICAgICAgICAgICB0aGlzLnByZXZQYWdlWCA9IGV2LnBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5wcmV2UGFnZVkgPSBldi5wYWdlWTtcbiAgICAgICAgICAgIHRoaXMucHJldlNjcm9sbFggPSB3aW5kb3cucGFnZVhPZmZzZXQ7XG4gICAgICAgICAgICB0aGlzLnByZXZTY3JvbGxZID0gd2luZG93LnBhZ2VZT2Zmc2V0O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3lTY3JvbGxXYXRjaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2hvdWxkV2F0Y2hTY3JvbGwpIHtcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLmhhbmRsZVNjcm9sbCwgdHJ1ZSk7IC8vIHVzZUNhcHR1cmVkPXRydWVcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gRXZlbnQgTm9ybWFsaXphdGlvblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLmNyZWF0ZUV2ZW50RnJvbU1vdXNlID0gZnVuY3Rpb24gKGV2LCBpc0ZpcnN0KSB7XG4gICAgICAgIHZhciBkZWx0YVggPSAwO1xuICAgICAgICB2YXIgZGVsdGFZID0gMDtcbiAgICAgICAgLy8gVE9ETzogcmVwZWF0IGNvZGVcbiAgICAgICAgaWYgKGlzRmlyc3QpIHtcbiAgICAgICAgICAgIHRoaXMub3JpZ1BhZ2VYID0gZXYucGFnZVg7XG4gICAgICAgICAgICB0aGlzLm9yaWdQYWdlWSA9IGV2LnBhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZGVsdGFYID0gZXYucGFnZVggLSB0aGlzLm9yaWdQYWdlWDtcbiAgICAgICAgICAgIGRlbHRhWSA9IGV2LnBhZ2VZIC0gdGhpcy5vcmlnUGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG9yaWdFdmVudDogZXYsXG4gICAgICAgICAgICBpc1RvdWNoOiBmYWxzZSxcbiAgICAgICAgICAgIHN1YmplY3RFbDogdGhpcy5zdWJqZWN0RWwsXG4gICAgICAgICAgICBwYWdlWDogZXYucGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogZXYucGFnZVksXG4gICAgICAgICAgICBkZWx0YVg6IGRlbHRhWCxcbiAgICAgICAgICAgIGRlbHRhWTogZGVsdGFZXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLmNyZWF0ZUV2ZW50RnJvbVRvdWNoID0gZnVuY3Rpb24gKGV2LCBpc0ZpcnN0KSB7XG4gICAgICAgIHZhciB0b3VjaGVzID0gZXYudG91Y2hlcztcbiAgICAgICAgdmFyIHBhZ2VYO1xuICAgICAgICB2YXIgcGFnZVk7XG4gICAgICAgIHZhciBkZWx0YVggPSAwO1xuICAgICAgICB2YXIgZGVsdGFZID0gMDtcbiAgICAgICAgLy8gaWYgdG91Y2ggY29vcmRzIGF2YWlsYWJsZSwgcHJlZmVyLFxuICAgICAgICAvLyBiZWNhdXNlIEZGIHdvdWxkIGdpdmUgYmFkIGV2LnBhZ2VYIGV2LnBhZ2VZXG4gICAgICAgIGlmICh0b3VjaGVzICYmIHRvdWNoZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBwYWdlWCA9IHRvdWNoZXNbMF0ucGFnZVg7XG4gICAgICAgICAgICBwYWdlWSA9IHRvdWNoZXNbMF0ucGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBwYWdlWCA9IGV2LnBhZ2VYO1xuICAgICAgICAgICAgcGFnZVkgPSBldi5wYWdlWTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUT0RPOiByZXBlYXQgY29kZVxuICAgICAgICBpZiAoaXNGaXJzdCkge1xuICAgICAgICAgICAgdGhpcy5vcmlnUGFnZVggPSBwYWdlWDtcbiAgICAgICAgICAgIHRoaXMub3JpZ1BhZ2VZID0gcGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkZWx0YVggPSBwYWdlWCAtIHRoaXMub3JpZ1BhZ2VYO1xuICAgICAgICAgICAgZGVsdGFZID0gcGFnZVkgLSB0aGlzLm9yaWdQYWdlWTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3JpZ0V2ZW50OiBldixcbiAgICAgICAgICAgIGlzVG91Y2g6IHRydWUsXG4gICAgICAgICAgICBzdWJqZWN0RWw6IHRoaXMuc3ViamVjdEVsLFxuICAgICAgICAgICAgcGFnZVg6IHBhZ2VYLFxuICAgICAgICAgICAgcGFnZVk6IHBhZ2VZLFxuICAgICAgICAgICAgZGVsdGFYOiBkZWx0YVgsXG4gICAgICAgICAgICBkZWx0YVk6IGRlbHRhWVxuICAgICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIFBvaW50ZXJEcmFnZ2luZztcbn0oKSk7XG4vLyBSZXR1cm5zIGEgYm9vbGVhbiB3aGV0aGVyIHRoaXMgd2FzIGEgbGVmdCBtb3VzZSBjbGljayBhbmQgbm8gY3RybCBrZXkgKHdoaWNoIG1lYW5zIHJpZ2h0IGNsaWNrIG9uIE1hYylcbmZ1bmN0aW9uIGlzUHJpbWFyeU1vdXNlQnV0dG9uKGV2KSB7XG4gICAgcmV0dXJuIGV2LmJ1dHRvbiA9PT0gMCAmJiAhZXYuY3RybEtleTtcbn1cbi8vIElnbm9yaW5nIGZha2UgbW91c2UgZXZlbnRzIGdlbmVyYXRlZCBieSB0b3VjaFxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gc3RhcnRJZ25vcmluZ01vdXNlKCkge1xuICAgIGlnbm9yZU1vdXNlRGVwdGgrKztcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWdub3JlTW91c2VEZXB0aC0tO1xuICAgIH0sIGNvbmZpZy50b3VjaE1vdXNlSWdub3JlV2FpdCk7XG59XG4vLyBXZSB3YW50IHRvIGF0dGFjaCB0b3VjaG1vdmUgYXMgZWFybHkgYXMgcG9zc2libGUgZm9yIFNhZmFyaVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gbGlzdGVuZXJDcmVhdGVkKCkge1xuICAgIGlmICghKGxpc3RlbmVyQ250KyspKSB7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBvbldpbmRvd1RvdWNoTW92ZSwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICB9XG59XG5mdW5jdGlvbiBsaXN0ZW5lckRlc3Ryb3llZCgpIHtcbiAgICBpZiAoISgtLWxpc3RlbmVyQ250KSkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb25XaW5kb3dUb3VjaE1vdmUsIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gb25XaW5kb3dUb3VjaE1vdmUoZXYpIHtcbiAgICBpZiAoaXNXaW5kb3dUb3VjaE1vdmVDYW5jZWxsZWQpIHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59XG5cbi8qXG5BbiBlZmZlY3QgaW4gd2hpY2ggYW4gZWxlbWVudCBmb2xsb3dzIHRoZSBtb3ZlbWVudCBvZiBhIHBvaW50ZXIgYWNyb3NzIHRoZSBzY3JlZW4uXG5UaGUgbW92aW5nIGVsZW1lbnQgaXMgYSBjbG9uZSBvZiBzb21lIG90aGVyIGVsZW1lbnQuXG5NdXN0IGNhbGwgc3RhcnQgKyBoYW5kbGVNb3ZlICsgc3RvcC5cbiovXG52YXIgRWxlbWVudE1pcnJvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFbGVtZW50TWlycm9yKCkge1xuICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlOyAvLyBtdXN0IGJlIGV4cGxpY2l0bHkgZW5hYmxlZFxuICAgICAgICB0aGlzLnNvdXJjZUVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5taXJyb3JFbCA9IG51bGw7XG4gICAgICAgIHRoaXMuc291cmNlRWxSZWN0ID0gbnVsbDsgLy8gc2NyZWVuIGNvb3JkcyByZWxhdGl2ZSB0byB2aWV3cG9ydFxuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIHNldCBkaXJlY3RseSBieSBjYWxsZXJcbiAgICAgICAgdGhpcy5wYXJlbnROb2RlID0gZG9jdW1lbnQuYm9keTtcbiAgICAgICAgdGhpcy56SW5kZXggPSA5OTk5O1xuICAgICAgICB0aGlzLnJldmVydER1cmF0aW9uID0gMDtcbiAgICB9XG4gICAgRWxlbWVudE1pcnJvci5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAoc291cmNlRWwsIHBhZ2VYLCBwYWdlWSkge1xuICAgICAgICB0aGlzLnNvdXJjZUVsID0gc291cmNlRWw7XG4gICAgICAgIHRoaXMuc291cmNlRWxSZWN0ID0gdGhpcy5zb3VyY2VFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdGhpcy5vcmlnU2NyZWVuWCA9IHBhZ2VYIC0gd2luZG93LnBhZ2VYT2Zmc2V0O1xuICAgICAgICB0aGlzLm9yaWdTY3JlZW5ZID0gcGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQ7XG4gICAgICAgIHRoaXMuZGVsdGFYID0gMDtcbiAgICAgICAgdGhpcy5kZWx0YVkgPSAwO1xuICAgICAgICB0aGlzLnVwZGF0ZUVsUG9zaXRpb24oKTtcbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmhhbmRsZU1vdmUgPSBmdW5jdGlvbiAocGFnZVgsIHBhZ2VZKSB7XG4gICAgICAgIHRoaXMuZGVsdGFYID0gKHBhZ2VYIC0gd2luZG93LnBhZ2VYT2Zmc2V0KSAtIHRoaXMub3JpZ1NjcmVlblg7XG4gICAgICAgIHRoaXMuZGVsdGFZID0gKHBhZ2VZIC0gd2luZG93LnBhZ2VZT2Zmc2V0KSAtIHRoaXMub3JpZ1NjcmVlblk7XG4gICAgICAgIHRoaXMudXBkYXRlRWxQb3NpdGlvbigpO1xuICAgIH07XG4gICAgLy8gY2FuIGJlIGNhbGxlZCBiZWZvcmUgc3RhcnRcbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS5zZXRJc1Zpc2libGUgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICBpZiAoYm9vbCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1pcnJvckVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWlycm9yRWwuc3R5bGUuZGlzcGxheSA9ICcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGJvb2w7IC8vIG5lZWRzIHRvIGhhcHBlbiBiZWZvcmUgdXBkYXRlRWxQb3NpdGlvblxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRWxQb3NpdGlvbigpOyAvLyBiZWNhdXNlIHdhcyBub3QgdXBkYXRpbmcgdGhlIHBvc2l0aW9uIHdoaWxlIGludmlzaWJsZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5taXJyb3JFbC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmlzVmlzaWJsZSA9IGJvb2w7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGFsd2F5cyBhc3luY1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLnN0b3AgPSBmdW5jdGlvbiAobmVlZHNSZXZlcnRBbmltYXRpb24sIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBkb25lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuY2xlYW51cCgpO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKG5lZWRzUmV2ZXJ0QW5pbWF0aW9uICYmXG4gICAgICAgICAgICB0aGlzLm1pcnJvckVsICYmXG4gICAgICAgICAgICB0aGlzLmlzVmlzaWJsZSAmJlxuICAgICAgICAgICAgdGhpcy5yZXZlcnREdXJhdGlvbiAmJiAvLyBpZiAwLCB0cmFuc2l0aW9uIHdvbid0IHdvcmtcbiAgICAgICAgICAgICh0aGlzLmRlbHRhWCB8fCB0aGlzLmRlbHRhWSkgLy8gaWYgc2FtZSBjb29yZHMsIHRyYW5zaXRpb24gd29uJ3Qgd29ya1xuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuZG9SZXZlcnRBbmltYXRpb24oZG9uZSwgdGhpcy5yZXZlcnREdXJhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGRvbmUsIDApO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS5kb1JldmVydEFuaW1hdGlvbiA9IGZ1bmN0aW9uIChjYWxsYmFjaywgcmV2ZXJ0RHVyYXRpb24pIHtcbiAgICAgICAgdmFyIG1pcnJvckVsID0gdGhpcy5taXJyb3JFbDtcbiAgICAgICAgdmFyIGZpbmFsU291cmNlRWxSZWN0ID0gdGhpcy5zb3VyY2VFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgLy8gYmVjYXVzZSBhdXRvc2Nyb2xsaW5nIG1pZ2h0IGhhdmUgaGFwcGVuZWRcbiAgICAgICAgbWlycm9yRWwuc3R5bGUudHJhbnNpdGlvbiA9XG4gICAgICAgICAgICAndG9wICcgKyByZXZlcnREdXJhdGlvbiArICdtcywnICtcbiAgICAgICAgICAgICAgICAnbGVmdCAnICsgcmV2ZXJ0RHVyYXRpb24gKyAnbXMnO1xuICAgICAgICBhcHBseVN0eWxlKG1pcnJvckVsLCB7XG4gICAgICAgICAgICBsZWZ0OiBmaW5hbFNvdXJjZUVsUmVjdC5sZWZ0LFxuICAgICAgICAgICAgdG9wOiBmaW5hbFNvdXJjZUVsUmVjdC50b3BcbiAgICAgICAgfSk7XG4gICAgICAgIHdoZW5UcmFuc2l0aW9uRG9uZShtaXJyb3JFbCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbWlycm9yRWwuc3R5bGUudHJhbnNpdGlvbiA9ICcnO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS5jbGVhbnVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5taXJyb3JFbCkge1xuICAgICAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLm1pcnJvckVsKTtcbiAgICAgICAgICAgIHRoaXMubWlycm9yRWwgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc291cmNlRWwgPSBudWxsO1xuICAgIH07XG4gICAgRWxlbWVudE1pcnJvci5wcm90b3R5cGUudXBkYXRlRWxQb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuc291cmNlRWwgJiYgdGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgICAgIGFwcGx5U3R5bGUodGhpcy5nZXRNaXJyb3JFbCgpLCB7XG4gICAgICAgICAgICAgICAgbGVmdDogdGhpcy5zb3VyY2VFbFJlY3QubGVmdCArIHRoaXMuZGVsdGFYLFxuICAgICAgICAgICAgICAgIHRvcDogdGhpcy5zb3VyY2VFbFJlY3QudG9wICsgdGhpcy5kZWx0YVlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS5nZXRNaXJyb3JFbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNvdXJjZUVsUmVjdCA9IHRoaXMuc291cmNlRWxSZWN0O1xuICAgICAgICB2YXIgbWlycm9yRWwgPSB0aGlzLm1pcnJvckVsO1xuICAgICAgICBpZiAoIW1pcnJvckVsKSB7XG4gICAgICAgICAgICBtaXJyb3JFbCA9IHRoaXMubWlycm9yRWwgPSB0aGlzLnNvdXJjZUVsLmNsb25lTm9kZSh0cnVlKTsgLy8gY2xvbmVDaGlsZHJlbj10cnVlXG4gICAgICAgICAgICAvLyB3ZSBkb24ndCB3YW50IGxvbmcgdGFwcyBvciBhbnkgbW91c2UgaW50ZXJhY3Rpb24gY2F1c2luZyBzZWxlY3Rpb24vbWVudXMuXG4gICAgICAgICAgICAvLyB3b3VsZCB1c2UgcHJldmVudFNlbGVjdGlvbigpLCBidXQgdGhhdCBwcmV2ZW50cyBzZWxlY3RzdGFydCwgY2F1c2luZyBwcm9ibGVtcy5cbiAgICAgICAgICAgIG1pcnJvckVsLmNsYXNzTGlzdC5hZGQoJ2ZjLXVuc2VsZWN0YWJsZScpO1xuICAgICAgICAgICAgbWlycm9yRWwuY2xhc3NMaXN0LmFkZCgnZmMtZHJhZ2dpbmcnKTtcbiAgICAgICAgICAgIGFwcGx5U3R5bGUobWlycm9yRWwsIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogJ2ZpeGVkJyxcbiAgICAgICAgICAgICAgICB6SW5kZXg6IHRoaXMuekluZGV4LFxuICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6ICcnLFxuICAgICAgICAgICAgICAgIGJveFNpemluZzogJ2JvcmRlci1ib3gnLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBzb3VyY2VFbFJlY3QucmlnaHQgLSBzb3VyY2VFbFJlY3QubGVmdCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHNvdXJjZUVsUmVjdC5ib3R0b20gLSBzb3VyY2VFbFJlY3QudG9wLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiAnYXV0bycsXG4gICAgICAgICAgICAgICAgYm90dG9tOiAnYXV0bycsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiAwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMucGFyZW50Tm9kZS5hcHBlbmRDaGlsZChtaXJyb3JFbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1pcnJvckVsO1xuICAgIH07XG4gICAgcmV0dXJuIEVsZW1lbnRNaXJyb3I7XG59KCkpO1xuXG4vKlxuSXMgYSBjYWNoZSBmb3IgYSBnaXZlbiBlbGVtZW50J3Mgc2Nyb2xsIGluZm9ybWF0aW9uIChhbGwgdGhlIGluZm8gdGhhdCBTY3JvbGxDb250cm9sbGVyIHN0b3JlcylcbmluIGFkZGl0aW9uIHRoZSBcImNsaWVudCByZWN0YW5nbGVcIiBvZiB0aGUgZWxlbWVudC4uIHRoZSBhcmVhIHdpdGhpbiB0aGUgc2Nyb2xsYmFycy5cblxuVGhlIGNhY2hlIGNhbiBiZSBpbiBvbmUgb2YgdHdvIG1vZGVzOlxuLSBkb2VzTGlzdGVuaW5nOmZhbHNlIC0gaWdub3JlcyB3aGVuIHRoZSBjb250YWluZXIgaXMgc2Nyb2xsZWQgYnkgc29tZW9uZSBlbHNlXG4tIGRvZXNMaXN0ZW5pbmc6dHJ1ZSAtIHdhdGNoIGZvciBzY3JvbGxpbmcgYW5kIHVwZGF0ZSB0aGUgY2FjaGVcbiovXG52YXIgU2Nyb2xsR2VvbUNhY2hlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTY3JvbGxHZW9tQ2FjaGUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2Nyb2xsR2VvbUNhY2hlKHNjcm9sbENvbnRyb2xsZXIsIGRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuaGFuZGxlU2Nyb2xsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuc2Nyb2xsVG9wID0gX3RoaXMuc2Nyb2xsQ29udHJvbGxlci5nZXRTY3JvbGxUb3AoKTtcbiAgICAgICAgICAgIF90aGlzLnNjcm9sbExlZnQgPSBfdGhpcy5zY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbExlZnQoKTtcbiAgICAgICAgICAgIF90aGlzLmhhbmRsZVNjcm9sbENoYW5nZSgpO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5zY3JvbGxDb250cm9sbGVyID0gc2Nyb2xsQ29udHJvbGxlcjtcbiAgICAgICAgX3RoaXMuZG9lc0xpc3RlbmluZyA9IGRvZXNMaXN0ZW5pbmc7XG4gICAgICAgIF90aGlzLnNjcm9sbFRvcCA9IF90aGlzLm9yaWdTY3JvbGxUb3AgPSBzY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbFRvcCgpO1xuICAgICAgICBfdGhpcy5zY3JvbGxMZWZ0ID0gX3RoaXMub3JpZ1Njcm9sbExlZnQgPSBzY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbExlZnQoKTtcbiAgICAgICAgX3RoaXMuc2Nyb2xsV2lkdGggPSBzY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbFdpZHRoKCk7XG4gICAgICAgIF90aGlzLnNjcm9sbEhlaWdodCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsSGVpZ2h0KCk7XG4gICAgICAgIF90aGlzLmNsaWVudFdpZHRoID0gc2Nyb2xsQ29udHJvbGxlci5nZXRDbGllbnRXaWR0aCgpO1xuICAgICAgICBfdGhpcy5jbGllbnRIZWlnaHQgPSBzY3JvbGxDb250cm9sbGVyLmdldENsaWVudEhlaWdodCgpO1xuICAgICAgICBfdGhpcy5jbGllbnRSZWN0ID0gX3RoaXMuY29tcHV0ZUNsaWVudFJlY3QoKTsgLy8gZG8gbGFzdCBpbiBjYXNlIGl0IG5lZWRzIGNhY2hlZCB2YWx1ZXNcbiAgICAgICAgaWYgKF90aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIF90aGlzLmdldEV2ZW50VGFyZ2V0KCkuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgX3RoaXMuaGFuZGxlU2Nyb2xsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZG9lc0xpc3RlbmluZykge1xuICAgICAgICAgICAgdGhpcy5nZXRFdmVudFRhcmdldCgpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbFRvcDtcbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuZ2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsTGVmdDtcbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuc2V0U2Nyb2xsVG9wID0gZnVuY3Rpb24gKHRvcCkge1xuICAgICAgICB0aGlzLnNjcm9sbENvbnRyb2xsZXIuc2V0U2Nyb2xsVG9wKHRvcCk7XG4gICAgICAgIGlmICghdGhpcy5kb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgICAgICAvLyB3ZSBhcmUgbm90IHJlbHlpbmcgb24gdGhlIGVsZW1lbnQgdG8gbm9ybWFsaXplIG91dC1vZi1ib3VuZHMgc2Nyb2xsIHZhbHVlc1xuICAgICAgICAgICAgLy8gc28gd2UgbmVlZCB0byBzYW5pdGl6ZSBvdXJzZWx2ZXNcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsVG9wID0gTWF0aC5tYXgoTWF0aC5taW4odG9wLCB0aGlzLmdldE1heFNjcm9sbFRvcCgpKSwgMCk7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVNjcm9sbENoYW5nZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLnNldFNjcm9sbExlZnQgPSBmdW5jdGlvbiAodG9wKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udHJvbGxlci5zZXRTY3JvbGxMZWZ0KHRvcCk7XG4gICAgICAgIGlmICghdGhpcy5kb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgICAgICAvLyB3ZSBhcmUgbm90IHJlbHlpbmcgb24gdGhlIGVsZW1lbnQgdG8gbm9ybWFsaXplIG91dC1vZi1ib3VuZHMgc2Nyb2xsIHZhbHVlc1xuICAgICAgICAgICAgLy8gc28gd2UgbmVlZCB0byBzYW5pdGl6ZSBvdXJzZWx2ZXNcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsTGVmdCA9IE1hdGgubWF4KE1hdGgubWluKHRvcCwgdGhpcy5nZXRNYXhTY3JvbGxMZWZ0KCkpLCAwKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuZ2V0Q2xpZW50V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsaWVudFdpZHRoO1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRDbGllbnRIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsaWVudEhlaWdodDtcbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuZ2V0U2Nyb2xsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbFdpZHRoO1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRTY3JvbGxIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbEhlaWdodDtcbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuaGFuZGxlU2Nyb2xsQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgcmV0dXJuIFNjcm9sbEdlb21DYWNoZTtcbn0oU2Nyb2xsQ29udHJvbGxlcikpO1xudmFyIEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRWxlbWVudFNjcm9sbEdlb21DYWNoZShlbCwgZG9lc0xpc3RlbmluZykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgbmV3IEVsZW1lbnRTY3JvbGxDb250cm9sbGVyKGVsKSwgZG9lc0xpc3RlbmluZykgfHwgdGhpcztcbiAgICB9XG4gICAgRWxlbWVudFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuZ2V0RXZlbnRUYXJnZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbENvbnRyb2xsZXIuZWw7XG4gICAgfTtcbiAgICBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5jb21wdXRlQ2xpZW50UmVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGNvbXB1dGVJbm5lclJlY3QodGhpcy5zY3JvbGxDb250cm9sbGVyLmVsKTtcbiAgICB9O1xuICAgIHJldHVybiBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlO1xufShTY3JvbGxHZW9tQ2FjaGUpKTtcbnZhciBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFdpbmRvd1Njcm9sbEdlb21DYWNoZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUoZG9lc0xpc3RlbmluZykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgbmV3IFdpbmRvd1Njcm9sbENvbnRyb2xsZXIoKSwgZG9lc0xpc3RlbmluZykgfHwgdGhpcztcbiAgICB9XG4gICAgV2luZG93U2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRFdmVudFRhcmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdztcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuY29tcHV0ZUNsaWVudFJlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsZWZ0OiB0aGlzLnNjcm9sbExlZnQsXG4gICAgICAgICAgICByaWdodDogdGhpcy5zY3JvbGxMZWZ0ICsgdGhpcy5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgIHRvcDogdGhpcy5zY3JvbGxUb3AsXG4gICAgICAgICAgICBib3R0b206IHRoaXMuc2Nyb2xsVG9wICsgdGhpcy5jbGllbnRIZWlnaHRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIC8vIHRoZSB3aW5kb3cgaXMgdGhlIG9ubHkgc2Nyb2xsIG9iamVjdCB0aGF0IGNoYW5nZXMgaXQncyByZWN0YW5nbGUgcmVsYXRpdmVcbiAgICAvLyB0byB0aGUgZG9jdW1lbnQncyB0b3BsZWZ0IGFzIGl0IHNjcm9sbHNcbiAgICBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmhhbmRsZVNjcm9sbENoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jbGllbnRSZWN0ID0gdGhpcy5jb21wdXRlQ2xpZW50UmVjdCgpO1xuICAgIH07XG4gICAgcmV0dXJuIFdpbmRvd1Njcm9sbEdlb21DYWNoZTtcbn0oU2Nyb2xsR2VvbUNhY2hlKSk7XG5cbi8vIElmIGF2YWlsYWJsZSB3ZSBhcmUgdXNpbmcgbmF0aXZlIFwicGVyZm9ybWFuY2VcIiBBUEkgaW5zdGVhZCBvZiBcIkRhdGVcIlxuLy8gUmVhZCBtb3JlIGFib3V0IGl0IG9uIE1ETjpcbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9QZXJmb3JtYW5jZVxudmFyIGdldFRpbWUgPSB0eXBlb2YgcGVyZm9ybWFuY2UgPT09ICdmdW5jdGlvbicgPyBwZXJmb3JtYW5jZS5ub3cgOiBEYXRlLm5vdztcbi8qXG5Gb3IgYSBwb2ludGVyIGludGVyYWN0aW9uLCBhdXRvbWF0aWNhbGx5IHNjcm9sbHMgY2VydGFpbiBzY3JvbGwgY29udGFpbmVycyB3aGVuIHRoZSBwb2ludGVyXG5hcHByb2FjaGVzIHRoZSBlZGdlLlxuXG5UaGUgY2FsbGVyIG11c3QgY2FsbCBzdGFydCArIGhhbmRsZU1vdmUgKyBzdG9wLlxuKi9cbnZhciBBdXRvU2Nyb2xsZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQXV0b1Njcm9sbGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIHNldCBieSBjYWxsZXJcbiAgICAgICAgdGhpcy5pc0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnNjcm9sbFF1ZXJ5ID0gW3dpbmRvdywgJy5mYy1zY3JvbGxlciddO1xuICAgICAgICB0aGlzLmVkZ2VUaHJlc2hvbGQgPSA1MDsgLy8gcGl4ZWxzXG4gICAgICAgIHRoaXMubWF4VmVsb2NpdHkgPSAzMDA7IC8vIHBpeGVscyBwZXIgc2Vjb25kXG4gICAgICAgIC8vIGludGVybmFsIHN0YXRlXG4gICAgICAgIHRoaXMucG9pbnRlclNjcmVlblggPSBudWxsO1xuICAgICAgICB0aGlzLnBvaW50ZXJTY3JlZW5ZID0gbnVsbDtcbiAgICAgICAgdGhpcy5pc0FuaW1hdGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnNjcm9sbENhY2hlcyA9IG51bGw7XG4gICAgICAgIC8vIHByb3RlY3QgYWdhaW5zdCB0aGUgaW5pdGlhbCBwb2ludGVyZG93biBiZWluZyB0b28gY2xvc2UgdG8gYW4gZWRnZSBhbmQgc3RhcnRpbmcgdGhlIHNjcm9sbFxuICAgICAgICB0aGlzLmV2ZXJNb3ZlZFVwID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlck1vdmVkRG93biA9IGZhbHNlO1xuICAgICAgICB0aGlzLmV2ZXJNb3ZlZExlZnQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVyTW92ZWRSaWdodCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFuaW1hdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNBbmltYXRpbmcpIHsgLy8gd2Fzbid0IGNhbmNlbGxlZCBiZXR3ZWVuIGFuaW1hdGlvbiBjYWxsc1xuICAgICAgICAgICAgICAgIHZhciBlZGdlID0gX3RoaXMuY29tcHV0ZUJlc3RFZGdlKF90aGlzLnBvaW50ZXJTY3JlZW5YICsgd2luZG93LnBhZ2VYT2Zmc2V0LCBfdGhpcy5wb2ludGVyU2NyZWVuWSArIHdpbmRvdy5wYWdlWU9mZnNldCk7XG4gICAgICAgICAgICAgICAgaWYgKGVkZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vdyA9IGdldFRpbWUoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGFuZGxlU2lkZShlZGdlLCAobm93IC0gX3RoaXMubXNTaW5jZVJlcXVlc3QpIC8gMTAwMCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnJlcXVlc3RBbmltYXRpb24obm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7IC8vIHdpbGwgc3RvcCBhbmltYXRpb25cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAocGFnZVgsIHBhZ2VZKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSB0aGlzLmJ1aWxkQ2FjaGVzKCk7XG4gICAgICAgICAgICB0aGlzLnBvaW50ZXJTY3JlZW5YID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblkgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRVcCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWREb3duID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZExlZnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZXZlck1vdmVkUmlnaHQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlTW92ZShwYWdlWCwgcGFnZVkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLmhhbmRsZU1vdmUgPSBmdW5jdGlvbiAocGFnZVgsIHBhZ2VZKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRW5hYmxlZCkge1xuICAgICAgICAgICAgdmFyIHBvaW50ZXJTY3JlZW5YID0gcGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQ7XG4gICAgICAgICAgICB2YXIgcG9pbnRlclNjcmVlblkgPSBwYWdlWSAtIHdpbmRvdy5wYWdlWU9mZnNldDtcbiAgICAgICAgICAgIHZhciB5RGVsdGEgPSB0aGlzLnBvaW50ZXJTY3JlZW5ZID09PSBudWxsID8gMCA6IHBvaW50ZXJTY3JlZW5ZIC0gdGhpcy5wb2ludGVyU2NyZWVuWTtcbiAgICAgICAgICAgIHZhciB4RGVsdGEgPSB0aGlzLnBvaW50ZXJTY3JlZW5YID09PSBudWxsID8gMCA6IHBvaW50ZXJTY3JlZW5YIC0gdGhpcy5wb2ludGVyU2NyZWVuWDtcbiAgICAgICAgICAgIGlmICh5RGVsdGEgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh5RGVsdGEgPiAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWREb3duID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh4RGVsdGEgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRMZWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHhEZWx0YSA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFJpZ2h0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblggPSBwb2ludGVyU2NyZWVuWDtcbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblkgPSBwb2ludGVyU2NyZWVuWTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0FuaW1hdGluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNBbmltYXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEFuaW1hdGlvbihnZXRUaW1lKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLnN0b3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5pc0FuaW1hdGluZyA9IGZhbHNlOyAvLyB3aWxsIHN0b3AgYW5pbWF0aW9uXG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zY3JvbGxDYWNoZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIHNjcm9sbENhY2hlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ2FjaGVzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5yZXF1ZXN0QW5pbWF0aW9uID0gZnVuY3Rpb24gKG5vdykge1xuICAgICAgICB0aGlzLm1zU2luY2VSZXF1ZXN0ID0gbm93O1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRlKTtcbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUuaGFuZGxlU2lkZSA9IGZ1bmN0aW9uIChlZGdlLCBzZWNvbmRzKSB7XG4gICAgICAgIHZhciBzY3JvbGxDYWNoZSA9IGVkZ2Uuc2Nyb2xsQ2FjaGU7XG4gICAgICAgIHZhciBlZGdlVGhyZXNob2xkID0gdGhpcy5lZGdlVGhyZXNob2xkO1xuICAgICAgICB2YXIgaW52RGlzdGFuY2UgPSBlZGdlVGhyZXNob2xkIC0gZWRnZS5kaXN0YW5jZTtcbiAgICAgICAgdmFyIHZlbG9jaXR5ID0gLy8gdGhlIGNsb3NlciB0byB0aGUgZWRnZSwgdGhlIGZhc3RlciB3ZSBzY3JvbGxcbiAgICAgICAgIChpbnZEaXN0YW5jZSAqIGludkRpc3RhbmNlKSAvIChlZGdlVGhyZXNob2xkICogZWRnZVRocmVzaG9sZCkgKiAvLyBxdWFkcmF0aWNcbiAgICAgICAgICAgIHRoaXMubWF4VmVsb2NpdHkgKiBzZWNvbmRzO1xuICAgICAgICB2YXIgc2lnbiA9IDE7XG4gICAgICAgIHN3aXRjaCAoZWRnZS5uYW1lKSB7XG4gICAgICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgICAgICAgICBzaWduID0gLTE7XG4gICAgICAgICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICAgICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuc2V0U2Nyb2xsTGVmdChzY3JvbGxDYWNoZS5nZXRTY3JvbGxMZWZ0KCkgKyB2ZWxvY2l0eSAqIHNpZ24pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgICAgICAgICBzaWduID0gLTE7XG4gICAgICAgICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICAgICAgICBjYXNlICdib3R0b20nOlxuICAgICAgICAgICAgICAgIHNjcm9sbENhY2hlLnNldFNjcm9sbFRvcChzY3JvbGxDYWNoZS5nZXRTY3JvbGxUb3AoKSArIHZlbG9jaXR5ICogc2lnbik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGxlZnQvdG9wIGFyZSByZWxhdGl2ZSB0byBkb2N1bWVudCB0b3BsZWZ0XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5jb21wdXRlQmVzdEVkZ2UgPSBmdW5jdGlvbiAobGVmdCwgdG9wKSB7XG4gICAgICAgIHZhciBlZGdlVGhyZXNob2xkID0gdGhpcy5lZGdlVGhyZXNob2xkO1xuICAgICAgICB2YXIgYmVzdFNpZGUgPSBudWxsO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zY3JvbGxDYWNoZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICB2YXIgcmVjdCA9IHNjcm9sbENhY2hlLmNsaWVudFJlY3Q7XG4gICAgICAgICAgICB2YXIgbGVmdERpc3QgPSBsZWZ0IC0gcmVjdC5sZWZ0O1xuICAgICAgICAgICAgdmFyIHJpZ2h0RGlzdCA9IHJlY3QucmlnaHQgLSBsZWZ0O1xuICAgICAgICAgICAgdmFyIHRvcERpc3QgPSB0b3AgLSByZWN0LnRvcDtcbiAgICAgICAgICAgIHZhciBib3R0b21EaXN0ID0gcmVjdC5ib3R0b20gLSB0b3A7XG4gICAgICAgICAgICAvLyBjb21wbGV0ZWx5IHdpdGhpbiB0aGUgcmVjdD9cbiAgICAgICAgICAgIGlmIChsZWZ0RGlzdCA+PSAwICYmIHJpZ2h0RGlzdCA+PSAwICYmIHRvcERpc3QgPj0gMCAmJiBib3R0b21EaXN0ID49IDApIHtcbiAgICAgICAgICAgICAgICBpZiAodG9wRGlzdCA8PSBlZGdlVGhyZXNob2xkICYmIHRoaXMuZXZlck1vdmVkVXAgJiYgc2Nyb2xsQ2FjaGUuY2FuU2Nyb2xsVXAoKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIWJlc3RTaWRlIHx8IGJlc3RTaWRlLmRpc3RhbmNlID4gdG9wRGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFNpZGUgPSB7IHNjcm9sbENhY2hlOiBzY3JvbGxDYWNoZSwgbmFtZTogJ3RvcCcsIGRpc3RhbmNlOiB0b3BEaXN0IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChib3R0b21EaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWREb3duICYmIHNjcm9sbENhY2hlLmNhblNjcm9sbERvd24oKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIWJlc3RTaWRlIHx8IGJlc3RTaWRlLmRpc3RhbmNlID4gYm90dG9tRGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFNpZGUgPSB7IHNjcm9sbENhY2hlOiBzY3JvbGxDYWNoZSwgbmFtZTogJ2JvdHRvbScsIGRpc3RhbmNlOiBib3R0b21EaXN0IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChsZWZ0RGlzdCA8PSBlZGdlVGhyZXNob2xkICYmIHRoaXMuZXZlck1vdmVkTGVmdCAmJiBzY3JvbGxDYWNoZS5jYW5TY3JvbGxMZWZ0KCkgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFiZXN0U2lkZSB8fCBiZXN0U2lkZS5kaXN0YW5jZSA+IGxlZnREaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGU6IHNjcm9sbENhY2hlLCBuYW1lOiAnbGVmdCcsIGRpc3RhbmNlOiBsZWZ0RGlzdCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmlnaHREaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRSaWdodCAmJiBzY3JvbGxDYWNoZS5jYW5TY3JvbGxSaWdodCgpICYmXG4gICAgICAgICAgICAgICAgICAgICghYmVzdFNpZGUgfHwgYmVzdFNpZGUuZGlzdGFuY2UgPiByaWdodERpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RTaWRlID0geyBzY3JvbGxDYWNoZTogc2Nyb2xsQ2FjaGUsIG5hbWU6ICdyaWdodCcsIGRpc3RhbmNlOiByaWdodERpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJlc3RTaWRlO1xuICAgIH07XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5idWlsZENhY2hlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVlcnlTY3JvbGxFbHMoKS5tYXAoZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBpZiAoZWwgPT09IHdpbmRvdykge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgV2luZG93U2Nyb2xsR2VvbUNhY2hlKGZhbHNlKTsgLy8gZmFsc2UgPSBkb24ndCBsaXN0ZW4gdG8gdXNlci1nZW5lcmF0ZWQgc2Nyb2xsc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlKGVsLCBmYWxzZSk7IC8vIGZhbHNlID0gZG9uJ3QgbGlzdGVuIHRvIHVzZXItZ2VuZXJhdGVkIHNjcm9sbHNcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLnF1ZXJ5U2Nyb2xsRWxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZWxzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbFF1ZXJ5OyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHF1ZXJ5ID0gX2FbX2ldO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBxdWVyeSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICBlbHMucHVzaChxdWVyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbHMucHVzaC5hcHBseShlbHMsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwocXVlcnkpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVscztcbiAgICB9O1xuICAgIHJldHVybiBBdXRvU2Nyb2xsZXI7XG59KCkpO1xuXG4vKlxuTW9uaXRvcnMgZHJhZ2dpbmcgb24gYW4gZWxlbWVudC4gSGFzIGEgbnVtYmVyIG9mIGhpZ2gtbGV2ZWwgZmVhdHVyZXM6XG4tIG1pbmltdW0gZGlzdGFuY2UgcmVxdWlyZWQgYmVmb3JlIGRyYWdnaW5nXG4tIG1pbmltdW0gd2FpdCB0aW1lIChcImRlbGF5XCIpIGJlZm9yZSBkcmFnZ2luZ1xuLSBhIG1pcnJvciBlbGVtZW50IHRoYXQgZm9sbG93cyB0aGUgcG9pbnRlclxuKi9cbnZhciBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29udGFpbmVyRWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY29udGFpbmVyRWwpIHx8IHRoaXM7XG4gICAgICAgIC8vIG9wdGlvbnMgdGhhdCBjYW4gYmUgZGlyZWN0bHkgc2V0IGJ5IGNhbGxlclxuICAgICAgICAvLyB0aGUgY2FsbGVyIGNhbiBhbHNvIHNldCB0aGUgUG9pbnRlckRyYWdnaW5nJ3Mgb3B0aW9ucyBhcyB3ZWxsXG4gICAgICAgIF90aGlzLmRlbGF5ID0gbnVsbDtcbiAgICAgICAgX3RoaXMubWluRGlzdGFuY2UgPSAwO1xuICAgICAgICBfdGhpcy50b3VjaFNjcm9sbEFsbG93ZWQgPSB0cnVlOyAvLyBwcmV2ZW50cyBkcmFnIGZyb20gc3RhcnRpbmcgYW5kIGJsb2NrcyBzY3JvbGxpbmcgZHVyaW5nIGRyYWdcbiAgICAgICAgX3RoaXMubWlycm9yTmVlZHNSZXZlcnQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNJbnRlcmFjdGluZyA9IGZhbHNlOyAvLyBpcyB0aGUgdXNlciB2YWxpZGx5IG1vdmluZyB0aGUgcG9pbnRlcj8gbGFzdHMgdW50aWwgcG9pbnRlcnVwXG4gICAgICAgIF90aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTsgLy8gaXMgaXQgSU5URU5URlVMTFkgZHJhZ2dpbmc/IGxhc3RzIHVudGlsIGFmdGVyIHJldmVydCBhbmltYXRpb25cbiAgICAgICAgX3RoaXMuaXNEZWxheUVuZGVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuZGVsYXlUaW1lb3V0SWQgPSBudWxsO1xuICAgICAgICBfdGhpcy5vblBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmlzRHJhZ2dpbmcpIHsgLy8gc28gbmV3IGRyYWcgZG9lc24ndCBoYXBwZW4gd2hpbGUgcmV2ZXJ0IGFuaW1hdGlvbiBpcyBnb2luZ1xuICAgICAgICAgICAgICAgIF90aGlzLmlzSW50ZXJhY3RpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIF90aGlzLmlzRGVsYXlFbmRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIF90aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBwcmV2ZW50U2VsZWN0aW9uKGRvY3VtZW50LmJvZHkpO1xuICAgICAgICAgICAgICAgIHByZXZlbnRDb250ZXh0TWVudShkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgICAgICAgICAvLyBwcmV2ZW50IGxpbmtzIGZyb20gYmVpbmcgdmlzaXRlZCBpZiB0aGVyZSdzIGFuIGV2ZW50dWFsIGRyYWcuXG4gICAgICAgICAgICAgICAgLy8gYWxzbyBwcmV2ZW50cyBzZWxlY3Rpb24gaW4gb2xkZXIgYnJvd3NlcnMgKG1heWJlPykuXG4gICAgICAgICAgICAgICAgLy8gbm90IG5lY2Vzc2FyeSBmb3IgdG91Y2gsIGJlc2lkZXMsIGJyb3dzZXIgd291bGQgY29tcGxhaW4gYWJvdXQgcGFzc2l2ZW5lc3MuXG4gICAgICAgICAgICAgICAgaWYgKCFldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGV2Lm9yaWdFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgZXYpO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMucG9pbnRlci5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGFjdGlvbnMgcmVsYXRlZCB0byBpbml0aWF0aW5nIGRyYWdzdGFydCtkcmFnbW92ZStkcmFnZW5kLi4uXG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm1pcnJvci5zZXRJc1Zpc2libGUoZmFsc2UpOyAvLyByZXNldC4gY2FsbGVyIG11c3Qgc2V0LXZpc2libGVcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubWlycm9yLnN0YXJ0KGV2LnN1YmplY3RFbCwgZXYucGFnZVgsIGV2LnBhZ2VZKTsgLy8gbXVzdCBoYXBwZW4gb24gZmlyc3QgcG9pbnRlciBkb3duXG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnN0YXJ0RGVsYXkoZXYpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLm1pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5oYW5kbGVEaXN0YW5jZVN1cnBhc3NlZChldik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLm9uUG9pbnRlck1vdmUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0ludGVyYWN0aW5nKSB7IC8vIGlmIGZhbHNlLCBzdGlsbCB3YWl0aW5nIGZvciBwcmV2aW91cyBkcmFnJ3MgcmV2ZXJ0XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIGV2KTtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pbkRpc3RhbmNlID0gX3RoaXMubWluRGlzdGFuY2U7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXN0YW5jZVNxID0gdm9pZCAwOyAvLyBjdXJyZW50IGRpc3RhbmNlIGZyb20gdGhlIG9yaWdpbiwgc3F1YXJlZFxuICAgICAgICAgICAgICAgICAgICB2YXIgZGVsdGFYID0gZXYuZGVsdGFYLCBkZWx0YVkgPSBldi5kZWx0YVk7XG4gICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlU3EgPSBkZWx0YVggKiBkZWx0YVggKyBkZWx0YVkgKiBkZWx0YVk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkaXN0YW5jZVNxID49IG1pbkRpc3RhbmNlICogbWluRGlzdGFuY2UpIHsgLy8gdXNlIHB5dGhhZ29yZWFuIHRoZW9yZW1cbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmhhbmRsZURpc3RhbmNlU3VycGFzc2VkKGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgICAgICAvLyBhIHJlYWwgcG9pbnRlciBtb3ZlPyAobm90IG9uZSBzaW11bGF0ZWQgYnkgc2Nyb2xsaW5nKVxuICAgICAgICAgICAgICAgICAgICBpZiAoZXYub3JpZ0V2ZW50LnR5cGUgIT09ICdzY3JvbGwnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5taXJyb3IuaGFuZGxlTW92ZShldi5wYWdlWCwgZXYucGFnZVkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuYXV0b1Njcm9sbGVyLmhhbmRsZU1vdmUoZXYucGFnZVgsIGV2LnBhZ2VZKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdtb3ZlJywgZXYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMub25Qb2ludGVyVXAgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0ludGVyYWN0aW5nKSB7IC8vIGlmIGZhbHNlLCBzdGlsbCB3YWl0aW5nIGZvciBwcmV2aW91cyBkcmFnJ3MgcmV2ZXJ0XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNJbnRlcmFjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGFsbG93U2VsZWN0aW9uKGRvY3VtZW50LmJvZHkpO1xuICAgICAgICAgICAgICAgIGFsbG93Q29udGV4dE1lbnUoZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVydXAnLCBldik7IC8vIGNhbiBwb3RlbnRpYWxseSBzZXQgbWlycm9yTmVlZHNSZXZlcnRcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5hdXRvU2Nyb2xsZXIuc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy50cnlTdG9wRHJhZyhldik7IC8vIHdoaWNoIHdpbGwgc3RvcCB0aGUgbWlycm9yXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5kZWxheVRpbWVvdXRJZCkge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoX3RoaXMuZGVsYXlUaW1lb3V0SWQpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5kZWxheVRpbWVvdXRJZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgcG9pbnRlciA9IF90aGlzLnBvaW50ZXIgPSBuZXcgUG9pbnRlckRyYWdnaW5nKGNvbnRhaW5lckVsKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLm9uUG9pbnRlckRvd24pO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJtb3ZlJywgX3RoaXMub25Qb2ludGVyTW92ZSk7XG4gICAgICAgIHBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcnVwJywgX3RoaXMub25Qb2ludGVyVXApO1xuICAgICAgICBfdGhpcy5taXJyb3IgPSBuZXcgRWxlbWVudE1pcnJvcigpO1xuICAgICAgICBfdGhpcy5hdXRvU2Nyb2xsZXIgPSBuZXcgQXV0b1Njcm9sbGVyKCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5wb2ludGVyLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnN0YXJ0RGVsYXkgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmRlbGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgdGhpcy5kZWxheVRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmRlbGF5VGltZW91dElkID0gbnVsbDtcbiAgICAgICAgICAgICAgICBfdGhpcy5oYW5kbGVEZWxheUVuZChldik7XG4gICAgICAgICAgICB9LCB0aGlzLmRlbGF5KTsgLy8gbm90IGFzc2lnbmFibGUgdG8gbnVtYmVyIVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEZWxheUVuZChldik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmhhbmRsZURlbGF5RW5kID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHRoaXMuaXNEZWxheUVuZGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy50cnlTdGFydERyYWcoZXYpO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuaGFuZGxlRGlzdGFuY2VTdXJwYXNzZWQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgdGhpcy5pc0Rpc3RhbmNlU3VycGFzc2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy50cnlTdGFydERyYWcoZXYpO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUudHJ5U3RhcnREcmFnID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLmlzRGVsYXlFbmRlZCAmJiB0aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5wb2ludGVyLndhc1RvdWNoU2Nyb2xsIHx8IHRoaXMudG91Y2hTY3JvbGxBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvck5lZWRzUmV2ZXJ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvU2Nyb2xsZXIuc3RhcnQoZXYucGFnZVgsIGV2LnBhZ2VZKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ3N0YXJ0JywgZXYpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRvdWNoU2Nyb2xsQWxsb3dlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wb2ludGVyLmNhbmNlbFRvdWNoU2Nyb2xsKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS50cnlTdG9wRHJhZyA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAvLyAuc3RvcCgpIGlzIEFMV0FZUyBhc3luY2hyb25vdXMsIHdoaWNoIHdlIE5FRUQgYmVjYXVzZSB3ZSB3YW50IGFsbCBwb2ludGVydXAgZXZlbnRzXG4gICAgICAgIC8vIHRoYXQgY29tZSBmcm9tIHRoZSBkb2N1bWVudCB0byBmaXJlIGJlZm9yZWhhbmQuIG11Y2ggbW9yZSBjb252ZW5pZW50IHRoaXMgd2F5LlxuICAgICAgICB0aGlzLm1pcnJvci5zdG9wKHRoaXMubWlycm9yTmVlZHNSZXZlcnQsIHRoaXMuc3RvcERyYWcuYmluZCh0aGlzLCBldikgLy8gYm91bmQgd2l0aCBhcmdzXG4gICAgICAgICk7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zdG9wRHJhZyA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdlbmQnLCBldik7XG4gICAgfTtcbiAgICAvLyBmaWxsIGluIHRoZSBpbXBsZW1lbnRhdGlvbnMuLi5cbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRJZ25vcmVNb3ZlID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgdGhpcy5wb2ludGVyLnNob3VsZElnbm9yZU1vdmUgPSBib29sO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9ySXNWaXNpYmxlID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgdGhpcy5taXJyb3Iuc2V0SXNWaXNpYmxlKGJvb2wpO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9yTmVlZHNSZXZlcnQgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLm1pcnJvck5lZWRzUmV2ZXJ0ID0gYm9vbDtcbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldEF1dG9TY3JvbGxFbmFibGVkID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgdGhpcy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gYm9vbDtcbiAgICB9O1xuICAgIHJldHVybiBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nO1xufShFbGVtZW50RHJhZ2dpbmcpKTtcblxuLypcbldoZW4gdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQsIGl0IHJlY29yZHMgdGhlIG9mZnNldCBvZiBhbiBlbGVtZW50IChyZWxhdGl2ZSB0byB0aGUgZG9jdW1lbnQgdG9wbGVmdCksXG5hbmQgY29udGludWVzIHRvIG1vbml0b3Igc2Nyb2xsaW5nLCB1cGRhdGluZyB0aGUgY2FjaGVkIGNvb3JkaW5hdGVzIGlmIGl0IG5lZWRzIHRvLlxuRG9lcyBub3QgYWNjZXNzIHRoZSBET00gYWZ0ZXIgaW5zdGFudGlhdGlvbiwgc28gaGlnaGx5IHBlcmZvcm1hbnQuXG5cbkFsc28ga2VlcHMgdHJhY2sgb2YgYWxsIHNjcm9sbGluZy9vdmVyZmxvdzpoaWRkZW4gY29udGFpbmVycyB0aGF0IGFyZSBwYXJlbnRzIG9mIHRoZSBnaXZlbiBlbGVtZW50XG5hbmQgYW4gZGV0ZXJtaW5lIGlmIGEgZ2l2ZW4gcG9pbnQgaXMgaW5zaWRlIHRoZSBjb21iaW5lZCBjbGlwcGluZyByZWN0YW5nbGUuXG4qL1xudmFyIE9mZnNldFRyYWNrZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2Zmc2V0VHJhY2tlcihlbCkge1xuICAgICAgICB0aGlzLm9yaWdSZWN0ID0gY29tcHV0ZVJlY3QoZWwpO1xuICAgICAgICAvLyB3aWxsIHdvcmsgZmluZSBmb3IgZGl2cyB0aGF0IGhhdmUgb3ZlcmZsb3c6aGlkZGVuXG4gICAgICAgIHRoaXMuc2Nyb2xsQ2FjaGVzID0gZ2V0Q2xpcHBpbmdQYXJlbnRzKGVsKS5tYXAoZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUoZWwsIHRydWUpOyAvLyBsaXN0ZW49dHJ1ZVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgT2Zmc2V0VHJhY2tlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsQ2FjaGVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBPZmZzZXRUcmFja2VyLnByb3RvdHlwZS5jb21wdXRlTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGxlZnQgPSB0aGlzLm9yaWdSZWN0LmxlZnQ7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbENhY2hlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzY3JvbGxDYWNoZSA9IF9hW19pXTtcbiAgICAgICAgICAgIGxlZnQgKz0gc2Nyb2xsQ2FjaGUub3JpZ1Njcm9sbExlZnQgLSBzY3JvbGxDYWNoZS5nZXRTY3JvbGxMZWZ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxlZnQ7XG4gICAgfTtcbiAgICBPZmZzZXRUcmFja2VyLnByb3RvdHlwZS5jb21wdXRlVG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdG9wID0gdGhpcy5vcmlnUmVjdC50b3A7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbENhY2hlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzY3JvbGxDYWNoZSA9IF9hW19pXTtcbiAgICAgICAgICAgIHRvcCArPSBzY3JvbGxDYWNoZS5vcmlnU2Nyb2xsVG9wIC0gc2Nyb2xsQ2FjaGUuZ2V0U2Nyb2xsVG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvcDtcbiAgICB9O1xuICAgIE9mZnNldFRyYWNrZXIucHJvdG90eXBlLmlzV2l0aGluQ2xpcHBpbmcgPSBmdW5jdGlvbiAocGFnZVgsIHBhZ2VZKSB7XG4gICAgICAgIHZhciBwb2ludCA9IHsgbGVmdDogcGFnZVgsIHRvcDogcGFnZVkgfTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsQ2FjaGVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgaWYgKCFpc0lnbm9yZWRDbGlwcGluZyhzY3JvbGxDYWNoZS5nZXRFdmVudFRhcmdldCgpKSAmJlxuICAgICAgICAgICAgICAgICFwb2ludEluc2lkZVJlY3QocG9pbnQsIHNjcm9sbENhY2hlLmNsaWVudFJlY3QpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgcmV0dXJuIE9mZnNldFRyYWNrZXI7XG59KCkpO1xuLy8gY2VydGFpbiBjbGlwcGluZyBjb250YWluZXJzIHNob3VsZCBuZXZlciBjb25zdHJhaW4gaW50ZXJhY3Rpb25zLCBsaWtlIDxodG1sPiBhbmQgPGJvZHk+XG4vLyBodHRwczovL2dpdGh1Yi5jb20vZnVsbGNhbGVuZGFyL2Z1bGxjYWxlbmRhci9pc3N1ZXMvMzYxNVxuZnVuY3Rpb24gaXNJZ25vcmVkQ2xpcHBpbmcobm9kZSkge1xuICAgIHZhciB0YWdOYW1lID0gbm9kZS50YWdOYW1lO1xuICAgIHJldHVybiB0YWdOYW1lID09PSAnSFRNTCcgfHwgdGFnTmFtZSA9PT0gJ0JPRFknO1xufVxuXG4vKlxuVHJhY2tzIG1vdmVtZW50IG92ZXIgbXVsdGlwbGUgZHJvcHBhYmxlIGFyZWFzIChha2EgXCJoaXRzXCIpXG50aGF0IGV4aXN0IGluIG9uZSBvciBtb3JlIERhdGVDb21wb25lbnRzLlxuUmVsaWVzIG9uIGFuIGV4aXN0aW5nIGRyYWdnYWJsZS5cblxuZW1pdHM6XG4tIHBvaW50ZXJkb3duXG4tIGRyYWdzdGFydFxuLSBoaXRjaGFuZ2UgLSBmaXJlcyBpbml0aWFsbHksIGV2ZW4gaWYgbm90IG92ZXIgYSBoaXRcbi0gcG9pbnRlcnVwXG4tIChoaXRjaGFuZ2UgLSBhZ2FpbiwgdG8gbnVsbCwgaWYgZW5kZWQgb3ZlciBhIGhpdClcbi0gZHJhZ2VuZFxuKi9cbnZhciBIaXREcmFnZ2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIaXREcmFnZ2luZyhkcmFnZ2luZywgZHJvcHBhYmxlU3RvcmUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gb3B0aW9ucyB0aGF0IGNhbiBiZSBzZXQgYnkgY2FsbGVyXG4gICAgICAgIHRoaXMudXNlU3ViamVjdENlbnRlciA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlcXVpcmVJbml0aWFsID0gdHJ1ZTsgLy8gaWYgZG9lc24ndCBzdGFydCBvdXQgb24gYSBoaXQsIHdvbid0IGVtaXQgYW55IGV2ZW50c1xuICAgICAgICB0aGlzLmluaXRpYWxIaXQgPSBudWxsO1xuICAgICAgICB0aGlzLm1vdmluZ0hpdCA9IG51bGw7XG4gICAgICAgIHRoaXMuZmluYWxIaXQgPSBudWxsOyAvLyB3b24ndCBldmVyIGJlIHBvcHVsYXRlZCBpZiBzaG91bGRJZ25vcmVNb3ZlXG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nO1xuICAgICAgICAgICAgX3RoaXMuaW5pdGlhbEhpdCA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5tb3ZpbmdIaXQgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMuZmluYWxIaXQgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMucHJlcGFyZUhpdHMoKTtcbiAgICAgICAgICAgIF90aGlzLnByb2Nlc3NGaXJzdENvb3JkKGV2KTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pbml0aWFsSGl0IHx8ICFfdGhpcy5yZXF1aXJlSW5pdGlhbCkge1xuICAgICAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcmRvd24nLCBldik7IC8vIFRPRE86IGZpcmUgdGhpcyBiZWZvcmUgY29tcHV0aW5nIHByb2Nlc3NGaXJzdENvb3JkLCBzbyBsaXN0ZW5lcnMgY2FuIGNhbmNlbC4gdGhpcyBnZXRzIGZpcmVkIGJ5IGFsbW9zdCBldmVyeSBoYW5kbGVyIDooXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkcmFnZ2luZy5zZXRJZ25vcmVNb3ZlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnc3RhcnQnLCBldik7XG4gICAgICAgICAgICBfdGhpcy5oYW5kbGVNb3ZlKGV2LCB0cnVlKTsgLy8gZm9yY2UgPSBmaXJlIGV2ZW4gaWYgaW5pdGlhbGx5IG51bGxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVEcmFnTW92ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnbW92ZScsIGV2KTtcbiAgICAgICAgICAgIF90aGlzLmhhbmRsZU1vdmUoZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMucmVsZWFzZUhpdHMoKTtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5tb3ZpbmdIaXQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2hpdHVwZGF0ZScsIG51bGwsIHRydWUsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmZpbmFsSGl0ID0gX3RoaXMubW92aW5nSGl0O1xuICAgICAgICAgICAgX3RoaXMubW92aW5nSGl0ID0gbnVsbDtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ2VuZCcsIGV2KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kcm9wcGFibGVTdG9yZSA9IGRyb3BwYWJsZVN0b3JlO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdtb3ZlJywgdGhpcy5oYW5kbGVEcmFnTW92ZSk7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIHRoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIHRoaXMuaGFuZGxlRHJhZ0VuZCk7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcgPSBkcmFnZ2luZztcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXJNaXhpbigpO1xuICAgIH1cbiAgICAvLyBzZXRzIGluaXRpYWxIaXRcbiAgICAvLyBzZXRzIGNvb3JkQWRqdXN0XG4gICAgSGl0RHJhZ2dpbmcucHJvdG90eXBlLnByb2Nlc3NGaXJzdENvb3JkID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHZhciBvcmlnUG9pbnQgPSB7IGxlZnQ6IGV2LnBhZ2VYLCB0b3A6IGV2LnBhZ2VZIH07XG4gICAgICAgIHZhciBhZGp1c3RlZFBvaW50ID0gb3JpZ1BvaW50O1xuICAgICAgICB2YXIgc3ViamVjdEVsID0gZXYuc3ViamVjdEVsO1xuICAgICAgICB2YXIgc3ViamVjdFJlY3Q7XG4gICAgICAgIGlmIChzdWJqZWN0RWwgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICBzdWJqZWN0UmVjdCA9IGNvbXB1dGVSZWN0KHN1YmplY3RFbCk7XG4gICAgICAgICAgICBhZGp1c3RlZFBvaW50ID0gY29uc3RyYWluUG9pbnQoYWRqdXN0ZWRQb2ludCwgc3ViamVjdFJlY3QpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbml0aWFsSGl0ID0gdGhpcy5pbml0aWFsSGl0ID0gdGhpcy5xdWVyeUhpdEZvck9mZnNldChhZGp1c3RlZFBvaW50LmxlZnQsIGFkanVzdGVkUG9pbnQudG9wKTtcbiAgICAgICAgaWYgKGluaXRpYWxIaXQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnVzZVN1YmplY3RDZW50ZXIgJiYgc3ViamVjdFJlY3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2xpY2VkU3ViamVjdFJlY3QgPSBpbnRlcnNlY3RSZWN0cyhzdWJqZWN0UmVjdCwgaW5pdGlhbEhpdC5yZWN0KTtcbiAgICAgICAgICAgICAgICBpZiAoc2xpY2VkU3ViamVjdFJlY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRqdXN0ZWRQb2ludCA9IGdldFJlY3RDZW50ZXIoc2xpY2VkU3ViamVjdFJlY3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY29vcmRBZGp1c3QgPSBkaWZmUG9pbnRzKGFkanVzdGVkUG9pbnQsIG9yaWdQb2ludCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNvb3JkQWRqdXN0ID0geyBsZWZ0OiAwLCB0b3A6IDAgfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGl0RHJhZ2dpbmcucHJvdG90eXBlLmhhbmRsZU1vdmUgPSBmdW5jdGlvbiAoZXYsIGZvcmNlSGFuZGxlKSB7XG4gICAgICAgIHZhciBoaXQgPSB0aGlzLnF1ZXJ5SGl0Rm9yT2Zmc2V0KGV2LnBhZ2VYICsgdGhpcy5jb29yZEFkanVzdC5sZWZ0LCBldi5wYWdlWSArIHRoaXMuY29vcmRBZGp1c3QudG9wKTtcbiAgICAgICAgaWYgKGZvcmNlSGFuZGxlIHx8ICFpc0hpdHNFcXVhbCh0aGlzLm1vdmluZ0hpdCwgaGl0KSkge1xuICAgICAgICAgICAgdGhpcy5tb3ZpbmdIaXQgPSBoaXQ7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignaGl0dXBkYXRlJywgaGl0LCBmYWxzZSwgZXYpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUucHJlcGFyZUhpdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub2Zmc2V0VHJhY2tlcnMgPSBtYXBIYXNoKHRoaXMuZHJvcHBhYmxlU3RvcmUsIGZ1bmN0aW9uIChpbnRlcmFjdGlvblNldHRpbmdzKSB7XG4gICAgICAgICAgICBpbnRlcmFjdGlvblNldHRpbmdzLmNvbXBvbmVudC5idWlsZFBvc2l0aW9uQ2FjaGVzKCk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE9mZnNldFRyYWNrZXIoaW50ZXJhY3Rpb25TZXR0aW5ncy5lbCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSGl0RHJhZ2dpbmcucHJvdG90eXBlLnJlbGVhc2VIaXRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb2Zmc2V0VHJhY2tlcnMgPSB0aGlzLm9mZnNldFRyYWNrZXJzO1xuICAgICAgICBmb3IgKHZhciBpZCBpbiBvZmZzZXRUcmFja2Vycykge1xuICAgICAgICAgICAgb2Zmc2V0VHJhY2tlcnNbaWRdLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9mZnNldFRyYWNrZXJzID0ge307XG4gICAgfTtcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUucXVlcnlIaXRGb3JPZmZzZXQgPSBmdW5jdGlvbiAob2Zmc2V0TGVmdCwgb2Zmc2V0VG9wKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMsIGRyb3BwYWJsZVN0b3JlID0gX2EuZHJvcHBhYmxlU3RvcmUsIG9mZnNldFRyYWNrZXJzID0gX2Eub2Zmc2V0VHJhY2tlcnM7XG4gICAgICAgIHZhciBiZXN0SGl0ID0gbnVsbDtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gZHJvcHBhYmxlU3RvcmUpIHtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnQgPSBkcm9wcGFibGVTdG9yZVtpZF0uY29tcG9uZW50O1xuICAgICAgICAgICAgdmFyIG9mZnNldFRyYWNrZXIgPSBvZmZzZXRUcmFja2Vyc1tpZF07XG4gICAgICAgICAgICBpZiAob2Zmc2V0VHJhY2tlci5pc1dpdGhpbkNsaXBwaW5nKG9mZnNldExlZnQsIG9mZnNldFRvcCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgb3JpZ2luTGVmdCA9IG9mZnNldFRyYWNrZXIuY29tcHV0ZUxlZnQoKTtcbiAgICAgICAgICAgICAgICB2YXIgb3JpZ2luVG9wID0gb2Zmc2V0VHJhY2tlci5jb21wdXRlVG9wKCk7XG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uTGVmdCA9IG9mZnNldExlZnQgLSBvcmlnaW5MZWZ0O1xuICAgICAgICAgICAgICAgIHZhciBwb3NpdGlvblRvcCA9IG9mZnNldFRvcCAtIG9yaWdpblRvcDtcbiAgICAgICAgICAgICAgICB2YXIgb3JpZ1JlY3QgPSBvZmZzZXRUcmFja2VyLm9yaWdSZWN0O1xuICAgICAgICAgICAgICAgIHZhciB3aWR0aCA9IG9yaWdSZWN0LnJpZ2h0IC0gb3JpZ1JlY3QubGVmdDtcbiAgICAgICAgICAgICAgICB2YXIgaGVpZ2h0ID0gb3JpZ1JlY3QuYm90dG9tIC0gb3JpZ1JlY3QudG9wO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAvLyBtdXN0IGJlIHdpdGhpbiB0aGUgZWxlbWVudCdzIGJvdW5kc1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uTGVmdCA+PSAwICYmIHBvc2l0aW9uTGVmdCA8IHdpZHRoICYmXG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uVG9wID49IDAgJiYgcG9zaXRpb25Ub3AgPCBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhpdCA9IGNvbXBvbmVudC5xdWVyeUhpdChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGhpdCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHRoZSBoaXQgaXMgd2l0aGluIGFjdGl2ZVJhbmdlLCBtZWFuaW5nIGl0J3Mgbm90IGEgZGVhbCBjZWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAhY29tcG9uZW50LnByb3BzLmRhdGVQcm9maWxlIHx8IC8vIGhhY2sgZm9yIERheVRpbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZUNvbnRhaW5zUmFuZ2UoY29tcG9uZW50LnByb3BzLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBoaXQuZGF0ZVNwYW4ucmFuZ2UpKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKCFiZXN0SGl0IHx8IGhpdC5sYXllciA+IGJlc3RIaXQubGF5ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBiZXR0ZXIgd2F5IHRvIHJlLW9yaWVudCByZWN0YW5nbGVcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpdC5yZWN0LmxlZnQgKz0gb3JpZ2luTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpdC5yZWN0LnJpZ2h0ICs9IG9yaWdpbkxlZnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBoaXQucmVjdC50b3AgKz0gb3JpZ2luVG9wO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QuYm90dG9tICs9IG9yaWdpblRvcDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlc3RIaXQgPSBoaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJlc3RIaXQ7XG4gICAgfTtcbiAgICByZXR1cm4gSGl0RHJhZ2dpbmc7XG59KCkpO1xuZnVuY3Rpb24gaXNIaXRzRXF1YWwoaGl0MCwgaGl0MSkge1xuICAgIGlmICghaGl0MCAmJiAhaGl0MSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKEJvb2xlYW4oaGl0MCkgIT09IEJvb2xlYW4oaGl0MSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gaXNEYXRlU3BhbnNFcXVhbChoaXQwLmRhdGVTcGFuLCBoaXQxLmRhdGVTcGFuKTtcbn1cblxuLypcbk1vbml0b3JzIHdoZW4gdGhlIHVzZXIgY2xpY2tzIG9uIGEgc3BlY2lmaWMgZGF0ZS90aW1lIG9mIGEgY29tcG9uZW50LlxuQSBwb2ludGVyZG93bitwb2ludGVydXAgb24gdGhlIHNhbWUgXCJoaXRcIiBjb25zdGl0dXRlcyBhIGNsaWNrLlxuKi9cbnZhciBEYXRlQ2xpY2tpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERhdGVDbGlja2luZywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXRlQ2xpY2tpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgZHJhZ2dpbmcgPSBfdGhpcy5kcmFnZ2luZztcbiAgICAgICAgICAgIC8vIGRvIHRoaXMgaW4gcG9pbnRlcmRvd24gKG5vdCBkcmFnZW5kKSBiZWNhdXNlIERPTSBtaWdodCBiZSBtdXRhdGVkIGJ5IHRoZSB0aW1lIGRyYWdlbmQgaXMgZmlyZWRcbiAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoIV90aGlzLmNvbXBvbmVudC5pc1ZhbGlkRGF0ZURvd25FbChkcmFnZ2luZy5wb2ludGVyLmRvd25FbCkpO1xuICAgICAgICB9O1xuICAgICAgICAvLyB3b24ndCBldmVuIGZpcmUgaWYgbW92aW5nIHdhcyBpZ25vcmVkXG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnQgPSBfdGhpcy5jb21wb25lbnQ7XG4gICAgICAgICAgICB2YXIgX2EgPSBjb21wb25lbnQuY29udGV4dCwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhciwgdmlldyA9IF9hLnZpZXc7XG4gICAgICAgICAgICB2YXIgcG9pbnRlciA9IF90aGlzLmRyYWdnaW5nLnBvaW50ZXI7XG4gICAgICAgICAgICBpZiAoIXBvaW50ZXIud2FzVG91Y2hTY3JvbGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgX2IgPSBfdGhpcy5oaXREcmFnZ2luZywgaW5pdGlhbEhpdCA9IF9iLmluaXRpYWxIaXQsIGZpbmFsSGl0ID0gX2IuZmluYWxIaXQ7XG4gICAgICAgICAgICAgICAgaWYgKGluaXRpYWxIaXQgJiYgZmluYWxIaXQgJiYgaXNIaXRzRXF1YWwoaW5pdGlhbEhpdCwgZmluYWxIaXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLnRyaWdnZXJEYXRlQ2xpY2soaW5pdGlhbEhpdC5kYXRlU3BhbiwgaW5pdGlhbEhpdC5kYXlFbCwgdmlldywgZXYub3JpZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjb21wb25lbnQgPSBzZXR0aW5ncy5jb21wb25lbnQ7XG4gICAgICAgIC8vIHdlIERPIHdhbnQgdG8gd2F0Y2ggcG9pbnRlciBtb3ZlcyBiZWNhdXNlIG90aGVyd2lzZSBmaW5hbEhpdCB3b24ndCBnZXQgcG9wdWxhdGVkXG4gICAgICAgIF90aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29tcG9uZW50LmVsKTtcbiAgICAgICAgX3RoaXMuZHJhZ2dpbmcuYXV0b1Njcm9sbGVyLmlzRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSBfdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyhfdGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCBfdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdlbmQnLCBfdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXRlQ2xpY2tpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVDbGlja2luZztcbn0oSW50ZXJhY3Rpb24pKTtcblxuLypcblRyYWNrcyB3aGVuIHRoZSB1c2VyIHNlbGVjdHMgYSBwb3J0aW9uIG9mIHRpbWUgb2YgYSBjb21wb25lbnQsXG5jb25zdGl0dXRlZCBieSBhIGRyYWcgb3ZlciBkYXRlIGNlbGxzLCB3aXRoIGEgcG9zc2libGUgZGVsYXkgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgZHJhZy5cbiovXG52YXIgRGF0ZVNlbGVjdGluZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF0ZVNlbGVjdGluZywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXRlU2VsZWN0aW5nKHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHNldHRpbmdzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5kcmFnU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLCBjb21wb25lbnQgPSBfYS5jb21wb25lbnQsIGRyYWdnaW5nID0gX2EuZHJhZ2dpbmc7XG4gICAgICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgICAgICB2YXIgY2FuU2VsZWN0ID0gb3B0aW9ucy5zZWxlY3RhYmxlICYmXG4gICAgICAgICAgICAgICAgY29tcG9uZW50LmlzVmFsaWREYXRlRG93bkVsKGV2Lm9yaWdFdmVudC50YXJnZXQpO1xuICAgICAgICAgICAgLy8gZG9uJ3QgYm90aGVyIHRvIHdhdGNoIGV4cGVuc2l2ZSBtb3ZlcyBpZiBjb21wb25lbnQgd29uJ3QgZG8gc2VsZWN0aW9uXG4gICAgICAgICAgICBkcmFnZ2luZy5zZXRJZ25vcmVNb3ZlKCFjYW5TZWxlY3QpO1xuICAgICAgICAgICAgLy8gaWYgdG91Y2gsIHJlcXVpcmUgdXNlciB0byBob2xkIGRvd25cbiAgICAgICAgICAgIGRyYWdnaW5nLmRlbGF5ID0gZXYuaXNUb3VjaCA/IGdldENvbXBvbmVudFRvdWNoRGVsYXkoY29tcG9uZW50KSA6IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIudW5zZWxlY3QoZXYpOyAvLyB1bnNlbGVjdCBwcmV2aW91cyBzZWxlY3Rpb25zXG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZUhpdFVwZGF0ZSA9IGZ1bmN0aW9uIChoaXQsIGlzRmluYWwpIHtcbiAgICAgICAgICAgIHZhciBjYWxlbmRhciA9IF90aGlzLmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgdmFyIGRyYWdTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICAgICAgdmFyIGlzSW52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGhpdCkge1xuICAgICAgICAgICAgICAgIGRyYWdTZWxlY3Rpb24gPSBqb2luSGl0c0ludG9TZWxlY3Rpb24oX3RoaXMuaGl0RHJhZ2dpbmcuaW5pdGlhbEhpdCwgaGl0LCBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyk7XG4gICAgICAgICAgICAgICAgaWYgKCFkcmFnU2VsZWN0aW9uIHx8ICFfdGhpcy5jb21wb25lbnQuaXNEYXRlU2VsZWN0aW9uVmFsaWQoZHJhZ1NlbGVjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ1NlbGVjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRyYWdTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdTRUxFQ1RfREFURVMnLCBzZWxlY3Rpb246IGRyYWdTZWxlY3Rpb24gfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghaXNGaW5hbCkgeyAvLyBvbmx5IHVuc2VsZWN0IGlmIG1vdmVkIGF3YXkgd2hpbGUgZHJhZ2dpbmdcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9EQVRFUycgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZHJhZ1NlbGVjdGlvbiA9IGRyYWdTZWxlY3Rpb247IC8vIG9ubHkgY2xlYXIgaWYgbW92ZWQgYXdheSBmcm9tIGFsbCBoaXRzIHdoaWxlIGRyYWdnaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJVcCA9IGZ1bmN0aW9uIChwZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5kcmFnU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gc2VsZWN0aW9uIGlzIGFscmVhZHkgcmVuZGVyZWQsIHNvIGp1c3QgbmVlZCB0byByZXBvcnQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIudHJpZ2dlckRhdGVTZWxlY3QoX3RoaXMuZHJhZ1NlbGVjdGlvbiwgcGV2KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5kcmFnU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSBjb21wb25lbnQuY29udGV4dC5vcHRpb25zO1xuICAgICAgICB2YXIgZHJhZ2dpbmcgPSBfdGhpcy5kcmFnZ2luZyA9IG5ldyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nKGNvbXBvbmVudC5lbCk7XG4gICAgICAgIGRyYWdnaW5nLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICBkcmFnZ2luZy5taW5EaXN0YW5jZSA9IG9wdGlvbnMuc2VsZWN0TWluRGlzdGFuY2UgfHwgMDtcbiAgICAgICAgZHJhZ2dpbmcuYXV0b1Njcm9sbGVyLmlzRW5hYmxlZCA9IG9wdGlvbnMuZHJhZ1Njcm9sbDtcbiAgICAgICAgdmFyIGhpdERyYWdnaW5nID0gX3RoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcoX3RoaXMuZHJhZ2dpbmcsIGludGVyYWN0aW9uU2V0dGluZ3NUb1N0b3JlKHNldHRpbmdzKSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCBfdGhpcy5oYW5kbGVEcmFnU3RhcnQpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdoaXR1cGRhdGUnLCBfdGhpcy5oYW5kbGVIaXRVcGRhdGUpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVydXAnLCBfdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERhdGVTZWxlY3RpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVTZWxlY3Rpbmc7XG59KEludGVyYWN0aW9uKSk7XG5mdW5jdGlvbiBnZXRDb21wb25lbnRUb3VjaERlbGF5KGNvbXBvbmVudCkge1xuICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICB2YXIgZGVsYXkgPSBvcHRpb25zLnNlbGVjdExvbmdQcmVzc0RlbGF5O1xuICAgIGlmIChkZWxheSA9PSBudWxsKSB7XG4gICAgICAgIGRlbGF5ID0gb3B0aW9ucy5sb25nUHJlc3NEZWxheTtcbiAgICB9XG4gICAgcmV0dXJuIGRlbGF5O1xufVxuZnVuY3Rpb24gam9pbkhpdHNJbnRvU2VsZWN0aW9uKGhpdDAsIGhpdDEsIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnMpIHtcbiAgICB2YXIgZGF0ZVNwYW4wID0gaGl0MC5kYXRlU3BhbjtcbiAgICB2YXIgZGF0ZVNwYW4xID0gaGl0MS5kYXRlU3BhbjtcbiAgICB2YXIgbXMgPSBbXG4gICAgICAgIGRhdGVTcGFuMC5yYW5nZS5zdGFydCxcbiAgICAgICAgZGF0ZVNwYW4wLnJhbmdlLmVuZCxcbiAgICAgICAgZGF0ZVNwYW4xLnJhbmdlLnN0YXJ0LFxuICAgICAgICBkYXRlU3BhbjEucmFuZ2UuZW5kXG4gICAgXTtcbiAgICBtcy5zb3J0KGNvbXBhcmVOdW1iZXJzKTtcbiAgICB2YXIgcHJvcHMgPSB7fTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnNfMSA9IGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM7IF9pIDwgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtZXIgPSBkYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzXzFbX2ldO1xuICAgICAgICB2YXIgcmVzID0gdHJhbnNmb3JtZXIoaGl0MCwgaGl0MSk7XG4gICAgICAgIGlmIChyZXMgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZXMpIHtcbiAgICAgICAgICAgIF9fYXNzaWduKHByb3BzLCByZXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHByb3BzLnJhbmdlID0geyBzdGFydDogbXNbMF0sIGVuZDogbXNbM10gfTtcbiAgICBwcm9wcy5hbGxEYXkgPSBkYXRlU3BhbjAuYWxsRGF5O1xuICAgIHJldHVybiBwcm9wcztcbn1cblxudmFyIEV2ZW50RHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEV2ZW50RHJhZ2dpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRXZlbnREcmFnZ2luZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgX3RoaXMuc3ViamVjdFNlZyA9IG51bGw7IC8vIHRoZSBzZWcgYmVpbmcgc2VsZWN0ZWQvZHJhZ2dlZFxuICAgICAgICBfdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmV2ZW50UmFuZ2UgPSBudWxsO1xuICAgICAgICBfdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7IC8vIHRoZSBldmVudHMgYmVpbmcgZHJhZ2dlZFxuICAgICAgICBfdGhpcy5yZWNlaXZpbmdDYWxlbmRhciA9IG51bGw7XG4gICAgICAgIF90aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICBfdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIG9yaWdUYXJnZXQgPSBldi5vcmlnRXZlbnQudGFyZ2V0O1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMsIGNvbXBvbmVudCA9IF9hLmNvbXBvbmVudCwgZHJhZ2dpbmcgPSBfYS5kcmFnZ2luZztcbiAgICAgICAgICAgIHZhciBtaXJyb3IgPSBkcmFnZ2luZy5taXJyb3I7XG4gICAgICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICB2YXIgc3ViamVjdFNlZyA9IF90aGlzLnN1YmplY3RTZWcgPSBnZXRFbFNlZyhldi5zdWJqZWN0RWwpO1xuICAgICAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBfdGhpcy5ldmVudFJhbmdlID0gc3ViamVjdFNlZy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgdmFyIGV2ZW50SW5zdGFuY2VJZCA9IGV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZDtcbiAgICAgICAgICAgIF90aGlzLnJlbGV2YW50RXZlbnRzID0gZ2V0UmVsZXZhbnRFdmVudHMoaW5pdGlhbENhbGVuZGFyLnN0YXRlLmV2ZW50U3RvcmUsIGV2ZW50SW5zdGFuY2VJZCk7XG4gICAgICAgICAgICBkcmFnZ2luZy5taW5EaXN0YW5jZSA9IGV2LmlzVG91Y2ggPyAwIDogb3B0aW9ucy5ldmVudERyYWdNaW5EaXN0YW5jZTtcbiAgICAgICAgICAgIGRyYWdnaW5nLmRlbGF5ID1cbiAgICAgICAgICAgICAgICAvLyBvbmx5IGRvIGEgdG91Y2ggZGVsYXkgaWYgdG91Y2ggYW5kIHRoaXMgZXZlbnQgaGFzbid0IGJlZW4gc2VsZWN0ZWQgeWV0XG4gICAgICAgICAgICAgICAgKGV2LmlzVG91Y2ggJiYgZXZlbnRJbnN0YW5jZUlkICE9PSBjb21wb25lbnQucHJvcHMuZXZlbnRTZWxlY3Rpb24pID9cbiAgICAgICAgICAgICAgICAgICAgZ2V0Q29tcG9uZW50VG91Y2hEZWxheSQxKGNvbXBvbmVudCkgOlxuICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgICAgICAgICAgbWlycm9yLnBhcmVudE5vZGUgPSBpbml0aWFsQ2FsZW5kYXIuZWw7XG4gICAgICAgICAgICBtaXJyb3IucmV2ZXJ0RHVyYXRpb24gPSBvcHRpb25zLmRyYWdSZXZlcnREdXJhdGlvbjtcbiAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwob3JpZ1RhcmdldCkgJiZcbiAgICAgICAgICAgICAgICAhZWxlbWVudENsb3Nlc3Qob3JpZ1RhcmdldCwgJy5mYy1yZXNpemVyJyk7IC8vIE5PVCBvbiBhIHJlc2l6ZXJcbiAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoIWlzVmFsaWQpO1xuICAgICAgICAgICAgLy8gZGlzYWJsZSBkcmFnZ2luZyBmb3IgZWxlbWVudHMgdGhhdCBhcmUgcmVzaXphYmxlIChpZSwgc2VsZWN0YWJsZSlcbiAgICAgICAgICAgIC8vIGJ1dCBhcmUgbm90IGRyYWdnYWJsZVxuICAgICAgICAgICAgX3RoaXMuaXNEcmFnZ2luZyA9IGlzVmFsaWQgJiZcbiAgICAgICAgICAgICAgICBldi5zdWJqZWN0RWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYy1kcmFnZ2FibGUnKTtcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgY29udGV4dCA9IF90aGlzLmNvbXBvbmVudC5jb250ZXh0O1xuICAgICAgICAgICAgdmFyIGluaXRpYWxDYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IF90aGlzLmV2ZW50UmFuZ2U7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZUlkID0gZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkO1xuICAgICAgICAgICAgaWYgKGV2LmlzVG91Y2gpIHtcbiAgICAgICAgICAgICAgICAvLyBuZWVkIHRvIHNlbGVjdCBhIGRpZmZlcmVudCBldmVudD9cbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRJbnN0YW5jZUlkICE9PSBfdGhpcy5jb21wb25lbnQucHJvcHMuZXZlbnRTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1NFTEVDVF9FVkVOVCcsIGV2ZW50SW5zdGFuY2VJZDogZXZlbnRJbnN0YW5jZUlkIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vdyB1c2luZyBtb3VzZSwgYnV0IHdhcyBwcmV2aW91cyB0b3VjaCBpbnRlcmFjdGlvbiwgY2xlYXIgc2VsZWN0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRUxFQ1RfRVZFTlQnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIudW5zZWxlY3QoZXYpOyAvLyB1bnNlbGVjdCAqZGF0ZSogc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnREcmFnU3RhcnQnLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiBfdGhpcy5zdWJqZWN0U2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IG5ldyBFdmVudEFwaShpbml0aWFsQ2FsZW5kYXIsIGV2ZW50UmFuZ2UuZGVmLCBldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGNvbnRleHQudmlld1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZUhpdFVwZGF0ZSA9IGZ1bmN0aW9uIChoaXQsIGlzRmluYWwpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciByZWxldmFudEV2ZW50cyA9IF90aGlzLnJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgdmFyIGluaXRpYWxIaXQgPSBfdGhpcy5oaXREcmFnZ2luZy5pbml0aWFsSGl0O1xuICAgICAgICAgICAgdmFyIGluaXRpYWxDYWxlbmRhciA9IF90aGlzLmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgLy8gc3RhdGVzIGJhc2VkIG9uIG5ldyBoaXRcbiAgICAgICAgICAgIHZhciByZWNlaXZpbmdDYWxlbmRhciA9IG51bGw7XG4gICAgICAgICAgICB2YXIgbXV0YXRpb24gPSBudWxsO1xuICAgICAgICAgICAgdmFyIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgICAgICB2YXIgaXNJbnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgaW50ZXJhY3Rpb24gPSB7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IHJlbGV2YW50RXZlbnRzLFxuICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IHRydWUsXG4gICAgICAgICAgICAgICAgb3JpZ1NlZzogX3RoaXMuc3ViamVjdFNlZ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChoaXQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVjZWl2aW5nQ29tcG9uZW50ID0gaGl0LmNvbXBvbmVudDtcbiAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhciA9IHJlY2VpdmluZ0NvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgIHZhciByZWNlaXZpbmdPcHRpb25zID0gcmVjZWl2aW5nQ29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbENhbGVuZGFyID09PSByZWNlaXZpbmdDYWxlbmRhciB8fFxuICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdPcHRpb25zLmVkaXRhYmxlICYmIHJlY2VpdmluZ09wdGlvbnMuZHJvcHBhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gY29tcHV0ZUV2ZW50TXV0YXRpb24oaW5pdGlhbEhpdCwgaGl0LCByZWNlaXZpbmdDYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IGFwcGx5TXV0YXRpb25Ub0V2ZW50U3RvcmUocmVsZXZhbnRFdmVudHMsIHJlY2VpdmluZ0NhbGVuZGFyLmV2ZW50VWlCYXNlcywgbXV0YXRpb24sIHJlY2VpdmluZ0NhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBtdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXJlY2VpdmluZ0NvbXBvbmVudC5pc0ludGVyYWN0aW9uVmFsaWQoaW50ZXJhY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzID0gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5kaXNwbGF5RHJhZyhyZWNlaXZpbmdDYWxlbmRhciwgaW50ZXJhY3Rpb24pO1xuICAgICAgICAgICAgaWYgKCFpc0ludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBlbmFibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpc2FibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNGaW5hbCkge1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsQ2FsZW5kYXIgPT09IHJlY2VpdmluZ0NhbGVuZGFyICYmIC8vIFRPRE86IHdyaXRlIHRlc3QgZm9yIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgaXNIaXRzRXF1YWwoaW5pdGlhbEhpdCwgaGl0KSkge1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLnNldE1pcnJvck5lZWRzUmV2ZXJ0KCFtdXRhdGlvbik7XG4gICAgICAgICAgICAgICAgLy8gcmVuZGVyIHRoZSBtaXJyb3IgaWYgbm8gYWxyZWFkeS1yZW5kZXJlZCBtaXJyb3JcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiB3aXNoIHdlIGNvdWxkIHNvbWVob3cgd2FpdCBmb3IgZGlzcGF0Y2ggdG8gZ3VhcmFudGVlIHJlbmRlclxuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLnNldE1pcnJvcklzVmlzaWJsZSghaGl0IHx8ICFkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuZmMtbWlycm9yJykpO1xuICAgICAgICAgICAgICAgIC8vIGFzc2lnbiBzdGF0ZXMgYmFzZWQgb24gbmV3IGhpdFxuICAgICAgICAgICAgICAgIF90aGlzLnJlY2VpdmluZ0NhbGVuZGFyID0gcmVjZWl2aW5nQ2FsZW5kYXI7XG4gICAgICAgICAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG11dGF0aW9uO1xuICAgICAgICAgICAgICAgIF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlclVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2xlYW51cCgpOyAvLyBiZWNhdXNlIGhhbmRsZURyYWdFbmQgd29uJ3QgZmlyZVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVEcmFnRW5kID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgIHZhciBjb250ZXh0ID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQ7XG4gICAgICAgICAgICAgICAgdmFyIGluaXRpYWxDYWxlbmRhcl8xID0gY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgICAgICAgICB2YXIgaW5pdGlhbFZpZXcgPSBjb250ZXh0LnZpZXc7XG4gICAgICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMsIHJlY2VpdmluZ0NhbGVuZGFyID0gX2EucmVjZWl2aW5nQ2FsZW5kYXIsIHZhbGlkTXV0YXRpb24gPSBfYS52YWxpZE11dGF0aW9uO1xuICAgICAgICAgICAgICAgIHZhciBldmVudERlZiA9IF90aGlzLmV2ZW50UmFuZ2UuZGVmO1xuICAgICAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlID0gX3RoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZTtcbiAgICAgICAgICAgICAgICB2YXIgZXZlbnRBcGkgPSBuZXcgRXZlbnRBcGkoaW5pdGlhbENhbGVuZGFyXzEsIGV2ZW50RGVmLCBldmVudEluc3RhbmNlKTtcbiAgICAgICAgICAgICAgICB2YXIgcmVsZXZhbnRFdmVudHNfMSA9IF90aGlzLnJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgICAgIHZhciBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBfdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgdmFyIGZpbmFsSGl0ID0gX3RoaXMuaGl0RHJhZ2dpbmcuZmluYWxIaXQ7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2xlYXJEcmFnKCk7IC8vIG11c3QgaGFwcGVuIGFmdGVyIHJldmVydCBhbmltYXRpb25cbiAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50RHJhZ1N0b3AnLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiBfdGhpcy5zdWJqZWN0U2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGV2ZW50QXBpLFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYub3JpZ0V2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlldzogaW5pdGlhbFZpZXdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgIGlmICh2YWxpZE11dGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGRyb3BwZWQgd2l0aGluIHNhbWUgY2FsZW5kYXJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlY2VpdmluZ0NhbGVuZGFyID09PSBpbml0aWFsQ2FsZW5kYXJfMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IG11dGF0ZWRSZWxldmFudEV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhbnNmb3JtZWQgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2IgPSBpbml0aWFsQ2FsZW5kYXJfMS5wbHVnaW5TeXN0ZW0uaG9va3MuZXZlbnREcm9wVHJhbnNmb3JtZXJzOyBfaSA8IF9iLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lciA9IF9iW19pXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfX2Fzc2lnbih0cmFuc2Zvcm1lZCwgdHJhbnNmb3JtZXIodmFsaWRNdXRhdGlvbiwgaW5pdGlhbENhbGVuZGFyXzEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldmVudERyb3BBcmcgPSBfX2Fzc2lnbih7fSwgdHJhbnNmb3JtZWQsIHsgZWw6IGV2LnN1YmplY3RFbCwgZGVsdGE6IHZhbGlkTXV0YXRpb24uZGF0ZXNEZWx0YSwgb2xkRXZlbnQ6IGV2ZW50QXBpLCBldmVudDogbmV3IEV2ZW50QXBpKC8vIHRoZSBkYXRhIEFGVEVSIHRoZSBtdXRhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLCBtdXRhdGVkUmVsZXZhbnRFdmVudHMuZGVmc1tldmVudERlZi5kZWZJZF0sIGV2ZW50SW5zdGFuY2UgPyBtdXRhdGVkUmVsZXZhbnRFdmVudHMuaW5zdGFuY2VzW2V2ZW50SW5zdGFuY2UuaW5zdGFuY2VJZF0gOiBudWxsKSwgcmV2ZXJ0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogcmVsZXZhbnRFdmVudHNfMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBqc0V2ZW50OiBldi5vcmlnRXZlbnQsIHZpZXc6IGluaXRpYWxWaWV3IH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEucHVibGljbHlUcmlnZ2VyKCdldmVudERyb3AnLCBbZXZlbnREcm9wQXJnXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkcm9wcGVkIGluIGRpZmZlcmVudCBjYWxlbmRhclxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHJlY2VpdmluZ0NhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50TGVhdmUnLCBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmFnZ2VkRWw6IGV2LnN1YmplY3RFbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGV2ZW50QXBpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiBpbml0aWFsVmlld1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRfSU5TVEFOQ0VTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZXM6IF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXYuaXNUb3VjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFTEVDVF9FVkVOVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50SW5zdGFuY2VJZDogZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZHJvcEFyZyA9IF9fYXNzaWduKHt9LCByZWNlaXZpbmdDYWxlbmRhci5idWlsZERhdGVQb2ludEFwaShmaW5hbEhpdC5kYXRlU3BhbiksIHsgZHJhZ2dlZEVsOiBldi5zdWJqZWN0RWwsIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCwgdmlldzogZmluYWxIaXQuY29tcG9uZW50IC8vIHNob3VsZCB0aGlzIGJlIGZpbmFsSGl0LmNvbXBvbmVudC52aWV3PyBTZWUgIzQ2NDRcbiAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZHJvcCcsIFtkcm9wQXJnXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50UmVjZWl2ZScsIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRFbDogZXYuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKC8vIHRoZSBkYXRhIEFGVEVSIHRoZSBtdXRhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhciwgbXV0YXRlZFJlbGV2YW50RXZlbnRzLmRlZnNbZXZlbnREZWYuZGVmSWRdLCBtdXRhdGVkUmVsZXZhbnRFdmVudHMuaW5zdGFuY2VzW2V2ZW50SW5zdGFuY2UuaW5zdGFuY2VJZF0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiBmaW5hbEhpdC5jb21wb25lbnQgLy8gc2hvdWxkIHRoaXMgYmUgZmluYWxIaXQuY29tcG9uZW50LnZpZXc/IFNlZSAjNDY0NFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5wdWJsaWNseVRyaWdnZXIoJ19ub0V2ZW50RHJvcCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmNsZWFudXAoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSBjb21wb25lbnQuY29udGV4dC5vcHRpb25zO1xuICAgICAgICB2YXIgZHJhZ2dpbmcgPSBfdGhpcy5kcmFnZ2luZyA9IG5ldyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nKGNvbXBvbmVudC5lbCk7XG4gICAgICAgIGRyYWdnaW5nLnBvaW50ZXIuc2VsZWN0b3IgPSBFdmVudERyYWdnaW5nLlNFTEVDVE9SO1xuICAgICAgICBkcmFnZ2luZy50b3VjaFNjcm9sbEFsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgZHJhZ2dpbmcuYXV0b1Njcm9sbGVyLmlzRW5hYmxlZCA9IG9wdGlvbnMuZHJhZ1Njcm9sbDtcbiAgICAgICAgdmFyIGhpdERyYWdnaW5nID0gX3RoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcoX3RoaXMuZHJhZ2dpbmcsIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLnVzZVN1YmplY3RDZW50ZXIgPSBzZXR0aW5ncy51c2VFdmVudENlbnRlcjtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCBfdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIF90aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIF90aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIF90aGlzLmhhbmRsZVBvaW50ZXJVcCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdlbmQnLCBfdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBFdmVudERyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRyYWdnaW5nLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIC8vIHJlbmRlciBhIGRyYWcgc3RhdGUgb24gdGhlIG5leHQgcmVjZWl2aW5nQ2FsZW5kYXJcbiAgICBFdmVudERyYWdnaW5nLnByb3RvdHlwZS5kaXNwbGF5RHJhZyA9IGZ1bmN0aW9uIChuZXh0Q2FsZW5kYXIsIHN0YXRlKSB7XG4gICAgICAgIHZhciBpbml0aWFsQ2FsZW5kYXIgPSB0aGlzLmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICB2YXIgcHJldkNhbGVuZGFyID0gdGhpcy5yZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgLy8gZG9lcyB0aGUgcHJldmlvdXMgY2FsZW5kYXIgbmVlZCB0byBiZSBjbGVhcmVkP1xuICAgICAgICBpZiAocHJldkNhbGVuZGFyICYmIHByZXZDYWxlbmRhciAhPT0gbmV4dENhbGVuZGFyKSB7XG4gICAgICAgICAgICAvLyBkb2VzIHRoZSBpbml0aWFsIGNhbGVuZGFyIG5lZWQgdG8gYmUgY2xlYXJlZD9cbiAgICAgICAgICAgIC8vIGlmIHNvLCBkb24ndCBjbGVhciBhbGwgdGhlIHdheS4gd2Ugc3RpbGwgbmVlZCB0byB0byBoaWRlIHRoZSBhZmZlY3RlZEV2ZW50c1xuICAgICAgICAgICAgaWYgKHByZXZDYWxlbmRhciA9PT0gaW5pdGlhbENhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgcHJldkNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9FVkVOVF9EUkFHJyxcbiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFmZmVjdGVkRXZlbnRzOiBzdGF0ZS5hZmZlY3RlZEV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdTZWc6IHN0YXRlLm9yaWdTZWdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIGNvbXBsZXRlbHkgY2xlYXIgdGhlIG9sZCBjYWxlbmRhciBpZiBpdCB3YXNuJ3QgdGhlIGluaXRpYWxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHByZXZDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAobmV4dENhbGVuZGFyKSB7XG4gICAgICAgICAgICBuZXh0Q2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnU0VUX0VWRU5UX0RSQUcnLCBzdGF0ZTogc3RhdGUgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmNsZWFyRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGluaXRpYWxDYWxlbmRhciA9IHRoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciByZWNlaXZpbmdDYWxlbmRhciA9IHRoaXMucmVjZWl2aW5nQ2FsZW5kYXI7XG4gICAgICAgIGlmIChyZWNlaXZpbmdDYWxlbmRhcikge1xuICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfRFJBRycgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlIGluaXRpYWwgY2FsZW5kYXIgbWlnaHQgaGF2ZSBhbiBkdW1teSBkcmFnIHN0YXRlIGZyb20gZGlzcGxheURyYWdcbiAgICAgICAgaWYgKGluaXRpYWxDYWxlbmRhciAhPT0gcmVjZWl2aW5nQ2FsZW5kYXIpIHtcbiAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnREcmFnZ2luZy5wcm90b3R5cGUuY2xlYW51cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdWJqZWN0U2VnID0gbnVsbDtcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlbnRSYW5nZSA9IG51bGw7XG4gICAgICAgIHRoaXMucmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgdGhpcy52YWxpZE11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgIH07XG4gICAgRXZlbnREcmFnZ2luZy5TRUxFQ1RPUiA9ICcuZmMtZHJhZ2dhYmxlLCAuZmMtcmVzaXphYmxlJzsgLy8gVE9ETzogdGVzdCB0aGlzIGluIElFMTFcbiAgICByZXR1cm4gRXZlbnREcmFnZ2luZztcbn0oSW50ZXJhY3Rpb24pKTtcbmZ1bmN0aW9uIGNvbXB1dGVFdmVudE11dGF0aW9uKGhpdDAsIGhpdDEsIG1hc3NhZ2Vycykge1xuICAgIHZhciBkYXRlU3BhbjAgPSBoaXQwLmRhdGVTcGFuO1xuICAgIHZhciBkYXRlU3BhbjEgPSBoaXQxLmRhdGVTcGFuO1xuICAgIHZhciBkYXRlMCA9IGRhdGVTcGFuMC5yYW5nZS5zdGFydDtcbiAgICB2YXIgZGF0ZTEgPSBkYXRlU3BhbjEucmFuZ2Uuc3RhcnQ7XG4gICAgdmFyIHN0YW5kYXJkUHJvcHMgPSB7fTtcbiAgICBpZiAoZGF0ZVNwYW4wLmFsbERheSAhPT0gZGF0ZVNwYW4xLmFsbERheSkge1xuICAgICAgICBzdGFuZGFyZFByb3BzLmFsbERheSA9IGRhdGVTcGFuMS5hbGxEYXk7XG4gICAgICAgIHN0YW5kYXJkUHJvcHMuaGFzRW5kID0gaGl0MS5jb21wb25lbnQuY29udGV4dC5vcHRpb25zLmFsbERheU1haW50YWluRHVyYXRpb247XG4gICAgICAgIGlmIChkYXRlU3BhbjEuYWxsRGF5KSB7XG4gICAgICAgICAgICAvLyBtZWFucyBkYXRlMSBpcyBhbHJlYWR5IHN0YXJ0LW9mLWRheSxcbiAgICAgICAgICAgIC8vIGJ1dCBkYXRlMCBuZWVkcyB0byBiZSBjb252ZXJ0ZWRcbiAgICAgICAgICAgIGRhdGUwID0gc3RhcnRPZkRheShkYXRlMCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIGRlbHRhID0gZGlmZkRhdGVzKGRhdGUwLCBkYXRlMSwgaGl0MC5jb21wb25lbnQuY29udGV4dC5kYXRlRW52LCBoaXQwLmNvbXBvbmVudCA9PT0gaGl0MS5jb21wb25lbnQgP1xuICAgICAgICBoaXQwLmNvbXBvbmVudC5sYXJnZVVuaXQgOlxuICAgICAgICBudWxsKTtcbiAgICBpZiAoZGVsdGEubWlsbGlzZWNvbmRzKSB7IC8vIGhhcyBob3Vycy9taW51dGVzL3NlY29uZHNcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5hbGxEYXkgPSBmYWxzZTtcbiAgICB9XG4gICAgdmFyIG11dGF0aW9uID0ge1xuICAgICAgICBkYXRlc0RlbHRhOiBkZWx0YSxcbiAgICAgICAgc3RhbmRhcmRQcm9wczogc3RhbmRhcmRQcm9wc1xuICAgIH07XG4gICAgZm9yICh2YXIgX2kgPSAwLCBtYXNzYWdlcnNfMSA9IG1hc3NhZ2VyczsgX2kgPCBtYXNzYWdlcnNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIG1hc3NhZ2VyID0gbWFzc2FnZXJzXzFbX2ldO1xuICAgICAgICBtYXNzYWdlcihtdXRhdGlvbiwgaGl0MCwgaGl0MSk7XG4gICAgfVxuICAgIHJldHVybiBtdXRhdGlvbjtcbn1cbmZ1bmN0aW9uIGdldENvbXBvbmVudFRvdWNoRGVsYXkkMShjb21wb25lbnQpIHtcbiAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgdmFyIGRlbGF5ID0gb3B0aW9ucy5ldmVudExvbmdQcmVzc0RlbGF5O1xuICAgIGlmIChkZWxheSA9PSBudWxsKSB7XG4gICAgICAgIGRlbGF5ID0gb3B0aW9ucy5sb25nUHJlc3NEZWxheTtcbiAgICB9XG4gICAgcmV0dXJuIGRlbGF5O1xufVxuXG52YXIgRXZlbnREcmFnZ2luZyQxID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhFdmVudERyYWdnaW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEV2ZW50RHJhZ2dpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIC8vIGludGVybmFsIHN0YXRlXG4gICAgICAgIF90aGlzLmRyYWdnaW5nU2VnID0gbnVsbDsgLy8gVE9ETzogcmVuYW1lIHRvIHJlc2l6aW5nU2VnPyBzdWJqZWN0U2VnP1xuICAgICAgICBfdGhpcy5ldmVudFJhbmdlID0gbnVsbDtcbiAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICBfdGhpcy52YWxpZE11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnQgPSBfdGhpcy5jb21wb25lbnQ7XG4gICAgICAgICAgICB2YXIgc2VnID0gX3RoaXMucXVlcnlTZWcoZXYpO1xuICAgICAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBfdGhpcy5ldmVudFJhbmdlID0gc2VnLmV2ZW50UmFuZ2U7XG4gICAgICAgICAgICBfdGhpcy5kcmFnZ2luZy5taW5EaXN0YW5jZSA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnMuZXZlbnREcmFnTWluRGlzdGFuY2U7XG4gICAgICAgICAgICAvLyBpZiB0b3VjaCwgbmVlZCB0byBiZSB3b3JraW5nIHdpdGggYSBzZWxlY3RlZCBldmVudFxuICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmcuc2V0SWdub3JlTW92ZSghX3RoaXMuY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwoZXYub3JpZ0V2ZW50LnRhcmdldCkgfHxcbiAgICAgICAgICAgICAgICAoZXYuaXNUb3VjaCAmJiBfdGhpcy5jb21wb25lbnQucHJvcHMuZXZlbnRTZWxlY3Rpb24gIT09IGV2ZW50UmFuZ2UuaW5zdGFuY2UuaW5zdGFuY2VJZCkpO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVEcmFnU3RhcnQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLmNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gX3RoaXMuZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIF90aGlzLnJlbGV2YW50RXZlbnRzID0gZ2V0UmVsZXZhbnRFdmVudHMoY2FsZW5kYXIuc3RhdGUuZXZlbnRTdG9yZSwgX3RoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkKTtcbiAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nU2VnID0gX3RoaXMucXVlcnlTZWcoZXYpO1xuICAgICAgICAgICAgY2FsZW5kYXIudW5zZWxlY3QoKTtcbiAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZXNpemVTdGFydCcsIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGVsOiBfdGhpcy5kcmFnZ2luZ1NlZy5lbCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IG5ldyBFdmVudEFwaShjYWxlbmRhciwgZXZlbnRSYW5nZS5kZWYsIGV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlSGl0VXBkYXRlID0gZnVuY3Rpb24gKGhpdCwgaXNGaW5hbCwgZXYpIHtcbiAgICAgICAgICAgIHZhciBjYWxlbmRhciA9IF90aGlzLmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgdmFyIHJlbGV2YW50RXZlbnRzID0gX3RoaXMucmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbEhpdCA9IF90aGlzLmhpdERyYWdnaW5nLmluaXRpYWxIaXQ7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZSA9IF90aGlzLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgICAgICB2YXIgbXV0YXRpb24gPSBudWxsO1xuICAgICAgICAgICAgdmFyIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgICAgICB2YXIgaXNJbnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgaW50ZXJhY3Rpb24gPSB7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IHJlbGV2YW50RXZlbnRzLFxuICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IHRydWUsXG4gICAgICAgICAgICAgICAgb3JpZ1NlZzogX3RoaXMuZHJhZ2dpbmdTZWdcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoaGl0KSB7XG4gICAgICAgICAgICAgICAgbXV0YXRpb24gPSBjb21wdXRlTXV0YXRpb24oaW5pdGlhbEhpdCwgaGl0LCBldi5zdWJqZWN0RWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYy1zdGFydC1yZXNpemVyJyksIGV2ZW50SW5zdGFuY2UucmFuZ2UsIGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtdXRhdGlvbikge1xuICAgICAgICAgICAgICAgIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IGFwcGx5TXV0YXRpb25Ub0V2ZW50U3RvcmUocmVsZXZhbnRFdmVudHMsIGNhbGVuZGFyLmV2ZW50VWlCYXNlcywgbXV0YXRpb24sIGNhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzID0gbXV0YXRlZFJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29tcG9uZW50LmlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRpb24gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobXV0YXRlZFJlbGV2YW50RXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX0VWRU5UX1JFU0laRScsXG4gICAgICAgICAgICAgICAgICAgIHN0YXRlOiBpbnRlcmFjdGlvblxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfUkVTSVpFJyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZW5hYmxlQ3Vyc29yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXNhYmxlQ3Vyc29yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzRmluYWwpIHtcbiAgICAgICAgICAgICAgICBpZiAobXV0YXRpb24gJiYgaXNIaXRzRXF1YWwoaW5pdGlhbEhpdCwgaGl0KSkge1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnZhbGlkTXV0YXRpb24gPSBtdXRhdGlvbjtcbiAgICAgICAgICAgICAgICBfdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBtdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLmNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgICAgIHZhciBldmVudERlZiA9IF90aGlzLmV2ZW50UmFuZ2UuZGVmO1xuICAgICAgICAgICAgdmFyIGV2ZW50SW5zdGFuY2UgPSBfdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICAgICAgdmFyIGV2ZW50QXBpID0gbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBldmVudERlZiwgZXZlbnRJbnN0YW5jZSk7XG4gICAgICAgICAgICB2YXIgcmVsZXZhbnRFdmVudHMgPSBfdGhpcy5yZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIHZhciBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBfdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50UmVzaXplU3RvcCcsIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGVsOiBfdGhpcy5kcmFnZ2luZ1NlZy5lbCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGV2ZW50QXBpLFxuICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIGlmIChfdGhpcy52YWxpZE11dGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogbXV0YXRlZFJlbGV2YW50RXZlbnRzXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlc2l6ZScsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLmRyYWdnaW5nU2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnREZWx0YTogX3RoaXMudmFsaWRNdXRhdGlvbi5zdGFydERlbHRhIHx8IGNyZWF0ZUR1cmF0aW9uKDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kRGVsdGE6IF90aGlzLnZhbGlkTXV0YXRpb24uZW5kRGVsdGEgfHwgY3JlYXRlRHVyYXRpb24oMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2RXZlbnQ6IGV2ZW50QXBpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IG5ldyBFdmVudEFwaSgvLyB0aGUgZGF0YSBBRlRFUiB0aGUgbXV0YXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLCBtdXRhdGVkUmVsZXZhbnRFdmVudHMuZGVmc1tldmVudERlZi5kZWZJZF0sIGV2ZW50SW5zdGFuY2UgPyBtdXRhdGVkUmVsZXZhbnRFdmVudHMuaW5zdGFuY2VzW2V2ZW50SW5zdGFuY2UuaW5zdGFuY2VJZF0gOiBudWxsKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldmVydDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IHJlbGV2YW50RXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYub3JpZ0V2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ19ub0V2ZW50UmVzaXplJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByZXNldCBhbGwgaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nU2VnID0gbnVsbDtcbiAgICAgICAgICAgIF90aGlzLnJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgIF90aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICAgICAgLy8gb2theSB0byBrZWVwIGV2ZW50SW5zdGFuY2UgYXJvdW5kLiB1c2VmdWwgdG8gc2V0IGl0IGluIGhhbmRsZVBvaW50ZXJEb3duXG4gICAgICAgIH07XG4gICAgICAgIHZhciBjb21wb25lbnQgPSBzZXR0aW5ncy5jb21wb25lbnQ7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29tcG9uZW50LmVsKTtcbiAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9ICcuZmMtcmVzaXplcic7XG4gICAgICAgIGRyYWdnaW5nLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICBkcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucy5kcmFnU2Nyb2xsO1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSBfdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyhfdGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCBfdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIF90aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIF90aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdlbmQnLCBfdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBFdmVudERyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRyYWdnaW5nLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLnF1ZXJ5U2VnID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHJldHVybiBnZXRFbFNlZyhlbGVtZW50Q2xvc2VzdChldi5zdWJqZWN0RWwsIHRoaXMuY29tcG9uZW50LmZnU2VnU2VsZWN0b3IpKTtcbiAgICB9O1xuICAgIHJldHVybiBFdmVudERyYWdnaW5nO1xufShJbnRlcmFjdGlvbikpO1xuZnVuY3Rpb24gY29tcHV0ZU11dGF0aW9uKGhpdDAsIGhpdDEsIGlzRnJvbVN0YXJ0LCBpbnN0YW5jZVJhbmdlLCB0cmFuc2Zvcm1zKSB7XG4gICAgdmFyIGRhdGVFbnYgPSBoaXQwLmNvbXBvbmVudC5jb250ZXh0LmRhdGVFbnY7XG4gICAgdmFyIGRhdGUwID0gaGl0MC5kYXRlU3Bhbi5yYW5nZS5zdGFydDtcbiAgICB2YXIgZGF0ZTEgPSBoaXQxLmRhdGVTcGFuLnJhbmdlLnN0YXJ0O1xuICAgIHZhciBkZWx0YSA9IGRpZmZEYXRlcyhkYXRlMCwgZGF0ZTEsIGRhdGVFbnYsIGhpdDAuY29tcG9uZW50LmxhcmdlVW5pdCk7XG4gICAgdmFyIHByb3BzID0ge307XG4gICAgZm9yICh2YXIgX2kgPSAwLCB0cmFuc2Zvcm1zXzEgPSB0cmFuc2Zvcm1zOyBfaSA8IHRyYW5zZm9ybXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRyYW5zZm9ybXNfMVtfaV07XG4gICAgICAgIHZhciByZXMgPSB0cmFuc2Zvcm0oaGl0MCwgaGl0MSk7XG4gICAgICAgIGlmIChyZXMgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZXMpIHtcbiAgICAgICAgICAgIF9fYXNzaWduKHByb3BzLCByZXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChpc0Zyb21TdGFydCkge1xuICAgICAgICBpZiAoZGF0ZUVudi5hZGQoaW5zdGFuY2VSYW5nZS5zdGFydCwgZGVsdGEpIDwgaW5zdGFuY2VSYW5nZS5lbmQpIHtcbiAgICAgICAgICAgIHByb3BzLnN0YXJ0RGVsdGEgPSBkZWx0YTtcbiAgICAgICAgICAgIHJldHVybiBwcm9wcztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYgKGRhdGVFbnYuYWRkKGluc3RhbmNlUmFuZ2UuZW5kLCBkZWx0YSkgPiBpbnN0YW5jZVJhbmdlLnN0YXJ0KSB7XG4gICAgICAgICAgICBwcm9wcy5lbmREZWx0YSA9IGRlbHRhO1xuICAgICAgICAgICAgcmV0dXJuIHByb3BzO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG52YXIgVW5zZWxlY3RBdXRvID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFVuc2VsZWN0QXV0byhjYWxlbmRhcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmlzUmVjZW50UG9pbnRlckRhdGVTZWxlY3QgPSBmYWxzZTsgLy8gd2lzaCB3ZSBjb3VsZCB1c2UgYSBzZWxlY3RvciB0byBkZXRlY3QgZGF0ZSBzZWxlY3Rpb24sIGJ1dCB1c2VzIGhpdCBzeXN0ZW1cbiAgICAgICAgdGhpcy5vblNlbGVjdCA9IGZ1bmN0aW9uIChzZWxlY3RJbmZvKSB7XG4gICAgICAgICAgICBpZiAoc2VsZWN0SW5mby5qc0V2ZW50KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNSZWNlbnRQb2ludGVyRGF0ZVNlbGVjdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMub25Eb2N1bWVudFBvaW50ZXJVcCA9IGZ1bmN0aW9uIChwZXYpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCBkb2N1bWVudFBvaW50ZXIgPSBfYS5kb2N1bWVudFBvaW50ZXI7XG4gICAgICAgICAgICB2YXIgc3RhdGUgPSBjYWxlbmRhci5zdGF0ZTtcbiAgICAgICAgICAgIC8vIHRvdWNoLXNjcm9sbGluZyBzaG91bGQgbmV2ZXIgdW5mb2N1cyBhbnkgdHlwZSBvZiBzZWxlY3Rpb25cbiAgICAgICAgICAgIGlmICghZG9jdW1lbnRQb2ludGVyLndhc1RvdWNoU2Nyb2xsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlLmRhdGVTZWxlY3Rpb24gJiYgLy8gYW4gZXhpc3RpbmcgZGF0ZSBzZWxlY3Rpb24/XG4gICAgICAgICAgICAgICAgICAgICFfdGhpcy5pc1JlY2VudFBvaW50ZXJEYXRlU2VsZWN0IC8vIGEgbmV3IHBvaW50ZXItaW5pdGlhdGVkIGRhdGUgc2VsZWN0aW9uIHNpbmNlIGxhc3Qgb25Eb2N1bWVudFBvaW50ZXJVcD9cbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHVuc2VsZWN0QXV0byA9IGNhbGVuZGFyLnZpZXdPcHQoJ3Vuc2VsZWN0QXV0bycpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdW5zZWxlY3RDYW5jZWwgPSBjYWxlbmRhci52aWV3T3B0KCd1bnNlbGVjdENhbmNlbCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodW5zZWxlY3RBdXRvICYmICghdW5zZWxlY3RBdXRvIHx8ICFlbGVtZW50Q2xvc2VzdChkb2N1bWVudFBvaW50ZXIuZG93bkVsLCB1bnNlbGVjdENhbmNlbCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxlbmRhci51bnNlbGVjdChwZXYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5ldmVudFNlbGVjdGlvbiAmJiAvLyBhbiBleGlzdGluZyBldmVudCBzZWxlY3RlZD9cbiAgICAgICAgICAgICAgICAgICAgIWVsZW1lbnRDbG9zZXN0KGRvY3VtZW50UG9pbnRlci5kb3duRWwsIEV2ZW50RHJhZ2dpbmcuU0VMRUNUT1IpIC8vIGludGVyYWN0aW9uIERJRE4nVCBzdGFydCBvbiBhbiBldmVudFxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9FVkVOVCcgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuaXNSZWNlbnRQb2ludGVyRGF0ZVNlbGVjdCA9IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNhbGVuZGFyID0gY2FsZW5kYXI7XG4gICAgICAgIHZhciBkb2N1bWVudFBvaW50ZXIgPSB0aGlzLmRvY3VtZW50UG9pbnRlciA9IG5ldyBQb2ludGVyRHJhZ2dpbmcoZG9jdW1lbnQpO1xuICAgICAgICBkb2N1bWVudFBvaW50ZXIuc2hvdWxkSWdub3JlTW92ZSA9IHRydWU7XG4gICAgICAgIGRvY3VtZW50UG9pbnRlci5zaG91bGRXYXRjaFNjcm9sbCA9IGZhbHNlO1xuICAgICAgICBkb2N1bWVudFBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcnVwJywgdGhpcy5vbkRvY3VtZW50UG9pbnRlclVwKTtcbiAgICAgICAgLypcbiAgICAgICAgVE9ETzogYmV0dGVyIHdheSB0byBrbm93IGFib3V0IHdoZXRoZXIgdGhlcmUgd2FzIGEgc2VsZWN0aW9uIHdpdGggdGhlIHBvaW50ZXJcbiAgICAgICAgKi9cbiAgICAgICAgY2FsZW5kYXIub24oJ3NlbGVjdCcsIHRoaXMub25TZWxlY3QpO1xuICAgIH1cbiAgICBVbnNlbGVjdEF1dG8ucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXIub2ZmKCdzZWxlY3QnLCB0aGlzLm9uU2VsZWN0KTtcbiAgICAgICAgdGhpcy5kb2N1bWVudFBvaW50ZXIuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIFVuc2VsZWN0QXV0bztcbn0oKSk7XG5cbi8qXG5HaXZlbiBhbiBhbHJlYWR5IGluc3RhbnRpYXRlZCBkcmFnZ2FibGUgb2JqZWN0IGZvciBvbmUtb3ItbW9yZSBlbGVtZW50cyxcbkludGVycHJldHMgYW55IGRyYWdnaW5nIGFzIGFuIGF0dGVtcHQgdG8gZHJhZyBhbiBldmVudHMgdGhhdCBsaXZlcyBvdXRzaWRlXG5vZiBhIGNhbGVuZGFyIG9udG8gYSBjYWxlbmRhci5cbiovXG52YXIgRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcoZHJhZ2dpbmcsIHN1cHBsaWVkRHJhZ01ldGEpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5yZWNlaXZpbmdDYWxlbmRhciA9IG51bGw7XG4gICAgICAgIHRoaXMuZHJvcHBhYmxlRXZlbnQgPSBudWxsOyAvLyB3aWxsIGV4aXN0IGZvciBhbGwgZHJhZ3MsIGV2ZW4gaWYgY3JlYXRlOmZhbHNlXG4gICAgICAgIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9IG51bGw7XG4gICAgICAgIHRoaXMuZHJhZ01ldGEgPSBudWxsO1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuZHJhZ01ldGEgPSBfdGhpcy5idWlsZERyYWdNZXRhKGV2LnN1YmplY3RFbCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlSGl0VXBkYXRlID0gZnVuY3Rpb24gKGhpdCwgaXNGaW5hbCwgZXYpIHtcbiAgICAgICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmhpdERyYWdnaW5nLmRyYWdnaW5nO1xuICAgICAgICAgICAgdmFyIHJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBkcm9wcGFibGVFdmVudCA9IG51bGw7XG4gICAgICAgICAgICB2YXIgaXNJbnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgaW50ZXJhY3Rpb24gPSB7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpLFxuICAgICAgICAgICAgICAgIGlzRXZlbnQ6IF90aGlzLmRyYWdNZXRhLmNyZWF0ZSxcbiAgICAgICAgICAgICAgICBvcmlnU2VnOiBudWxsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGhpdCkge1xuICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyID0gaGl0LmNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jYW5Ecm9wRWxPbkNhbGVuZGFyKGV2LnN1YmplY3RFbCwgcmVjZWl2aW5nQ2FsZW5kYXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyb3BwYWJsZUV2ZW50ID0gY29tcHV0ZUV2ZW50Rm9yRGF0ZVNwYW4oaGl0LmRhdGVTcGFuLCBfdGhpcy5kcmFnTWV0YSwgcmVjZWl2aW5nQ2FsZW5kYXIpO1xuICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzID0gZXZlbnRUdXBsZVRvU3RvcmUoZHJvcHBhYmxlRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSAhaXNJbnRlcmFjdGlvblZhbGlkKGludGVyYWN0aW9uLCByZWNlaXZpbmdDYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0ludmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BwYWJsZUV2ZW50ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmRpc3BsYXlEcmFnKHJlY2VpdmluZ0NhbGVuZGFyLCBpbnRlcmFjdGlvbik7XG4gICAgICAgICAgICAvLyBzaG93IG1pcnJvciBpZiBubyBhbHJlYWR5LXJlbmRlcmVkIG1pcnJvciBlbGVtZW50IE9SIGlmIHdlIGFyZSBzaHV0dGluZyBkb3duIHRoZSBtaXJyb3IgKD8pXG4gICAgICAgICAgICAvLyBUT0RPOiB3aXNoIHdlIGNvdWxkIHNvbWVob3cgd2FpdCBmb3IgZGlzcGF0Y2ggdG8gZ3VhcmFudGVlIHJlbmRlclxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0TWlycm9ySXNWaXNpYmxlKGlzRmluYWwgfHwgIWRyb3BwYWJsZUV2ZW50IHx8ICFkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuZmMtbWlycm9yJykpO1xuICAgICAgICAgICAgaWYgKCFpc0ludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBlbmFibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpc2FibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNGaW5hbCkge1xuICAgICAgICAgICAgICAgIGRyYWdnaW5nLnNldE1pcnJvck5lZWRzUmV2ZXJ0KCFkcm9wcGFibGVFdmVudCk7XG4gICAgICAgICAgICAgICAgX3RoaXMucmVjZWl2aW5nQ2FsZW5kYXIgPSByZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgICAgICAgICBfdGhpcy5kcm9wcGFibGVFdmVudCA9IGRyb3BwYWJsZUV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdFbmQgPSBmdW5jdGlvbiAocGV2KSB7XG4gICAgICAgICAgICB2YXIgX2EgPSBfdGhpcywgcmVjZWl2aW5nQ2FsZW5kYXIgPSBfYS5yZWNlaXZpbmdDYWxlbmRhciwgZHJvcHBhYmxlRXZlbnQgPSBfYS5kcm9wcGFibGVFdmVudDtcbiAgICAgICAgICAgIF90aGlzLmNsZWFyRHJhZygpO1xuICAgICAgICAgICAgaWYgKHJlY2VpdmluZ0NhbGVuZGFyICYmIGRyb3BwYWJsZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIGZpbmFsSGl0ID0gX3RoaXMuaGl0RHJhZ2dpbmcuZmluYWxIaXQ7XG4gICAgICAgICAgICAgICAgdmFyIGZpbmFsVmlldyA9IGZpbmFsSGl0LmNvbXBvbmVudC5jb250ZXh0LnZpZXc7XG4gICAgICAgICAgICAgICAgdmFyIGRyYWdNZXRhID0gX3RoaXMuZHJhZ01ldGE7XG4gICAgICAgICAgICAgICAgdmFyIGFyZyA9IF9fYXNzaWduKHt9LCByZWNlaXZpbmdDYWxlbmRhci5idWlsZERhdGVQb2ludEFwaShmaW5hbEhpdC5kYXRlU3BhbiksIHsgZHJhZ2dlZEVsOiBwZXYuc3ViamVjdEVsLCBqc0V2ZW50OiBwZXYub3JpZ0V2ZW50LCB2aWV3OiBmaW5hbFZpZXcgfSk7XG4gICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdkcm9wJywgW2FyZ10pO1xuICAgICAgICAgICAgICAgIGlmIChkcmFnTWV0YS5jcmVhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFR1cGxlVG9TdG9yZShkcm9wcGFibGVFdmVudClcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwZXYuaXNUb3VjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdTRUxFQ1RfRVZFTlQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50SW5zdGFuY2VJZDogZHJvcHBhYmxlRXZlbnQuaW5zdGFuY2UuaW5zdGFuY2VJZFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gc2lnbmFsIHRoYXQgYW4gZXh0ZXJuYWwgZXZlbnQgbGFuZGVkXG4gICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZWNlaXZlJywgW1xuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRFbDogcGV2LnN1YmplY3RFbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKHJlY2VpdmluZ0NhbGVuZGFyLCBkcm9wcGFibGVFdmVudC5kZWYsIGRyb3BwYWJsZUV2ZW50Lmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiBmaW5hbFZpZXdcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMucmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMuZHJvcHBhYmxlRXZlbnQgPSBudWxsO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSB0aGlzLmhpdERyYWdnaW5nID0gbmV3IEhpdERyYWdnaW5nKGRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUpO1xuICAgICAgICBoaXREcmFnZ2luZy5yZXF1aXJlSW5pdGlhbCA9IGZhbHNlOyAvLyB3aWxsIHN0YXJ0IG91dHNpZGUgb2YgYSBjb21wb25lbnRcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgdGhpcy5oYW5kbGVEcmFnU3RhcnQpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdoaXR1cGRhdGUnLCB0aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdlbmQnLCB0aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICB0aGlzLnN1cHBsaWVkRHJhZ01ldGEgPSBzdXBwbGllZERyYWdNZXRhO1xuICAgIH1cbiAgICBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuYnVpbGREcmFnTWV0YSA9IGZ1bmN0aW9uIChzdWJqZWN0RWwpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnN1cHBsaWVkRHJhZ01ldGEgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VEcmFnTWV0YSh0aGlzLnN1cHBsaWVkRHJhZ01ldGEpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiB0aGlzLnN1cHBsaWVkRHJhZ01ldGEgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZURyYWdNZXRhKHRoaXMuc3VwcGxpZWREcmFnTWV0YShzdWJqZWN0RWwpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBnZXREcmFnTWV0YUZyb21FbChzdWJqZWN0RWwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuZGlzcGxheURyYWcgPSBmdW5jdGlvbiAobmV4dENhbGVuZGFyLCBzdGF0ZSkge1xuICAgICAgICB2YXIgcHJldkNhbGVuZGFyID0gdGhpcy5yZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgaWYgKHByZXZDYWxlbmRhciAmJiBwcmV2Q2FsZW5kYXIgIT09IG5leHRDYWxlbmRhcikge1xuICAgICAgICAgICAgcHJldkNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0Q2FsZW5kYXIpIHtcbiAgICAgICAgICAgIG5leHRDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdTRVRfRVZFTlRfRFJBRycsIHN0YXRlOiBzdGF0ZSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmNsZWFyRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVjZWl2aW5nQ2FsZW5kYXIpIHtcbiAgICAgICAgICAgIHRoaXMucmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfRFJBRycgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV4dGVybmFsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5jYW5Ecm9wRWxPbkNhbGVuZGFyID0gZnVuY3Rpb24gKGVsLCByZWNlaXZpbmdDYWxlbmRhcikge1xuICAgICAgICB2YXIgZHJvcEFjY2VwdCA9IHJlY2VpdmluZ0NhbGVuZGFyLm9wdCgnZHJvcEFjY2VwdCcpO1xuICAgICAgICBpZiAodHlwZW9mIGRyb3BBY2NlcHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBkcm9wQWNjZXB0KGVsKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgZHJvcEFjY2VwdCA9PT0gJ3N0cmluZycgJiYgZHJvcEFjY2VwdCkge1xuICAgICAgICAgICAgcmV0dXJuIEJvb2xlYW4oZWxlbWVudE1hdGNoZXMoZWwsIGRyb3BBY2NlcHQpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIHJldHVybiBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZztcbn0oKSk7XG4vLyBVdGlscyBmb3IgY29tcHV0aW5nIGV2ZW50IHN0b3JlIGZyb20gdGhlIERyYWdNZXRhXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBjb21wdXRlRXZlbnRGb3JEYXRlU3BhbihkYXRlU3BhbiwgZHJhZ01ldGEsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRlZlByb3BzID0gX19hc3NpZ24oe30sIGRyYWdNZXRhLmxlZnRvdmVyUHJvcHMpO1xuICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtID0gX2FbX2ldO1xuICAgICAgICBfX2Fzc2lnbihkZWZQcm9wcywgdHJhbnNmb3JtKGRhdGVTcGFuLCBkcmFnTWV0YSkpO1xuICAgIH1cbiAgICB2YXIgZGVmID0gcGFyc2VFdmVudERlZihkZWZQcm9wcywgZHJhZ01ldGEuc291cmNlSWQsIGRhdGVTcGFuLmFsbERheSwgY2FsZW5kYXIub3B0KCdmb3JjZUV2ZW50RHVyYXRpb24nKSB8fCBCb29sZWFuKGRyYWdNZXRhLmR1cmF0aW9uKSwgLy8gaGFzRW5kXG4gICAgY2FsZW5kYXIpO1xuICAgIHZhciBzdGFydCA9IGRhdGVTcGFuLnJhbmdlLnN0YXJ0O1xuICAgIC8vIG9ubHkgcmVseSBvbiB0aW1lIGluZm8gaWYgZHJvcCB6b25lIGlzIGFsbC1kYXksXG4gICAgLy8gb3RoZXJ3aXNlLCB3ZSBhbHJlYWR5IGtub3cgdGhlIHRpbWVcbiAgICBpZiAoZGF0ZVNwYW4uYWxsRGF5ICYmIGRyYWdNZXRhLnN0YXJ0VGltZSkge1xuICAgICAgICBzdGFydCA9IGNhbGVuZGFyLmRhdGVFbnYuYWRkKHN0YXJ0LCBkcmFnTWV0YS5zdGFydFRpbWUpO1xuICAgIH1cbiAgICB2YXIgZW5kID0gZHJhZ01ldGEuZHVyYXRpb24gP1xuICAgICAgICBjYWxlbmRhci5kYXRlRW52LmFkZChzdGFydCwgZHJhZ01ldGEuZHVyYXRpb24pIDpcbiAgICAgICAgY2FsZW5kYXIuZ2V0RGVmYXVsdEV2ZW50RW5kKGRhdGVTcGFuLmFsbERheSwgc3RhcnQpO1xuICAgIHZhciBpbnN0YW5jZSA9IGNyZWF0ZUV2ZW50SW5zdGFuY2UoZGVmLmRlZklkLCB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfSk7XG4gICAgcmV0dXJuIHsgZGVmOiBkZWYsIGluc3RhbmNlOiBpbnN0YW5jZSB9O1xufVxuLy8gVXRpbHMgZm9yIGV4dHJhY3RpbmcgZGF0YSBmcm9tIGVsZW1lbnRcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGdldERyYWdNZXRhRnJvbUVsKGVsKSB7XG4gICAgdmFyIHN0ciA9IGdldEVtYmVkZGVkRWxEYXRhKGVsLCAnZXZlbnQnKTtcbiAgICB2YXIgb2JqID0gc3RyID9cbiAgICAgICAgSlNPTi5wYXJzZShzdHIpIDpcbiAgICAgICAgeyBjcmVhdGU6IGZhbHNlIH07IC8vIGlmIG5vIGVtYmVkZGVkIGRhdGEsIGFzc3VtZSBubyBldmVudCBjcmVhdGlvblxuICAgIHJldHVybiBwYXJzZURyYWdNZXRhKG9iaik7XG59XG5jb25maWcuZGF0YUF0dHJQcmVmaXggPSAnJztcbmZ1bmN0aW9uIGdldEVtYmVkZGVkRWxEYXRhKGVsLCBuYW1lKSB7XG4gICAgdmFyIHByZWZpeCA9IGNvbmZpZy5kYXRhQXR0clByZWZpeDtcbiAgICB2YXIgcHJlZml4ZWROYW1lID0gKHByZWZpeCA/IHByZWZpeCArICctJyA6ICcnKSArIG5hbWU7XG4gICAgcmV0dXJuIGVsLmdldEF0dHJpYnV0ZSgnZGF0YS0nICsgcHJlZml4ZWROYW1lKSB8fCAnJztcbn1cblxuLypcbk1ha2VzIGFuIGVsZW1lbnQgKHRoYXQgaXMgKmV4dGVybmFsKiB0byBhbnkgY2FsZW5kYXIpIGRyYWdnYWJsZS5cbkNhbiBwYXNzIGluIGRhdGEgdGhhdCBkZXRlcm1pbmVzIGhvdyBhbiBldmVudCB3aWxsIGJlIGNyZWF0ZWQgd2hlbiBkcm9wcGVkIG9udG8gYSBjYWxlbmRhci5cbkxldmVyYWdlcyBGdWxsQ2FsZW5kYXIncyBpbnRlcm5hbCBkcmFnLW4tZHJvcCBmdW5jdGlvbmFsaXR5IFdJVEhPVVQgYSB0aGlyZC1wYXJ0eSBkcmFnIHN5c3RlbS5cbiovXG52YXIgRXh0ZXJuYWxEcmFnZ2FibGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRXh0ZXJuYWxEcmFnZ2FibGUoZWwsIHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChzZXR0aW5ncyA9PT0gdm9pZCAwKSB7IHNldHRpbmdzID0ge307IH1cbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuZHJhZ2dpbmc7XG4gICAgICAgICAgICB2YXIgX2EgPSBfdGhpcy5zZXR0aW5ncywgbWluRGlzdGFuY2UgPSBfYS5taW5EaXN0YW5jZSwgbG9uZ1ByZXNzRGVsYXkgPSBfYS5sb25nUHJlc3NEZWxheTtcbiAgICAgICAgICAgIGRyYWdnaW5nLm1pbkRpc3RhbmNlID1cbiAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSAhPSBudWxsID9cbiAgICAgICAgICAgICAgICAgICAgbWluRGlzdGFuY2UgOlxuICAgICAgICAgICAgICAgICAgICAoZXYuaXNUb3VjaCA/IDAgOiBnbG9iYWxEZWZhdWx0cy5ldmVudERyYWdNaW5EaXN0YW5jZSk7XG4gICAgICAgICAgICBkcmFnZ2luZy5kZWxheSA9XG4gICAgICAgICAgICAgICAgZXYuaXNUb3VjaCA/IC8vIFRPRE86IGV2ZW50dWFsbHkgcmVhZCBldmVudExvbmdQcmVzc0RlbGF5IGluc3RlYWQgdnZ2XG4gICAgICAgICAgICAgICAgICAgIChsb25nUHJlc3NEZWxheSAhPSBudWxsID8gbG9uZ1ByZXNzRGVsYXkgOiBnbG9iYWxEZWZhdWx0cy5sb25nUHJlc3NEZWxheSkgOlxuICAgICAgICAgICAgICAgICAgICAwO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKGV2LmlzVG91Y2ggJiZcbiAgICAgICAgICAgICAgICBfdGhpcy5kcmFnZ2luZy5kZWxheSAmJlxuICAgICAgICAgICAgICAgIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLWV2ZW50JykpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kcmFnZ2luZy5taXJyb3IuZ2V0TWlycm9yRWwoKS5jbGFzc0xpc3QuYWRkKCdmYy1zZWxlY3RlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IHRoaXMuZHJhZ2dpbmcgPSBuZXcgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhlbCk7XG4gICAgICAgIGRyYWdnaW5nLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoc2V0dGluZ3MuaXRlbVNlbGVjdG9yICE9IG51bGwpIHtcbiAgICAgICAgICAgIGRyYWdnaW5nLnBvaW50ZXIuc2VsZWN0b3IgPSBzZXR0aW5ncy5pdGVtU2VsZWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldHRpbmdzLmFwcGVuZFRvICE9IG51bGwpIHtcbiAgICAgICAgICAgIGRyYWdnaW5nLm1pcnJvci5wYXJlbnROb2RlID0gc2V0dGluZ3MuYXBwZW5kVG87IC8vIFRPRE86IHdyaXRlIHRlc3RzXG4gICAgICAgIH1cbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgdGhpcy5oYW5kbGVEcmFnU3RhcnQpO1xuICAgICAgICBuZXcgRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcoZHJhZ2dpbmcsIHNldHRpbmdzLmV2ZW50RGF0YSk7XG4gICAgfVxuICAgIEV4dGVybmFsRHJhZ2dhYmxlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRyYWdnaW5nLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIHJldHVybiBFeHRlcm5hbERyYWdnYWJsZTtcbn0oKSk7XG5cbi8qXG5EZXRlY3RzIHdoZW4gYSAqVEhJUkQtUEFSVFkqIGRyYWctbi1kcm9wIHN5c3RlbSBpbnRlcmFjdHMgd2l0aCBlbGVtZW50cy5cblRoZSB0aGlyZC1wYXJ0eSBzeXN0ZW0gaXMgcmVzcG9uc2libGUgZm9yIGRyYXdpbmcgdGhlIHZpc3VhbHMgZWZmZWN0cyBvZiB0aGUgZHJhZy5cblRoaXMgY2xhc3Mgc2ltcGx5IG1vbml0b3JzIGZvciBwb2ludGVyIG1vdmVtZW50cyBhbmQgZmlyZXMgZXZlbnRzLlxuSXQgYWxzbyBoYXMgdGhlIGFiaWxpdHkgdG8gaGlkZSB0aGUgbW92aW5nIGVsZW1lbnQgKHRoZSBcIm1pcnJvclwiKSBkdXJpbmcgdGhlIGRyYWcuXG4qL1xudmFyIEluZmVycmVkRWxlbWVudERyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhJbmZlcnJlZEVsZW1lbnREcmFnZ2luZywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBJbmZlcnJlZEVsZW1lbnREcmFnZ2luZyhjb250YWluZXJFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjb250YWluZXJFbCkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc2hvdWxkSWdub3JlTW92ZSA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5taXJyb3JTZWxlY3RvciA9ICcnO1xuICAgICAgICBfdGhpcy5jdXJyZW50TWlycm9yRWwgPSBudWxsO1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIGV2KTtcbiAgICAgICAgICAgIGlmICghX3RoaXMuc2hvdWxkSWdub3JlTW92ZSkge1xuICAgICAgICAgICAgICAgIC8vIGZpcmUgZHJhZ3N0YXJ0IHJpZ2h0IGF3YXkuIGRvZXMgbm90IHN1cHBvcnQgZGVsYXkgb3IgbWluLWRpc3RhbmNlXG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnc3RhcnQnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJNb3ZlID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdtb3ZlJywgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyVXAgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgZXYpO1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgLy8gZmlyZSBkcmFnZW5kIHJpZ2h0IGF3YXkuIGRvZXMgbm90IHN1cHBvcnQgYSByZXZlcnQgYW5pbWF0aW9uXG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnZW5kJywgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgcG9pbnRlciA9IF90aGlzLnBvaW50ZXIgPSBuZXcgUG9pbnRlckRyYWdnaW5nKGNvbnRhaW5lckVsKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVybW92ZScsIF90aGlzLmhhbmRsZVBvaW50ZXJNb3ZlKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVydXAnLCBfdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEluZmVycmVkRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBvaW50ZXIuZGVzdHJveSgpO1xuICAgIH07XG4gICAgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldElnbm9yZU1vdmUgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLnNob3VsZElnbm9yZU1vdmUgPSBib29sO1xuICAgIH07XG4gICAgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldE1pcnJvcklzVmlzaWJsZSA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIGlmIChib29sKSB7XG4gICAgICAgICAgICAvLyByZXN0b3JlIGEgcHJldmlvdXNseSBoaWRkZW4gZWxlbWVudC5cbiAgICAgICAgICAgIC8vIHVzZSB0aGUgcmVmZXJlbmNlIGluIGNhc2UgdGhlIHNlbGVjdG9yIGNsYXNzIGhhcyBhbHJlYWR5IGJlZW4gcmVtb3ZlZC5cbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRNaXJyb3JFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudE1pcnJvckVsLnN0eWxlLnZpc2liaWxpdHkgPSAnJztcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgbWlycm9yRWwgPSB0aGlzLm1pcnJvclNlbGVjdG9yID9cbiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMubWlycm9yU2VsZWN0b3IpIDpcbiAgICAgICAgICAgICAgICBudWxsO1xuICAgICAgICAgICAgaWYgKG1pcnJvckVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TWlycm9yRWwgPSBtaXJyb3JFbDtcbiAgICAgICAgICAgICAgICBtaXJyb3JFbC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBJbmZlcnJlZEVsZW1lbnREcmFnZ2luZztcbn0oRWxlbWVudERyYWdnaW5nKSk7XG5cbi8qXG5CcmlkZ2VzIHRoaXJkLXBhcnR5IGRyYWctbi1kcm9wIHN5c3RlbXMgd2l0aCBGdWxsQ2FsZW5kYXIuXG5NdXN0IGJlIGluc3RhbnRpYXRlZCBhbmQgZGVzdHJveWVkIGJ5IGNhbGxlci5cbiovXG52YXIgVGhpcmRQYXJ0eURyYWdnYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUaGlyZFBhcnR5RHJhZ2dhYmxlKGNvbnRhaW5lck9yU2V0dGluZ3MsIHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBjb250YWluZXJFbCA9IGRvY3VtZW50O1xuICAgICAgICBpZiAoXG4gICAgICAgIC8vIHdpc2ggd2UgY291bGQganVzdCB0ZXN0IGluc3RhbmNlb2YgRXZlbnRUYXJnZXQsIGJ1dCBkb2Vzbid0IHdvcmsgaW4gSUUxMVxuICAgICAgICBjb250YWluZXJPclNldHRpbmdzID09PSBkb2N1bWVudCB8fFxuICAgICAgICAgICAgY29udGFpbmVyT3JTZXR0aW5ncyBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lckVsID0gY29udGFpbmVyT3JTZXR0aW5ncztcbiAgICAgICAgICAgIHNldHRpbmdzID0gc2V0dGluZ3MgfHwge307XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzZXR0aW5ncyA9IChjb250YWluZXJPclNldHRpbmdzIHx8IHt9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZHJhZ2dpbmcgPSB0aGlzLmRyYWdnaW5nID0gbmV3IEluZmVycmVkRWxlbWVudERyYWdnaW5nKGNvbnRhaW5lckVsKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy5pdGVtU2VsZWN0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gc2V0dGluZ3MuaXRlbVNlbGVjdG9yO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbnRhaW5lckVsID09PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9ICdbZGF0YS1ldmVudF0nO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0dGluZ3MubWlycm9yU2VsZWN0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkcmFnZ2luZy5taXJyb3JTZWxlY3RvciA9IHNldHRpbmdzLm1pcnJvclNlbGVjdG9yO1xuICAgICAgICB9XG4gICAgICAgIG5ldyBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyhkcmFnZ2luZywgc2V0dGluZ3MuZXZlbnREYXRhKTtcbiAgICB9XG4gICAgVGhpcmRQYXJ0eURyYWdnYWJsZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gVGhpcmRQYXJ0eURyYWdnYWJsZTtcbn0oKSk7XG5cbnZhciBtYWluID0gY3JlYXRlUGx1Z2luKHtcbiAgICBjb21wb25lbnRJbnRlcmFjdGlvbnM6IFtEYXRlQ2xpY2tpbmcsIERhdGVTZWxlY3RpbmcsIEV2ZW50RHJhZ2dpbmcsIEV2ZW50RHJhZ2dpbmckMV0sXG4gICAgY2FsZW5kYXJJbnRlcmFjdGlvbnM6IFtVbnNlbGVjdEF1dG9dLFxuICAgIGVsZW1lbnREcmFnZ2luZ0ltcGw6IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmdcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBtYWluO1xuZXhwb3J0IHsgRXh0ZXJuYWxEcmFnZ2FibGUgYXMgRHJhZ2dhYmxlLCBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLCBQb2ludGVyRHJhZ2dpbmcsIFRoaXJkUGFydHlEcmFnZ2FibGUgfTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1vYmplY3QnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKCFpc09iamVjdChpdCkpIHtcbiAgICB0aHJvdyBUeXBlRXJyb3IoU3RyaW5nKGl0KSArICcgaXMgbm90IGFuIG9iamVjdCcpO1xuICB9IHJldHVybiBpdDtcbn07XG4iLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoaXQpLnNsaWNlKDgsIC0xKTtcbn07XG4iLCJ2YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydCcpO1xudmFyIGNsYXNzb2ZSYXcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcbnZhciB3ZWxsS25vd25TeW1ib2wgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvd2VsbC1rbm93bi1zeW1ib2wnKTtcblxudmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7XG4vLyBFUzMgd3JvbmcgaGVyZVxudmFyIENPUlJFQ1RfQVJHVU1FTlRTID0gY2xhc3NvZlJhdyhmdW5jdGlvbiAoKSB7IHJldHVybiBhcmd1bWVudHM7IH0oKSkgPT0gJ0FyZ3VtZW50cyc7XG5cbi8vIGZhbGxiYWNrIGZvciBJRTExIFNjcmlwdCBBY2Nlc3MgRGVuaWVkIGVycm9yXG52YXIgdHJ5R2V0ID0gZnVuY3Rpb24gKGl0LCBrZXkpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gaXRba2V5XTtcbiAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxufTtcblxuLy8gZ2V0dGluZyB0YWcgZnJvbSBFUzYrIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYFxubW9kdWxlLmV4cG9ydHMgPSBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPyBjbGFzc29mUmF3IDogZnVuY3Rpb24gKGl0KSB7XG4gIHZhciBPLCB0YWcsIHJlc3VsdDtcbiAgcmV0dXJuIGl0ID09PSB1bmRlZmluZWQgPyAnVW5kZWZpbmVkJyA6IGl0ID09PSBudWxsID8gJ051bGwnXG4gICAgLy8gQEB0b1N0cmluZ1RhZyBjYXNlXG4gICAgOiB0eXBlb2YgKHRhZyA9IHRyeUdldChPID0gT2JqZWN0KGl0KSwgVE9fU1RSSU5HX1RBRykpID09ICdzdHJpbmcnID8gdGFnXG4gICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgOiBDT1JSRUNUX0FSR1VNRU5UUyA/IGNsYXNzb2ZSYXcoTylcbiAgICAvLyBFUzMgYXJndW1lbnRzIGZhbGxiYWNrXG4gICAgOiAocmVzdWx0ID0gY2xhc3NvZlJhdyhPKSkgPT0gJ09iamVjdCcgJiYgdHlwZW9mIE8uY2FsbGVlID09ICdmdW5jdGlvbicgPyAnQXJndW1lbnRzJyA6IHJlc3VsdDtcbn07XG4iLCJ2YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtZGVmaW5lLXByb3BlcnR5Jyk7XG52YXIgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NyZWF0ZS1wcm9wZXJ0eS1kZXNjcmlwdG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gREVTQ1JJUFRPUlMgPyBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIHJldHVybiBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKG9iamVjdCwga2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgdmFsdWUpKTtcbn0gOiBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIG9iamVjdFtrZXldID0gdmFsdWU7XG4gIHJldHVybiBvYmplY3Q7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYml0bWFwLCB2YWx1ZSkge1xuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGU6ICEoYml0bWFwICYgMSksXG4gICAgY29uZmlndXJhYmxlOiAhKGJpdG1hcCAmIDIpLFxuICAgIHdyaXRhYmxlOiAhKGJpdG1hcCAmIDQpLFxuICAgIHZhbHVlOiB2YWx1ZVxuICB9O1xufTtcbiIsInZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xuXG4vLyBUaGFuaydzIElFOCBmb3IgaGlzIGZ1bm55IGRlZmluZVByb3BlcnR5XG5tb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pWzFdICE9IDc7XG59KTtcbiIsInZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtb2JqZWN0Jyk7XG5cbnZhciBkb2N1bWVudCA9IGdsb2JhbC5kb2N1bWVudDtcbi8vIHR5cGVvZiBkb2N1bWVudC5jcmVhdGVFbGVtZW50IGlzICdvYmplY3QnIGluIG9sZCBJRVxudmFyIEVYSVNUUyA9IGlzT2JqZWN0KGRvY3VtZW50KSAmJiBpc09iamVjdChkb2N1bWVudC5jcmVhdGVFbGVtZW50KTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIEVYSVNUUyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoaXQpIDoge307XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYykge1xuICB0cnkge1xuICAgIHJldHVybiAhIWV4ZWMoKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcbiIsInZhciBjaGVjayA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaXQgJiYgaXQuTWF0aCA9PSBNYXRoICYmIGl0O1xufTtcblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzg2I2lzc3VlY29tbWVudC0xMTU3NTkwMjhcbm1vZHVsZS5leHBvcnRzID1cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVmXG4gIGNoZWNrKHR5cGVvZiBnbG9iYWxUaGlzID09ICdvYmplY3QnICYmIGdsb2JhbFRoaXMpIHx8XG4gIGNoZWNrKHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgd2luZG93KSB8fFxuICBjaGVjayh0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmKSB8fFxuICBjaGVjayh0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCkgfHxcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jXG4gIEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG4iLCJ2YXIgaGFzT3duUHJvcGVydHkgPSB7fS5oYXNPd25Qcm9wZXJ0eTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIGtleSkge1xuICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChpdCwga2V5KTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHt9O1xuIiwidmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2RvY3VtZW50LWNyZWF0ZS1lbGVtZW50Jyk7XG5cbi8vIFRoYW5rJ3MgSUU4IGZvciBoaXMgZnVubnkgZGVmaW5lUHJvcGVydHlcbm1vZHVsZS5leHBvcnRzID0gIURFU0NSSVBUT1JTICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3JlYXRlRWxlbWVudCgnZGl2JyksICdhJywge1xuICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfVxuICB9KS5hICE9IDc7XG59KTtcbiIsInZhciBzdG9yZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQtc3RvcmUnKTtcblxudmFyIGZ1bmN0aW9uVG9TdHJpbmcgPSBGdW5jdGlvbi50b1N0cmluZztcblxuLy8gdGhpcyBoZWxwZXIgYnJva2VuIGluIGAzLjQuMS0zLjQuNGAsIHNvIHdlIGNhbid0IHVzZSBgc2hhcmVkYCBoZWxwZXJcbmlmICh0eXBlb2Ygc3RvcmUuaW5zcGVjdFNvdXJjZSAhPSAnZnVuY3Rpb24nKSB7XG4gIHN0b3JlLmluc3BlY3RTb3VyY2UgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb25Ub1N0cmluZy5jYWxsKGl0KTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdG9yZS5pbnNwZWN0U291cmNlO1xuIiwidmFyIE5BVElWRV9XRUFLX01BUCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9uYXRpdmUtd2Vhay1tYXAnKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtb2JqZWN0Jyk7XG52YXIgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NyZWF0ZS1ub24tZW51bWVyYWJsZS1wcm9wZXJ0eScpO1xudmFyIG9iamVjdEhhcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9oYXMnKTtcbnZhciBzaGFyZWRLZXkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvc2hhcmVkLWtleScpO1xudmFyIGhpZGRlbktleXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGlkZGVuLWtleXMnKTtcblxudmFyIFdlYWtNYXAgPSBnbG9iYWwuV2Vha01hcDtcbnZhciBzZXQsIGdldCwgaGFzO1xuXG52YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaGFzKGl0KSA/IGdldChpdCkgOiBzZXQoaXQsIHt9KTtcbn07XG5cbnZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkge1xuICByZXR1cm4gZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIHN0YXRlO1xuICAgIGlmICghaXNPYmplY3QoaXQpIHx8IChzdGF0ZSA9IGdldChpdCkpLnR5cGUgIT09IFRZUEUpIHtcbiAgICAgIHRocm93IFR5cGVFcnJvcignSW5jb21wYXRpYmxlIHJlY2VpdmVyLCAnICsgVFlQRSArICcgcmVxdWlyZWQnKTtcbiAgICB9IHJldHVybiBzdGF0ZTtcbiAgfTtcbn07XG5cbmlmIChOQVRJVkVfV0VBS19NQVApIHtcbiAgdmFyIHN0b3JlID0gbmV3IFdlYWtNYXAoKTtcbiAgdmFyIHdtZ2V0ID0gc3RvcmUuZ2V0O1xuICB2YXIgd21oYXMgPSBzdG9yZS5oYXM7XG4gIHZhciB3bXNldCA9IHN0b3JlLnNldDtcbiAgc2V0ID0gZnVuY3Rpb24gKGl0LCBtZXRhZGF0YSkge1xuICAgIHdtc2V0LmNhbGwoc3RvcmUsIGl0LCBtZXRhZGF0YSk7XG4gICAgcmV0dXJuIG1ldGFkYXRhO1xuICB9O1xuICBnZXQgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gd21nZXQuY2FsbChzdG9yZSwgaXQpIHx8IHt9O1xuICB9O1xuICBoYXMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gd21oYXMuY2FsbChzdG9yZSwgaXQpO1xuICB9O1xufSBlbHNlIHtcbiAgdmFyIFNUQVRFID0gc2hhcmVkS2V5KCdzdGF0ZScpO1xuICBoaWRkZW5LZXlzW1NUQVRFXSA9IHRydWU7XG4gIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHtcbiAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoaXQsIFNUQVRFLCBtZXRhZGF0YSk7XG4gICAgcmV0dXJuIG1ldGFkYXRhO1xuICB9O1xuICBnZXQgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gb2JqZWN0SGFzKGl0LCBTVEFURSkgPyBpdFtTVEFURV0gOiB7fTtcbiAgfTtcbiAgaGFzID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgcmV0dXJuIG9iamVjdEhhcyhpdCwgU1RBVEUpO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2V0OiBzZXQsXG4gIGdldDogZ2V0LFxuICBoYXM6IGhhcyxcbiAgZW5mb3JjZTogZW5mb3JjZSxcbiAgZ2V0dGVyRm9yOiBnZXR0ZXJGb3Jcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZmFsc2U7XG4iLCJ2YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAhIU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgJiYgIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgLy8gQ2hyb21lIDM4IFN5bWJvbCBoYXMgaW5jb3JyZWN0IHRvU3RyaW5nIGNvbnZlcnNpb25cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVmXG4gIHJldHVybiAhU3RyaW5nKFN5bWJvbCgpKTtcbn0pO1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciBpbnNwZWN0U291cmNlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2luc3BlY3Qtc291cmNlJyk7XG5cbnZhciBXZWFrTWFwID0gZ2xvYmFsLldlYWtNYXA7XG5cbm1vZHVsZS5leHBvcnRzID0gdHlwZW9mIFdlYWtNYXAgPT09ICdmdW5jdGlvbicgJiYgL25hdGl2ZSBjb2RlLy50ZXN0KGluc3BlY3RTb3VyY2UoV2Vha01hcCkpO1xuIiwidmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgSUU4X0RPTV9ERUZJTkUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaWU4LWRvbS1kZWZpbmUnKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcbnZhciB0b1ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1wcmltaXRpdmUnKTtcblxudmFyIG5hdGl2ZURlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xuXG4vLyBgT2JqZWN0LmRlZmluZVByb3BlcnR5YCBtZXRob2Rcbi8vIGh0dHBzOi8vdGMzOS5naXRodWIuaW8vZWNtYTI2Mi8jc2VjLW9iamVjdC5kZWZpbmVwcm9wZXJ0eVxuZXhwb3J0cy5mID0gREVTQ1JJUFRPUlMgPyBuYXRpdmVEZWZpbmVQcm9wZXJ0eSA6IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1ByaW1pdGl2ZShQLCB0cnVlKTtcbiAgYW5PYmplY3QoQXR0cmlidXRlcyk7XG4gIGlmIChJRThfRE9NX0RFRklORSkgdHJ5IHtcbiAgICByZXR1cm4gbmF0aXZlRGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgVHlwZUVycm9yKCdBY2Nlc3NvcnMgbm90IHN1cHBvcnRlZCcpO1xuICBpZiAoJ3ZhbHVlJyBpbiBBdHRyaWJ1dGVzKSBPW1BdID0gQXR0cmlidXRlcy52YWx1ZTtcbiAgcmV0dXJuIE87XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIFRPX1NUUklOR19UQUdfU1VQUE9SVCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1zdHJpbmctdGFnLXN1cHBvcnQnKTtcbnZhciBjbGFzc29mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NsYXNzb2YnKTtcblxuLy8gYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZCBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9lY21hMjYyLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZ1xubW9kdWxlLmV4cG9ydHMgPSBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPyB7fS50b1N0cmluZyA6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICByZXR1cm4gJ1tvYmplY3QgJyArIGNsYXNzb2YodGhpcykgKyAnXSc7XG59O1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY3JlYXRlLW5vbi1lbnVtZXJhYmxlLXByb3BlcnR5Jyk7XG52YXIgaGFzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2hhcycpO1xudmFyIHNldEdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zZXQtZ2xvYmFsJyk7XG52YXIgaW5zcGVjdFNvdXJjZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pbnNwZWN0LXNvdXJjZScpO1xudmFyIEludGVybmFsU3RhdGVNb2R1bGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaW50ZXJuYWwtc3RhdGUnKTtcblxudmFyIGdldEludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLmdldDtcbnZhciBlbmZvcmNlSW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZW5mb3JjZTtcbnZhciBURU1QTEFURSA9IFN0cmluZyhTdHJpbmcpLnNwbGl0KCdTdHJpbmcnKTtcblxuKG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE8sIGtleSwgdmFsdWUsIG9wdGlvbnMpIHtcbiAgdmFyIHVuc2FmZSA9IG9wdGlvbnMgPyAhIW9wdGlvbnMudW5zYWZlIDogZmFsc2U7XG4gIHZhciBzaW1wbGUgPSBvcHRpb25zID8gISFvcHRpb25zLmVudW1lcmFibGUgOiBmYWxzZTtcbiAgdmFyIG5vVGFyZ2V0R2V0ID0gb3B0aW9ucyA/ICEhb3B0aW9ucy5ub1RhcmdldEdldCA6IGZhbHNlO1xuICBpZiAodHlwZW9mIHZhbHVlID09ICdmdW5jdGlvbicpIHtcbiAgICBpZiAodHlwZW9mIGtleSA9PSAnc3RyaW5nJyAmJiAhaGFzKHZhbHVlLCAnbmFtZScpKSBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkodmFsdWUsICduYW1lJywga2V5KTtcbiAgICBlbmZvcmNlSW50ZXJuYWxTdGF0ZSh2YWx1ZSkuc291cmNlID0gVEVNUExBVEUuam9pbih0eXBlb2Yga2V5ID09ICdzdHJpbmcnID8ga2V5IDogJycpO1xuICB9XG4gIGlmIChPID09PSBnbG9iYWwpIHtcbiAgICBpZiAoc2ltcGxlKSBPW2tleV0gPSB2YWx1ZTtcbiAgICBlbHNlIHNldEdsb2JhbChrZXksIHZhbHVlKTtcbiAgICByZXR1cm47XG4gIH0gZWxzZSBpZiAoIXVuc2FmZSkge1xuICAgIGRlbGV0ZSBPW2tleV07XG4gIH0gZWxzZSBpZiAoIW5vVGFyZ2V0R2V0ICYmIE9ba2V5XSkge1xuICAgIHNpbXBsZSA9IHRydWU7XG4gIH1cbiAgaWYgKHNpbXBsZSkgT1trZXldID0gdmFsdWU7XG4gIGVsc2UgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KE8sIGtleSwgdmFsdWUpO1xuLy8gYWRkIGZha2UgRnVuY3Rpb24jdG9TdHJpbmcgZm9yIGNvcnJlY3Qgd29yayB3cmFwcGVkIG1ldGhvZHMgLyBjb25zdHJ1Y3RvcnMgd2l0aCBtZXRob2RzIGxpa2UgTG9EYXNoIGlzTmF0aXZlXG59KShGdW5jdGlvbi5wcm90b3R5cGUsICd0b1N0cmluZycsIGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICByZXR1cm4gdHlwZW9mIHRoaXMgPT0gJ2Z1bmN0aW9uJyAmJiBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpLnNvdXJjZSB8fCBpbnNwZWN0U291cmNlKHRoaXMpO1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYW4tb2JqZWN0Jyk7XG5cbi8vIGBSZWdFeHAucHJvdG90eXBlLmZsYWdzYCBnZXR0ZXIgaW1wbGVtZW50YXRpb25cbi8vIGh0dHBzOi8vdGMzOS5naXRodWIuaW8vZWNtYTI2Mi8jc2VjLWdldC1yZWdleHAucHJvdG90eXBlLmZsYWdzXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHRoYXQgPSBhbk9iamVjdCh0aGlzKTtcbiAgdmFyIHJlc3VsdCA9ICcnO1xuICBpZiAodGhhdC5nbG9iYWwpIHJlc3VsdCArPSAnZyc7XG4gIGlmICh0aGF0Lmlnbm9yZUNhc2UpIHJlc3VsdCArPSAnaSc7XG4gIGlmICh0aGF0Lm11bHRpbGluZSkgcmVzdWx0ICs9ICdtJztcbiAgaWYgKHRoYXQuZG90QWxsKSByZXN1bHQgKz0gJ3MnO1xuICBpZiAodGhhdC51bmljb2RlKSByZXN1bHQgKz0gJ3UnO1xuICBpZiAodGhhdC5zdGlja3kpIHJlc3VsdCArPSAneSc7XG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY3JlYXRlLW5vbi1lbnVtZXJhYmxlLXByb3BlcnR5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgdHJ5IHtcbiAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoZ2xvYmFsLCBrZXksIHZhbHVlKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBnbG9iYWxba2V5XSA9IHZhbHVlO1xuICB9IHJldHVybiB2YWx1ZTtcbn07XG4iLCJ2YXIgc2hhcmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NoYXJlZCcpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91aWQnKTtcblxudmFyIGtleXMgPSBzaGFyZWQoJ2tleXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiBrZXlzW2tleV0gfHwgKGtleXNba2V5XSA9IHVpZChrZXkpKTtcbn07XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHNldEdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zZXQtZ2xvYmFsJyk7XG5cbnZhciBTSEFSRUQgPSAnX19jb3JlLWpzX3NoYXJlZF9fJztcbnZhciBzdG9yZSA9IGdsb2JhbFtTSEFSRURdIHx8IHNldEdsb2JhbChTSEFSRUQsIHt9KTtcblxubW9kdWxlLmV4cG9ydHMgPSBzdG9yZTtcbiIsInZhciBJU19QVVJFID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLXB1cmUnKTtcbnZhciBzdG9yZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQtc3RvcmUnKTtcblxuKG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgcmV0dXJuIHN0b3JlW2tleV0gfHwgKHN0b3JlW2tleV0gPSB2YWx1ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUgOiB7fSk7XG59KSgndmVyc2lvbnMnLCBbXSkucHVzaCh7XG4gIHZlcnNpb246ICczLjYuNScsXG4gIG1vZGU6IElTX1BVUkUgPyAncHVyZScgOiAnZ2xvYmFsJyxcbiAgY29weXJpZ2h0OiAnwqkgMjAyMCBEZW5pcyBQdXNoa2FyZXYgKHpsb2lyb2NrLnJ1KSdcbn0pO1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW9iamVjdCcpO1xuXG4vLyBgVG9QcmltaXRpdmVgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9lY21hMjYyLyNzZWMtdG9wcmltaXRpdmVcbi8vIGluc3RlYWQgb2YgdGhlIEVTNiBzcGVjIHZlcnNpb24sIHdlIGRpZG4ndCBpbXBsZW1lbnQgQEB0b1ByaW1pdGl2ZSBjYXNlXG4vLyBhbmQgdGhlIHNlY29uZCBhcmd1bWVudCAtIGZsYWcgLSBwcmVmZXJyZWQgdHlwZSBpcyBhIHN0cmluZ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5wdXQsIFBSRUZFUlJFRF9TVFJJTkcpIHtcbiAgaWYgKCFpc09iamVjdChpbnB1dCkpIHJldHVybiBpbnB1dDtcbiAgdmFyIGZuLCB2YWw7XG4gIGlmIChQUkVGRVJSRURfU1RSSU5HICYmIHR5cGVvZiAoZm4gPSBpbnB1dC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpbnB1dCkpKSByZXR1cm4gdmFsO1xuICBpZiAodHlwZW9mIChmbiA9IGlucHV0LnZhbHVlT2YpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKCFQUkVGRVJSRURfU1RSSU5HICYmIHR5cGVvZiAoZm4gPSBpbnB1dC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpbnB1dCkpKSByZXR1cm4gdmFsO1xuICB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWVcIik7XG59O1xuIiwidmFyIHdlbGxLbm93blN5bWJvbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy93ZWxsLWtub3duLXN5bWJvbCcpO1xuXG52YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTtcbnZhciB0ZXN0ID0ge307XG5cbnRlc3RbVE9fU1RSSU5HX1RBR10gPSAneic7XG5cbm1vZHVsZS5leHBvcnRzID0gU3RyaW5nKHRlc3QpID09PSAnW29iamVjdCB6XSc7XG4iLCJ2YXIgaWQgPSAwO1xudmFyIHBvc3RmaXggPSBNYXRoLnJhbmRvbSgpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuICdTeW1ib2woJyArIFN0cmluZyhrZXkgPT09IHVuZGVmaW5lZCA/ICcnIDoga2V5KSArICcpXycgKyAoKytpZCArIHBvc3RmaXgpLnRvU3RyaW5nKDM2KTtcbn07XG4iLCJ2YXIgTkFUSVZFX1NZTUJPTCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9uYXRpdmUtc3ltYm9sJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTkFUSVZFX1NZTUJPTFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgJiYgIVN5bWJvbC5zaGFtXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlZlxuICAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnO1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciBzaGFyZWQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvc2hhcmVkJyk7XG52YXIgaGFzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2hhcycpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91aWQnKTtcbnZhciBOQVRJVkVfU1lNQk9MID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL25hdGl2ZS1zeW1ib2wnKTtcbnZhciBVU0VfU1lNQk9MX0FTX1VJRCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91c2Utc3ltYm9sLWFzLXVpZCcpO1xuXG52YXIgV2VsbEtub3duU3ltYm9sc1N0b3JlID0gc2hhcmVkKCd3a3MnKTtcbnZhciBTeW1ib2wgPSBnbG9iYWwuU3ltYm9sO1xudmFyIGNyZWF0ZVdlbGxLbm93blN5bWJvbCA9IFVTRV9TWU1CT0xfQVNfVUlEID8gU3ltYm9sIDogU3ltYm9sICYmIFN5bWJvbC53aXRob3V0U2V0dGVyIHx8IHVpZDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobmFtZSkge1xuICBpZiAoIWhhcyhXZWxsS25vd25TeW1ib2xzU3RvcmUsIG5hbWUpKSB7XG4gICAgaWYgKE5BVElWRV9TWU1CT0wgJiYgaGFzKFN5bWJvbCwgbmFtZSkpIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXSA9IFN5bWJvbFtuYW1lXTtcbiAgICBlbHNlIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXSA9IGNyZWF0ZVdlbGxLbm93blN5bWJvbCgnU3ltYm9sLicgKyBuYW1lKTtcbiAgfSByZXR1cm4gV2VsbEtub3duU3ltYm9sc1N0b3JlW25hbWVdO1xufTtcbiIsInZhciByZWRlZmluZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWRlZmluZScpO1xuXG52YXIgRGF0ZVByb3RvdHlwZSA9IERhdGUucHJvdG90eXBlO1xudmFyIElOVkFMSURfREFURSA9ICdJbnZhbGlkIERhdGUnO1xudmFyIFRPX1NUUklORyA9ICd0b1N0cmluZyc7XG52YXIgbmF0aXZlRGF0ZVRvU3RyaW5nID0gRGF0ZVByb3RvdHlwZVtUT19TVFJJTkddO1xudmFyIGdldFRpbWUgPSBEYXRlUHJvdG90eXBlLmdldFRpbWU7XG5cbi8vIGBEYXRlLnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL2VjbWEyNjIvI3NlYy1kYXRlLnByb3RvdHlwZS50b3N0cmluZ1xuaWYgKG5ldyBEYXRlKE5hTikgKyAnJyAhPSBJTlZBTElEX0RBVEUpIHtcbiAgcmVkZWZpbmUoRGF0ZVByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICB2YXIgdmFsdWUgPSBnZXRUaW1lLmNhbGwodGhpcyk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZVxuICAgIHJldHVybiB2YWx1ZSA9PT0gdmFsdWUgPyBuYXRpdmVEYXRlVG9TdHJpbmcuY2FsbCh0aGlzKSA6IElOVkFMSURfREFURTtcbiAgfSk7XG59XG4iLCJ2YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydCcpO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZGVmaW5lJyk7XG52YXIgdG9TdHJpbmcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LXRvLXN0cmluZycpO1xuXG4vLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL2VjbWEyNjIvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nXG5pZiAoIVRPX1NUUklOR19UQUdfU1VQUE9SVCkge1xuICByZWRlZmluZShPYmplY3QucHJvdG90eXBlLCAndG9TdHJpbmcnLCB0b1N0cmluZywgeyB1bnNhZmU6IHRydWUgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVkZWZpbmUnKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGZsYWdzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3JlZ2V4cC1mbGFncycpO1xuXG52YXIgVE9fU1RSSU5HID0gJ3RvU3RyaW5nJztcbnZhciBSZWdFeHBQcm90b3R5cGUgPSBSZWdFeHAucHJvdG90eXBlO1xudmFyIG5hdGl2ZVRvU3RyaW5nID0gUmVnRXhwUHJvdG90eXBlW1RPX1NUUklOR107XG5cbnZhciBOT1RfR0VORVJJQyA9IGZhaWxzKGZ1bmN0aW9uICgpIHsgcmV0dXJuIG5hdGl2ZVRvU3RyaW5nLmNhbGwoeyBzb3VyY2U6ICdhJywgZmxhZ3M6ICdiJyB9KSAhPSAnL2EvYic7IH0pO1xuLy8gRkY0NC0gUmVnRXhwI3RvU3RyaW5nIGhhcyBhIHdyb25nIG5hbWVcbnZhciBJTkNPUlJFQ1RfTkFNRSA9IG5hdGl2ZVRvU3RyaW5nLm5hbWUgIT0gVE9fU1RSSU5HO1xuXG4vLyBgUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG5pZiAoTk9UX0dFTkVSSUMgfHwgSU5DT1JSRUNUX05BTUUpIHtcbiAgcmVkZWZpbmUoUmVnRXhwLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICB2YXIgUiA9IGFuT2JqZWN0KHRoaXMpO1xuICAgIHZhciBwID0gU3RyaW5nKFIuc291cmNlKTtcbiAgICB2YXIgcmYgPSBSLmZsYWdzO1xuICAgIHZhciBmID0gU3RyaW5nKHJmID09PSB1bmRlZmluZWQgJiYgUiBpbnN0YW5jZW9mIFJlZ0V4cCAmJiAhKCdmbGFncycgaW4gUmVnRXhwUHJvdG90eXBlKSA/IGZsYWdzLmNhbGwoUikgOiByZik7XG4gICAgcmV0dXJuICcvJyArIHAgKyAnLycgKyBmO1xuICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbn1cbiIsInZhciBnO1xuXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxuZyA9IChmdW5jdGlvbigpIHtcblx0cmV0dXJuIHRoaXM7XG59KSgpO1xuXG50cnkge1xuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcblx0ZyA9IGcgfHwgbmV3IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKTtcbn0gY2F0Y2ggKGUpIHtcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcblx0aWYgKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpIGcgPSB3aW5kb3c7XG59XG5cbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XG5cbm1vZHVsZS5leHBvcnRzID0gZztcbiJdLCJzb3VyY2VSb290IjoiIn0=