(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
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 = { '= 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' } }, '
'); 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 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, '&') .replace(//g, '>') .replace(/'/g, ''') .replace(/"/g, '"') .replace(/\n/g, '
'); } // 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 tag or a non-clickable 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 '' + innerHtml + ''; } else { return '' + innerHtml + ''; } } 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('

 

')); // 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 = ""; buttonAriaAttr = ' aria-label="' + buttonName + '"'; } buttonEl = htmlToElement(// type="button" so that it doesn't submit a form ''); 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
surrounding the more link component.isValidSegDownEl(ev.target)) { // our way to simulate a link click for elements that can't be 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) + '"' : '') + '>'; }; 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 '' + ' 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) + ''; } 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 = '' + parts.join('') + ''; }; 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('
' + '' + '' + '
' + '
')); 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 = '' + Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(timeText) + ''; } } titleHtml = '' + (Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(eventDef.title || '') || ' ') + // we always want one line of height ''; return '
' + '
' + (context.options.dir === 'rtl' ? titleHtml + ' ' + timeHtml : // put a natural space in between timeHtml + ' ' + titleHtml // ) + '
' + (isResizableFromStart ? '
' : '') + (isResizableFromEnd ? '
' : '') + '
'; }; // 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 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 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 elements of the level+col matrix var loneCellMatrix = []; // lookup for 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"])('
'); // 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 = ''; 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"])('
' + '
' + '
'); 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 = '
' + '' + Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(title) + '' + '' + '
' + '
' + '
' + '
'; 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(''); } if (this.context.options.dir === 'rtl') { parts.reverse(); } return '' + parts.join('') + ''; }; 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 ''; } 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 '' + '
' + '
' + '' + bgRow.renderHtml({ cells: this.props.cells[row], dateProfile: this.props.dateProfile, renderIntroHtml: this.renderProps.renderBgIntroHtml }) + '
' + '
' + '
' + '' + (this.getIsNumbersVisible() ? '' + this.renderNumberTrHtml(row) + '' : '') + '
' + '
' + '
'; }; 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 '' + '' + (isRtl ? '' : intro) + this.renderNumberCellsHtml(row) + (isRtl ? intro : '') + ''; }; 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 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 ''; // 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 += ''; 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 += ''; 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 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" links and 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 elements in the row var limitedNodes; // array of temporarily hidden level and segment 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" 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 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 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 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
wrapper around the 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 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 '' + '' + '' + // needed for matchCellWidths Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["htmlEscape"])(options.weekLabel) + '' + ''; } 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 '' + '' + 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 ) + ''; } 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 ''; } 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 ''; } 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 '' + '' + (options.columnHeader ? '' + '' + '' + '' + '' : '') + '' + '' + '' + '' + '' + '
 
'; }; // 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 and // https://github.com/fullcalendar/fullcalendar/issues/3615 function isIgnoredClipping(node) { var tagName = node.tagName; return tagName === 'HTML' || tagName === 'BODY'; } /* Tracks movement over multiple droppable areas (aka "hits") that exist in one or more DateComponents. Relies on an existing draggable. emits: - pointerdown - dragstart - hitchange - fires initially, even if not over a hit - pointerup - (hitchange - again, to null, if ended over a hit) - dragend */ var HitDragging = /** @class */ (function () { function HitDragging(dragging, droppableStore) { var _this = this; // options that can be set by caller this.useSubjectCenter = false; this.requireInitial = true; // if doesn't start out on a hit, won't emit any events this.initialHit = null; this.movingHit = null; this.finalHit = null; // won't ever be populated if shouldIgnoreMove this.handlePointerDown = function (ev) { var dragging = _this.dragging; _this.initialHit = null; _this.movingHit = null; _this.finalHit = null; _this.prepareHits(); _this.processFirstCoord(ev); if (_this.initialHit || !_this.requireInitial) { dragging.setIgnoreMove(false); _this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :( } else { dragging.setIgnoreMove(true); } }; this.handleDragStart = function (ev) { _this.emitter.trigger('dragstart', ev); _this.handleMove(ev, true); // force = fire even if initially null }; this.handleDragMove = function (ev) { _this.emitter.trigger('dragmove', ev); _this.handleMove(ev); }; this.handlePointerUp = function (ev) { _this.releaseHits(); _this.emitter.trigger('pointerup', ev); }; this.handleDragEnd = function (ev) { if (_this.movingHit) { _this.emitter.trigger('hitupdate', null, true, ev); } _this.finalHit = _this.movingHit; _this.movingHit = null; _this.emitter.trigger('dragend', ev); }; this.droppableStore = droppableStore; dragging.emitter.on('pointerdown', this.handlePointerDown); dragging.emitter.on('dragstart', this.handleDragStart); dragging.emitter.on('dragmove', this.handleDragMove); dragging.emitter.on('pointerup', this.handlePointerUp); dragging.emitter.on('dragend', this.handleDragEnd); this.dragging = dragging; this.emitter = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EmitterMixin"](); } // sets initialHit // sets coordAdjust HitDragging.prototype.processFirstCoord = function (ev) { var origPoint = { left: ev.pageX, top: ev.pageY }; var adjustedPoint = origPoint; var subjectEl = ev.subjectEl; var subjectRect; if (subjectEl !== document) { subjectRect = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["computeRect"])(subjectEl); adjustedPoint = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["constrainPoint"])(adjustedPoint, subjectRect); } var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top); if (initialHit) { if (this.useSubjectCenter && subjectRect) { var slicedSubjectRect = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["intersectRects"])(subjectRect, initialHit.rect); if (slicedSubjectRect) { adjustedPoint = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getRectCenter"])(slicedSubjectRect); } } this.coordAdjust = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffPoints"])(adjustedPoint, origPoint); } else { this.coordAdjust = { left: 0, top: 0 }; } }; HitDragging.prototype.handleMove = function (ev, forceHandle) { var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top); if (forceHandle || !isHitsEqual(this.movingHit, hit)) { this.movingHit = hit; this.emitter.trigger('hitupdate', hit, false, ev); } }; HitDragging.prototype.prepareHits = function () { this.offsetTrackers = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["mapHash"])(this.droppableStore, function (interactionSettings) { interactionSettings.component.buildPositionCaches(); return new OffsetTracker(interactionSettings.el); }); }; HitDragging.prototype.releaseHits = function () { var offsetTrackers = this.offsetTrackers; for (var id in offsetTrackers) { offsetTrackers[id].destroy(); } this.offsetTrackers = {}; }; HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) { var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers; var bestHit = null; for (var id in droppableStore) { var component = droppableStore[id].component; var offsetTracker = offsetTrackers[id]; if (offsetTracker.isWithinClipping(offsetLeft, offsetTop)) { var originLeft = offsetTracker.computeLeft(); var originTop = offsetTracker.computeTop(); var positionLeft = offsetLeft - originLeft; var positionTop = offsetTop - originTop; var origRect = offsetTracker.origRect; var width = origRect.right - origRect.left; var height = origRect.bottom - origRect.top; if ( // must be within the element's bounds positionLeft >= 0 && positionLeft < width && positionTop >= 0 && positionTop < height) { var hit = component.queryHit(positionLeft, positionTop, width, height); if (hit && ( // make sure the hit is within activeRange, meaning it's not a deal cell !component.props.dateProfile || // hack for DayTile Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["rangeContainsRange"])(component.props.dateProfile.activeRange, hit.dateSpan.range)) && (!bestHit || hit.layer > bestHit.layer)) { // TODO: better way to re-orient rectangle hit.rect.left += originLeft; hit.rect.right += originLeft; hit.rect.top += originTop; hit.rect.bottom += originTop; bestHit = hit; } } } } return bestHit; }; return HitDragging; }()); function isHitsEqual(hit0, hit1) { if (!hit0 && !hit1) { return true; } if (Boolean(hit0) !== Boolean(hit1)) { return false; } return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["isDateSpansEqual"])(hit0.dateSpan, hit1.dateSpan); } /* Monitors when the user clicks on a specific date/time of a component. A pointerdown+pointerup on the same "hit" constitutes a click. */ var DateClicking = /** @class */ (function (_super) { __extends(DateClicking, _super); function DateClicking(settings) { var _this = _super.call(this, settings) || this; _this.handlePointerDown = function (ev) { var dragging = _this.dragging; // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired dragging.setIgnoreMove(!_this.component.isValidDateDownEl(dragging.pointer.downEl)); }; // won't even fire if moving was ignored _this.handleDragEnd = function (ev) { var component = _this.component; var _a = component.context, calendar = _a.calendar, view = _a.view; var pointer = _this.dragging.pointer; if (!pointer.wasTouchScroll) { var _b = _this.hitDragging, initialHit = _b.initialHit, finalHit = _b.finalHit; if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) { calendar.triggerDateClick(initialHit.dateSpan, initialHit.dayEl, view, ev.origEvent); } } }; var component = settings.component; // we DO want to watch pointer moves because otherwise finalHit won't get populated _this.dragging = new FeaturefulElementDragging(component.el); _this.dragging.autoScroller.isEnabled = false; var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsToStore"])(settings)); hitDragging.emitter.on('pointerdown', _this.handlePointerDown); hitDragging.emitter.on('dragend', _this.handleDragEnd); return _this; } DateClicking.prototype.destroy = function () { this.dragging.destroy(); }; return DateClicking; }(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"])); /* Tracks when the user selects a portion of time of a component, constituted by a drag over date cells, with a possible delay at the beginning of the drag. */ var DateSelecting = /** @class */ (function (_super) { __extends(DateSelecting, _super); function DateSelecting(settings) { var _this = _super.call(this, settings) || this; _this.dragSelection = null; _this.handlePointerDown = function (ev) { var _a = _this, component = _a.component, dragging = _a.dragging; var options = component.context.options; var canSelect = options.selectable && component.isValidDateDownEl(ev.origEvent.target); // don't bother to watch expensive moves if component won't do selection dragging.setIgnoreMove(!canSelect); // if touch, require user to hold down dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null; }; _this.handleDragStart = function (ev) { _this.component.context.calendar.unselect(ev); // unselect previous selections }; _this.handleHitUpdate = function (hit, isFinal) { var calendar = _this.component.context.calendar; var dragSelection = null; var isInvalid = false; if (hit) { dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, calendar.pluginSystem.hooks.dateSelectionTransformers); if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) { isInvalid = true; dragSelection = null; } } if (dragSelection) { calendar.dispatch({ type: 'SELECT_DATES', selection: dragSelection }); } else if (!isFinal) { // only unselect if moved away while dragging calendar.dispatch({ type: 'UNSELECT_DATES' }); } if (!isInvalid) { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])(); } else { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])(); } if (!isFinal) { _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging } }; _this.handlePointerUp = function (pev) { if (_this.dragSelection) { // selection is already rendered, so just need to report selection _this.component.context.calendar.triggerDateSelect(_this.dragSelection, pev); _this.dragSelection = null; } }; var component = settings.component; var options = component.context.options; var dragging = _this.dragging = new FeaturefulElementDragging(component.el); dragging.touchScrollAllowed = false; dragging.minDistance = options.selectMinDistance || 0; dragging.autoScroller.isEnabled = options.dragScroll; var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsToStore"])(settings)); hitDragging.emitter.on('pointerdown', _this.handlePointerDown); hitDragging.emitter.on('dragstart', _this.handleDragStart); hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); hitDragging.emitter.on('pointerup', _this.handlePointerUp); return _this; } DateSelecting.prototype.destroy = function () { this.dragging.destroy(); }; return DateSelecting; }(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"])); function getComponentTouchDelay(component) { var options = component.context.options; var delay = options.selectLongPressDelay; if (delay == null) { delay = options.longPressDelay; } return delay; } function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) { var dateSpan0 = hit0.dateSpan; var dateSpan1 = hit1.dateSpan; var ms = [ dateSpan0.range.start, dateSpan0.range.end, dateSpan1.range.start, dateSpan1.range.end ]; ms.sort(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["compareNumbers"]); var props = {}; for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) { var transformer = dateSelectionTransformers_1[_i]; var res = transformer(hit0, hit1); if (res === false) { return null; } else if (res) { __assign(props, res); } } props.range = { start: ms[0], end: ms[3] }; props.allDay = dateSpan0.allDay; return props; } var EventDragging = /** @class */ (function (_super) { __extends(EventDragging, _super); function EventDragging(settings) { var _this = _super.call(this, settings) || this; // internal state _this.subjectSeg = null; // the seg being selected/dragged _this.isDragging = false; _this.eventRange = null; _this.relevantEvents = null; // the events being dragged _this.receivingCalendar = null; _this.validMutation = null; _this.mutatedRelevantEvents = null; _this.handlePointerDown = function (ev) { var origTarget = ev.origEvent.target; var _a = _this, component = _a.component, dragging = _a.dragging; var mirror = dragging.mirror; var options = component.context.options; var initialCalendar = component.context.calendar; var subjectSeg = _this.subjectSeg = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getElSeg"])(ev.subjectEl); var eventRange = _this.eventRange = subjectSeg.eventRange; var eventInstanceId = eventRange.instance.instanceId; _this.relevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getRelevantEvents"])(initialCalendar.state.eventStore, eventInstanceId); dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance; dragging.delay = // only do a touch delay if touch and this event hasn't been selected yet (ev.isTouch && eventInstanceId !== component.props.eventSelection) ? getComponentTouchDelay$1(component) : null; mirror.parentNode = initialCalendar.el; mirror.revertDuration = options.dragRevertDuration; var isValid = component.isValidSegDownEl(origTarget) && !Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(origTarget, '.fc-resizer'); // NOT on a resizer dragging.setIgnoreMove(!isValid); // disable dragging for elements that are resizable (ie, selectable) // but are not draggable _this.isDragging = isValid && ev.subjectEl.classList.contains('fc-draggable'); }; _this.handleDragStart = function (ev) { var context = _this.component.context; var initialCalendar = context.calendar; var eventRange = _this.eventRange; var eventInstanceId = eventRange.instance.instanceId; if (ev.isTouch) { // need to select a different event? if (eventInstanceId !== _this.component.props.eventSelection) { initialCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId }); } } else { // if now using mouse, but was previous touch interaction, clear selected event initialCalendar.dispatch({ type: 'UNSELECT_EVENT' }); } if (_this.isDragging) { initialCalendar.unselect(ev); // unselect *date* selection initialCalendar.publiclyTrigger('eventDragStart', [ { el: _this.subjectSeg.el, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](initialCalendar, eventRange.def, eventRange.instance), jsEvent: ev.origEvent, view: context.view } ]); } }; _this.handleHitUpdate = function (hit, isFinal) { if (!_this.isDragging) { return; } var relevantEvents = _this.relevantEvents; var initialHit = _this.hitDragging.initialHit; var initialCalendar = _this.component.context.calendar; // states based on new hit var receivingCalendar = null; var mutation = null; var mutatedRelevantEvents = null; var isInvalid = false; var interaction = { affectedEvents: relevantEvents, mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(), isEvent: true, origSeg: _this.subjectSeg }; if (hit) { var receivingComponent = hit.component; receivingCalendar = receivingComponent.context.calendar; var receivingOptions = receivingComponent.context.options; if (initialCalendar === receivingCalendar || receivingOptions.editable && receivingOptions.droppable) { mutation = computeEventMutation(initialHit, hit, receivingCalendar.pluginSystem.hooks.eventDragMutationMassagers); if (mutation) { mutatedRelevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyMutationToEventStore"])(relevantEvents, receivingCalendar.eventUiBases, mutation, receivingCalendar); interaction.mutatedEvents = mutatedRelevantEvents; if (!receivingComponent.isInteractionValid(interaction)) { isInvalid = true; mutation = null; mutatedRelevantEvents = null; interaction.mutatedEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(); } } } else { receivingCalendar = null; } } _this.displayDrag(receivingCalendar, interaction); if (!isInvalid) { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])(); } else { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])(); } if (!isFinal) { if (initialCalendar === receivingCalendar && // TODO: write test for this isHitsEqual(initialHit, hit)) { mutation = null; } _this.dragging.setMirrorNeedsRevert(!mutation); // render the mirror if no already-rendered mirror // TODO: wish we could somehow wait for dispatch to guarantee render _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-mirror')); // assign states based on new hit _this.receivingCalendar = receivingCalendar; _this.validMutation = mutation; _this.mutatedRelevantEvents = mutatedRelevantEvents; } }; _this.handlePointerUp = function () { if (!_this.isDragging) { _this.cleanup(); // because handleDragEnd won't fire } }; _this.handleDragEnd = function (ev) { if (_this.isDragging) { var context = _this.component.context; var initialCalendar_1 = context.calendar; var initialView = context.view; var _a = _this, receivingCalendar = _a.receivingCalendar, validMutation = _a.validMutation; var eventDef = _this.eventRange.def; var eventInstance = _this.eventRange.instance; var eventApi = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](initialCalendar_1, eventDef, eventInstance); var relevantEvents_1 = _this.relevantEvents; var mutatedRelevantEvents = _this.mutatedRelevantEvents; var finalHit = _this.hitDragging.finalHit; _this.clearDrag(); // must happen after revert animation initialCalendar_1.publiclyTrigger('eventDragStop', [ { el: _this.subjectSeg.el, event: eventApi, jsEvent: ev.origEvent, view: initialView } ]); if (validMutation) { // dropped within same calendar if (receivingCalendar === initialCalendar_1) { initialCalendar_1.dispatch({ type: 'MERGE_EVENTS', eventStore: mutatedRelevantEvents }); var transformed = {}; for (var _i = 0, _b = initialCalendar_1.pluginSystem.hooks.eventDropTransformers; _i < _b.length; _i++) { var transformer = _b[_i]; __assign(transformed, transformer(validMutation, initialCalendar_1)); } var eventDropArg = __assign({}, transformed, { el: ev.subjectEl, delta: validMutation.datesDelta, oldEvent: eventApi, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](// the data AFTER the mutation initialCalendar_1, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () { initialCalendar_1.dispatch({ type: 'MERGE_EVENTS', eventStore: relevantEvents_1 }); }, jsEvent: ev.origEvent, view: initialView }); initialCalendar_1.publiclyTrigger('eventDrop', [eventDropArg]); // dropped in different calendar } else if (receivingCalendar) { initialCalendar_1.publiclyTrigger('eventLeave', [ { draggedEl: ev.subjectEl, event: eventApi, view: initialView } ]); initialCalendar_1.dispatch({ type: 'REMOVE_EVENT_INSTANCES', instances: _this.mutatedRelevantEvents.instances }); receivingCalendar.dispatch({ type: 'MERGE_EVENTS', eventStore: _this.mutatedRelevantEvents }); if (ev.isTouch) { receivingCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstance.instanceId }); } var dropArg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component // should this be finalHit.component.view? See #4644 }); receivingCalendar.publiclyTrigger('drop', [dropArg]); receivingCalendar.publiclyTrigger('eventReceive', [ { draggedEl: ev.subjectEl, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](// the data AFTER the mutation receivingCalendar, mutatedRelevantEvents.defs[eventDef.defId], mutatedRelevantEvents.instances[eventInstance.instanceId]), view: finalHit.component // should this be finalHit.component.view? See #4644 } ]); } } else { initialCalendar_1.publiclyTrigger('_noEventDrop'); } } _this.cleanup(); }; var component = _this.component; var options = component.context.options; var dragging = _this.dragging = new FeaturefulElementDragging(component.el); dragging.pointer.selector = EventDragging.SELECTOR; dragging.touchScrollAllowed = false; dragging.autoScroller.isEnabled = options.dragScroll; var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsStore"]); hitDragging.useSubjectCenter = settings.useEventCenter; hitDragging.emitter.on('pointerdown', _this.handlePointerDown); hitDragging.emitter.on('dragstart', _this.handleDragStart); hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); hitDragging.emitter.on('pointerup', _this.handlePointerUp); hitDragging.emitter.on('dragend', _this.handleDragEnd); return _this; } EventDragging.prototype.destroy = function () { this.dragging.destroy(); }; // render a drag state on the next receivingCalendar EventDragging.prototype.displayDrag = function (nextCalendar, state) { var initialCalendar = this.component.context.calendar; var prevCalendar = this.receivingCalendar; // does the previous calendar need to be cleared? if (prevCalendar && prevCalendar !== nextCalendar) { // does the initial calendar need to be cleared? // if so, don't clear all the way. we still need to to hide the affectedEvents if (prevCalendar === initialCalendar) { prevCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: { affectedEvents: state.affectedEvents, mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(), isEvent: true, origSeg: state.origSeg } }); // completely clear the old calendar if it wasn't the initial } else { prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); } } if (nextCalendar) { nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state }); } }; EventDragging.prototype.clearDrag = function () { var initialCalendar = this.component.context.calendar; var receivingCalendar = this.receivingCalendar; if (receivingCalendar) { receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); } // the initial calendar might have an dummy drag state from displayDrag if (initialCalendar !== receivingCalendar) { initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); } }; EventDragging.prototype.cleanup = function () { this.subjectSeg = null; this.isDragging = false; this.eventRange = null; this.relevantEvents = null; this.receivingCalendar = null; this.validMutation = null; this.mutatedRelevantEvents = null; }; EventDragging.SELECTOR = '.fc-draggable, .fc-resizable'; // TODO: test this in IE11 return EventDragging; }(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"])); function computeEventMutation(hit0, hit1, massagers) { var dateSpan0 = hit0.dateSpan; var dateSpan1 = hit1.dateSpan; var date0 = dateSpan0.range.start; var date1 = dateSpan1.range.start; var standardProps = {}; if (dateSpan0.allDay !== dateSpan1.allDay) { standardProps.allDay = dateSpan1.allDay; standardProps.hasEnd = hit1.component.context.options.allDayMaintainDuration; if (dateSpan1.allDay) { // means date1 is already start-of-day, // but date0 needs to be converted date0 = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["startOfDay"])(date0); } } var delta = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffDates"])(date0, date1, hit0.component.context.dateEnv, hit0.component === hit1.component ? hit0.component.largeUnit : null); if (delta.milliseconds) { // has hours/minutes/seconds standardProps.allDay = false; } var mutation = { datesDelta: delta, standardProps: standardProps }; for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) { var massager = massagers_1[_i]; massager(mutation, hit0, hit1); } return mutation; } function getComponentTouchDelay$1(component) { var options = component.context.options; var delay = options.eventLongPressDelay; if (delay == null) { delay = options.longPressDelay; } return delay; } var EventDragging$1 = /** @class */ (function (_super) { __extends(EventDragging, _super); function EventDragging(settings) { var _this = _super.call(this, settings) || this; // internal state _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg? _this.eventRange = null; _this.relevantEvents = null; _this.validMutation = null; _this.mutatedRelevantEvents = null; _this.handlePointerDown = function (ev) { var component = _this.component; var seg = _this.querySeg(ev); var eventRange = _this.eventRange = seg.eventRange; _this.dragging.minDistance = component.context.options.eventDragMinDistance; // if touch, need to be working with a selected event _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) || (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId)); }; _this.handleDragStart = function (ev) { var _a = _this.component.context, calendar = _a.calendar, view = _a.view; var eventRange = _this.eventRange; _this.relevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getRelevantEvents"])(calendar.state.eventStore, _this.eventRange.instance.instanceId); _this.draggingSeg = _this.querySeg(ev); calendar.unselect(); calendar.publiclyTrigger('eventResizeStart', [ { el: _this.draggingSeg.el, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](calendar, eventRange.def, eventRange.instance), jsEvent: ev.origEvent, view: view } ]); }; _this.handleHitUpdate = function (hit, isFinal, ev) { var calendar = _this.component.context.calendar; var relevantEvents = _this.relevantEvents; var initialHit = _this.hitDragging.initialHit; var eventInstance = _this.eventRange.instance; var mutation = null; var mutatedRelevantEvents = null; var isInvalid = false; var interaction = { affectedEvents: relevantEvents, mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(), isEvent: true, origSeg: _this.draggingSeg }; if (hit) { mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-start-resizer'), eventInstance.range, calendar.pluginSystem.hooks.eventResizeJoinTransforms); } if (mutation) { mutatedRelevantEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["applyMutationToEventStore"])(relevantEvents, calendar.eventUiBases, mutation, calendar); interaction.mutatedEvents = mutatedRelevantEvents; if (!_this.component.isInteractionValid(interaction)) { isInvalid = true; mutation = null; mutatedRelevantEvents = null; interaction.mutatedEvents = null; } } if (mutatedRelevantEvents) { calendar.dispatch({ type: 'SET_EVENT_RESIZE', state: interaction }); } else { calendar.dispatch({ type: 'UNSET_EVENT_RESIZE' }); } if (!isInvalid) { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])(); } else { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])(); } if (!isFinal) { if (mutation && isHitsEqual(initialHit, hit)) { mutation = null; } _this.validMutation = mutation; _this.mutatedRelevantEvents = mutatedRelevantEvents; } }; _this.handleDragEnd = function (ev) { var _a = _this.component.context, calendar = _a.calendar, view = _a.view; var eventDef = _this.eventRange.def; var eventInstance = _this.eventRange.instance; var eventApi = new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](calendar, eventDef, eventInstance); var relevantEvents = _this.relevantEvents; var mutatedRelevantEvents = _this.mutatedRelevantEvents; calendar.publiclyTrigger('eventResizeStop', [ { el: _this.draggingSeg.el, event: eventApi, jsEvent: ev.origEvent, view: view } ]); if (_this.validMutation) { calendar.dispatch({ type: 'MERGE_EVENTS', eventStore: mutatedRelevantEvents }); calendar.publiclyTrigger('eventResize', [ { el: _this.draggingSeg.el, startDelta: _this.validMutation.startDelta || Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createDuration"])(0), endDelta: _this.validMutation.endDelta || Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createDuration"])(0), prevEvent: eventApi, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](// the data AFTER the mutation calendar, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () { calendar.dispatch({ type: 'MERGE_EVENTS', eventStore: relevantEvents }); }, jsEvent: ev.origEvent, view: view } ]); } else { calendar.publiclyTrigger('_noEventResize'); } // reset all internal state _this.draggingSeg = null; _this.relevantEvents = null; _this.validMutation = null; // okay to keep eventInstance around. useful to set it in handlePointerDown }; var component = settings.component; var dragging = _this.dragging = new FeaturefulElementDragging(component.el); dragging.pointer.selector = '.fc-resizer'; dragging.touchScrollAllowed = false; dragging.autoScroller.isEnabled = component.context.options.dragScroll; var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsToStore"])(settings)); hitDragging.emitter.on('pointerdown', _this.handlePointerDown); hitDragging.emitter.on('dragstart', _this.handleDragStart); hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); hitDragging.emitter.on('dragend', _this.handleDragEnd); return _this; } EventDragging.prototype.destroy = function () { this.dragging.destroy(); }; EventDragging.prototype.querySeg = function (ev) { return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["getElSeg"])(Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(ev.subjectEl, this.component.fgSegSelector)); }; return EventDragging; }(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["Interaction"])); function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) { var dateEnv = hit0.component.context.dateEnv; var date0 = hit0.dateSpan.range.start; var date1 = hit1.dateSpan.range.start; var delta = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["diffDates"])(date0, date1, dateEnv, hit0.component.largeUnit); var props = {}; for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) { var transform = transforms_1[_i]; var res = transform(hit0, hit1); if (res === false) { return null; } else if (res) { __assign(props, res); } } if (isFromStart) { if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) { props.startDelta = delta; return props; } } else { if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) { props.endDelta = delta; return props; } } return null; } var UnselectAuto = /** @class */ (function () { function UnselectAuto(calendar) { var _this = this; this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system this.onSelect = function (selectInfo) { if (selectInfo.jsEvent) { _this.isRecentPointerDateSelect = true; } }; this.onDocumentPointerUp = function (pev) { var _a = _this, calendar = _a.calendar, documentPointer = _a.documentPointer; var state = calendar.state; // touch-scrolling should never unfocus any type of selection if (!documentPointer.wasTouchScroll) { if (state.dateSelection && // an existing date selection? !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp? ) { var unselectAuto = calendar.viewOpt('unselectAuto'); var unselectCancel = calendar.viewOpt('unselectCancel'); if (unselectAuto && (!unselectAuto || !Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(documentPointer.downEl, unselectCancel))) { calendar.unselect(pev); } } if (state.eventSelection && // an existing event selected? !Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementClosest"])(documentPointer.downEl, EventDragging.SELECTOR) // interaction DIDN'T start on an event ) { calendar.dispatch({ type: 'UNSELECT_EVENT' }); } } _this.isRecentPointerDateSelect = false; }; this.calendar = calendar; var documentPointer = this.documentPointer = new PointerDragging(document); documentPointer.shouldIgnoreMove = true; documentPointer.shouldWatchScroll = false; documentPointer.emitter.on('pointerup', this.onDocumentPointerUp); /* TODO: better way to know about whether there was a selection with the pointer */ calendar.on('select', this.onSelect); } UnselectAuto.prototype.destroy = function () { this.calendar.off('select', this.onSelect); this.documentPointer.destroy(); }; return UnselectAuto; }()); /* Given an already instantiated draggable object for one-or-more elements, Interprets any dragging as an attempt to drag an events that lives outside of a calendar onto a calendar. */ var ExternalElementDragging = /** @class */ (function () { function ExternalElementDragging(dragging, suppliedDragMeta) { var _this = this; this.receivingCalendar = null; this.droppableEvent = null; // will exist for all drags, even if create:false this.suppliedDragMeta = null; this.dragMeta = null; this.handleDragStart = function (ev) { _this.dragMeta = _this.buildDragMeta(ev.subjectEl); }; this.handleHitUpdate = function (hit, isFinal, ev) { var dragging = _this.hitDragging.dragging; var receivingCalendar = null; var droppableEvent = null; var isInvalid = false; var interaction = { affectedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(), mutatedEvents: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(), isEvent: _this.dragMeta.create, origSeg: null }; if (hit) { receivingCalendar = hit.component.context.calendar; if (_this.canDropElOnCalendar(ev.subjectEl, receivingCalendar)) { droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingCalendar); interaction.mutatedEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["eventTupleToStore"])(droppableEvent); isInvalid = !Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["isInteractionValid"])(interaction, receivingCalendar); if (isInvalid) { interaction.mutatedEvents = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEmptyEventStore"])(); droppableEvent = null; } } } _this.displayDrag(receivingCalendar, interaction); // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?) // TODO: wish we could somehow wait for dispatch to guarantee render dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-mirror')); if (!isInvalid) { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["enableCursor"])(); } else { Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["disableCursor"])(); } if (!isFinal) { dragging.setMirrorNeedsRevert(!droppableEvent); _this.receivingCalendar = receivingCalendar; _this.droppableEvent = droppableEvent; } }; this.handleDragEnd = function (pev) { var _a = _this, receivingCalendar = _a.receivingCalendar, droppableEvent = _a.droppableEvent; _this.clearDrag(); if (receivingCalendar && droppableEvent) { var finalHit = _this.hitDragging.finalHit; var finalView = finalHit.component.context.view; var dragMeta = _this.dragMeta; var arg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }); receivingCalendar.publiclyTrigger('drop', [arg]); if (dragMeta.create) { receivingCalendar.dispatch({ type: 'MERGE_EVENTS', eventStore: Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["eventTupleToStore"])(droppableEvent) }); if (pev.isTouch) { receivingCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: droppableEvent.instance.instanceId }); } // signal that an external event landed receivingCalendar.publiclyTrigger('eventReceive', [ { draggedEl: pev.subjectEl, event: new _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["EventApi"](receivingCalendar, droppableEvent.def, droppableEvent.instance), view: finalView } ]); } } _this.receivingCalendar = null; _this.droppableEvent = null; }; var hitDragging = this.hitDragging = new HitDragging(dragging, _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["interactionSettingsStore"]); hitDragging.requireInitial = false; // will start outside of a component hitDragging.emitter.on('dragstart', this.handleDragStart); hitDragging.emitter.on('hitupdate', this.handleHitUpdate); hitDragging.emitter.on('dragend', this.handleDragEnd); this.suppliedDragMeta = suppliedDragMeta; } ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) { if (typeof this.suppliedDragMeta === 'object') { return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseDragMeta"])(this.suppliedDragMeta); } else if (typeof this.suppliedDragMeta === 'function') { return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseDragMeta"])(this.suppliedDragMeta(subjectEl)); } else { return getDragMetaFromEl(subjectEl); } }; ExternalElementDragging.prototype.displayDrag = function (nextCalendar, state) { var prevCalendar = this.receivingCalendar; if (prevCalendar && prevCalendar !== nextCalendar) { prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); } if (nextCalendar) { nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state }); } }; ExternalElementDragging.prototype.clearDrag = function () { if (this.receivingCalendar) { this.receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); } }; ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingCalendar) { var dropAccept = receivingCalendar.opt('dropAccept'); if (typeof dropAccept === 'function') { return dropAccept(el); } else if (typeof dropAccept === 'string' && dropAccept) { return Boolean(Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["elementMatches"])(el, dropAccept)); } return true; }; return ExternalElementDragging; }()); // Utils for computing event store from the DragMeta // ---------------------------------------------------------------------------------------------------- function computeEventForDateSpan(dateSpan, dragMeta, calendar) { var defProps = __assign({}, dragMeta.leftoverProps); for (var _i = 0, _a = calendar.pluginSystem.hooks.externalDefTransforms; _i < _a.length; _i++) { var transform = _a[_i]; __assign(defProps, transform(dateSpan, dragMeta)); } var def = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseEventDef"])(defProps, dragMeta.sourceId, dateSpan.allDay, calendar.opt('forceEventDuration') || Boolean(dragMeta.duration), // hasEnd calendar); var start = dateSpan.range.start; // only rely on time info if drop zone is all-day, // otherwise, we already know the time if (dateSpan.allDay && dragMeta.startTime) { start = calendar.dateEnv.add(start, dragMeta.startTime); } var end = dragMeta.duration ? calendar.dateEnv.add(start, dragMeta.duration) : calendar.getDefaultEventEnd(dateSpan.allDay, start); var instance = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createEventInstance"])(def.defId, { start: start, end: end }); return { def: def, instance: instance }; } // Utils for extracting data from element // ---------------------------------------------------------------------------------------------------- function getDragMetaFromEl(el) { var str = getEmbeddedElData(el, 'event'); var obj = str ? JSON.parse(str) : { create: false }; // if no embedded data, assume no event creation return Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["parseDragMeta"])(obj); } _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["config"].dataAttrPrefix = ''; function getEmbeddedElData(el, name) { var prefix = _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["config"].dataAttrPrefix; var prefixedName = (prefix ? prefix + '-' : '') + name; return el.getAttribute('data-' + prefixedName) || ''; } /* Makes an element (that is *external* to any calendar) draggable. Can pass in data that determines how an event will be created when dropped onto a calendar. Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system. */ var ExternalDraggable = /** @class */ (function () { function ExternalDraggable(el, settings) { var _this = this; if (settings === void 0) { settings = {}; } this.handlePointerDown = function (ev) { var dragging = _this.dragging; var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay; dragging.minDistance = minDistance != null ? minDistance : (ev.isTouch ? 0 : _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["globalDefaults"].eventDragMinDistance); dragging.delay = ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv (longPressDelay != null ? longPressDelay : _fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["globalDefaults"].longPressDelay) : 0; }; this.handleDragStart = function (ev) { if (ev.isTouch && _this.dragging.delay && ev.subjectEl.classList.contains('fc-event')) { _this.dragging.mirror.getMirrorEl().classList.add('fc-selected'); } }; this.settings = settings; var dragging = this.dragging = new FeaturefulElementDragging(el); dragging.touchScrollAllowed = false; if (settings.itemSelector != null) { dragging.pointer.selector = settings.itemSelector; } if (settings.appendTo != null) { dragging.mirror.parentNode = settings.appendTo; // TODO: write tests } dragging.emitter.on('pointerdown', this.handlePointerDown); dragging.emitter.on('dragstart', this.handleDragStart); new ExternalElementDragging(dragging, settings.eventData); } ExternalDraggable.prototype.destroy = function () { this.dragging.destroy(); }; return ExternalDraggable; }()); /* Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements. The third-party system is responsible for drawing the visuals effects of the drag. This class simply monitors for pointer movements and fires events. It also has the ability to hide the moving element (the "mirror") during the drag. */ var InferredElementDragging = /** @class */ (function (_super) { __extends(InferredElementDragging, _super); function InferredElementDragging(containerEl) { var _this = _super.call(this, containerEl) || this; _this.shouldIgnoreMove = false; _this.mirrorSelector = ''; _this.currentMirrorEl = null; _this.handlePointerDown = function (ev) { _this.emitter.trigger('pointerdown', ev); if (!_this.shouldIgnoreMove) { // fire dragstart right away. does not support delay or min-distance _this.emitter.trigger('dragstart', ev); } }; _this.handlePointerMove = function (ev) { if (!_this.shouldIgnoreMove) { _this.emitter.trigger('dragmove', ev); } }; _this.handlePointerUp = function (ev) { _this.emitter.trigger('pointerup', ev); if (!_this.shouldIgnoreMove) { // fire dragend right away. does not support a revert animation _this.emitter.trigger('dragend', ev); } }; var pointer = _this.pointer = new PointerDragging(containerEl); pointer.emitter.on('pointerdown', _this.handlePointerDown); pointer.emitter.on('pointermove', _this.handlePointerMove); pointer.emitter.on('pointerup', _this.handlePointerUp); return _this; } InferredElementDragging.prototype.destroy = function () { this.pointer.destroy(); }; InferredElementDragging.prototype.setIgnoreMove = function (bool) { this.shouldIgnoreMove = bool; }; InferredElementDragging.prototype.setMirrorIsVisible = function (bool) { if (bool) { // restore a previously hidden element. // use the reference in case the selector class has already been removed. if (this.currentMirrorEl) { this.currentMirrorEl.style.visibility = ''; this.currentMirrorEl = null; } } else { var mirrorEl = this.mirrorSelector ? document.querySelector(this.mirrorSelector) : null; if (mirrorEl) { this.currentMirrorEl = mirrorEl; mirrorEl.style.visibility = 'hidden'; } } }; return InferredElementDragging; }(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["ElementDragging"])); /* Bridges third-party drag-n-drop systems with FullCalendar. Must be instantiated and destroyed by caller. */ var ThirdPartyDraggable = /** @class */ (function () { function ThirdPartyDraggable(containerOrSettings, settings) { var containerEl = document; if ( // wish we could just test instanceof EventTarget, but doesn't work in IE11 containerOrSettings === document || containerOrSettings instanceof Element) { containerEl = containerOrSettings; settings = settings || {}; } else { settings = (containerOrSettings || {}); } var dragging = this.dragging = new InferredElementDragging(containerEl); if (typeof settings.itemSelector === 'string') { dragging.pointer.selector = settings.itemSelector; } else if (containerEl === document) { dragging.pointer.selector = '[data-event]'; } if (typeof settings.mirrorSelector === 'string') { dragging.mirrorSelector = settings.mirrorSelector; } new ExternalElementDragging(dragging, settings.eventData); } ThirdPartyDraggable.prototype.destroy = function () { this.dragging.destroy(); }; return ThirdPartyDraggable; }()); var main = Object(_fullcalendar_core__WEBPACK_IMPORTED_MODULE_0__["createPlugin"])({ componentInteractions: [DateClicking, DateSelecting, EventDragging, EventDragging$1], calendarInteractions: [UnselectAuto], elementDraggingImpl: FeaturefulElementDragging }); /* harmony default export */ __webpack_exports__["default"] = (main); /***/ }), /***/ "./node_modules/core-js/internals/a-callable.js": /*!******************************************************!*\ !*** ./node_modules/core-js/internals/a-callable.js ***! \******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var tryToString = __webpack_require__(/*! ../internals/try-to-string */ "./node_modules/core-js/internals/try-to-string.js"); var $TypeError = TypeError; // `Assert: IsCallable(argument) is true` module.exports = function (argument) { if (isCallable(argument)) return argument; throw new $TypeError(tryToString(argument) + ' is not a function'); }; /***/ }), /***/ "./node_modules/core-js/internals/an-object.js": /*!*****************************************************!*\ !*** ./node_modules/core-js/internals/an-object.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js"); var $String = String; var $TypeError = TypeError; // `Assert: Type(argument) is Object` module.exports = function (argument) { if (isObject(argument)) return argument; throw new $TypeError($String(argument) + ' is not an object'); }; /***/ }), /***/ "./node_modules/core-js/internals/classof-raw.js": /*!*******************************************************!*\ !*** ./node_modules/core-js/internals/classof-raw.js ***! \*******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); var toString = uncurryThis({}.toString); var stringSlice = uncurryThis(''.slice); module.exports = function (it) { return stringSlice(toString(it), 8, -1); }; /***/ }), /***/ "./node_modules/core-js/internals/classof.js": /*!***************************************************!*\ !*** ./node_modules/core-js/internals/classof.js ***! \***************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var classofRaw = __webpack_require__(/*! ../internals/classof-raw */ "./node_modules/core-js/internals/classof-raw.js"); var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ "./node_modules/core-js/internals/well-known-symbol.js"); var TO_STRING_TAG = wellKnownSymbol('toStringTag'); var $Object = Object; // ES3 wrong here var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) === 'Arguments'; // fallback for IE11 Script Access Denied error var tryGet = function (it, key) { try { return it[key]; } catch (error) { /* empty */ } }; // getting tag from ES6+ `Object.prototype.toString` module.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) { var O, tag, result; return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag // builtinTag case : CORRECT_ARGUMENTS ? classofRaw(O) // ES3 arguments fallback : (result = classofRaw(O)) === 'Object' && isCallable(O.callee) ? 'Arguments' : result; }; /***/ }), /***/ "./node_modules/core-js/internals/create-non-enumerable-property.js": /*!**************************************************************************!*\ !*** ./node_modules/core-js/internals/create-non-enumerable-property.js ***! \**************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js"); var definePropertyModule = __webpack_require__(/*! ../internals/object-define-property */ "./node_modules/core-js/internals/object-define-property.js"); var createPropertyDescriptor = __webpack_require__(/*! ../internals/create-property-descriptor */ "./node_modules/core-js/internals/create-property-descriptor.js"); module.exports = DESCRIPTORS ? function (object, key, value) { return definePropertyModule.f(object, key, createPropertyDescriptor(1, value)); } : function (object, key, value) { object[key] = value; return object; }; /***/ }), /***/ "./node_modules/core-js/internals/create-property-descriptor.js": /*!**********************************************************************!*\ !*** ./node_modules/core-js/internals/create-property-descriptor.js ***! \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = function (bitmap, value) { return { enumerable: !(bitmap & 1), configurable: !(bitmap & 2), writable: !(bitmap & 4), value: value }; }; /***/ }), /***/ "./node_modules/core-js/internals/define-built-in.js": /*!***********************************************************!*\ !*** ./node_modules/core-js/internals/define-built-in.js ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var definePropertyModule = __webpack_require__(/*! ../internals/object-define-property */ "./node_modules/core-js/internals/object-define-property.js"); var makeBuiltIn = __webpack_require__(/*! ../internals/make-built-in */ "./node_modules/core-js/internals/make-built-in.js"); var defineGlobalProperty = __webpack_require__(/*! ../internals/define-global-property */ "./node_modules/core-js/internals/define-global-property.js"); module.exports = function (O, key, value, options) { if (!options) options = {}; var simple = options.enumerable; var name = options.name !== undefined ? options.name : key; if (isCallable(value)) makeBuiltIn(value, name, options); if (options.global) { if (simple) O[key] = value; else defineGlobalProperty(key, value); } else { try { if (!options.unsafe) delete O[key]; else if (O[key]) simple = true; } catch (error) { /* empty */ } if (simple) O[key] = value; else definePropertyModule.f(O, key, { value: value, enumerable: false, configurable: !options.nonConfigurable, writable: !options.nonWritable }); } return O; }; /***/ }), /***/ "./node_modules/core-js/internals/define-global-property.js": /*!******************************************************************!*\ !*** ./node_modules/core-js/internals/define-global-property.js ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); // eslint-disable-next-line es/no-object-defineproperty -- safe var defineProperty = Object.defineProperty; module.exports = function (key, value) { try { defineProperty(global, key, { value: value, configurable: true, writable: true }); } catch (error) { global[key] = value; } return value; }; /***/ }), /***/ "./node_modules/core-js/internals/descriptors.js": /*!*******************************************************!*\ !*** ./node_modules/core-js/internals/descriptors.js ***! \*******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); // Detect IE8's incomplete defineProperty implementation module.exports = !fails(function () { // eslint-disable-next-line es/no-object-defineproperty -- required for testing return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] !== 7; }); /***/ }), /***/ "./node_modules/core-js/internals/document-create-element.js": /*!*******************************************************************!*\ !*** ./node_modules/core-js/internals/document-create-element.js ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js"); var document = global.document; // typeof document.createElement is 'object' in old IE var EXISTS = isObject(document) && isObject(document.createElement); module.exports = function (it) { return EXISTS ? document.createElement(it) : {}; }; /***/ }), /***/ "./node_modules/core-js/internals/engine-user-agent.js": /*!*************************************************************!*\ !*** ./node_modules/core-js/internals/engine-user-agent.js ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = typeof navigator != 'undefined' && String(navigator.userAgent) || ''; /***/ }), /***/ "./node_modules/core-js/internals/engine-v8-version.js": /*!*************************************************************!*\ !*** ./node_modules/core-js/internals/engine-v8-version.js ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var userAgent = __webpack_require__(/*! ../internals/engine-user-agent */ "./node_modules/core-js/internals/engine-user-agent.js"); var process = global.process; var Deno = global.Deno; var versions = process && process.versions || Deno && Deno.version; var v8 = versions && versions.v8; var match, version; if (v8) { match = v8.split('.'); // in old Chrome, versions of V8 isn't V8 = Chrome / 10 // but their correct versions are not interesting for us version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]); } // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0` // so check `userAgent` even if `.v8` exists, but 0 if (!version && userAgent) { match = userAgent.match(/Edge\/(\d+)/); if (!match || match[1] >= 74) { match = userAgent.match(/Chrome\/(\d+)/); if (match) version = +match[1]; } } module.exports = version; /***/ }), /***/ "./node_modules/core-js/internals/fails.js": /*!*************************************************!*\ !*** ./node_modules/core-js/internals/fails.js ***! \*************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = function (exec) { try { return !!exec(); } catch (error) { return true; } }; /***/ }), /***/ "./node_modules/core-js/internals/function-bind-native.js": /*!****************************************************************!*\ !*** ./node_modules/core-js/internals/function-bind-native.js ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); module.exports = !fails(function () { // eslint-disable-next-line es/no-function-prototype-bind -- safe var test = (function () { /* empty */ }).bind(); // eslint-disable-next-line no-prototype-builtins -- safe return typeof test != 'function' || test.hasOwnProperty('prototype'); }); /***/ }), /***/ "./node_modules/core-js/internals/function-call.js": /*!*********************************************************!*\ !*** ./node_modules/core-js/internals/function-call.js ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var NATIVE_BIND = __webpack_require__(/*! ../internals/function-bind-native */ "./node_modules/core-js/internals/function-bind-native.js"); var call = Function.prototype.call; module.exports = NATIVE_BIND ? call.bind(call) : function () { return call.apply(call, arguments); }; /***/ }), /***/ "./node_modules/core-js/internals/function-name.js": /*!*********************************************************!*\ !*** ./node_modules/core-js/internals/function-name.js ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js"); var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js"); var FunctionPrototype = Function.prototype; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor; var EXISTS = hasOwn(FunctionPrototype, 'name'); // additional protection from minified / mangled / dropped function names var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something'; var CONFIGURABLE = EXISTS && (!DESCRIPTORS || (DESCRIPTORS && getDescriptor(FunctionPrototype, 'name').configurable)); module.exports = { EXISTS: EXISTS, PROPER: PROPER, CONFIGURABLE: CONFIGURABLE }; /***/ }), /***/ "./node_modules/core-js/internals/function-uncurry-this.js": /*!*****************************************************************!*\ !*** ./node_modules/core-js/internals/function-uncurry-this.js ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var NATIVE_BIND = __webpack_require__(/*! ../internals/function-bind-native */ "./node_modules/core-js/internals/function-bind-native.js"); var FunctionPrototype = Function.prototype; var call = FunctionPrototype.call; var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call); module.exports = NATIVE_BIND ? uncurryThisWithBind : function (fn) { return function () { return call.apply(fn, arguments); }; }; /***/ }), /***/ "./node_modules/core-js/internals/get-built-in.js": /*!********************************************************!*\ !*** ./node_modules/core-js/internals/get-built-in.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var aFunction = function (argument) { return isCallable(argument) ? argument : undefined; }; module.exports = function (namespace, method) { return arguments.length < 2 ? aFunction(global[namespace]) : global[namespace] && global[namespace][method]; }; /***/ }), /***/ "./node_modules/core-js/internals/get-method.js": /*!******************************************************!*\ !*** ./node_modules/core-js/internals/get-method.js ***! \******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var aCallable = __webpack_require__(/*! ../internals/a-callable */ "./node_modules/core-js/internals/a-callable.js"); var isNullOrUndefined = __webpack_require__(/*! ../internals/is-null-or-undefined */ "./node_modules/core-js/internals/is-null-or-undefined.js"); // `GetMethod` abstract operation // https://tc39.es/ecma262/#sec-getmethod module.exports = function (V, P) { var func = V[P]; return isNullOrUndefined(func) ? undefined : aCallable(func); }; /***/ }), /***/ "./node_modules/core-js/internals/global.js": /*!**************************************************!*\ !*** ./node_modules/core-js/internals/global.js ***! \**************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(global) { var check = function (it) { return it && it.Math === Math && it; }; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 module.exports = // eslint-disable-next-line es/no-global-this -- safe check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || // eslint-disable-next-line no-restricted-globals -- safe check(typeof self == 'object' && self) || check(typeof global == 'object' && global) || check(typeof this == 'object' && this) || // eslint-disable-next-line no-new-func -- fallback (function () { return this; })() || Function('return this')(); /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js"))) /***/ }), /***/ "./node_modules/core-js/internals/has-own-property.js": /*!************************************************************!*\ !*** ./node_modules/core-js/internals/has-own-property.js ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); var toObject = __webpack_require__(/*! ../internals/to-object */ "./node_modules/core-js/internals/to-object.js"); var hasOwnProperty = uncurryThis({}.hasOwnProperty); // `HasOwnProperty` abstract operation // https://tc39.es/ecma262/#sec-hasownproperty // eslint-disable-next-line es/no-object-hasown -- safe module.exports = Object.hasOwn || function hasOwn(it, key) { return hasOwnProperty(toObject(it), key); }; /***/ }), /***/ "./node_modules/core-js/internals/hidden-keys.js": /*!*******************************************************!*\ !*** ./node_modules/core-js/internals/hidden-keys.js ***! \*******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = {}; /***/ }), /***/ "./node_modules/core-js/internals/ie8-dom-define.js": /*!**********************************************************!*\ !*** ./node_modules/core-js/internals/ie8-dom-define.js ***! \**********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js"); var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); var createElement = __webpack_require__(/*! ../internals/document-create-element */ "./node_modules/core-js/internals/document-create-element.js"); // Thanks to IE8 for its funny defineProperty module.exports = !DESCRIPTORS && !fails(function () { // eslint-disable-next-line es/no-object-defineproperty -- required for testing return Object.defineProperty(createElement('div'), 'a', { get: function () { return 7; } }).a !== 7; }); /***/ }), /***/ "./node_modules/core-js/internals/inspect-source.js": /*!**********************************************************!*\ !*** ./node_modules/core-js/internals/inspect-source.js ***! \**********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var store = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js"); var functionToString = uncurryThis(Function.toString); // this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper if (!isCallable(store.inspectSource)) { store.inspectSource = function (it) { return functionToString(it); }; } module.exports = store.inspectSource; /***/ }), /***/ "./node_modules/core-js/internals/internal-state.js": /*!**********************************************************!*\ !*** ./node_modules/core-js/internals/internal-state.js ***! \**********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var NATIVE_WEAK_MAP = __webpack_require__(/*! ../internals/weak-map-basic-detection */ "./node_modules/core-js/internals/weak-map-basic-detection.js"); var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js"); var createNonEnumerableProperty = __webpack_require__(/*! ../internals/create-non-enumerable-property */ "./node_modules/core-js/internals/create-non-enumerable-property.js"); var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js"); var shared = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js"); var sharedKey = __webpack_require__(/*! ../internals/shared-key */ "./node_modules/core-js/internals/shared-key.js"); var hiddenKeys = __webpack_require__(/*! ../internals/hidden-keys */ "./node_modules/core-js/internals/hidden-keys.js"); var OBJECT_ALREADY_INITIALIZED = 'Object already initialized'; var TypeError = global.TypeError; var WeakMap = global.WeakMap; var set, get, has; var enforce = function (it) { return has(it) ? get(it) : set(it, {}); }; var getterFor = function (TYPE) { return function (it) { var state; if (!isObject(it) || (state = get(it)).type !== TYPE) { throw new TypeError('Incompatible receiver, ' + TYPE + ' required'); } return state; }; }; if (NATIVE_WEAK_MAP || shared.state) { var store = shared.state || (shared.state = new WeakMap()); /* eslint-disable no-self-assign -- prototype methods protection */ store.get = store.get; store.has = store.has; store.set = store.set; /* eslint-enable no-self-assign -- prototype methods protection */ set = function (it, metadata) { if (store.has(it)) throw new TypeError(OBJECT_ALREADY_INITIALIZED); metadata.facade = it; store.set(it, metadata); return metadata; }; get = function (it) { return store.get(it) || {}; }; has = function (it) { return store.has(it); }; } else { var STATE = sharedKey('state'); hiddenKeys[STATE] = true; set = function (it, metadata) { if (hasOwn(it, STATE)) throw new TypeError(OBJECT_ALREADY_INITIALIZED); metadata.facade = it; createNonEnumerableProperty(it, STATE, metadata); return metadata; }; get = function (it) { return hasOwn(it, STATE) ? it[STATE] : {}; }; has = function (it) { return hasOwn(it, STATE); }; } module.exports = { set: set, get: get, has: has, enforce: enforce, getterFor: getterFor }; /***/ }), /***/ "./node_modules/core-js/internals/is-callable.js": /*!*******************************************************!*\ !*** ./node_modules/core-js/internals/is-callable.js ***! \*******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot var documentAll = typeof document == 'object' && document.all; // `IsCallable` abstract operation // https://tc39.es/ecma262/#sec-iscallable // eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing module.exports = typeof documentAll == 'undefined' && documentAll !== undefined ? function (argument) { return typeof argument == 'function' || argument === documentAll; } : function (argument) { return typeof argument == 'function'; }; /***/ }), /***/ "./node_modules/core-js/internals/is-null-or-undefined.js": /*!****************************************************************!*\ !*** ./node_modules/core-js/internals/is-null-or-undefined.js ***! \****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; // we can't use just `it == null` since of `document.all` special case // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec module.exports = function (it) { return it === null || it === undefined; }; /***/ }), /***/ "./node_modules/core-js/internals/is-object.js": /*!*****************************************************!*\ !*** ./node_modules/core-js/internals/is-object.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); module.exports = function (it) { return typeof it == 'object' ? it !== null : isCallable(it); }; /***/ }), /***/ "./node_modules/core-js/internals/is-pure.js": /*!***************************************************!*\ !*** ./node_modules/core-js/internals/is-pure.js ***! \***************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = false; /***/ }), /***/ "./node_modules/core-js/internals/is-symbol.js": /*!*****************************************************!*\ !*** ./node_modules/core-js/internals/is-symbol.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var getBuiltIn = __webpack_require__(/*! ../internals/get-built-in */ "./node_modules/core-js/internals/get-built-in.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var isPrototypeOf = __webpack_require__(/*! ../internals/object-is-prototype-of */ "./node_modules/core-js/internals/object-is-prototype-of.js"); var USE_SYMBOL_AS_UID = __webpack_require__(/*! ../internals/use-symbol-as-uid */ "./node_modules/core-js/internals/use-symbol-as-uid.js"); var $Object = Object; module.exports = USE_SYMBOL_AS_UID ? function (it) { return typeof it == 'symbol'; } : function (it) { var $Symbol = getBuiltIn('Symbol'); return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it)); }; /***/ }), /***/ "./node_modules/core-js/internals/make-built-in.js": /*!*********************************************************!*\ !*** ./node_modules/core-js/internals/make-built-in.js ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js"); var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js"); var CONFIGURABLE_FUNCTION_NAME = __webpack_require__(/*! ../internals/function-name */ "./node_modules/core-js/internals/function-name.js").CONFIGURABLE; var inspectSource = __webpack_require__(/*! ../internals/inspect-source */ "./node_modules/core-js/internals/inspect-source.js"); var InternalStateModule = __webpack_require__(/*! ../internals/internal-state */ "./node_modules/core-js/internals/internal-state.js"); var enforceInternalState = InternalStateModule.enforce; var getInternalState = InternalStateModule.get; var $String = String; // eslint-disable-next-line es/no-object-defineproperty -- safe var defineProperty = Object.defineProperty; var stringSlice = uncurryThis(''.slice); var replace = uncurryThis(''.replace); var join = uncurryThis([].join); var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () { return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8; }); var TEMPLATE = String(String).split('String'); var makeBuiltIn = module.exports = function (value, name, options) { if (stringSlice($String(name), 0, 7) === 'Symbol(') { name = '[' + replace($String(name), /^Symbol\(([^)]*)\).*$/, '$1') + ']'; } if (options && options.getter) name = 'get ' + name; if (options && options.setter) name = 'set ' + name; if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) { if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true }); else value.name = name; } if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) { defineProperty(value, 'length', { value: options.arity }); } try { if (options && hasOwn(options, 'constructor') && options.constructor) { if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false }); // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable } else if (value.prototype) value.prototype = undefined; } catch (error) { /* empty */ } var state = enforceInternalState(value); if (!hasOwn(state, 'source')) { state.source = join(TEMPLATE, typeof name == 'string' ? name : ''); } return value; }; // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative // eslint-disable-next-line no-extend-native -- required Function.prototype.toString = makeBuiltIn(function toString() { return isCallable(this) && getInternalState(this).source || inspectSource(this); }, 'toString'); /***/ }), /***/ "./node_modules/core-js/internals/object-define-property.js": /*!******************************************************************!*\ !*** ./node_modules/core-js/internals/object-define-property.js ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js"); var IE8_DOM_DEFINE = __webpack_require__(/*! ../internals/ie8-dom-define */ "./node_modules/core-js/internals/ie8-dom-define.js"); var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(/*! ../internals/v8-prototype-define-bug */ "./node_modules/core-js/internals/v8-prototype-define-bug.js"); var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js"); var toPropertyKey = __webpack_require__(/*! ../internals/to-property-key */ "./node_modules/core-js/internals/to-property-key.js"); var $TypeError = TypeError; // eslint-disable-next-line es/no-object-defineproperty -- safe var $defineProperty = Object.defineProperty; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ENUMERABLE = 'enumerable'; var CONFIGURABLE = 'configurable'; var WRITABLE = 'writable'; // `Object.defineProperty` method // https://tc39.es/ecma262/#sec-object.defineproperty exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) { anObject(O); P = toPropertyKey(P); anObject(Attributes); if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) { var current = $getOwnPropertyDescriptor(O, P); if (current && current[WRITABLE]) { O[P] = Attributes.value; Attributes = { configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE], enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE], writable: false }; } } return $defineProperty(O, P, Attributes); } : $defineProperty : function defineProperty(O, P, Attributes) { anObject(O); P = toPropertyKey(P); anObject(Attributes); if (IE8_DOM_DEFINE) try { return $defineProperty(O, P, Attributes); } catch (error) { /* empty */ } if ('get' in Attributes || 'set' in Attributes) throw new $TypeError('Accessors not supported'); if ('value' in Attributes) O[P] = Attributes.value; return O; }; /***/ }), /***/ "./node_modules/core-js/internals/object-is-prototype-of.js": /*!******************************************************************!*\ !*** ./node_modules/core-js/internals/object-is-prototype-of.js ***! \******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); module.exports = uncurryThis({}.isPrototypeOf); /***/ }), /***/ "./node_modules/core-js/internals/object-to-string.js": /*!************************************************************!*\ !*** ./node_modules/core-js/internals/object-to-string.js ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js"); var classof = __webpack_require__(/*! ../internals/classof */ "./node_modules/core-js/internals/classof.js"); // `Object.prototype.toString` method implementation // https://tc39.es/ecma262/#sec-object.prototype.tostring module.exports = TO_STRING_TAG_SUPPORT ? {}.toString : function toString() { return '[object ' + classof(this) + ']'; }; /***/ }), /***/ "./node_modules/core-js/internals/ordinary-to-primitive.js": /*!*****************************************************************!*\ !*** ./node_modules/core-js/internals/ordinary-to-primitive.js ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var call = __webpack_require__(/*! ../internals/function-call */ "./node_modules/core-js/internals/function-call.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js"); var $TypeError = TypeError; // `OrdinaryToPrimitive` abstract operation // https://tc39.es/ecma262/#sec-ordinarytoprimitive module.exports = function (input, pref) { var fn, val; if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val; if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val; if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val; throw new $TypeError("Can't convert object to primitive value"); }; /***/ }), /***/ "./node_modules/core-js/internals/regexp-flags.js": /*!********************************************************!*\ !*** ./node_modules/core-js/internals/regexp-flags.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js"); // `RegExp.prototype.flags` getter implementation // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags module.exports = function () { var that = anObject(this); var result = ''; if (that.hasIndices) result += 'd'; if (that.global) result += 'g'; if (that.ignoreCase) result += 'i'; if (that.multiline) result += 'm'; if (that.dotAll) result += 's'; if (that.unicode) result += 'u'; if (that.unicodeSets) result += 'v'; if (that.sticky) result += 'y'; return result; }; /***/ }), /***/ "./node_modules/core-js/internals/regexp-get-flags.js": /*!************************************************************!*\ !*** ./node_modules/core-js/internals/regexp-get-flags.js ***! \************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var call = __webpack_require__(/*! ../internals/function-call */ "./node_modules/core-js/internals/function-call.js"); var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js"); var isPrototypeOf = __webpack_require__(/*! ../internals/object-is-prototype-of */ "./node_modules/core-js/internals/object-is-prototype-of.js"); var regExpFlags = __webpack_require__(/*! ../internals/regexp-flags */ "./node_modules/core-js/internals/regexp-flags.js"); var RegExpPrototype = RegExp.prototype; module.exports = function (R) { var flags = R.flags; return flags === undefined && !('flags' in RegExpPrototype) && !hasOwn(R, 'flags') && isPrototypeOf(RegExpPrototype, R) ? call(regExpFlags, R) : flags; }; /***/ }), /***/ "./node_modules/core-js/internals/require-object-coercible.js": /*!********************************************************************!*\ !*** ./node_modules/core-js/internals/require-object-coercible.js ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isNullOrUndefined = __webpack_require__(/*! ../internals/is-null-or-undefined */ "./node_modules/core-js/internals/is-null-or-undefined.js"); var $TypeError = TypeError; // `RequireObjectCoercible` abstract operation // https://tc39.es/ecma262/#sec-requireobjectcoercible module.exports = function (it) { if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it); return it; }; /***/ }), /***/ "./node_modules/core-js/internals/shared-key.js": /*!******************************************************!*\ !*** ./node_modules/core-js/internals/shared-key.js ***! \******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var shared = __webpack_require__(/*! ../internals/shared */ "./node_modules/core-js/internals/shared.js"); var uid = __webpack_require__(/*! ../internals/uid */ "./node_modules/core-js/internals/uid.js"); var keys = shared('keys'); module.exports = function (key) { return keys[key] || (keys[key] = uid(key)); }; /***/ }), /***/ "./node_modules/core-js/internals/shared-store.js": /*!********************************************************!*\ !*** ./node_modules/core-js/internals/shared-store.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var IS_PURE = __webpack_require__(/*! ../internals/is-pure */ "./node_modules/core-js/internals/is-pure.js"); var globalThis = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var defineGlobalProperty = __webpack_require__(/*! ../internals/define-global-property */ "./node_modules/core-js/internals/define-global-property.js"); var SHARED = '__core-js_shared__'; var store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {}); (store.versions || (store.versions = [])).push({ version: '3.37.1', mode: IS_PURE ? 'pure' : 'global', copyright: '© 2014-2024 Denis Pushkarev (zloirock.ru)', license: 'https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE', source: 'https://github.com/zloirock/core-js' }); /***/ }), /***/ "./node_modules/core-js/internals/shared.js": /*!**************************************************!*\ !*** ./node_modules/core-js/internals/shared.js ***! \**************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var store = __webpack_require__(/*! ../internals/shared-store */ "./node_modules/core-js/internals/shared-store.js"); module.exports = function (key, value) { return store[key] || (store[key] = value || {}); }; /***/ }), /***/ "./node_modules/core-js/internals/symbol-constructor-detection.js": /*!************************************************************************!*\ !*** ./node_modules/core-js/internals/symbol-constructor-detection.js ***! \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* eslint-disable es/no-symbol -- required for testing */ var V8_VERSION = __webpack_require__(/*! ../internals/engine-v8-version */ "./node_modules/core-js/internals/engine-v8-version.js"); var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var $String = global.String; // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing module.exports = !!Object.getOwnPropertySymbols && !fails(function () { var symbol = Symbol('symbol detection'); // Chrome 38 Symbol has incorrect toString conversion // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will, // of course, fail. return !$String(symbol) || !(Object(symbol) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances !Symbol.sham && V8_VERSION && V8_VERSION < 41; }); /***/ }), /***/ "./node_modules/core-js/internals/to-object.js": /*!*****************************************************!*\ !*** ./node_modules/core-js/internals/to-object.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ "./node_modules/core-js/internals/require-object-coercible.js"); var $Object = Object; // `ToObject` abstract operation // https://tc39.es/ecma262/#sec-toobject module.exports = function (argument) { return $Object(requireObjectCoercible(argument)); }; /***/ }), /***/ "./node_modules/core-js/internals/to-primitive.js": /*!********************************************************!*\ !*** ./node_modules/core-js/internals/to-primitive.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var call = __webpack_require__(/*! ../internals/function-call */ "./node_modules/core-js/internals/function-call.js"); var isObject = __webpack_require__(/*! ../internals/is-object */ "./node_modules/core-js/internals/is-object.js"); var isSymbol = __webpack_require__(/*! ../internals/is-symbol */ "./node_modules/core-js/internals/is-symbol.js"); var getMethod = __webpack_require__(/*! ../internals/get-method */ "./node_modules/core-js/internals/get-method.js"); var ordinaryToPrimitive = __webpack_require__(/*! ../internals/ordinary-to-primitive */ "./node_modules/core-js/internals/ordinary-to-primitive.js"); var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ "./node_modules/core-js/internals/well-known-symbol.js"); var $TypeError = TypeError; var TO_PRIMITIVE = wellKnownSymbol('toPrimitive'); // `ToPrimitive` abstract operation // https://tc39.es/ecma262/#sec-toprimitive module.exports = function (input, pref) { if (!isObject(input) || isSymbol(input)) return input; var exoticToPrim = getMethod(input, TO_PRIMITIVE); var result; if (exoticToPrim) { if (pref === undefined) pref = 'default'; result = call(exoticToPrim, input, pref); if (!isObject(result) || isSymbol(result)) return result; throw new $TypeError("Can't convert object to primitive value"); } if (pref === undefined) pref = 'number'; return ordinaryToPrimitive(input, pref); }; /***/ }), /***/ "./node_modules/core-js/internals/to-property-key.js": /*!***********************************************************!*\ !*** ./node_modules/core-js/internals/to-property-key.js ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var toPrimitive = __webpack_require__(/*! ../internals/to-primitive */ "./node_modules/core-js/internals/to-primitive.js"); var isSymbol = __webpack_require__(/*! ../internals/is-symbol */ "./node_modules/core-js/internals/is-symbol.js"); // `ToPropertyKey` abstract operation // https://tc39.es/ecma262/#sec-topropertykey module.exports = function (argument) { var key = toPrimitive(argument, 'string'); return isSymbol(key) ? key : key + ''; }; /***/ }), /***/ "./node_modules/core-js/internals/to-string-tag-support.js": /*!*****************************************************************!*\ !*** ./node_modules/core-js/internals/to-string-tag-support.js ***! \*****************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var wellKnownSymbol = __webpack_require__(/*! ../internals/well-known-symbol */ "./node_modules/core-js/internals/well-known-symbol.js"); var TO_STRING_TAG = wellKnownSymbol('toStringTag'); var test = {}; test[TO_STRING_TAG] = 'z'; module.exports = String(test) === '[object z]'; /***/ }), /***/ "./node_modules/core-js/internals/to-string.js": /*!*****************************************************!*\ !*** ./node_modules/core-js/internals/to-string.js ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var classof = __webpack_require__(/*! ../internals/classof */ "./node_modules/core-js/internals/classof.js"); var $String = String; module.exports = function (argument) { if (classof(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string'); return $String(argument); }; /***/ }), /***/ "./node_modules/core-js/internals/try-to-string.js": /*!*********************************************************!*\ !*** ./node_modules/core-js/internals/try-to-string.js ***! \*********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var $String = String; module.exports = function (argument) { try { return $String(argument); } catch (error) { return 'Object'; } }; /***/ }), /***/ "./node_modules/core-js/internals/uid.js": /*!***********************************************!*\ !*** ./node_modules/core-js/internals/uid.js ***! \***********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); var id = 0; var postfix = Math.random(); var toString = uncurryThis(1.0.toString); module.exports = function (key) { return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36); }; /***/ }), /***/ "./node_modules/core-js/internals/use-symbol-as-uid.js": /*!*************************************************************!*\ !*** ./node_modules/core-js/internals/use-symbol-as-uid.js ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* eslint-disable es/no-symbol -- required for testing */ var NATIVE_SYMBOL = __webpack_require__(/*! ../internals/symbol-constructor-detection */ "./node_modules/core-js/internals/symbol-constructor-detection.js"); module.exports = NATIVE_SYMBOL && !Symbol.sham && typeof Symbol.iterator == 'symbol'; /***/ }), /***/ "./node_modules/core-js/internals/v8-prototype-define-bug.js": /*!*******************************************************************!*\ !*** ./node_modules/core-js/internals/v8-prototype-define-bug.js ***! \*******************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var DESCRIPTORS = __webpack_require__(/*! ../internals/descriptors */ "./node_modules/core-js/internals/descriptors.js"); var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); // V8 ~ Chrome 36- // https://bugs.chromium.org/p/v8/issues/detail?id=3334 module.exports = DESCRIPTORS && fails(function () { // eslint-disable-next-line es/no-object-defineproperty -- required for testing return Object.defineProperty(function () { /* empty */ }, 'prototype', { value: 42, writable: false }).prototype !== 42; }); /***/ }), /***/ "./node_modules/core-js/internals/weak-map-basic-detection.js": /*!********************************************************************!*\ !*** ./node_modules/core-js/internals/weak-map-basic-detection.js ***! \********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var isCallable = __webpack_require__(/*! ../internals/is-callable */ "./node_modules/core-js/internals/is-callable.js"); var WeakMap = global.WeakMap; module.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap)); /***/ }), /***/ "./node_modules/core-js/internals/well-known-symbol.js": /*!*************************************************************!*\ !*** ./node_modules/core-js/internals/well-known-symbol.js ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var global = __webpack_require__(/*! ../internals/global */ "./node_modules/core-js/internals/global.js"); var shared = __webpack_require__(/*! ../internals/shared */ "./node_modules/core-js/internals/shared.js"); var hasOwn = __webpack_require__(/*! ../internals/has-own-property */ "./node_modules/core-js/internals/has-own-property.js"); var uid = __webpack_require__(/*! ../internals/uid */ "./node_modules/core-js/internals/uid.js"); var NATIVE_SYMBOL = __webpack_require__(/*! ../internals/symbol-constructor-detection */ "./node_modules/core-js/internals/symbol-constructor-detection.js"); var USE_SYMBOL_AS_UID = __webpack_require__(/*! ../internals/use-symbol-as-uid */ "./node_modules/core-js/internals/use-symbol-as-uid.js"); var Symbol = global.Symbol; var WellKnownSymbolsStore = shared('wks'); var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol['for'] || Symbol : Symbol && Symbol.withoutSetter || uid; module.exports = function (name) { if (!hasOwn(WellKnownSymbolsStore, name)) { WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol, name) ? Symbol[name] : createWellKnownSymbol('Symbol.' + name); } return WellKnownSymbolsStore[name]; }; /***/ }), /***/ "./node_modules/core-js/modules/es.date.to-string.js": /*!***********************************************************!*\ !*** ./node_modules/core-js/modules/es.date.to-string.js ***! \***********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; // TODO: Remove from `core-js@4` var uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ "./node_modules/core-js/internals/function-uncurry-this.js"); var defineBuiltIn = __webpack_require__(/*! ../internals/define-built-in */ "./node_modules/core-js/internals/define-built-in.js"); var DatePrototype = Date.prototype; var INVALID_DATE = 'Invalid Date'; var TO_STRING = 'toString'; var nativeDateToString = uncurryThis(DatePrototype[TO_STRING]); var thisTimeValue = uncurryThis(DatePrototype.getTime); // `Date.prototype.toString` method // https://tc39.es/ecma262/#sec-date.prototype.tostring if (String(new Date(NaN)) !== INVALID_DATE) { defineBuiltIn(DatePrototype, TO_STRING, function toString() { var value = thisTimeValue(this); // eslint-disable-next-line no-self-compare -- NaN check return value === value ? nativeDateToString(this) : INVALID_DATE; }); } /***/ }), /***/ "./node_modules/core-js/modules/es.object.to-string.js": /*!*************************************************************!*\ !*** ./node_modules/core-js/modules/es.object.to-string.js ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var TO_STRING_TAG_SUPPORT = __webpack_require__(/*! ../internals/to-string-tag-support */ "./node_modules/core-js/internals/to-string-tag-support.js"); var defineBuiltIn = __webpack_require__(/*! ../internals/define-built-in */ "./node_modules/core-js/internals/define-built-in.js"); var toString = __webpack_require__(/*! ../internals/object-to-string */ "./node_modules/core-js/internals/object-to-string.js"); // `Object.prototype.toString` method // https://tc39.es/ecma262/#sec-object.prototype.tostring if (!TO_STRING_TAG_SUPPORT) { defineBuiltIn(Object.prototype, 'toString', toString, { unsafe: true }); } /***/ }), /***/ "./node_modules/core-js/modules/es.regexp.to-string.js": /*!*************************************************************!*\ !*** ./node_modules/core-js/modules/es.regexp.to-string.js ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var PROPER_FUNCTION_NAME = __webpack_require__(/*! ../internals/function-name */ "./node_modules/core-js/internals/function-name.js").PROPER; var defineBuiltIn = __webpack_require__(/*! ../internals/define-built-in */ "./node_modules/core-js/internals/define-built-in.js"); var anObject = __webpack_require__(/*! ../internals/an-object */ "./node_modules/core-js/internals/an-object.js"); var $toString = __webpack_require__(/*! ../internals/to-string */ "./node_modules/core-js/internals/to-string.js"); var fails = __webpack_require__(/*! ../internals/fails */ "./node_modules/core-js/internals/fails.js"); var getRegExpFlags = __webpack_require__(/*! ../internals/regexp-get-flags */ "./node_modules/core-js/internals/regexp-get-flags.js"); var TO_STRING = 'toString'; var RegExpPrototype = RegExp.prototype; var nativeToString = RegExpPrototype[TO_STRING]; var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) !== '/a/b'; }); // FF44- RegExp#toString has a wrong name var INCORRECT_NAME = PROPER_FUNCTION_NAME && nativeToString.name !== TO_STRING; // `RegExp.prototype.toString` method // https://tc39.es/ecma262/#sec-regexp.prototype.tostring if (NOT_GENERIC || INCORRECT_NAME) { defineBuiltIn(RegExpPrototype, TO_STRING, function toString() { var R = anObject(this); var pattern = $toString(R.source); var flags = $toString(getRegExpFlags(R)); return '/' + pattern + '/' + flags; }, { unsafe: true }); } /***/ }), /***/ "./node_modules/webpack/buildin/global.js": /*!***********************************!*\ !*** (webpack)/buildin/global.js ***! \***********************************/ /*! no static exports found */ /***/ (function(module, exports) { var g; // This works in non-strict mode g = (function() { return this; })(); try { // This works if eval is allowed (see CSP) g = g || new Function("return this")(); } catch (e) { // This works if the window reference is available if (typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; /***/ }) }]); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL2xvY2FsZXMvZnIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvY29yZS9tYWluLmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9jb3JlL21haW4uZXNtLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9AZnVsbGNhbGVuZGFyL2RheWdyaWQvbWFpbi5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL0BmdWxsY2FsZW5kYXIvZGF5Z3JpZC9tYWluLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZ1bGxjYWxlbmRhci9pbnRlcmFjdGlvbi9tYWluLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvYS1jYWxsYWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvYW4tb2JqZWN0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9jbGFzc29mLXJhdy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvY2xhc3NvZi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvY3JlYXRlLW5vbi1lbnVtZXJhYmxlLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9jcmVhdGUtcHJvcGVydHktZGVzY3JpcHRvci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZGVmaW5lLWJ1aWx0LWluLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9kZWZpbmUtZ2xvYmFsLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9kZXNjcmlwdG9ycy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZG9jdW1lbnQtY3JlYXRlLWVsZW1lbnQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2VuZ2luZS11c2VyLWFnZW50LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9lbmdpbmUtdjgtdmVyc2lvbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZmFpbHMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2Z1bmN0aW9uLWJpbmQtbmF0aXZlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mdW5jdGlvbi1jYWxsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mdW5jdGlvbi1uYW1lLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9mdW5jdGlvbi11bmN1cnJ5LXRoaXMuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2dldC1idWlsdC1pbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZ2V0LW1ldGhvZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9oYXMtb3duLXByb3BlcnR5LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9oaWRkZW4ta2V5cy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvaWU4LWRvbS1kZWZpbmUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2luc3BlY3Qtc291cmNlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9pbnRlcm5hbC1zdGF0ZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvaXMtY2FsbGFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLW51bGwtb3ItdW5kZWZpbmVkLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9pcy1vYmplY3QuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLXB1cmUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL2lzLXN5bWJvbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvbWFrZS1idWlsdC1pbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LWRlZmluZS1wcm9wZXJ0eS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LWlzLXByb3RvdHlwZS1vZi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb2JqZWN0LXRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvb3JkaW5hcnktdG8tcHJpbWl0aXZlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9yZWdleHAtZmxhZ3MuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3JlZ2V4cC1nZXQtZmxhZ3MuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3JlcXVpcmUtb2JqZWN0LWNvZXJjaWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2hhcmVkLWtleS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvc2hhcmVkLXN0b3JlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy9zaGFyZWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3N5bWJvbC1jb25zdHJ1Y3Rvci1kZXRlY3Rpb24uanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RvLW9iamVjdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvdG8tcHJpbWl0aXZlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy90by1wcm9wZXJ0eS1rZXkuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvdG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy90cnktdG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy91aWQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvaW50ZXJuYWxzL3VzZS1zeW1ib2wtYXMtdWlkLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy92OC1wcm90b3R5cGUtZGVmaW5lLWJ1Zy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9pbnRlcm5hbHMvd2Vhay1tYXAtYmFzaWMtZGV0ZWN0aW9uLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2ludGVybmFscy93ZWxsLWtub3duLXN5bWJvbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmRhdGUudG8tc3RyaW5nLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMub2JqZWN0LnRvLXN0cmluZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnJlZ2V4cC50by1zdHJpbmcuanMiLCJ3ZWJwYWNrOi8vLyh3ZWJwYWNrKS9idWlsZGluL2dsb2JhbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBLElBQUksS0FBNEQ7QUFDaEUsSUFBSSxTQUNxSTtBQUN6SSxDQUFDLG9CQUFvQjs7QUFFckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDOzs7Ozs7Ozs7Ozs7QUM5QkQsdUM7Ozs7Ozs7Ozs7OztBQ0FBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Q7QUFDbEQ7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsMkJBQTJCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBLFlBQVk7QUFDWjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQsaUZBQWlGO0FBQ2pGLHFCQUFxQjtBQUNyQix5QkFBeUI7QUFDekIseUJBQXlCO0FBQ3pCO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFGQUFxRjtBQUNyRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvRUFBb0U7QUFDcEUsd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQW1CO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQix1Q0FBdUM7QUFDeEQsaUJBQWlCLHlCQUF5QjtBQUMxQztBQUNBO0FBQ0Esd0JBQXdCLGNBQWM7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHVCQUF1QjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLHNCQUFzQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQix1QkFBdUI7QUFDM0M7QUFDQTtBQUNBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsZUFBZTtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDO0FBQ2xDO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDLHNDQUFzQztBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9FQUFvRTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVUsZ0JBQWdCLHNDQUFzQyxpQkFBaUIsRUFBRTtBQUNuRix5QkFBeUIsdURBQXVEO0FBQ2hGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixzQkFBc0I7QUFDekM7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0RBQWdELE9BQU87QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsMkJBQTJCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIseUJBQXlCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxRQUFRO0FBQ2pEO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxRQUFRO0FBQ3pDO0FBQ0E7QUFDQSxrQ0FBa0M7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLGlCQUFpQjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw2Q0FBNkMseUJBQXlCO0FBQ3RFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQyxzQ0FBc0M7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLHNCQUFzQjtBQUNyRTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQseUJBQXlCO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFNBQVMsZUFBZTtBQUNwQztBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIsOEJBQThCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEMsS0FBSztBQUNMLFlBQVk7QUFDWjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQW1CO0FBQ2xDO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEMsaUNBQWlDLHFDQUFxQztBQUN0RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEMsNkJBQTZCLHlDQUF5QztBQUN0RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRDtBQUMzRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0EsZUFBZSxTQUFTO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEMsb0JBQW9CO0FBQ3BCO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHFCQUFxQjtBQUN4RCxrQ0FBa0Msb0JBQW9CO0FBQ3REO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0EsbUNBQW1DO0FBQ25DLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRDtBQUN0RDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSx5REFBeUQ7QUFDekQ7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0EsOEJBQThCLDhCQUE4QjtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyx1QkFBdUI7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixlQUFlO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFLGdCQUFnQjtBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUVBQW1FO0FBQ25FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsZ0JBQWdCO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxnQkFBZ0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2Qiw2Q0FBNkM7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUVBQXVFO0FBQ3ZFLHlDQUF5QztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBLHNCQUFzQixFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsUUFBUSxFQUFFO0FBQzlHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTCxzQkFBc0IsZ0JBQWdCLDJDQUEyQztBQUNqRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsc0JBQXNCLDRCQUE0QixnQkFBZ0I7QUFDNUYsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxzQkFBc0I7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0RBQStEO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQ7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVELHdCQUF3QjtBQUMvRSxtREFBbUQsd0JBQXdCO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQztBQUNuQyxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnRUFBZ0U7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFT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M0Q7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQ7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQ7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLGlCQUFpQjtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLDhCQUE4QixlQUFlO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLG9CQUFv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QTtBQUNBLEdBQUcsR0FBRyxlQUFlO0FBQ3JCOzs7Ozs7Ozs7Ozs7QUN6QkE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0Q0FBNEM7O0FBRTVDIiwiZmlsZSI6InZlbmRvcnN+ZnVsbGNhbGVuZGFyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG4gICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcbiAgICAoZ2xvYmFsID0gZ2xvYmFsIHx8IHNlbGYsIChnbG9iYWwuRnVsbENhbGVuZGFyTG9jYWxlcyA9IGdsb2JhbC5GdWxsQ2FsZW5kYXJMb2NhbGVzIHx8IHt9LCBnbG9iYWwuRnVsbENhbGVuZGFyTG9jYWxlcy5mciA9IGZhY3RvcnkoKSkpO1xufSh0aGlzLCBmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuICAgIHZhciBmciA9IHtcbiAgICAgICAgY29kZTogXCJmclwiLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsXG4gICAgICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgICAgICBidXR0b25UZXh0OiB7XG4gICAgICAgICAgICBwcmV2OiBcIlByw6ljw6lkZW50XCIsXG4gICAgICAgICAgICBuZXh0OiBcIlN1aXZhbnRcIixcbiAgICAgICAgICAgIHRvZGF5OiBcIkF1am91cmQnaHVpXCIsXG4gICAgICAgICAgICB5ZWFyOiBcIkFubsOpZVwiLFxuICAgICAgICAgICAgbW9udGg6IFwiTW9pc1wiLFxuICAgICAgICAgICAgd2VlazogXCJTZW1haW5lXCIsXG4gICAgICAgICAgICBkYXk6IFwiSm91clwiLFxuICAgICAgICAgICAgbGlzdDogXCJQbGFubmluZ1wiXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtMYWJlbDogXCJTZW0uXCIsXG4gICAgICAgIGFsbERheUh0bWw6IFwiVG91dGUgbGE8YnIvPmpvdXJuw6llXCIsXG4gICAgICAgIGV2ZW50TGltaXRUZXh0OiBcImVuIHBsdXNcIixcbiAgICAgICAgbm9FdmVudHNNZXNzYWdlOiBcIkF1Y3VuIMOpdsOpbmVtZW50IMOgIGFmZmljaGVyXCJcbiAgICB9O1xuXG4gICAgcmV0dXJuIGZyO1xuXG59KSk7XG4iLCIvLyBleHRyYWN0ZWQgYnkgbWluaS1jc3MtZXh0cmFjdC1wbHVnaW4iLCIvKiFcbkZ1bGxDYWxlbmRhciBDb3JlIFBhY2thZ2UgdjQuNC4yXG5Eb2NzICYgTGljZW5zZTogaHR0cHM6Ly9mdWxsY2FsZW5kYXIuaW8vXG4oYykgMjAxOSBBZGFtIFNoYXdcbiovXG5cbi8vIENyZWF0aW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG52YXIgZWxlbWVudFByb3BIYXNoID0ge1xuICAgIGNsYXNzTmFtZTogdHJ1ZSxcbiAgICBjb2xTcGFuOiB0cnVlLFxuICAgIHJvd1NwYW46IHRydWVcbn07XG52YXIgY29udGFpbmVyVGFnSGFzaCA9IHtcbiAgICAnPHRyJzogJ3Rib2R5JyxcbiAgICAnPHRkJzogJ3RyJ1xufTtcbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnTmFtZSwgYXR0cnMsIGNvbnRlbnQpIHtcbiAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZ05hbWUpO1xuICAgIGlmIChhdHRycykge1xuICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBhdHRycykge1xuICAgICAgICAgICAgaWYgKGF0dHJOYW1lID09PSAnc3R5bGUnKSB7XG4gICAgICAgICAgICAgICAgYXBwbHlTdHlsZShlbCwgYXR0cnNbYXR0ck5hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGVsZW1lbnRQcm9wSGFzaFthdHRyTmFtZV0pIHtcbiAgICAgICAgICAgICAgICBlbFthdHRyTmFtZV0gPSBhdHRyc1thdHRyTmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJzW2F0dHJOYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICBlbC5pbm5lckhUTUwgPSBjb250ZW50OyAvLyBzaG9ydGN1dC4gbm8gbmVlZCB0byBwcm9jZXNzIEhUTUwgaW4gYW55IHdheVxuICAgIH1cbiAgICBlbHNlIGlmIChjb250ZW50ICE9IG51bGwpIHtcbiAgICAgICAgYXBwZW5kVG9FbGVtZW50KGVsLCBjb250ZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGVsO1xufVxuZnVuY3Rpb24gaHRtbFRvRWxlbWVudChodG1sKSB7XG4gICAgaHRtbCA9IGh0bWwudHJpbSgpO1xuICAgIHZhciBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGNvbXB1dGVDb250YWluZXJUYWcoaHRtbCkpO1xuICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSBodG1sO1xuICAgIHJldHVybiBjb250YWluZXIuZmlyc3RDaGlsZDtcbn1cbmZ1bmN0aW9uIGh0bWxUb0VsZW1lbnRzKGh0bWwpIHtcbiAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoaHRtbFRvTm9kZUxpc3QoaHRtbCkpO1xufVxuZnVuY3Rpb24gaHRtbFRvTm9kZUxpc3QoaHRtbCkge1xuICAgIGh0bWwgPSBodG1sLnRyaW0oKTtcbiAgICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChjb21wdXRlQ29udGFpbmVyVGFnKGh0bWwpKTtcbiAgICBjb250YWluZXIuaW5uZXJIVE1MID0gaHRtbDtcbiAgICByZXR1cm4gY29udGFpbmVyLmNoaWxkTm9kZXM7XG59XG4vLyBhc3N1bWVzIGh0bWwgYWxyZWFkeSB0cmltbWVkIGFuZCB0YWcgbmFtZXMgYXJlIGxvd2VyY2FzZVxuZnVuY3Rpb24gY29tcHV0ZUNvbnRhaW5lclRhZyhodG1sKSB7XG4gICAgcmV0dXJuIGNvbnRhaW5lclRhZ0hhc2hbaHRtbC5zdWJzdHIoMCwgMykgLy8gZmFzdGVyIHRoYW4gdXNpbmcgcmVnZXhcbiAgICBdIHx8ICdkaXYnO1xufVxuZnVuY3Rpb24gYXBwZW5kVG9FbGVtZW50KGVsLCBjb250ZW50KSB7XG4gICAgdmFyIGNoaWxkTm9kZXMgPSBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBlbC5hcHBlbmRDaGlsZChjaGlsZE5vZGVzW2ldKTtcbiAgICB9XG59XG5mdW5jdGlvbiBwcmVwZW5kVG9FbGVtZW50KHBhcmVudCwgY29udGVudCkge1xuICAgIHZhciBuZXdFbHMgPSBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpO1xuICAgIHZhciBhZnRlckVsID0gcGFyZW50LmZpcnN0Q2hpbGQgfHwgbnVsbDsgLy8gaWYgbm8gZmlyc3RDaGlsZCwgd2lsbCBhcHBlbmQgdG8gZW5kLCBidXQgdGhhdCdzIG9rYXksIGIvYyB0aGVyZSB3ZXJlIG5vIGNoaWxkcmVuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuZXdFbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShuZXdFbHNbaV0sIGFmdGVyRWwpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGluc2VydEFmdGVyRWxlbWVudChyZWZFbCwgY29udGVudCkge1xuICAgIHZhciBuZXdFbHMgPSBub3JtYWxpemVDb250ZW50KGNvbnRlbnQpO1xuICAgIHZhciBhZnRlckVsID0gcmVmRWwubmV4dFNpYmxpbmcgfHwgbnVsbDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5ld0Vscy5sZW5ndGg7IGkrKykge1xuICAgICAgICByZWZFbC5wYXJlbnROb2RlLmluc2VydEJlZm9yZShuZXdFbHNbaV0sIGFmdGVyRWwpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG5vcm1hbGl6ZUNvbnRlbnQoY29udGVudCkge1xuICAgIHZhciBlbHM7XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICBlbHMgPSBodG1sVG9FbGVtZW50cyhjb250ZW50KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoY29udGVudCBpbnN0YW5jZW9mIE5vZGUpIHtcbiAgICAgICAgZWxzID0gW2NvbnRlbnRdO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gTm9kZVtdIG9yIE5vZGVMaXN0XG4gICAgICAgIGVscyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNvbnRlbnQpO1xuICAgIH1cbiAgICByZXR1cm4gZWxzO1xufVxuZnVuY3Rpb24gcmVtb3ZlRWxlbWVudChlbCkge1xuICAgIGlmIChlbC5wYXJlbnROb2RlKSB7XG4gICAgICAgIGVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZWwpO1xuICAgIH1cbn1cbi8vIFF1ZXJ5aW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBmcm9tIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FbGVtZW50L2Nsb3Nlc3RcbnZhciBtYXRjaGVzTWV0aG9kID0gRWxlbWVudC5wcm90b3R5cGUubWF0Y2hlcyB8fFxuICAgIEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXNTZWxlY3RvciB8fFxuICAgIEVsZW1lbnQucHJvdG90eXBlLm1zTWF0Y2hlc1NlbGVjdG9yO1xudmFyIGNsb3Nlc3RNZXRob2QgPSBFbGVtZW50LnByb3RvdHlwZS5jbG9zZXN0IHx8IGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgIC8vIHBvbHlmaWxsXG4gICAgdmFyIGVsID0gdGhpcztcbiAgICBpZiAoIWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jb250YWlucyhlbCkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRvIHtcbiAgICAgICAgaWYgKGVsZW1lbnRNYXRjaGVzKGVsLCBzZWxlY3RvcikpIHtcbiAgICAgICAgICAgIHJldHVybiBlbDtcbiAgICAgICAgfVxuICAgICAgICBlbCA9IGVsLnBhcmVudEVsZW1lbnQgfHwgZWwucGFyZW50Tm9kZTtcbiAgICB9IHdoaWxlIChlbCAhPT0gbnVsbCAmJiBlbC5ub2RlVHlwZSA9PT0gMSk7XG4gICAgcmV0dXJuIG51bGw7XG59O1xuZnVuY3Rpb24gZWxlbWVudENsb3Nlc3QoZWwsIHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIGNsb3Nlc3RNZXRob2QuY2FsbChlbCwgc2VsZWN0b3IpO1xufVxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXMoZWwsIHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIG1hdGNoZXNNZXRob2QuY2FsbChlbCwgc2VsZWN0b3IpO1xufVxuLy8gYWNjZXB0cyBtdWx0aXBsZSBzdWJqZWN0IGVsc1xuLy8gcmV0dXJucyBhIHJlYWwgYXJyYXkuIGdvb2QgZm9yIG1ldGhvZHMgbGlrZSBmb3JFYWNoXG5mdW5jdGlvbiBmaW5kRWxlbWVudHMoY29udGFpbmVyLCBzZWxlY3Rvcikge1xuICAgIHZhciBjb250YWluZXJzID0gY29udGFpbmVyIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQgPyBbY29udGFpbmVyXSA6IGNvbnRhaW5lcjtcbiAgICB2YXIgYWxsTWF0Y2hlcyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29udGFpbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbWF0Y2hlcyA9IGNvbnRhaW5lcnNbaV0ucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWF0Y2hlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgYWxsTWF0Y2hlcy5wdXNoKG1hdGNoZXNbal0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhbGxNYXRjaGVzO1xufVxuLy8gYWNjZXB0cyBtdWx0aXBsZSBzdWJqZWN0IGVsc1xuLy8gb25seSBxdWVyaWVzIGRpcmVjdCBjaGlsZCBlbGVtZW50c1xuZnVuY3Rpb24gZmluZENoaWxkcmVuKHBhcmVudCwgc2VsZWN0b3IpIHtcbiAgICB2YXIgcGFyZW50cyA9IHBhcmVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ID8gW3BhcmVudF0gOiBwYXJlbnQ7XG4gICAgdmFyIGFsbE1hdGNoZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBwYXJlbnRzW2ldLmNoaWxkcmVuOyAvLyBvbmx5IGV2ZXIgZWxlbWVudHNcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY2hpbGROb2Rlc1tqXTtcbiAgICAgICAgICAgIGlmICghc2VsZWN0b3IgfHwgZWxlbWVudE1hdGNoZXMoY2hpbGROb2RlLCBzZWxlY3RvcikpIHtcbiAgICAgICAgICAgICAgICBhbGxNYXRjaGVzLnB1c2goY2hpbGROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYWxsTWF0Y2hlcztcbn1cbi8vIEF0dHJpYnV0ZXNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGZvcmNlQ2xhc3NOYW1lKGVsLCBjbGFzc05hbWUsIGJvb2wpIHtcbiAgICBpZiAoYm9vbCkge1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBlbC5jbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSk7XG4gICAgfVxufVxuLy8gU3R5bGVcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbnZhciBQSVhFTF9QUk9QX1JFID0gLyh0b3B8bGVmdHxyaWdodHxib3R0b218d2lkdGh8aGVpZ2h0KSQvaTtcbmZ1bmN0aW9uIGFwcGx5U3R5bGUoZWwsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgYXBwbHlTdHlsZVByb3AoZWwsIHByb3BOYW1lLCBwcm9wc1twcm9wTmFtZV0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFwcGx5U3R5bGVQcm9wKGVsLCBuYW1lLCB2YWwpIHtcbiAgICBpZiAodmFsID09IG51bGwpIHtcbiAgICAgICAgZWwuc3R5bGVbbmFtZV0gPSAnJztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicgJiYgUElYRUxfUFJPUF9SRS50ZXN0KG5hbWUpKSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gdmFsICsgJ3B4JztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGVsLnN0eWxlW25hbWVdID0gdmFsO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcG9pbnRJbnNpZGVSZWN0KHBvaW50LCByZWN0KSB7XG4gICAgcmV0dXJuIHBvaW50LmxlZnQgPj0gcmVjdC5sZWZ0ICYmXG4gICAgICAgIHBvaW50LmxlZnQgPCByZWN0LnJpZ2h0ICYmXG4gICAgICAgIHBvaW50LnRvcCA+PSByZWN0LnRvcCAmJlxuICAgICAgICBwb2ludC50b3AgPCByZWN0LmJvdHRvbTtcbn1cbi8vIFJldHVybnMgYSBuZXcgcmVjdGFuZ2xlIHRoYXQgaXMgdGhlIGludGVyc2VjdGlvbiBvZiB0aGUgdHdvIHJlY3RhbmdsZXMuIElmIHRoZXkgZG9uJ3QgaW50ZXJzZWN0LCByZXR1cm5zIGZhbHNlXG5mdW5jdGlvbiBpbnRlcnNlY3RSZWN0cyhyZWN0MSwgcmVjdDIpIHtcbiAgICB2YXIgcmVzID0ge1xuICAgICAgICBsZWZ0OiBNYXRoLm1heChyZWN0MS5sZWZ0LCByZWN0Mi5sZWZ0KSxcbiAgICAgICAgcmlnaHQ6IE1hdGgubWluKHJlY3QxLnJpZ2h0LCByZWN0Mi5yaWdodCksXG4gICAgICAgIHRvcDogTWF0aC5tYXgocmVjdDEudG9wLCByZWN0Mi50b3ApLFxuICAgICAgICBib3R0b206IE1hdGgubWluKHJlY3QxLmJvdHRvbSwgcmVjdDIuYm90dG9tKVxuICAgIH07XG4gICAgaWYgKHJlcy5sZWZ0IDwgcmVzLnJpZ2h0ICYmIHJlcy50b3AgPCByZXMuYm90dG9tKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIHRyYW5zbGF0ZVJlY3QocmVjdCwgZGVsdGFYLCBkZWx0YVkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiByZWN0LmxlZnQgKyBkZWx0YVgsXG4gICAgICAgIHJpZ2h0OiByZWN0LnJpZ2h0ICsgZGVsdGFYLFxuICAgICAgICB0b3A6IHJlY3QudG9wICsgZGVsdGFZLFxuICAgICAgICBib3R0b206IHJlY3QuYm90dG9tICsgZGVsdGFZXG4gICAgfTtcbn1cbi8vIFJldHVybnMgYSBuZXcgcG9pbnQgdGhhdCB3aWxsIGhhdmUgYmVlbiBtb3ZlZCB0byByZXNpZGUgd2l0aGluIHRoZSBnaXZlbiByZWN0YW5nbGVcbmZ1bmN0aW9uIGNvbnN0cmFpblBvaW50KHBvaW50LCByZWN0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogTWF0aC5taW4oTWF0aC5tYXgocG9pbnQubGVmdCwgcmVjdC5sZWZ0KSwgcmVjdC5yaWdodCksXG4gICAgICAgIHRvcDogTWF0aC5taW4oTWF0aC5tYXgocG9pbnQudG9wLCByZWN0LnRvcCksIHJlY3QuYm90dG9tKVxuICAgIH07XG59XG4vLyBSZXR1cm5zIGEgcG9pbnQgdGhhdCBpcyB0aGUgY2VudGVyIG9mIHRoZSBnaXZlbiByZWN0YW5nbGVcbmZ1bmN0aW9uIGdldFJlY3RDZW50ZXIocmVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IChyZWN0LmxlZnQgKyByZWN0LnJpZ2h0KSAvIDIsXG4gICAgICAgIHRvcDogKHJlY3QudG9wICsgcmVjdC5ib3R0b20pIC8gMlxuICAgIH07XG59XG4vLyBTdWJ0cmFjdHMgcG9pbnQyJ3MgY29vcmRpbmF0ZXMgZnJvbSBwb2ludDEncyBjb29yZGluYXRlcywgcmV0dXJuaW5nIGEgZGVsdGFcbmZ1bmN0aW9uIGRpZmZQb2ludHMocG9pbnQxLCBwb2ludDIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiBwb2ludDEubGVmdCAtIHBvaW50Mi5sZWZ0LFxuICAgICAgICB0b3A6IHBvaW50MS50b3AgLSBwb2ludDIudG9wXG4gICAgfTtcbn1cblxuLy8gTG9naWMgZm9yIGRldGVybWluaW5nIGlmLCB3aGVuIHRoZSBlbGVtZW50IGlzIHJpZ2h0LXRvLWxlZnQsIHRoZSBzY3JvbGxiYXIgYXBwZWFycyBvbiB0aGUgbGVmdCBzaWRlXG52YXIgaXNSdGxTY3JvbGxiYXJPbkxlZnQgPSBudWxsO1xuZnVuY3Rpb24gZ2V0SXNSdGxTY3JvbGxiYXJPbkxlZnQoKSB7XG4gICAgaWYgKGlzUnRsU2Nyb2xsYmFyT25MZWZ0ID09PSBudWxsKSB7XG4gICAgICAgIGlzUnRsU2Nyb2xsYmFyT25MZWZ0ID0gY29tcHV0ZUlzUnRsU2Nyb2xsYmFyT25MZWZ0KCk7XG4gICAgfVxuICAgIHJldHVybiBpc1J0bFNjcm9sbGJhck9uTGVmdDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVJc1J0bFNjcm9sbGJhck9uTGVmdCgpIHtcbiAgICB2YXIgb3V0ZXJFbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHtcbiAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgdG9wOiAtMTAwMCxcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICBib3JkZXI6IDAsXG4gICAgICAgICAgICBwYWRkaW5nOiAwLFxuICAgICAgICAgICAgb3ZlcmZsb3c6ICdzY3JvbGwnLFxuICAgICAgICAgICAgZGlyZWN0aW9uOiAncnRsJ1xuICAgICAgICB9XG4gICAgfSwgJzxkaXY+PC9kaXY+Jyk7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChvdXRlckVsKTtcbiAgICB2YXIgaW5uZXJFbCA9IG91dGVyRWwuZmlyc3RDaGlsZDtcbiAgICB2YXIgcmVzID0gaW5uZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ID4gb3V0ZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuICAgIHJlbW92ZUVsZW1lbnQob3V0ZXJFbCk7XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIFRoZSBzY3JvbGxiYXIgd2lkdGggY29tcHV0YXRpb25zIGluIGNvbXB1dGVFZGdlcyBhcmUgc29tZXRpbWVzIGZsYXdlZCB3aGVuIGl0IGNvbWVzIHRvXG4vLyByZXRpbmEgZGlzcGxheXMsIHJvdW5kaW5nLCBhbmQgSUUxMS4gTWFzc2FnZSB0aGVtIGludG8gYSB1c2FibGUgdmFsdWUuXG5mdW5jdGlvbiBzYW5pdGl6ZVNjcm9sbGJhcldpZHRoKHdpZHRoKSB7XG4gICAgd2lkdGggPSBNYXRoLm1heCgwLCB3aWR0aCk7IC8vIG5vIG5lZ2F0aXZlc1xuICAgIHdpZHRoID0gTWF0aC5yb3VuZCh3aWR0aCk7XG4gICAgcmV0dXJuIHdpZHRoO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlRWRnZXMoZWwsIGdldFBhZGRpbmcpIHtcbiAgICBpZiAoZ2V0UGFkZGluZyA9PT0gdm9pZCAwKSB7IGdldFBhZGRpbmcgPSBmYWxzZTsgfVxuICAgIHZhciBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIHZhciBib3JkZXJMZWZ0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5ib3JkZXJMZWZ0V2lkdGgsIDEwKSB8fCAwO1xuICAgIHZhciBib3JkZXJSaWdodCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUuYm9yZGVyUmlnaHRXaWR0aCwgMTApIHx8IDA7XG4gICAgdmFyIGJvcmRlclRvcCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUuYm9yZGVyVG9wV2lkdGgsIDEwKSB8fCAwO1xuICAgIHZhciBib3JkZXJCb3R0b20gPSBwYXJzZUludChjb21wdXRlZFN0eWxlLmJvcmRlckJvdHRvbVdpZHRoLCAxMCkgfHwgMDtcbiAgICAvLyBtdXN0IHVzZSBvZmZzZXQoV2lkdGh8SGVpZ2h0KSBiZWNhdXNlIGNvbXBhdGlibGUgd2l0aCBjbGllbnQoV2lkdGh8SGVpZ2h0KVxuICAgIHZhciBzY3JvbGxiYXJMZWZ0UmlnaHQgPSBzYW5pdGl6ZVNjcm9sbGJhcldpZHRoKGVsLm9mZnNldFdpZHRoIC0gZWwuY2xpZW50V2lkdGggLSBib3JkZXJMZWZ0IC0gYm9yZGVyUmlnaHQpO1xuICAgIHZhciBzY3JvbGxiYXJCb3R0b20gPSBzYW5pdGl6ZVNjcm9sbGJhcldpZHRoKGVsLm9mZnNldEhlaWdodCAtIGVsLmNsaWVudEhlaWdodCAtIGJvcmRlclRvcCAtIGJvcmRlckJvdHRvbSk7XG4gICAgdmFyIHJlcyA9IHtcbiAgICAgICAgYm9yZGVyTGVmdDogYm9yZGVyTGVmdCxcbiAgICAgICAgYm9yZGVyUmlnaHQ6IGJvcmRlclJpZ2h0LFxuICAgICAgICBib3JkZXJUb3A6IGJvcmRlclRvcCxcbiAgICAgICAgYm9yZGVyQm90dG9tOiBib3JkZXJCb3R0b20sXG4gICAgICAgIHNjcm9sbGJhckJvdHRvbTogc2Nyb2xsYmFyQm90dG9tLFxuICAgICAgICBzY3JvbGxiYXJMZWZ0OiAwLFxuICAgICAgICBzY3JvbGxiYXJSaWdodDogMFxuICAgIH07XG4gICAgaWYgKGdldElzUnRsU2Nyb2xsYmFyT25MZWZ0KCkgJiYgY29tcHV0ZWRTdHlsZS5kaXJlY3Rpb24gPT09ICdydGwnKSB7IC8vIGlzIHRoZSBzY3JvbGxiYXIgb24gdGhlIGxlZnQgc2lkZT9cbiAgICAgICAgcmVzLnNjcm9sbGJhckxlZnQgPSBzY3JvbGxiYXJMZWZ0UmlnaHQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXMuc2Nyb2xsYmFyUmlnaHQgPSBzY3JvbGxiYXJMZWZ0UmlnaHQ7XG4gICAgfVxuICAgIGlmIChnZXRQYWRkaW5nKSB7XG4gICAgICAgIHJlcy5wYWRkaW5nTGVmdCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUucGFkZGluZ0xlZnQsIDEwKSB8fCAwO1xuICAgICAgICByZXMucGFkZGluZ1JpZ2h0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nUmlnaHQsIDEwKSB8fCAwO1xuICAgICAgICByZXMucGFkZGluZ1RvcCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUucGFkZGluZ1RvcCwgMTApIHx8IDA7XG4gICAgICAgIHJlcy5wYWRkaW5nQm90dG9tID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nQm90dG9tLCAxMCkgfHwgMDtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGNvbXB1dGVJbm5lclJlY3QoZWwsIGdvV2l0aGluUGFkZGluZykge1xuICAgIGlmIChnb1dpdGhpblBhZGRpbmcgPT09IHZvaWQgMCkgeyBnb1dpdGhpblBhZGRpbmcgPSBmYWxzZTsgfVxuICAgIHZhciBvdXRlclJlY3QgPSBjb21wdXRlUmVjdChlbCk7XG4gICAgdmFyIGVkZ2VzID0gY29tcHV0ZUVkZ2VzKGVsLCBnb1dpdGhpblBhZGRpbmcpO1xuICAgIHZhciByZXMgPSB7XG4gICAgICAgIGxlZnQ6IG91dGVyUmVjdC5sZWZ0ICsgZWRnZXMuYm9yZGVyTGVmdCArIGVkZ2VzLnNjcm9sbGJhckxlZnQsXG4gICAgICAgIHJpZ2h0OiBvdXRlclJlY3QucmlnaHQgLSBlZGdlcy5ib3JkZXJSaWdodCAtIGVkZ2VzLnNjcm9sbGJhclJpZ2h0LFxuICAgICAgICB0b3A6IG91dGVyUmVjdC50b3AgKyBlZGdlcy5ib3JkZXJUb3AsXG4gICAgICAgIGJvdHRvbTogb3V0ZXJSZWN0LmJvdHRvbSAtIGVkZ2VzLmJvcmRlckJvdHRvbSAtIGVkZ2VzLnNjcm9sbGJhckJvdHRvbVxuICAgIH07XG4gICAgaWYgKGdvV2l0aGluUGFkZGluZykge1xuICAgICAgICByZXMubGVmdCArPSBlZGdlcy5wYWRkaW5nTGVmdDtcbiAgICAgICAgcmVzLnJpZ2h0IC09IGVkZ2VzLnBhZGRpbmdSaWdodDtcbiAgICAgICAgcmVzLnRvcCArPSBlZGdlcy5wYWRkaW5nVG9wO1xuICAgICAgICByZXMuYm90dG9tIC09IGVkZ2VzLnBhZGRpbmdCb3R0b207XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBjb21wdXRlUmVjdChlbCkge1xuICAgIHZhciByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGVmdDogcmVjdC5sZWZ0ICsgd2luZG93LnBhZ2VYT2Zmc2V0LFxuICAgICAgICB0b3A6IHJlY3QudG9wICsgd2luZG93LnBhZ2VZT2Zmc2V0LFxuICAgICAgICByaWdodDogcmVjdC5yaWdodCArIHdpbmRvdy5wYWdlWE9mZnNldCxcbiAgICAgICAgYm90dG9tOiByZWN0LmJvdHRvbSArIHdpbmRvdy5wYWdlWU9mZnNldFxuICAgIH07XG59XG5mdW5jdGlvbiBjb21wdXRlVmlld3BvcnRSZWN0KCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IHdpbmRvdy5wYWdlWE9mZnNldCxcbiAgICAgICAgcmlnaHQ6IHdpbmRvdy5wYWdlWE9mZnNldCArIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCxcbiAgICAgICAgdG9wOiB3aW5kb3cucGFnZVlPZmZzZXQsXG4gICAgICAgIGJvdHRvbTogd2luZG93LnBhZ2VZT2Zmc2V0ICsgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodFxuICAgIH07XG59XG5mdW5jdGlvbiBjb21wdXRlSGVpZ2h0QW5kTWFyZ2lucyhlbCkge1xuICAgIHJldHVybiBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgKyBjb21wdXRlVk1hcmdpbnMoZWwpO1xufVxuZnVuY3Rpb24gY29tcHV0ZVZNYXJnaW5zKGVsKSB7XG4gICAgdmFyIGNvbXB1dGVkID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIHJldHVybiBwYXJzZUludChjb21wdXRlZC5tYXJnaW5Ub3AsIDEwKSArXG4gICAgICAgIHBhcnNlSW50KGNvbXB1dGVkLm1hcmdpbkJvdHRvbSwgMTApO1xufVxuLy8gZG9lcyBub3QgcmV0dXJuIHdpbmRvd1xuZnVuY3Rpb24gZ2V0Q2xpcHBpbmdQYXJlbnRzKGVsKSB7XG4gICAgdmFyIHBhcmVudHMgPSBbXTtcbiAgICB3aGlsZSAoZWwgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgeyAvLyB3aWxsIHN0b3Agd2hlbiBnZXRzIHRvIGRvY3VtZW50IG9yIG51bGxcbiAgICAgICAgdmFyIGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICAgIGlmIChjb21wdXRlZFN0eWxlLnBvc2l0aW9uID09PSAnZml4ZWQnKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoKC8oYXV0b3xzY3JvbGwpLykudGVzdChjb21wdXRlZFN0eWxlLm92ZXJmbG93ICsgY29tcHV0ZWRTdHlsZS5vdmVyZmxvd1kgKyBjb21wdXRlZFN0eWxlLm92ZXJmbG93WCkpIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaChlbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWwgPSBlbC5wYXJlbnROb2RlO1xuICAgIH1cbiAgICByZXR1cm4gcGFyZW50cztcbn1cbmZ1bmN0aW9uIGNvbXB1dGVDbGlwcGluZ1JlY3QoZWwpIHtcbiAgICByZXR1cm4gZ2V0Q2xpcHBpbmdQYXJlbnRzKGVsKVxuICAgICAgICAubWFwKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gY29tcHV0ZUlubmVyUmVjdChlbCk7XG4gICAgfSlcbiAgICAgICAgLmNvbmNhdChjb21wdXRlVmlld3BvcnRSZWN0KCkpXG4gICAgICAgIC5yZWR1Y2UoZnVuY3Rpb24gKHJlY3QwLCByZWN0MSkge1xuICAgICAgICByZXR1cm4gaW50ZXJzZWN0UmVjdHMocmVjdDAsIHJlY3QxKSB8fCByZWN0MTsgLy8gc2hvdWxkIGFsd2F5cyBpbnRlcnNlY3RcbiAgICB9KTtcbn1cblxuLy8gU3RvcHMgYSBtb3VzZS90b3VjaCBldmVudCBmcm9tIGRvaW5nIGl0J3MgbmF0aXZlIGJyb3dzZXIgYWN0aW9uXG5mdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChldikge1xuICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG59XG4vLyBFdmVudCBEZWxlZ2F0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBsaXN0ZW5CeVNlbGVjdG9yKGNvbnRhaW5lciwgZXZlbnRUeXBlLCBzZWxlY3RvciwgaGFuZGxlcikge1xuICAgIGZ1bmN0aW9uIHJlYWxIYW5kbGVyKGV2KSB7XG4gICAgICAgIHZhciBtYXRjaGVkQ2hpbGQgPSBlbGVtZW50Q2xvc2VzdChldi50YXJnZXQsIHNlbGVjdG9yKTtcbiAgICAgICAgaWYgKG1hdGNoZWRDaGlsZCkge1xuICAgICAgICAgICAgaGFuZGxlci5jYWxsKG1hdGNoZWRDaGlsZCwgZXYsIG1hdGNoZWRDaGlsZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCByZWFsSGFuZGxlcik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCByZWFsSGFuZGxlcik7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGxpc3RlblRvSG92ZXJCeVNlbGVjdG9yKGNvbnRhaW5lciwgc2VsZWN0b3IsIG9uTW91c2VFbnRlciwgb25Nb3VzZUxlYXZlKSB7XG4gICAgdmFyIGN1cnJlbnRNYXRjaGVkQ2hpbGQ7XG4gICAgcmV0dXJuIGxpc3RlbkJ5U2VsZWN0b3IoY29udGFpbmVyLCAnbW91c2VvdmVyJywgc2VsZWN0b3IsIGZ1bmN0aW9uIChldiwgbWF0Y2hlZENoaWxkKSB7XG4gICAgICAgIGlmIChtYXRjaGVkQ2hpbGQgIT09IGN1cnJlbnRNYXRjaGVkQ2hpbGQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRNYXRjaGVkQ2hpbGQgPSBtYXRjaGVkQ2hpbGQ7XG4gICAgICAgICAgICBvbk1vdXNlRW50ZXIoZXYsIG1hdGNoZWRDaGlsZCk7XG4gICAgICAgICAgICB2YXIgcmVhbE9uTW91c2VMZWF2ZV8xID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudE1hdGNoZWRDaGlsZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgb25Nb3VzZUxlYXZlKGV2LCBtYXRjaGVkQ2hpbGQpO1xuICAgICAgICAgICAgICAgIG1hdGNoZWRDaGlsZC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgcmVhbE9uTW91c2VMZWF2ZV8xKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBsaXN0ZW4gdG8gdGhlIG5leHQgbW91c2VsZWF2ZSwgYW5kIHRoZW4gdW5hdHRhY2hcbiAgICAgICAgICAgIG1hdGNoZWRDaGlsZC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgcmVhbE9uTW91c2VMZWF2ZV8xKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLy8gQW5pbWF0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG52YXIgdHJhbnNpdGlvbkV2ZW50TmFtZXMgPSBbXG4gICAgJ3dlYmtpdFRyYW5zaXRpb25FbmQnLFxuICAgICdvdHJhbnNpdGlvbmVuZCcsXG4gICAgJ29UcmFuc2l0aW9uRW5kJyxcbiAgICAnbXNUcmFuc2l0aW9uRW5kJyxcbiAgICAndHJhbnNpdGlvbmVuZCdcbl07XG4vLyB0cmlnZ2VyZWQgb25seSB3aGVuIHRoZSBuZXh0IHNpbmdsZSBzdWJzZXF1ZW50IHRyYW5zaXRpb24gZmluaXNoZXNcbmZ1bmN0aW9uIHdoZW5UcmFuc2l0aW9uRG9uZShlbCwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVhbENhbGxiYWNrID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGNhbGxiYWNrKGV2KTtcbiAgICAgICAgdHJhbnNpdGlvbkV2ZW50TmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgcmVhbENhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICB0cmFuc2l0aW9uRXZlbnROYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChldmVudE5hbWUpIHtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIHJlYWxDYWxsYmFjayk7IC8vIGNyb3NzLWJyb3dzZXIgd2F5IHRvIGRldGVybWluZSB3aGVuIHRoZSB0cmFuc2l0aW9uIGZpbmlzaGVzXG4gICAgfSk7XG59XG5cbnZhciBEQVlfSURTID0gWydzdW4nLCAnbW9uJywgJ3R1ZScsICd3ZWQnLCAndGh1JywgJ2ZyaScsICdzYXQnXTtcbi8vIEFkZGluZ1xuZnVuY3Rpb24gYWRkV2Vla3MobSwgbikge1xuICAgIHZhciBhID0gZGF0ZVRvVXRjQXJyYXkobSk7XG4gICAgYVsyXSArPSBuICogNztcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoYSk7XG59XG5mdW5jdGlvbiBhZGREYXlzKG0sIG4pIHtcbiAgICB2YXIgYSA9IGRhdGVUb1V0Y0FycmF5KG0pO1xuICAgIGFbMl0gKz0gbjtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoYSk7XG59XG5mdW5jdGlvbiBhZGRNcyhtLCBuKSB7XG4gICAgdmFyIGEgPSBkYXRlVG9VdGNBcnJheShtKTtcbiAgICBhWzZdICs9IG47XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGEpO1xufVxuLy8gRGlmZmluZyAoYWxsIHJldHVybiBmbG9hdHMpXG5mdW5jdGlvbiBkaWZmV2Vla3MobTAsIG0xKSB7XG4gICAgcmV0dXJuIGRpZmZEYXlzKG0wLCBtMSkgLyA3O1xufVxuZnVuY3Rpb24gZGlmZkRheXMobTAsIG0xKSB7XG4gICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gKDEwMDAgKiA2MCAqIDYwICogMjQpO1xufVxuZnVuY3Rpb24gZGlmZkhvdXJzKG0wLCBtMSkge1xuICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvICgxMDAwICogNjAgKiA2MCk7XG59XG5mdW5jdGlvbiBkaWZmTWludXRlcyhtMCwgbTEpIHtcbiAgICByZXR1cm4gKG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSkgLyAoMTAwMCAqIDYwKTtcbn1cbmZ1bmN0aW9uIGRpZmZTZWNvbmRzKG0wLCBtMSkge1xuICAgIHJldHVybiAobTEudmFsdWVPZigpIC0gbTAudmFsdWVPZigpKSAvIDEwMDA7XG59XG5mdW5jdGlvbiBkaWZmRGF5QW5kVGltZShtMCwgbTEpIHtcbiAgICB2YXIgbTBkYXkgPSBzdGFydE9mRGF5KG0wKTtcbiAgICB2YXIgbTFkYXkgPSBzdGFydE9mRGF5KG0xKTtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogMCxcbiAgICAgICAgbW9udGhzOiAwLFxuICAgICAgICBkYXlzOiBNYXRoLnJvdW5kKGRpZmZEYXlzKG0wZGF5LCBtMWRheSkpLFxuICAgICAgICBtaWxsaXNlY29uZHM6IChtMS52YWx1ZU9mKCkgLSBtMWRheS52YWx1ZU9mKCkpIC0gKG0wLnZhbHVlT2YoKSAtIG0wZGF5LnZhbHVlT2YoKSlcbiAgICB9O1xufVxuLy8gRGlmZmluZyBXaG9sZSBVbml0c1xuZnVuY3Rpb24gZGlmZldob2xlV2Vla3MobTAsIG0xKSB7XG4gICAgdmFyIGQgPSBkaWZmV2hvbGVEYXlzKG0wLCBtMSk7XG4gICAgaWYgKGQgIT09IG51bGwgJiYgZCAlIDcgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGQgLyA3O1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIGRpZmZXaG9sZURheXMobTAsIG0xKSB7XG4gICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKGRpZmZEYXlzKG0wLCBtMSkpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbi8vIFN0YXJ0LU9mXG5mdW5jdGlvbiBzdGFydE9mRGF5KG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKClcbiAgICBdKTtcbn1cbmZ1bmN0aW9uIHN0YXJ0T2ZIb3VyKG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgICAgIG0uZ2V0VVRDSG91cnMoKVxuICAgIF0pO1xufVxuZnVuY3Rpb24gc3RhcnRPZk1pbnV0ZShtKSB7XG4gICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKFtcbiAgICAgICAgbS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICBtLmdldFVUQ01vbnRoKCksXG4gICAgICAgIG0uZ2V0VVRDRGF0ZSgpLFxuICAgICAgICBtLmdldFVUQ0hvdXJzKCksXG4gICAgICAgIG0uZ2V0VVRDTWludXRlcygpXG4gICAgXSk7XG59XG5mdW5jdGlvbiBzdGFydE9mU2Vjb25kKG0pIHtcbiAgICByZXR1cm4gYXJyYXlUb1V0Y0RhdGUoW1xuICAgICAgICBtLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgIG0uZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgbS5nZXRVVENEYXRlKCksXG4gICAgICAgIG0uZ2V0VVRDSG91cnMoKSxcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCksXG4gICAgICAgIG0uZ2V0VVRDU2Vjb25kcygpXG4gICAgXSk7XG59XG4vLyBXZWVrIENvbXB1dGF0aW9uXG5mdW5jdGlvbiB3ZWVrT2ZZZWFyKG1hcmtlciwgZG93LCBkb3kpIHtcbiAgICB2YXIgeSA9IG1hcmtlci5nZXRVVENGdWxsWWVhcigpO1xuICAgIHZhciB3ID0gd2Vla09mR2l2ZW5ZZWFyKG1hcmtlciwgeSwgZG93LCBkb3kpO1xuICAgIGlmICh3IDwgMSkge1xuICAgICAgICByZXR1cm4gd2Vla09mR2l2ZW5ZZWFyKG1hcmtlciwgeSAtIDEsIGRvdywgZG95KTtcbiAgICB9XG4gICAgdmFyIG5leHRXID0gd2Vla09mR2l2ZW5ZZWFyKG1hcmtlciwgeSArIDEsIGRvdywgZG95KTtcbiAgICBpZiAobmV4dFcgPj0gMSkge1xuICAgICAgICByZXR1cm4gTWF0aC5taW4odywgbmV4dFcpO1xuICAgIH1cbiAgICByZXR1cm4gdztcbn1cbmZ1bmN0aW9uIHdlZWtPZkdpdmVuWWVhcihtYXJrZXIsIHllYXIsIGRvdywgZG95KSB7XG4gICAgdmFyIGZpcnN0V2Vla1N0YXJ0ID0gYXJyYXlUb1V0Y0RhdGUoW3llYXIsIDAsIDEgKyBmaXJzdFdlZWtPZmZzZXQoeWVhciwgZG93LCBkb3kpXSk7XG4gICAgdmFyIGRheVN0YXJ0ID0gc3RhcnRPZkRheShtYXJrZXIpO1xuICAgIHZhciBkYXlzID0gTWF0aC5yb3VuZChkaWZmRGF5cyhmaXJzdFdlZWtTdGFydCwgZGF5U3RhcnQpKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihkYXlzIC8gNykgKyAxOyAvLyB6ZXJvLWluZGV4ZWRcbn1cbi8vIHN0YXJ0LW9mLWZpcnN0LXdlZWsgLSBzdGFydC1vZi15ZWFyXG5mdW5jdGlvbiBmaXJzdFdlZWtPZmZzZXQoeWVhciwgZG93LCBkb3kpIHtcbiAgICAvLyBmaXJzdC13ZWVrIGRheSAtLSB3aGljaCBqYW51YXJ5IGlzIGFsd2F5cyBpbiB0aGUgZmlyc3Qgd2VlayAoNCBmb3IgaXNvLCAxIGZvciBvdGhlcilcbiAgICB2YXIgZndkID0gNyArIGRvdyAtIGRveTtcbiAgICAvLyBmaXJzdC13ZWVrIGRheSBsb2NhbCB3ZWVrZGF5IC0tIHdoaWNoIGxvY2FsIHdlZWtkYXkgaXMgZndkXG4gICAgdmFyIGZ3ZGx3ID0gKDcgKyBhcnJheVRvVXRjRGF0ZShbeWVhciwgMCwgZndkXSkuZ2V0VVRDRGF5KCkgLSBkb3cpICUgNztcbiAgICByZXR1cm4gLWZ3ZGx3ICsgZndkIC0gMTtcbn1cbi8vIEFycmF5IENvbnZlcnNpb25cbmZ1bmN0aW9uIGRhdGVUb0xvY2FsQXJyYXkoZGF0ZSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgICBkYXRlLmdldERhdGUoKSxcbiAgICAgICAgZGF0ZS5nZXRIb3VycygpLFxuICAgICAgICBkYXRlLmdldE1pbnV0ZXMoKSxcbiAgICAgICAgZGF0ZS5nZXRTZWNvbmRzKCksXG4gICAgICAgIGRhdGUuZ2V0TWlsbGlzZWNvbmRzKClcbiAgICBdO1xufVxuZnVuY3Rpb24gYXJyYXlUb0xvY2FsRGF0ZShhKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKGFbMF0sIGFbMV0gfHwgMCwgYVsyXSA9PSBudWxsID8gMSA6IGFbMl0sIC8vIGRheSBvZiBtb250aFxuICAgIGFbM10gfHwgMCwgYVs0XSB8fCAwLCBhWzVdIHx8IDApO1xufVxuZnVuY3Rpb24gZGF0ZVRvVXRjQXJyYXkoZGF0ZSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGRhdGUuZ2V0VVRDRnVsbFllYXIoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENNb250aCgpLFxuICAgICAgICBkYXRlLmdldFVUQ0RhdGUoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENIb3VycygpLFxuICAgICAgICBkYXRlLmdldFVUQ01pbnV0ZXMoKSxcbiAgICAgICAgZGF0ZS5nZXRVVENTZWNvbmRzKCksXG4gICAgICAgIGRhdGUuZ2V0VVRDTWlsbGlzZWNvbmRzKClcbiAgICBdO1xufVxuZnVuY3Rpb24gYXJyYXlUb1V0Y0RhdGUoYSkge1xuICAgIC8vIGFjY29yZGluZyB0byB3ZWIgc3RhbmRhcmRzIChhbmQgU2FmYXJpKSwgYSBtb250aCBpbmRleCBpcyByZXF1aXJlZC5cbiAgICAvLyBtYXNzYWdlIGlmIG9ubHkgZ2l2ZW4gYSB5ZWFyLlxuICAgIGlmIChhLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBhID0gYS5jb25jYXQoWzBdKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDLmFwcGx5KERhdGUsIGEpKTtcbn1cbi8vIE90aGVyIFV0aWxzXG5mdW5jdGlvbiBpc1ZhbGlkRGF0ZShtKSB7XG4gICAgcmV0dXJuICFpc05hTihtLnZhbHVlT2YoKSk7XG59XG5mdW5jdGlvbiB0aW1lQXNNcyhtKSB7XG4gICAgcmV0dXJuIG0uZ2V0VVRDSG91cnMoKSAqIDEwMDAgKiA2MCAqIDYwICtcbiAgICAgICAgbS5nZXRVVENNaW51dGVzKCkgKiAxMDAwICogNjAgK1xuICAgICAgICBtLmdldFVUQ1NlY29uZHMoKSAqIDEwMDAgK1xuICAgICAgICBtLmdldFVUQ01pbGxpc2Vjb25kcygpO1xufVxuXG52YXIgSU5URVJOQUxfVU5JVFMgPSBbJ3llYXJzJywgJ21vbnRocycsICdkYXlzJywgJ21pbGxpc2Vjb25kcyddO1xudmFyIFBBUlNFX1JFID0gL14oLT8pKD86KFxcZCspXFwuKT8oXFxkKyk6KFxcZFxcZCkoPzo6KFxcZFxcZCkoPzpcXC4oXFxkXFxkXFxkKSk/KT8vO1xuLy8gUGFyc2luZyBhbmQgQ3JlYXRpb25cbmZ1bmN0aW9uIGNyZWF0ZUR1cmF0aW9uKGlucHV0LCB1bml0KSB7XG4gICAgdmFyIF9hO1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVN0cmluZyhpbnB1dCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgaW5wdXQpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgIHJldHVybiBub3JtYWxpemVPYmplY3QoaW5wdXQpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiBub3JtYWxpemVPYmplY3QoKF9hID0ge30sIF9hW3VuaXQgfHwgJ21pbGxpc2Vjb25kcyddID0gaW5wdXQsIF9hKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59XG5mdW5jdGlvbiBwYXJzZVN0cmluZyhzKSB7XG4gICAgdmFyIG0gPSBQQVJTRV9SRS5leGVjKHMpO1xuICAgIGlmIChtKSB7XG4gICAgICAgIHZhciBzaWduID0gbVsxXSA/IC0xIDogMTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHllYXJzOiAwLFxuICAgICAgICAgICAgbW9udGhzOiAwLFxuICAgICAgICAgICAgZGF5czogc2lnbiAqIChtWzJdID8gcGFyc2VJbnQobVsyXSwgMTApIDogMCksXG4gICAgICAgICAgICBtaWxsaXNlY29uZHM6IHNpZ24gKiAoKG1bM10gPyBwYXJzZUludChtWzNdLCAxMCkgOiAwKSAqIDYwICogNjAgKiAxMDAwICsgLy8gaG91cnNcbiAgICAgICAgICAgICAgICAobVs0XSA/IHBhcnNlSW50KG1bNF0sIDEwKSA6IDApICogNjAgKiAxMDAwICsgLy8gbWludXRlc1xuICAgICAgICAgICAgICAgIChtWzVdID8gcGFyc2VJbnQobVs1XSwgMTApIDogMCkgKiAxMDAwICsgLy8gc2Vjb25kc1xuICAgICAgICAgICAgICAgIChtWzZdID8gcGFyc2VJbnQobVs2XSwgMTApIDogMCkgLy8gbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5mdW5jdGlvbiBub3JtYWxpemVPYmplY3Qob2JqKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IG9iai55ZWFycyB8fCBvYmoueWVhciB8fCAwLFxuICAgICAgICBtb250aHM6IG9iai5tb250aHMgfHwgb2JqLm1vbnRoIHx8IDAsXG4gICAgICAgIGRheXM6IChvYmouZGF5cyB8fCBvYmouZGF5IHx8IDApICtcbiAgICAgICAgICAgIGdldFdlZWtzRnJvbUlucHV0KG9iaikgKiA3LFxuICAgICAgICBtaWxsaXNlY29uZHM6IChvYmouaG91cnMgfHwgb2JqLmhvdXIgfHwgMCkgKiA2MCAqIDYwICogMTAwMCArIC8vIGhvdXJzXG4gICAgICAgICAgICAob2JqLm1pbnV0ZXMgfHwgb2JqLm1pbnV0ZSB8fCAwKSAqIDYwICogMTAwMCArIC8vIG1pbnV0ZXNcbiAgICAgICAgICAgIChvYmouc2Vjb25kcyB8fCBvYmouc2Vjb25kIHx8IDApICogMTAwMCArIC8vIHNlY29uZHNcbiAgICAgICAgICAgIChvYmoubWlsbGlzZWNvbmRzIHx8IG9iai5taWxsaXNlY29uZCB8fCBvYmoubXMgfHwgMCkgLy8gbXNcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0V2Vla3NGcm9tSW5wdXQob2JqKSB7XG4gICAgcmV0dXJuIG9iai53ZWVrcyB8fCBvYmoud2VlayB8fCAwO1xufVxuLy8gRXF1YWxpdHlcbmZ1bmN0aW9uIGR1cmF0aW9uc0VxdWFsKGQwLCBkMSkge1xuICAgIHJldHVybiBkMC55ZWFycyA9PT0gZDEueWVhcnMgJiZcbiAgICAgICAgZDAubW9udGhzID09PSBkMS5tb250aHMgJiZcbiAgICAgICAgZDAuZGF5cyA9PT0gZDEuZGF5cyAmJlxuICAgICAgICBkMC5taWxsaXNlY29uZHMgPT09IGQxLm1pbGxpc2Vjb25kcztcbn1cbmZ1bmN0aW9uIGlzU2luZ2xlRGF5KGR1cikge1xuICAgIHJldHVybiBkdXIueWVhcnMgPT09IDAgJiYgZHVyLm1vbnRocyA9PT0gMCAmJiBkdXIuZGF5cyA9PT0gMSAmJiBkdXIubWlsbGlzZWNvbmRzID09PSAwO1xufVxuLy8gU2ltcGxlIE1hdGhcbmZ1bmN0aW9uIGFkZER1cmF0aW9ucyhkMCwgZDEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZDAueWVhcnMgKyBkMS55ZWFycyxcbiAgICAgICAgbW9udGhzOiBkMC5tb250aHMgKyBkMS5tb250aHMsXG4gICAgICAgIGRheXM6IGQwLmRheXMgKyBkMS5kYXlzLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQwLm1pbGxpc2Vjb25kcyArIGQxLm1pbGxpc2Vjb25kc1xuICAgIH07XG59XG5mdW5jdGlvbiBzdWJ0cmFjdER1cmF0aW9ucyhkMSwgZDApIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZDEueWVhcnMgLSBkMC55ZWFycyxcbiAgICAgICAgbW9udGhzOiBkMS5tb250aHMgLSBkMC5tb250aHMsXG4gICAgICAgIGRheXM6IGQxLmRheXMgLSBkMC5kYXlzLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQxLm1pbGxpc2Vjb25kcyAtIGQwLm1pbGxpc2Vjb25kc1xuICAgIH07XG59XG5mdW5jdGlvbiBtdWx0aXBseUR1cmF0aW9uKGQsIG4pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB5ZWFyczogZC55ZWFycyAqIG4sXG4gICAgICAgIG1vbnRoczogZC5tb250aHMgKiBuLFxuICAgICAgICBkYXlzOiBkLmRheXMgKiBuLFxuICAgICAgICBtaWxsaXNlY29uZHM6IGQubWlsbGlzZWNvbmRzICogblxuICAgIH07XG59XG4vLyBDb252ZXJzaW9uc1xuLy8gXCJSb3VnaFwiIGJlY2F1c2UgdGhleSBhcmUgYmFzZWQgb24gYXZlcmFnZS1jYXNlIEdyZWdvcmlhbiBtb250aHMveWVhcnNcbmZ1bmN0aW9uIGFzUm91Z2hZZWFycyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaERheXMoZHVyKSAvIDM2NTtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hNb250aHMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hEYXlzKGR1cikgLyAzMDtcbn1cbmZ1bmN0aW9uIGFzUm91Z2hEYXlzKGR1cikge1xuICAgIHJldHVybiBhc1JvdWdoTXMoZHVyKSAvIDg2NGU1O1xufVxuZnVuY3Rpb24gYXNSb3VnaE1pbnV0ZXMoZHVyKSB7XG4gICAgcmV0dXJuIGFzUm91Z2hNcyhkdXIpIC8gKDEwMDAgKiA2MCk7XG59XG5mdW5jdGlvbiBhc1JvdWdoU2Vjb25kcyhkdXIpIHtcbiAgICByZXR1cm4gYXNSb3VnaE1zKGR1cikgLyAxMDAwO1xufVxuZnVuY3Rpb24gYXNSb3VnaE1zKGR1cikge1xuICAgIHJldHVybiBkdXIueWVhcnMgKiAoMzY1ICogODY0ZTUpICtcbiAgICAgICAgZHVyLm1vbnRocyAqICgzMCAqIDg2NGU1KSArXG4gICAgICAgIGR1ci5kYXlzICogODY0ZTUgK1xuICAgICAgICBkdXIubWlsbGlzZWNvbmRzO1xufVxuLy8gQWR2YW5jZWQgTWF0aFxuZnVuY3Rpb24gd2hvbGVEaXZpZGVEdXJhdGlvbnMobnVtZXJhdG9yLCBkZW5vbWluYXRvcikge1xuICAgIHZhciByZXMgPSBudWxsO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgSU5URVJOQUxfVU5JVFMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHVuaXQgPSBJTlRFUk5BTF9VTklUU1tpXTtcbiAgICAgICAgaWYgKGRlbm9taW5hdG9yW3VuaXRdKSB7XG4gICAgICAgICAgICB2YXIgbG9jYWxSZXMgPSBudW1lcmF0b3JbdW5pdF0gLyBkZW5vbWluYXRvclt1bml0XTtcbiAgICAgICAgICAgIGlmICghaXNJbnQobG9jYWxSZXMpIHx8IChyZXMgIT09IG51bGwgJiYgcmVzICE9PSBsb2NhbFJlcykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcyA9IGxvY2FsUmVzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG51bWVyYXRvclt1bml0XSkge1xuICAgICAgICAgICAgLy8gbmVlZHMgdG8gZGl2aWRlIGJ5IHNvbWV0aGluZyBidXQgY2FuJ3QhXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGR1ciwgZG9udFJldHVybldlZWtzKSB7XG4gICAgdmFyIG1zID0gZHVyLm1pbGxpc2Vjb25kcztcbiAgICBpZiAobXMpIHtcbiAgICAgICAgaWYgKG1zICUgMTAwMCAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IG1zIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zICUgKDEwMDAgKiA2MCkgIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdzZWNvbmQnLCB2YWx1ZTogbXMgLyAxMDAwIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zICUgKDEwMDAgKiA2MCAqIDYwKSAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbnV0ZScsIHZhbHVlOiBtcyAvICgxMDAwICogNjApIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1zKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnaG91cicsIHZhbHVlOiBtcyAvICgxMDAwICogNjAgKiA2MCkgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZHVyLmRheXMpIHtcbiAgICAgICAgaWYgKCFkb250UmV0dXJuV2Vla3MgJiYgZHVyLmRheXMgJSA3ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnd2VlaycsIHZhbHVlOiBkdXIuZGF5cyAvIDcgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB1bml0OiAnZGF5JywgdmFsdWU6IGR1ci5kYXlzIH07XG4gICAgfVxuICAgIGlmIChkdXIubW9udGhzKSB7XG4gICAgICAgIHJldHVybiB7IHVuaXQ6ICdtb250aCcsIHZhbHVlOiBkdXIubW9udGhzIH07XG4gICAgfVxuICAgIGlmIChkdXIueWVhcnMpIHtcbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3llYXInLCB2YWx1ZTogZHVyLnllYXJzIH07XG4gICAgfVxuICAgIHJldHVybiB7IHVuaXQ6ICdtaWxsaXNlY29uZCcsIHZhbHVlOiAwIH07XG59XG5cbi8qIEZ1bGxDYWxlbmRhci1zcGVjaWZpYyBET00gVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbi8vIEdpdmVuIHRoZSBzY3JvbGxiYXIgd2lkdGhzIG9mIHNvbWUgb3RoZXIgY29udGFpbmVyLCBjcmVhdGUgYm9yZGVycy9tYXJnaW5zIG9uIHJvd0VscyBpbiBvcmRlciB0byBtYXRjaCB0aGUgbGVmdFxuLy8gYW5kIHJpZ2h0IHNwYWNlIHRoYXQgd2FzIG9mZnNldCBieSB0aGUgc2Nyb2xsYmFycy4gQSAxLXBpeGVsIGJvcmRlciBmaXJzdCwgdGhlbiBtYXJnaW4gYmV5b25kIHRoYXQuXG5mdW5jdGlvbiBjb21wZW5zYXRlU2Nyb2xsKHJvd0VsLCBzY3JvbGxiYXJXaWR0aHMpIHtcbiAgICBpZiAoc2Nyb2xsYmFyV2lkdGhzLmxlZnQpIHtcbiAgICAgICAgYXBwbHlTdHlsZShyb3dFbCwge1xuICAgICAgICAgICAgYm9yZGVyTGVmdFdpZHRoOiAxLFxuICAgICAgICAgICAgbWFyZ2luTGVmdDogc2Nyb2xsYmFyV2lkdGhzLmxlZnQgLSAxXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoc2Nyb2xsYmFyV2lkdGhzLnJpZ2h0KSB7XG4gICAgICAgIGFwcGx5U3R5bGUocm93RWwsIHtcbiAgICAgICAgICAgIGJvcmRlclJpZ2h0V2lkdGg6IDEsXG4gICAgICAgICAgICBtYXJnaW5SaWdodDogc2Nyb2xsYmFyV2lkdGhzLnJpZ2h0IC0gMVxuICAgICAgICB9KTtcbiAgICB9XG59XG4vLyBVbmRvZXMgY29tcGVuc2F0ZVNjcm9sbCBhbmQgcmVzdG9yZXMgYWxsIGJvcmRlcnMvbWFyZ2luc1xuZnVuY3Rpb24gdW5jb21wZW5zYXRlU2Nyb2xsKHJvd0VsKSB7XG4gICAgYXBwbHlTdHlsZShyb3dFbCwge1xuICAgICAgICBtYXJnaW5MZWZ0OiAnJyxcbiAgICAgICAgbWFyZ2luUmlnaHQ6ICcnLFxuICAgICAgICBib3JkZXJMZWZ0V2lkdGg6ICcnLFxuICAgICAgICBib3JkZXJSaWdodFdpZHRoOiAnJ1xuICAgIH0pO1xufVxuLy8gTWFrZSB0aGUgbW91c2UgY3Vyc29yIGV4cHJlc3MgdGhhdCBhbiBldmVudCBpcyBub3QgYWxsb3dlZCBpbiB0aGUgY3VycmVudCBhcmVhXG5mdW5jdGlvbiBkaXNhYmxlQ3Vyc29yKCkge1xuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgnZmMtbm90LWFsbG93ZWQnKTtcbn1cbi8vIFJldHVybnMgdGhlIG1vdXNlIGN1cnNvciB0byBpdHMgb3JpZ2luYWwgbG9va1xuZnVuY3Rpb24gZW5hYmxlQ3Vyc29yKCkge1xuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnZmMtbm90LWFsbG93ZWQnKTtcbn1cbi8vIEdpdmVuIGEgdG90YWwgYXZhaWxhYmxlIGhlaWdodCB0byBmaWxsLCBoYXZlIGBlbHNgIChlc3NlbnRpYWxseSBjaGlsZCByb3dzKSBleHBhbmQgdG8gYWNjb21vZGF0ZS5cbi8vIEJ5IGRlZmF1bHQsIGFsbCBlbGVtZW50cyB0aGF0IGFyZSBzaG9ydGVyIHRoYW4gdGhlIHJlY29tbWVuZGVkIGhlaWdodCBhcmUgZXhwYW5kZWQgdW5pZm9ybWx5LCBub3QgY29uc2lkZXJpbmdcbi8vIGFueSBvdGhlciBlbHMgdGhhdCBhcmUgYWxyZWFkeSB0b28gdGFsbC4gaWYgYHNob3VsZFJlZGlzdHJpYnV0ZWAgaXMgb24sIGl0IGNvbnNpZGVycyB0aGVzZSB0YWxsIHJvd3MgYW5kXG4vLyByZWR1Y2VzIHRoZSBhdmFpbGFibGUgaGVpZ2h0LlxuZnVuY3Rpb24gZGlzdHJpYnV0ZUhlaWdodChlbHMsIGF2YWlsYWJsZUhlaWdodCwgc2hvdWxkUmVkaXN0cmlidXRlKSB7XG4gICAgLy8gKkZMT09SSU5HIE5PVEUqOiB3ZSBmbG9vciBpbiBjZXJ0YWluIHBsYWNlcyBiZWNhdXNlIHpvb20gY2FuIGdpdmUgaW5hY2N1cmF0ZSBmbG9hdGluZy1wb2ludCBkaW1lbnNpb25zLFxuICAgIC8vIGFuZCBpdCBpcyBiZXR0ZXIgdG8gYmUgc2hvcnRlciB0aGFuIHRhbGxlciwgdG8gYXZvaWQgY3JlYXRpbmcgdW5uZWNlc3Nhcnkgc2Nyb2xsYmFycy5cbiAgICB2YXIgbWluT2Zmc2V0MSA9IE1hdGguZmxvb3IoYXZhaWxhYmxlSGVpZ2h0IC8gZWxzLmxlbmd0aCk7IC8vIGZvciBub24tbGFzdCBlbGVtZW50XG4gICAgdmFyIG1pbk9mZnNldDIgPSBNYXRoLmZsb29yKGF2YWlsYWJsZUhlaWdodCAtIG1pbk9mZnNldDEgKiAoZWxzLmxlbmd0aCAtIDEpKTsgLy8gZm9yIGxhc3QgZWxlbWVudCAqRkxPT1JJTkcgTk9URSpcbiAgICB2YXIgZmxleEVscyA9IFtdOyAvLyBlbGVtZW50cyB0aGF0IGFyZSBhbGxvd2VkIHRvIGV4cGFuZC4gYXJyYXkgb2YgRE9NIG5vZGVzXG4gICAgdmFyIGZsZXhPZmZzZXRzID0gW107IC8vIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpdCB0YWtlcyB1cFxuICAgIHZhciBmbGV4SGVpZ2h0cyA9IFtdOyAvLyBhY3R1YWwgY3NzIGhlaWdodFxuICAgIHZhciB1c2VkSGVpZ2h0ID0gMDtcbiAgICB1bmRpc3RyaWJ1dGVIZWlnaHQoZWxzKTsgLy8gZ2l2ZSBhbGwgZWxlbWVudHMgdGhlaXIgbmF0dXJhbCBoZWlnaHRcbiAgICAvLyBmaW5kIGVsZW1lbnRzIHRoYXQgYXJlIGJlbG93IHRoZSByZWNvbW1lbmRlZCBoZWlnaHQgKGV4cGFuZGFibGUpLlxuICAgIC8vIGltcG9ydGFudCB0byBxdWVyeSBmb3IgaGVpZ2h0cyBpbiBhIHNpbmdsZSBmaXJzdCBwYXNzICh0byBhdm9pZCByZWZsb3cgb3NjaWxsYXRpb24pLlxuICAgIGVscy5mb3JFYWNoKGZ1bmN0aW9uIChlbCwgaSkge1xuICAgICAgICB2YXIgbWluT2Zmc2V0ID0gaSA9PT0gZWxzLmxlbmd0aCAtIDEgPyBtaW5PZmZzZXQyIDogbWluT2Zmc2V0MTtcbiAgICAgICAgdmFyIG5hdHVyYWxIZWlnaHQgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgICAgIHZhciBuYXR1cmFsT2Zmc2V0ID0gbmF0dXJhbEhlaWdodCArIGNvbXB1dGVWTWFyZ2lucyhlbCk7XG4gICAgICAgIGlmIChuYXR1cmFsT2Zmc2V0IDwgbWluT2Zmc2V0KSB7XG4gICAgICAgICAgICBmbGV4RWxzLnB1c2goZWwpO1xuICAgICAgICAgICAgZmxleE9mZnNldHMucHVzaChuYXR1cmFsT2Zmc2V0KTtcbiAgICAgICAgICAgIGZsZXhIZWlnaHRzLnB1c2gobmF0dXJhbEhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyB0aGlzIGVsZW1lbnQgc3RyZXRjaGVzIHBhc3QgcmVjb21tZW5kZWQgaGVpZ2h0IChub24tZXhwYW5kYWJsZSkuIG1hcmsgdGhlIHNwYWNlIGFzIG9jY3VwaWVkLlxuICAgICAgICAgICAgdXNlZEhlaWdodCArPSBuYXR1cmFsT2Zmc2V0O1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgLy8gcmVhZGp1c3QgdGhlIHJlY29tbWVuZGVkIGhlaWdodCB0byBvbmx5IGNvbnNpZGVyIHRoZSBoZWlnaHQgYXZhaWxhYmxlIHRvIG5vbi1tYXhlZC1vdXQgcm93cy5cbiAgICBpZiAoc2hvdWxkUmVkaXN0cmlidXRlKSB7XG4gICAgICAgIGF2YWlsYWJsZUhlaWdodCAtPSB1c2VkSGVpZ2h0O1xuICAgICAgICBtaW5PZmZzZXQxID0gTWF0aC5mbG9vcihhdmFpbGFibGVIZWlnaHQgLyBmbGV4RWxzLmxlbmd0aCk7XG4gICAgICAgIG1pbk9mZnNldDIgPSBNYXRoLmZsb29yKGF2YWlsYWJsZUhlaWdodCAtIG1pbk9mZnNldDEgKiAoZmxleEVscy5sZW5ndGggLSAxKSk7IC8vICpGTE9PUklORyBOT1RFKlxuICAgIH1cbiAgICAvLyBhc3NpZ24gaGVpZ2h0cyB0byBhbGwgZXhwYW5kYWJsZSBlbGVtZW50c1xuICAgIGZsZXhFbHMuZm9yRWFjaChmdW5jdGlvbiAoZWwsIGkpIHtcbiAgICAgICAgdmFyIG1pbk9mZnNldCA9IGkgPT09IGZsZXhFbHMubGVuZ3RoIC0gMSA/IG1pbk9mZnNldDIgOiBtaW5PZmZzZXQxO1xuICAgICAgICB2YXIgbmF0dXJhbE9mZnNldCA9IGZsZXhPZmZzZXRzW2ldO1xuICAgICAgICB2YXIgbmF0dXJhbEhlaWdodCA9IGZsZXhIZWlnaHRzW2ldO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gbWluT2Zmc2V0IC0gKG5hdHVyYWxPZmZzZXQgLSBuYXR1cmFsSGVpZ2h0KTsgLy8gc3VidHJhY3QgdGhlIG1hcmdpbi9wYWRkaW5nXG4gICAgICAgIGlmIChuYXR1cmFsT2Zmc2V0IDwgbWluT2Zmc2V0KSB7IC8vIHdlIGNoZWNrIHRoaXMgYWdhaW4gYmVjYXVzZSByZWRpc3RyaWJ1dGlvbiBtaWdodCBoYXZlIGNoYW5nZWQgdGhpbmdzXG4gICAgICAgICAgICBlbC5zdHlsZS5oZWlnaHQgPSBuZXdIZWlnaHQgKyAncHgnO1xuICAgICAgICB9XG4gICAgfSk7XG59XG4vLyBVbmRvZXMgZGlzdHJ1YnV0ZUhlaWdodCwgcmVzdG9yaW5nIGFsbCBlbHMgdG8gdGhlaXIgbmF0dXJhbCBoZWlnaHRcbmZ1bmN0aW9uIHVuZGlzdHJpYnV0ZUhlaWdodChlbHMpIHtcbiAgICBlbHMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgZWwuc3R5bGUuaGVpZ2h0ID0gJyc7XG4gICAgfSk7XG59XG4vLyBHaXZlbiBgZWxzYCwgYSBzZXQgb2YgPHRkPiBjZWxscywgZmluZCB0aGUgY2VsbCB3aXRoIHRoZSBsYXJnZXN0IG5hdHVyYWwgd2lkdGggYW5kIHNldCB0aGUgd2lkdGhzIG9mIGFsbCB0aGVcbi8vIGNlbGxzIHRvIGJlIHRoYXQgd2lkdGguXG4vLyBQUkVSRVFVSVNJVEU6IGlmIHlvdSB3YW50IGEgY2VsbCB0byB0YWtlIHVwIHdpZHRoLCBpdCBuZWVkcyB0byBoYXZlIGEgc2luZ2xlIGlubmVyIGVsZW1lbnQgdy8gZGlzcGxheTppbmxpbmVcbmZ1bmN0aW9uIG1hdGNoQ2VsbFdpZHRocyhlbHMpIHtcbiAgICB2YXIgbWF4SW5uZXJXaWR0aCA9IDA7XG4gICAgZWxzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBpbm5lckVsID0gZWwuZmlyc3RDaGlsZDsgLy8gaG9wZWZ1bGx5IGFuIGVsZW1lbnRcbiAgICAgICAgaWYgKGlubmVyRWwgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGlubmVyV2lkdGhfMSA9IGlubmVyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG4gICAgICAgICAgICBpZiAoaW5uZXJXaWR0aF8xID4gbWF4SW5uZXJXaWR0aCkge1xuICAgICAgICAgICAgICAgIG1heElubmVyV2lkdGggPSBpbm5lcldpZHRoXzE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBtYXhJbm5lcldpZHRoKys7IC8vIHNvbWV0aW1lcyBub3QgYWNjdXJhdGUgb2Ygd2lkdGggdGhlIHRleHQgbmVlZHMgdG8gc3RheSBvbiBvbmUgbGluZS4gaW5zdXJhbmNlXG4gICAgZWxzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIGVsLnN0eWxlLndpZHRoID0gbWF4SW5uZXJXaWR0aCArICdweCc7XG4gICAgfSk7XG4gICAgcmV0dXJuIG1heElubmVyV2lkdGg7XG59XG4vLyBHaXZlbiBvbmUgZWxlbWVudCB0aGF0IHJlc2lkZXMgaW5zaWRlIGFub3RoZXIsXG4vLyBTdWJ0cmFjdHMgdGhlIGhlaWdodCBvZiB0aGUgaW5uZXIgZWxlbWVudCBmcm9tIHRoZSBvdXRlciBlbGVtZW50LlxuZnVuY3Rpb24gc3VidHJhY3RJbm5lckVsSGVpZ2h0KG91dGVyRWwsIGlubmVyRWwpIHtcbiAgICAvLyBlZmZpbicgSUU4LzkvMTAvMTEgc29tZXRpbWVzIHJldHVybnMgMCBmb3IgZGltZW5zaW9ucy4gdGhpcyB3ZWlyZCBoYWNrIHdhcyB0aGUgb25seSB0aGluZyB0aGF0IHdvcmtlZFxuICAgIHZhciByZWZsb3dTdHlsZVByb3BzID0ge1xuICAgICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICAgbGVmdDogLTEgLy8gZW5zdXJlIHJlZmxvdyBpbiBjYXNlIHRoZSBlbCB3YXMgYWxyZWFkeSByZWxhdGl2ZS4gbmVnYXRpdmUgaXMgbGVzcyBsaWtlbHkgdG8gY2F1c2UgbmV3IHNjcm9sbFxuICAgIH07XG4gICAgYXBwbHlTdHlsZShvdXRlckVsLCByZWZsb3dTdHlsZVByb3BzKTtcbiAgICBhcHBseVN0eWxlKGlubmVyRWwsIHJlZmxvd1N0eWxlUHJvcHMpO1xuICAgIHZhciBkaWZmID0gLy8gZ3JhYiB0aGUgZGltZW5zaW9uc1xuICAgICBvdXRlckVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCAtXG4gICAgICAgIGlubmVyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xuICAgIC8vIHVuZG8gaGFja1xuICAgIHZhciByZXNldFN0eWxlUHJvcHMgPSB7IHBvc2l0aW9uOiAnJywgbGVmdDogJycgfTtcbiAgICBhcHBseVN0eWxlKG91dGVyRWwsIHJlc2V0U3R5bGVQcm9wcyk7XG4gICAgYXBwbHlTdHlsZShpbm5lckVsLCByZXNldFN0eWxlUHJvcHMpO1xuICAgIHJldHVybiBkaWZmO1xufVxuLyogU2VsZWN0aW9uXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIHByZXZlbnRTZWxlY3Rpb24oZWwpIHtcbiAgICBlbC5jbGFzc0xpc3QuYWRkKCdmYy11bnNlbGVjdGFibGUnKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdzZWxlY3RzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcbn1cbmZ1bmN0aW9uIGFsbG93U2VsZWN0aW9uKGVsKSB7XG4gICAgZWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtdW5zZWxlY3RhYmxlJyk7XG4gICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG4vKiBDb250ZXh0IE1lbnVcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gcHJldmVudENvbnRleHRNZW51KGVsKSB7XG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG5mdW5jdGlvbiBhbGxvd0NvbnRleHRNZW51KGVsKSB7XG4gICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBwcmV2ZW50RGVmYXVsdCk7XG59XG4vKiBPYmplY3QgT3JkZXJpbmcgYnkgRmllbGRcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gcGFyc2VGaWVsZFNwZWNzKGlucHV0KSB7XG4gICAgdmFyIHNwZWNzID0gW107XG4gICAgdmFyIHRva2VucyA9IFtdO1xuICAgIHZhciBpO1xuICAgIHZhciB0b2tlbjtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICB0b2tlbnMgPSBpbnB1dC5zcGxpdCgvXFxzKixcXHMqLyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0b2tlbnMgPSBbaW5wdXRdO1xuICAgIH1cbiAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICB0b2tlbnMgPSBpbnB1dDtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHNwZWNzLnB1c2godG9rZW4uY2hhckF0KDApID09PSAnLScgP1xuICAgICAgICAgICAgICAgIHsgZmllbGQ6IHRva2VuLnN1YnN0cmluZygxKSwgb3JkZXI6IC0xIH0gOlxuICAgICAgICAgICAgICAgIHsgZmllbGQ6IHRva2VuLCBvcmRlcjogMSB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdG9rZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHNwZWNzLnB1c2goeyBmdW5jOiB0b2tlbiB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3BlY3M7XG59XG5mdW5jdGlvbiBjb21wYXJlQnlGaWVsZFNwZWNzKG9iajAsIG9iajEsIGZpZWxkU3BlY3MpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgY21wO1xuICAgIGZvciAoaSA9IDA7IGkgPCBmaWVsZFNwZWNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNtcCA9IGNvbXBhcmVCeUZpZWxkU3BlYyhvYmowLCBvYmoxLCBmaWVsZFNwZWNzW2ldKTtcbiAgICAgICAgaWYgKGNtcCkge1xuICAgICAgICAgICAgcmV0dXJuIGNtcDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIGNvbXBhcmVCeUZpZWxkU3BlYyhvYmowLCBvYmoxLCBmaWVsZFNwZWMpIHtcbiAgICBpZiAoZmllbGRTcGVjLmZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIGZpZWxkU3BlYy5mdW5jKG9iajAsIG9iajEpO1xuICAgIH1cbiAgICByZXR1cm4gZmxleGlibGVDb21wYXJlKG9iajBbZmllbGRTcGVjLmZpZWxkXSwgb2JqMVtmaWVsZFNwZWMuZmllbGRdKVxuICAgICAgICAqIChmaWVsZFNwZWMub3JkZXIgfHwgMSk7XG59XG5mdW5jdGlvbiBmbGV4aWJsZUNvbXBhcmUoYSwgYikge1xuICAgIGlmICghYSAmJiAhYikge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKGIgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmIChhID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoYSkubG9jYWxlQ29tcGFyZShTdHJpbmcoYikpO1xuICAgIH1cbiAgICByZXR1cm4gYSAtIGI7XG59XG4vKiBTdHJpbmcgVXRpbGl0aWVzXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmZ1bmN0aW9uIGNhcGl0YWxpc2VGaXJzdExldHRlcihzdHIpIHtcbiAgICByZXR1cm4gc3RyLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyLnNsaWNlKDEpO1xufVxuZnVuY3Rpb24gcGFkU3RhcnQodmFsLCBsZW4pIHtcbiAgICB2YXIgcyA9IFN0cmluZyh2YWwpO1xuICAgIHJldHVybiAnMDAwJy5zdWJzdHIoMCwgbGVuIC0gcy5sZW5ndGgpICsgcztcbn1cbi8qIE51bWJlciBVdGlsaXRpZXNcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gY29tcGFyZU51bWJlcnMoYSwgYikge1xuICAgIHJldHVybiBhIC0gYjtcbn1cbmZ1bmN0aW9uIGlzSW50KG4pIHtcbiAgICByZXR1cm4gbiAlIDEgPT09IDA7XG59XG4vKiBXZWlyZCBVdGlsaXRpZXNcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuZnVuY3Rpb24gYXBwbHlBbGwoZnVuY3Rpb25zLCB0aGlzT2JqLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiBmdW5jdGlvbnMgPT09ICdmdW5jdGlvbicpIHsgLy8gc3VwcGxpZWQgYSBzaW5nbGUgZnVuY3Rpb25cbiAgICAgICAgZnVuY3Rpb25zID0gW2Z1bmN0aW9uc107XG4gICAgfVxuICAgIGlmIChmdW5jdGlvbnMpIHtcbiAgICAgICAgdmFyIGkgPSB2b2lkIDA7XG4gICAgICAgIHZhciByZXQgPSB2b2lkIDA7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBmdW5jdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJldCA9IGZ1bmN0aW9uc1tpXS5hcHBseSh0aGlzT2JqLCBhcmdzKSB8fCByZXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG59XG5mdW5jdGlvbiBmaXJzdERlZmluZWQoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICBhcmdzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYXJnc1tpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJnc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgYXMgbG9uZyBhcyBpdCBjb250aW51ZXMgdG8gYmUgaW52b2tlZCwgd2lsbCBub3Rcbi8vIGJlIHRyaWdnZXJlZC4gVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIGl0IHN0b3BzIGJlaW5nIGNhbGxlZCBmb3Jcbi8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxuLy8gbGVhZGluZyBlZGdlLCBpbnN0ZWFkIG9mIHRoZSB0cmFpbGluZy5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qYXNoa2VuYXMvdW5kZXJzY29yZS9ibG9iLzEuNi4wL3VuZGVyc2NvcmUuanMjTDcxNFxuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCkge1xuICAgIHZhciB0aW1lb3V0O1xuICAgIHZhciBhcmdzO1xuICAgIHZhciBjb250ZXh0O1xuICAgIHZhciB0aW1lc3RhbXA7XG4gICAgdmFyIHJlc3VsdDtcbiAgICB2YXIgbGF0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBsYXN0ID0gbmV3IERhdGUoKS52YWx1ZU9mKCkgLSB0aW1lc3RhbXA7XG4gICAgICAgIGlmIChsYXN0IDwgd2FpdCkge1xuICAgICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHRpbWVzdGFtcCA9IG5ldyBEYXRlKCkudmFsdWVPZigpO1xuICAgICAgICBpZiAoIXRpbWVvdXQpIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG59XG4vLyBOdW1iZXIgYW5kIEJvb2xlYW4gYXJlIG9ubHkgdHlwZXMgdGhhdCBkZWZhdWx0cyBvciBub3QgY29tcHV0ZWQgZm9yXG4vLyBUT0RPOiB3cml0ZSBtb3JlIGNvbW1lbnRzXG5mdW5jdGlvbiByZWZpbmVQcm9wcyhyYXdQcm9wcywgcHJvY2Vzc29ycywgZGVmYXVsdHMsIGxlZnRvdmVyUHJvcHMpIHtcbiAgICBpZiAoZGVmYXVsdHMgPT09IHZvaWQgMCkgeyBkZWZhdWx0cyA9IHt9OyB9XG4gICAgdmFyIHJlZmluZWQgPSB7fTtcbiAgICBmb3IgKHZhciBrZXkgaW4gcHJvY2Vzc29ycykge1xuICAgICAgICB2YXIgcHJvY2Vzc29yID0gcHJvY2Vzc29yc1trZXldO1xuICAgICAgICBpZiAocmF3UHJvcHNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBmb3VuZFxuICAgICAgICAgICAgaWYgKHByb2Nlc3NvciA9PT0gRnVuY3Rpb24pIHtcbiAgICAgICAgICAgICAgICByZWZpbmVkW2tleV0gPSB0eXBlb2YgcmF3UHJvcHNba2V5XSA9PT0gJ2Z1bmN0aW9uJyA/IHJhd1Byb3BzW2tleV0gOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocHJvY2Vzc29yKSB7IC8vIGEgcmVmaW5pbmcgZnVuY3Rpb24/XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gcHJvY2Vzc29yKHJhd1Byb3BzW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gcmF3UHJvcHNba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkZWZhdWx0c1trZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIHRoZXJlJ3MgYW4gZXhwbGljaXQgZGVmYXVsdFxuICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gZGVmYXVsdHNba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIG11c3QgY29tcHV0ZSBhIGRlZmF1bHRcbiAgICAgICAgICAgIGlmIChwcm9jZXNzb3IgPT09IFN0cmluZykge1xuICAgICAgICAgICAgICAgIHJlZmluZWRba2V5XSA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgaXMgZGVmYXVsdCBmb3IgU3RyaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghcHJvY2Vzc29yIHx8IHByb2Nlc3NvciA9PT0gTnVtYmVyIHx8IHByb2Nlc3NvciA9PT0gQm9vbGVhbiB8fCBwcm9jZXNzb3IgPT09IEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZFtrZXldID0gbnVsbDsgLy8gYXNzaWduIG51bGwgZm9yIG90aGVyIG5vbi1jdXN0b20gcHJvY2Vzc29yIGZ1bmNzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWZpbmVkW2tleV0gPSBwcm9jZXNzb3IobnVsbCk7IC8vIHJ1biB0aGUgY3VzdG9tIHByb2Nlc3NvciBmdW5jXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxlZnRvdmVyUHJvcHMpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHJhd1Byb3BzKSB7XG4gICAgICAgICAgICBpZiAocHJvY2Vzc29yc1trZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBsZWZ0b3ZlclByb3BzW2tleV0gPSByYXdQcm9wc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWZpbmVkO1xufVxuLyogRGF0ZSBzdHVmZiB0aGF0IGRvZXNuJ3QgYmVsb25nIGluIGRhdGVsaWIgY29yZVxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4vLyBnaXZlbiBhIHRpbWVkIHJhbmdlLCBjb21wdXRlcyBhbiBhbGwtZGF5IHJhbmdlIHRoYXQgaGFzIHRoZSBzYW1lIGV4YWN0IGR1cmF0aW9uLFxuLy8gYnV0IHdob3NlIHN0YXJ0IHRpbWUgaXMgYWxpZ25lZCB3aXRoIHRoZSBzdGFydCBvZiB0aGUgZGF5LlxuZnVuY3Rpb24gY29tcHV0ZUFsaWduZWREYXlSYW5nZSh0aW1lZFJhbmdlKSB7XG4gICAgdmFyIGRheUNudCA9IE1hdGguZmxvb3IoZGlmZkRheXModGltZWRSYW5nZS5zdGFydCwgdGltZWRSYW5nZS5lbmQpKSB8fCAxO1xuICAgIHZhciBzdGFydCA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5zdGFydCk7XG4gICAgdmFyIGVuZCA9IGFkZERheXMoc3RhcnQsIGRheUNudCk7XG4gICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xufVxuLy8gZ2l2ZW4gYSB0aW1lZCByYW5nZSwgY29tcHV0ZXMgYW4gYWxsLWRheSByYW5nZSBiYXNlZCBvbiBob3cgZm9yIHRoZSBlbmQgZGF0ZSBibGVlZHMgaW50byB0aGUgbmV4dCBkYXlcbi8vIFRPRE86IGdpdmUgbmV4dERheVRocmVzaG9sZCBhIGRlZmF1bHQgYXJnXG5mdW5jdGlvbiBjb21wdXRlVmlzaWJsZURheVJhbmdlKHRpbWVkUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQpIHtcbiAgICBpZiAobmV4dERheVRocmVzaG9sZCA9PT0gdm9pZCAwKSB7IG5leHREYXlUaHJlc2hvbGQgPSBjcmVhdGVEdXJhdGlvbigwKTsgfVxuICAgIHZhciBzdGFydERheSA9IG51bGw7XG4gICAgdmFyIGVuZERheSA9IG51bGw7XG4gICAgaWYgKHRpbWVkUmFuZ2UuZW5kKSB7XG4gICAgICAgIGVuZERheSA9IHN0YXJ0T2ZEYXkodGltZWRSYW5nZS5lbmQpO1xuICAgICAgICB2YXIgZW5kVGltZU1TID0gdGltZWRSYW5nZS5lbmQudmFsdWVPZigpIC0gZW5kRGF5LnZhbHVlT2YoKTsgLy8gIyBvZiBtaWxsaXNlY29uZHMgaW50byBgZW5kRGF5YFxuICAgICAgICAvLyBJZiB0aGUgZW5kIHRpbWUgaXMgYWN0dWFsbHkgaW5jbHVzaXZlbHkgcGFydCBvZiB0aGUgbmV4dCBkYXkgYW5kIGlzIGVxdWFsIHRvIG9yXG4gICAgICAgIC8vIGJleW9uZCB0aGUgbmV4dCBkYXkgdGhyZXNob2xkLCBhZGp1c3QgdGhlIGVuZCB0byBiZSB0aGUgZXhjbHVzaXZlIGVuZCBvZiBgZW5kRGF5YC5cbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBsZWF2aW5nIGl0IGFzIGluY2x1c2l2ZSB3aWxsIGNhdXNlIGl0IHRvIGV4Y2x1ZGUgYGVuZERheWAuXG4gICAgICAgIGlmIChlbmRUaW1lTVMgJiYgZW5kVGltZU1TID49IGFzUm91Z2hNcyhuZXh0RGF5VGhyZXNob2xkKSkge1xuICAgICAgICAgICAgZW5kRGF5ID0gYWRkRGF5cyhlbmREYXksIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0aW1lZFJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0RGF5ID0gc3RhcnRPZkRheSh0aW1lZFJhbmdlLnN0YXJ0KTsgLy8gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF5IHRoZSByYW5nZSBzdGFydHNcbiAgICAgICAgLy8gSWYgZW5kIGlzIHdpdGhpbiBgc3RhcnREYXlgIGJ1dCBub3QgcGFzdCBuZXh0RGF5VGhyZXNob2xkLCBhc3NpZ24gdGhlIGRlZmF1bHQgZHVyYXRpb24gb2Ygb25lIGRheS5cbiAgICAgICAgaWYgKGVuZERheSAmJiBlbmREYXkgPD0gc3RhcnREYXkpIHtcbiAgICAgICAgICAgIGVuZERheSA9IGFkZERheXMoc3RhcnREYXksIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydERheSwgZW5kOiBlbmREYXkgfTtcbn1cbi8vIHNwYW5zIGZyb20gb25lIGRheSBpbnRvIGFub3RoZXI/XG5mdW5jdGlvbiBpc011bHRpRGF5UmFuZ2UocmFuZ2UpIHtcbiAgICB2YXIgdmlzaWJsZVJhbmdlID0gY29tcHV0ZVZpc2libGVEYXlSYW5nZShyYW5nZSk7XG4gICAgcmV0dXJuIGRpZmZEYXlzKHZpc2libGVSYW5nZS5zdGFydCwgdmlzaWJsZVJhbmdlLmVuZCkgPiAxO1xufVxuZnVuY3Rpb24gZGlmZkRhdGVzKGRhdGUwLCBkYXRlMSwgZGF0ZUVudiwgbGFyZ2VVbml0KSB7XG4gICAgaWYgKGxhcmdlVW5pdCA9PT0gJ3llYXInKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbihkYXRlRW52LmRpZmZXaG9sZVllYXJzKGRhdGUwLCBkYXRlMSksICd5ZWFyJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGxhcmdlVW5pdCA9PT0gJ21vbnRoJykge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oZGF0ZUVudi5kaWZmV2hvbGVNb250aHMoZGF0ZTAsIGRhdGUxKSwgJ21vbnRoJyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gZGlmZkRheUFuZFRpbWUoZGF0ZTAsIGRhdGUxKTsgLy8gcmV0dXJucyBhIGR1cmF0aW9uXG4gICAgfVxufVxuXG4vKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5mdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG52YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfTtcclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59O1xuXG5mdW5jdGlvbiBwYXJzZVJlY3VycmluZyhldmVudElucHV0LCBhbGxEYXlEZWZhdWx0LCBkYXRlRW52LCByZWN1cnJpbmdUeXBlcywgbGVmdG92ZXJzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWN1cnJpbmdUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbG9jYWxMZWZ0b3ZlcnMgPSB7fTtcbiAgICAgICAgdmFyIHBhcnNlZCA9IHJlY3VycmluZ1R5cGVzW2ldLnBhcnNlKGV2ZW50SW5wdXQsIGxvY2FsTGVmdG92ZXJzLCBkYXRlRW52KTtcbiAgICAgICAgaWYgKHBhcnNlZCkge1xuICAgICAgICAgICAgdmFyIGFsbERheSA9IGxvY2FsTGVmdG92ZXJzLmFsbERheTtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2NhbExlZnRvdmVycy5hbGxEYXk7IC8vIHJlbW92ZSBmcm9tIGxlZnRvdmVyc1xuICAgICAgICAgICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYWxsRGF5ID0gYWxsRGF5RGVmYXVsdDtcbiAgICAgICAgICAgICAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWxsRGF5ID0gcGFyc2VkLmFsbERheUd1ZXNzO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbERheSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX19hc3NpZ24obGVmdG92ZXJzLCBsb2NhbExlZnRvdmVycyk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFsbERheTogYWxsRGF5LFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBwYXJzZWQuZHVyYXRpb24sXG4gICAgICAgICAgICAgICAgdHlwZURhdGE6IHBhcnNlZC50eXBlRGF0YSxcbiAgICAgICAgICAgICAgICB0eXBlSWQ6IGlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG4vKlxuRXZlbnQgTVVTVCBoYXZlIGEgcmVjdXJyaW5nRGVmXG4qL1xuZnVuY3Rpb24gZXhwYW5kUmVjdXJyaW5nUmFuZ2VzKGV2ZW50RGVmLCBkdXJhdGlvbiwgZnJhbWluZ1JhbmdlLCBkYXRlRW52LCByZWN1cnJpbmdUeXBlcykge1xuICAgIHZhciB0eXBlRGVmID0gcmVjdXJyaW5nVHlwZXNbZXZlbnREZWYucmVjdXJyaW5nRGVmLnR5cGVJZF07XG4gICAgdmFyIG1hcmtlcnMgPSB0eXBlRGVmLmV4cGFuZChldmVudERlZi5yZWN1cnJpbmdEZWYudHlwZURhdGEsIHtcbiAgICAgICAgc3RhcnQ6IGRhdGVFbnYuc3VidHJhY3QoZnJhbWluZ1JhbmdlLnN0YXJ0LCBkdXJhdGlvbiksXG4gICAgICAgIGVuZDogZnJhbWluZ1JhbmdlLmVuZFxuICAgIH0sIGRhdGVFbnYpO1xuICAgIC8vIHRoZSByZWN1cnJlbmNlIHBsdWdpbnMgZG9uJ3QgZ3VhcmFudGVlIHRoYXQgYWxsLWRheSBldmVudHMgYXJlIHN0YXJ0LW9mLWRheSwgc28gd2UgaGF2ZSB0b1xuICAgIGlmIChldmVudERlZi5hbGxEYXkpIHtcbiAgICAgICAgbWFya2VycyA9IG1hcmtlcnMubWFwKHN0YXJ0T2ZEYXkpO1xuICAgIH1cbiAgICByZXR1cm4gbWFya2Vycztcbn1cblxudmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbi8vIE1lcmdlcyBhbiBhcnJheSBvZiBvYmplY3RzIGludG8gYSBzaW5nbGUgb2JqZWN0LlxuLy8gVGhlIHNlY29uZCBhcmd1bWVudCBhbGxvd3MgZm9yIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIHdobydzIG9iamVjdCB2YWx1ZXMgd2lsbCBiZSBtZXJnZWQgdG9nZXRoZXIuXG5mdW5jdGlvbiBtZXJnZVByb3BzKHByb3BPYmpzLCBjb21wbGV4UHJvcHMpIHtcbiAgICB2YXIgZGVzdCA9IHt9O1xuICAgIHZhciBpO1xuICAgIHZhciBuYW1lO1xuICAgIHZhciBjb21wbGV4T2JqcztcbiAgICB2YXIgajtcbiAgICB2YXIgdmFsO1xuICAgIHZhciBwcm9wcztcbiAgICBpZiAoY29tcGxleFByb3BzKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb21wbGV4UHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5hbWUgPSBjb21wbGV4UHJvcHNbaV07XG4gICAgICAgICAgICBjb21wbGV4T2JqcyA9IFtdO1xuICAgICAgICAgICAgLy8gY29sbGVjdCB0aGUgdHJhaWxpbmcgb2JqZWN0IHZhbHVlcywgc3RvcHBpbmcgd2hlbiBhIG5vbi1vYmplY3QgaXMgZGlzY292ZXJlZFxuICAgICAgICAgICAgZm9yIChqID0gcHJvcE9ianMubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICB2YWwgPSBwcm9wT2Jqc1tqXVtuYW1lXTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsKSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICBjb21wbGV4T2Jqcy51bnNoaWZ0KHZhbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3RbbmFtZV0gPSB2YWw7IC8vIGlmIHRoZXJlIHdlcmUgbm8gb2JqZWN0cywgdGhpcyB2YWx1ZSB3aWxsIGJlIHVzZWRcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgdGhlIHRyYWlsaW5nIHZhbHVlcyB3ZXJlIG9iamVjdHMsIHVzZSB0aGUgbWVyZ2VkIHZhbHVlXG4gICAgICAgICAgICBpZiAoY29tcGxleE9ianMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVzdFtuYW1lXSA9IG1lcmdlUHJvcHMoY29tcGxleE9ianMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGNvcHkgdmFsdWVzIGludG8gdGhlIGRlc3RpbmF0aW9uLCBnb2luZyBmcm9tIGxhc3QgdG8gZmlyc3RcbiAgICBmb3IgKGkgPSBwcm9wT2Jqcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBwcm9wcyA9IHByb3BPYmpzW2ldO1xuICAgICAgICBmb3IgKG5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgIGlmICghKG5hbWUgaW4gZGVzdCkpIHsgLy8gaWYgYWxyZWFkeSBhc3NpZ25lZCBieSBwcmV2aW91cyBwcm9wcyBvciBjb21wbGV4IHByb3BzLCBkb24ndCByZWFzc2lnblxuICAgICAgICAgICAgICAgIGRlc3RbbmFtZV0gPSBwcm9wc1tuYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn1cbmZ1bmN0aW9uIGZpbHRlckhhc2goaGFzaCwgZnVuYykge1xuICAgIHZhciBmaWx0ZXJlZCA9IHt9O1xuICAgIGZvciAodmFyIGtleSBpbiBoYXNoKSB7XG4gICAgICAgIGlmIChmdW5jKGhhc2hba2V5XSwga2V5KSkge1xuICAgICAgICAgICAgZmlsdGVyZWRba2V5XSA9IGhhc2hba2V5XTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmlsdGVyZWQ7XG59XG5mdW5jdGlvbiBtYXBIYXNoKGhhc2gsIGZ1bmMpIHtcbiAgICB2YXIgbmV3SGFzaCA9IHt9O1xuICAgIGZvciAodmFyIGtleSBpbiBoYXNoKSB7XG4gICAgICAgIG5ld0hhc2hba2V5XSA9IGZ1bmMoaGFzaFtrZXldLCBrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3SGFzaDtcbn1cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGEpIHtcbiAgICB2YXIgaGFzaCA9IHt9O1xuICAgIGZvciAodmFyIF9pID0gMCwgYV8xID0gYTsgX2kgPCBhXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gYV8xW19pXTtcbiAgICAgICAgaGFzaFtpdGVtXSA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBoYXNoO1xufVxuZnVuY3Rpb24gaGFzaFZhbHVlc1RvQXJyYXkob2JqKSB7XG4gICAgdmFyIGEgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgIGEucHVzaChvYmpba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufVxuZnVuY3Rpb24gaXNQcm9wc0VxdWFsKG9iajAsIG9iajEpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqMCkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmowLCBrZXkpKSB7XG4gICAgICAgICAgICBpZiAoIShrZXkgaW4gb2JqMSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIga2V5IGluIG9iajEpIHtcbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqMSwga2V5KSkge1xuICAgICAgICAgICAgaWYgKG9iajBba2V5XSAhPT0gb2JqMVtrZXldKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBwYXJzZUV2ZW50cyhyYXdFdmVudHMsIHNvdXJjZUlkLCBjYWxlbmRhciwgYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICB2YXIgZXZlbnRTdG9yZSA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgIGZvciAodmFyIF9pID0gMCwgcmF3RXZlbnRzXzEgPSByYXdFdmVudHM7IF9pIDwgcmF3RXZlbnRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciByYXdFdmVudCA9IHJhd0V2ZW50c18xW19pXTtcbiAgICAgICAgdmFyIHR1cGxlID0gcGFyc2VFdmVudChyYXdFdmVudCwgc291cmNlSWQsIGNhbGVuZGFyLCBhbGxvd09wZW5SYW5nZSk7XG4gICAgICAgIGlmICh0dXBsZSkge1xuICAgICAgICAgICAgZXZlbnRUdXBsZVRvU3RvcmUodHVwbGUsIGV2ZW50U3RvcmUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBldmVudFN0b3JlO1xufVxuZnVuY3Rpb24gZXZlbnRUdXBsZVRvU3RvcmUodHVwbGUsIGV2ZW50U3RvcmUpIHtcbiAgICBpZiAoZXZlbnRTdG9yZSA9PT0gdm9pZCAwKSB7IGV2ZW50U3RvcmUgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTsgfVxuICAgIGV2ZW50U3RvcmUuZGVmc1t0dXBsZS5kZWYuZGVmSWRdID0gdHVwbGUuZGVmO1xuICAgIGlmICh0dXBsZS5pbnN0YW5jZSkge1xuICAgICAgICBldmVudFN0b3JlLmluc3RhbmNlc1t0dXBsZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSA9IHR1cGxlLmluc3RhbmNlO1xuICAgIH1cbiAgICByZXR1cm4gZXZlbnRTdG9yZTtcbn1cbmZ1bmN0aW9uIGV4cGFuZFJlY3VycmluZyhldmVudFN0b3JlLCBmcmFtaW5nUmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRhdGVFbnYgPSBjYWxlbmRhci5kYXRlRW52O1xuICAgIHZhciBkZWZzID0gZXZlbnRTdG9yZS5kZWZzLCBpbnN0YW5jZXMgPSBldmVudFN0b3JlLmluc3RhbmNlcztcbiAgICAvLyByZW1vdmUgZXhpc3RpbmcgcmVjdXJyaW5nIGluc3RhbmNlc1xuICAgIGluc3RhbmNlcyA9IGZpbHRlckhhc2goaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgcmV0dXJuICFkZWZzW2luc3RhbmNlLmRlZklkXS5yZWN1cnJpbmdEZWY7XG4gICAgfSk7XG4gICAgZm9yICh2YXIgZGVmSWQgaW4gZGVmcykge1xuICAgICAgICB2YXIgZGVmID0gZGVmc1tkZWZJZF07XG4gICAgICAgIGlmIChkZWYucmVjdXJyaW5nRGVmKSB7XG4gICAgICAgICAgICB2YXIgZHVyYXRpb24gPSBkZWYucmVjdXJyaW5nRGVmLmR1cmF0aW9uO1xuICAgICAgICAgICAgaWYgKCFkdXJhdGlvbikge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gZGVmLmFsbERheSA/XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdGFydHMgPSBleHBhbmRSZWN1cnJpbmdSYW5nZXMoZGVmLCBkdXJhdGlvbiwgZnJhbWluZ1JhbmdlLCBjYWxlbmRhci5kYXRlRW52LCBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MucmVjdXJyaW5nVHlwZXMpO1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBzdGFydHNfMSA9IHN0YXJ0czsgX2kgPCBzdGFydHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RhcnQgPSBzdGFydHNfMVtfaV07XG4gICAgICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWZJZCwge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogc3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogZGF0ZUVudi5hZGQoc3RhcnQsIGR1cmF0aW9uKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGluc3RhbmNlc1tpbnN0YW5jZS5pbnN0YW5jZUlkXSA9IGluc3RhbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGRlZnM6IGRlZnMsIGluc3RhbmNlczogaW5zdGFuY2VzIH07XG59XG4vLyByZXRyaWV2ZXMgZXZlbnRzIHRoYXQgaGF2ZSB0aGUgc2FtZSBncm91cElkIGFzIHRoZSBpbnN0YW5jZSBzcGVjaWZpZWQgYnkgYGluc3RhbmNlSWRgXG4vLyBvciB0aGV5IGFyZSB0aGUgc2FtZSBhcyB0aGUgaW5zdGFuY2UuXG4vLyB3aHkgbWlnaHQgaW5zdGFuY2VJZCBub3QgYmUgaW4gdGhlIHN0b3JlPyBhbiBldmVudCBmcm9tIGFub3RoZXIgY2FsZW5kYXI/XG5mdW5jdGlvbiBnZXRSZWxldmFudEV2ZW50cyhldmVudFN0b3JlLCBpbnN0YW5jZUlkKSB7XG4gICAgdmFyIGluc3RhbmNlID0gZXZlbnRTdG9yZS5pbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgIHZhciBkZWZfMSA9IGV2ZW50U3RvcmUuZGVmc1tpbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIC8vIGdldCBldmVudHMvaW5zdGFuY2VzIHdpdGggc2FtZSBncm91cFxuICAgICAgICB2YXIgbmV3U3RvcmUgPSBmaWx0ZXJFdmVudFN0b3JlRGVmcyhldmVudFN0b3JlLCBmdW5jdGlvbiAobG9va0RlZikge1xuICAgICAgICAgICAgcmV0dXJuIGlzRXZlbnREZWZzR3JvdXBlZChkZWZfMSwgbG9va0RlZik7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBhZGQgdGhlIG9yaWdpbmFsXG4gICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgdXNlIGV2ZW50VHVwbGVUb1N0b3JlIG9yIHNvbWV0aGluZyBsaWtlIGl0XG4gICAgICAgIG5ld1N0b3JlLmRlZnNbZGVmXzEuZGVmSWRdID0gZGVmXzE7XG4gICAgICAgIG5ld1N0b3JlLmluc3RhbmNlc1tpbnN0YW5jZS5pbnN0YW5jZUlkXSA9IGluc3RhbmNlO1xuICAgICAgICByZXR1cm4gbmV3U3RvcmU7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbn1cbmZ1bmN0aW9uIGlzRXZlbnREZWZzR3JvdXBlZChkZWYwLCBkZWYxKSB7XG4gICAgcmV0dXJuIEJvb2xlYW4oZGVmMC5ncm91cElkICYmIGRlZjAuZ3JvdXBJZCA9PT0gZGVmMS5ncm91cElkKTtcbn1cbmZ1bmN0aW9uIHRyYW5zZm9ybVJhd0V2ZW50cyhyYXdFdmVudHMsIGV2ZW50U291cmNlLCBjYWxlbmRhcikge1xuICAgIHZhciBjYWxFYWNoVHJhbnNmb3JtID0gY2FsZW5kYXIub3B0KCdldmVudERhdGFUcmFuc2Zvcm0nKTtcbiAgICB2YXIgc291cmNlRWFjaFRyYW5zZm9ybSA9IGV2ZW50U291cmNlID8gZXZlbnRTb3VyY2UuZXZlbnREYXRhVHJhbnNmb3JtIDogbnVsbDtcbiAgICBpZiAoc291cmNlRWFjaFRyYW5zZm9ybSkge1xuICAgICAgICByYXdFdmVudHMgPSB0cmFuc2Zvcm1FYWNoUmF3RXZlbnQocmF3RXZlbnRzLCBzb3VyY2VFYWNoVHJhbnNmb3JtKTtcbiAgICB9XG4gICAgaWYgKGNhbEVhY2hUcmFuc2Zvcm0pIHtcbiAgICAgICAgcmF3RXZlbnRzID0gdHJhbnNmb3JtRWFjaFJhd0V2ZW50KHJhd0V2ZW50cywgY2FsRWFjaFRyYW5zZm9ybSk7XG4gICAgfVxuICAgIHJldHVybiByYXdFdmVudHM7XG59XG5mdW5jdGlvbiB0cmFuc2Zvcm1FYWNoUmF3RXZlbnQocmF3RXZlbnRzLCBmdW5jKSB7XG4gICAgdmFyIHJlZmluZWRFdmVudHM7XG4gICAgaWYgKCFmdW5jKSB7XG4gICAgICAgIHJlZmluZWRFdmVudHMgPSByYXdFdmVudHM7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZWZpbmVkRXZlbnRzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgcmF3RXZlbnRzXzIgPSByYXdFdmVudHM7IF9pIDwgcmF3RXZlbnRzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcmF3RXZlbnQgPSByYXdFdmVudHNfMltfaV07XG4gICAgICAgICAgICB2YXIgcmVmaW5lZEV2ZW50ID0gZnVuYyhyYXdFdmVudCk7XG4gICAgICAgICAgICBpZiAocmVmaW5lZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgcmVmaW5lZEV2ZW50cy5wdXNoKHJlZmluZWRFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChyZWZpbmVkRXZlbnQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlZmluZWRFdmVudHMucHVzaChyYXdFdmVudCk7XG4gICAgICAgICAgICB9IC8vIGlmIGEgZGlmZmVyZW50IGZhbHN5IHZhbHVlLCBkbyBub3RoaW5nXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlZmluZWRFdmVudHM7XG59XG5mdW5jdGlvbiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKSB7XG4gICAgcmV0dXJuIHsgZGVmczoge30sIGluc3RhbmNlczoge30gfTtcbn1cbmZ1bmN0aW9uIG1lcmdlRXZlbnRTdG9yZXMoc3RvcmUwLCBzdG9yZTEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkZWZzOiBfX2Fzc2lnbih7fSwgc3RvcmUwLmRlZnMsIHN0b3JlMS5kZWZzKSxcbiAgICAgICAgaW5zdGFuY2VzOiBfX2Fzc2lnbih7fSwgc3RvcmUwLmluc3RhbmNlcywgc3RvcmUxLmluc3RhbmNlcylcbiAgICB9O1xufVxuZnVuY3Rpb24gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZmlsdGVyRnVuYykge1xuICAgIHZhciBkZWZzID0gZmlsdGVySGFzaChldmVudFN0b3JlLmRlZnMsIGZpbHRlckZ1bmMpO1xuICAgIHZhciBpbnN0YW5jZXMgPSBmaWx0ZXJIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgcmV0dXJuIGRlZnNbaW5zdGFuY2UuZGVmSWRdOyAvLyBzdGlsbCBleGlzdHM/XG4gICAgfSk7XG4gICAgcmV0dXJuIHsgZGVmczogZGVmcywgaW5zdGFuY2VzOiBpbnN0YW5jZXMgfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VSYW5nZShpbnB1dCwgZGF0ZUVudikge1xuICAgIHZhciBzdGFydCA9IG51bGw7XG4gICAgdmFyIGVuZCA9IG51bGw7XG4gICAgaWYgKGlucHV0LnN0YXJ0KSB7XG4gICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoaW5wdXQuc3RhcnQpO1xuICAgIH1cbiAgICBpZiAoaW5wdXQuZW5kKSB7XG4gICAgICAgIGVuZCA9IGRhdGVFbnYuY3JlYXRlTWFya2VyKGlucHV0LmVuZCk7XG4gICAgfVxuICAgIGlmICghc3RhcnQgJiYgIWVuZCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHN0YXJ0ICYmIGVuZCAmJiBlbmQgPCBzdGFydCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xufVxuLy8gU0lERS1FRkZFQ1Q6IHdpbGwgbXV0YXRlIHJhbmdlcy5cbi8vIFdpbGwgcmV0dXJuIGEgbmV3IGFycmF5IHJlc3VsdC5cbmZ1bmN0aW9uIGludmVydFJhbmdlcyhyYW5nZXMsIGNvbnN0cmFpbnRSYW5nZSkge1xuICAgIHZhciBpbnZlcnRlZFJhbmdlcyA9IFtdO1xuICAgIHZhciBzdGFydCA9IGNvbnN0cmFpbnRSYW5nZS5zdGFydDsgLy8gdGhlIGVuZCBvZiB0aGUgcHJldmlvdXMgcmFuZ2UuIHRoZSBzdGFydCBvZiB0aGUgbmV3IHJhbmdlXG4gICAgdmFyIGk7XG4gICAgdmFyIGRhdGVSYW5nZTtcbiAgICAvLyByYW5nZXMgbmVlZCB0byBiZSBpbiBvcmRlci4gcmVxdWlyZWQgZm9yIG91ciBkYXRlLXdhbGtpbmcgYWxnb3JpdGhtXG4gICAgcmFuZ2VzLnNvcnQoY29tcGFyZVJhbmdlcyk7XG4gICAgZm9yIChpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkYXRlUmFuZ2UgPSByYW5nZXNbaV07XG4gICAgICAgIC8vIGFkZCB0aGUgc3BhbiBvZiB0aW1lIGJlZm9yZSB0aGUgZXZlbnQgKGlmIHRoZXJlIGlzIGFueSlcbiAgICAgICAgaWYgKGRhdGVSYW5nZS5zdGFydCA+IHN0YXJ0KSB7IC8vIGNvbXBhcmUgbWlsbGlzZWNvbmQgdGltZSAoc2tpcCBhbnkgYW1iaWcgbG9naWMpXG4gICAgICAgICAgICBpbnZlcnRlZFJhbmdlcy5wdXNoKHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGRhdGVSYW5nZS5zdGFydCB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZVJhbmdlLmVuZCA+IHN0YXJ0KSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVSYW5nZS5lbmQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gYWRkIHRoZSBzcGFuIG9mIHRpbWUgYWZ0ZXIgdGhlIGxhc3QgZXZlbnQgKGlmIHRoZXJlIGlzIGFueSlcbiAgICBpZiAoc3RhcnQgPCBjb25zdHJhaW50UmFuZ2UuZW5kKSB7IC8vIGNvbXBhcmUgbWlsbGlzZWNvbmQgdGltZSAoc2tpcCBhbnkgYW1iaWcgbG9naWMpXG4gICAgICAgIGludmVydGVkUmFuZ2VzLnB1c2goeyBzdGFydDogc3RhcnQsIGVuZDogY29uc3RyYWludFJhbmdlLmVuZCB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGludmVydGVkUmFuZ2VzO1xufVxuZnVuY3Rpb24gY29tcGFyZVJhbmdlcyhyYW5nZTAsIHJhbmdlMSkge1xuICAgIHJldHVybiByYW5nZTAuc3RhcnQudmFsdWVPZigpIC0gcmFuZ2UxLnN0YXJ0LnZhbHVlT2YoKTsgLy8gZWFybGllciByYW5nZXMgZ28gZmlyc3Rcbn1cbmZ1bmN0aW9uIGludGVyc2VjdFJhbmdlcyhyYW5nZTAsIHJhbmdlMSkge1xuICAgIHZhciBzdGFydCA9IHJhbmdlMC5zdGFydDtcbiAgICB2YXIgZW5kID0gcmFuZ2UwLmVuZDtcbiAgICB2YXIgbmV3UmFuZ2UgPSBudWxsO1xuICAgIGlmIChyYW5nZTEuc3RhcnQgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKHN0YXJ0ID09PSBudWxsKSB7XG4gICAgICAgICAgICBzdGFydCA9IHJhbmdlMS5zdGFydDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gbmV3IERhdGUoTWF0aC5tYXgoc3RhcnQudmFsdWVPZigpLCByYW5nZTEuc3RhcnQudmFsdWVPZigpKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHJhbmdlMS5lbmQgIT0gbnVsbCkge1xuICAgICAgICBpZiAoZW5kID09PSBudWxsKSB7XG4gICAgICAgICAgICBlbmQgPSByYW5nZTEuZW5kO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZW5kID0gbmV3IERhdGUoTWF0aC5taW4oZW5kLnZhbHVlT2YoKSwgcmFuZ2UxLmVuZC52YWx1ZU9mKCkpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoc3RhcnQgPT09IG51bGwgfHwgZW5kID09PSBudWxsIHx8IHN0YXJ0IDwgZW5kKSB7XG4gICAgICAgIG5ld1JhbmdlID0geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfVxuICAgIHJldHVybiBuZXdSYW5nZTtcbn1cbmZ1bmN0aW9uIHJhbmdlc0VxdWFsKHJhbmdlMCwgcmFuZ2UxKSB7XG4gICAgcmV0dXJuIChyYW5nZTAuc3RhcnQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UwLnN0YXJ0LnZhbHVlT2YoKSkgPT09IChyYW5nZTEuc3RhcnQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UxLnN0YXJ0LnZhbHVlT2YoKSkgJiZcbiAgICAgICAgKHJhbmdlMC5lbmQgPT09IG51bGwgPyBudWxsIDogcmFuZ2UwLmVuZC52YWx1ZU9mKCkpID09PSAocmFuZ2UxLmVuZCA9PT0gbnVsbCA/IG51bGwgOiByYW5nZTEuZW5kLnZhbHVlT2YoKSk7XG59XG5mdW5jdGlvbiByYW5nZXNJbnRlcnNlY3QocmFuZ2UwLCByYW5nZTEpIHtcbiAgICByZXR1cm4gKHJhbmdlMC5lbmQgPT09IG51bGwgfHwgcmFuZ2UxLnN0YXJ0ID09PSBudWxsIHx8IHJhbmdlMC5lbmQgPiByYW5nZTEuc3RhcnQpICYmXG4gICAgICAgIChyYW5nZTAuc3RhcnQgPT09IG51bGwgfHwgcmFuZ2UxLmVuZCA9PT0gbnVsbCB8fCByYW5nZTAuc3RhcnQgPCByYW5nZTEuZW5kKTtcbn1cbmZ1bmN0aW9uIHJhbmdlQ29udGFpbnNSYW5nZShvdXRlclJhbmdlLCBpbm5lclJhbmdlKSB7XG4gICAgcmV0dXJuIChvdXRlclJhbmdlLnN0YXJ0ID09PSBudWxsIHx8IChpbm5lclJhbmdlLnN0YXJ0ICE9PSBudWxsICYmIGlubmVyUmFuZ2Uuc3RhcnQgPj0gb3V0ZXJSYW5nZS5zdGFydCkpICYmXG4gICAgICAgIChvdXRlclJhbmdlLmVuZCA9PT0gbnVsbCB8fCAoaW5uZXJSYW5nZS5lbmQgIT09IG51bGwgJiYgaW5uZXJSYW5nZS5lbmQgPD0gb3V0ZXJSYW5nZS5lbmQpKTtcbn1cbmZ1bmN0aW9uIHJhbmdlQ29udGFpbnNNYXJrZXIocmFuZ2UsIGRhdGUpIHtcbiAgICByZXR1cm4gKHJhbmdlLnN0YXJ0ID09PSBudWxsIHx8IGRhdGUgPj0gcmFuZ2Uuc3RhcnQpICYmXG4gICAgICAgIChyYW5nZS5lbmQgPT09IG51bGwgfHwgZGF0ZSA8IHJhbmdlLmVuZCk7XG59XG4vLyBJZiB0aGUgZ2l2ZW4gZGF0ZSBpcyBub3Qgd2l0aGluIHRoZSBnaXZlbiByYW5nZSwgbW92ZSBpdCBpbnNpZGUuXG4vLyAoSWYgaXQncyBwYXN0IHRoZSBlbmQsIG1ha2UgaXQgb25lIG1pbGxpc2Vjb25kIGJlZm9yZSB0aGUgZW5kKS5cbmZ1bmN0aW9uIGNvbnN0cmFpbk1hcmtlclRvUmFuZ2UoZGF0ZSwgcmFuZ2UpIHtcbiAgICBpZiAocmFuZ2Uuc3RhcnQgIT0gbnVsbCAmJiBkYXRlIDwgcmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgcmV0dXJuIHJhbmdlLnN0YXJ0O1xuICAgIH1cbiAgICBpZiAocmFuZ2UuZW5kICE9IG51bGwgJiYgZGF0ZSA+PSByYW5nZS5lbmQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHJhbmdlLmVuZC52YWx1ZU9mKCkgLSAxKTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGU7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUV4YWN0KGFycmF5LCBleGFjdFZhbCkge1xuICAgIHZhciByZW1vdmVDbnQgPSAwO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoaSA8IGFycmF5Lmxlbmd0aCkge1xuICAgICAgICBpZiAoYXJyYXlbaV0gPT09IGV4YWN0VmFsKSB7XG4gICAgICAgICAgICBhcnJheS5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICByZW1vdmVDbnQrKztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVtb3ZlQ250O1xufVxuZnVuY3Rpb24gaXNBcnJheXNFcXVhbChhMCwgYTEpIHtcbiAgICB2YXIgbGVuID0gYTAubGVuZ3RoO1xuICAgIHZhciBpO1xuICAgIGlmIChsZW4gIT09IGExLmxlbmd0aCkgeyAvLyBub3QgYXJyYXk/IG9yIG5vdCBzYW1lIGxlbmd0aD9cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYgKGEwW2ldICE9PSBhMVtpXSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1vaXplKHdvcmtlckZ1bmMpIHtcbiAgICB2YXIgYXJncztcbiAgICB2YXIgcmVzO1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghYXJncyB8fCAhaXNBcnJheXNFcXVhbChhcmdzLCBhcmd1bWVudHMpKSB7XG4gICAgICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgcmVzID0gd29ya2VyRnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbn1cbi8qXG5hbHdheXMgZXhlY3V0ZXMgdGhlIHdvcmtlckZ1bmMsIGJ1dCBpZiB0aGUgcmVzdWx0IGlzIGVxdWFsIHRvIHRoZSBwcmV2aW91cyByZXN1bHQsXG5yZXR1cm4gdGhlIHByZXZpb3VzIHJlc3VsdCBpbnN0ZWFkLlxuKi9cbmZ1bmN0aW9uIG1lbW9pemVPdXRwdXQod29ya2VyRnVuYywgZXF1YWxpdHlGdW5jKSB7XG4gICAgdmFyIGNhY2hlZFJlcyA9IG51bGw7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5ld1JlcyA9IHdvcmtlckZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKGNhY2hlZFJlcyA9PT0gbnVsbCB8fCAhKGNhY2hlZFJlcyA9PT0gbmV3UmVzIHx8IGVxdWFsaXR5RnVuYyhjYWNoZWRSZXMsIG5ld1JlcykpKSB7XG4gICAgICAgICAgICBjYWNoZWRSZXMgPSBuZXdSZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhY2hlZFJlcztcbiAgICB9O1xufVxuXG52YXIgRVhURU5ERURfU0VUVElOR1NfQU5EX1NFVkVSSVRJRVMgPSB7XG4gICAgd2VlazogMyxcbiAgICBzZXBhcmF0b3I6IDAsXG4gICAgb21pdFplcm9NaW51dGU6IDAsXG4gICAgbWVyaWRpZW06IDAsXG4gICAgb21pdENvbW1hczogMFxufTtcbnZhciBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFUyA9IHtcbiAgICB0aW1lWm9uZU5hbWU6IDcsXG4gICAgZXJhOiA2LFxuICAgIHllYXI6IDUsXG4gICAgbW9udGg6IDQsXG4gICAgZGF5OiAyLFxuICAgIHdlZWtkYXk6IDIsXG4gICAgaG91cjogMSxcbiAgICBtaW51dGU6IDEsXG4gICAgc2Vjb25kOiAxXG59O1xudmFyIE1FUklESUVNX1JFID0gL1xccyooW2FwXSlcXC4/bVxcLj8vaTsgLy8gZWF0cyB1cCBsZWFkaW5nIHNwYWNlcyB0b29cbnZhciBDT01NQV9SRSA9IC8sL2c7IC8vIHdlIG5lZWQgcmUgZm9yIGdsb2JhbG5lc3NcbnZhciBNVUxUSV9TUEFDRV9SRSA9IC9cXHMrL2c7XG52YXIgTFRSX1JFID0gL1xcdTIwMGUvZzsgLy8gY29udHJvbCBjaGFyYWN0ZXJcbnZhciBVVENfUkUgPSAvVVRDfEdNVC87XG52YXIgTmF0aXZlRm9ybWF0dGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE5hdGl2ZUZvcm1hdHRlcihmb3JtYXRTZXR0aW5ncykge1xuICAgICAgICB2YXIgc3RhbmRhcmREYXRlUHJvcHMgPSB7fTtcbiAgICAgICAgdmFyIGV4dGVuZGVkU2V0dGluZ3MgPSB7fTtcbiAgICAgICAgdmFyIHNldmVyaXR5ID0gMDtcbiAgICAgICAgZm9yICh2YXIgbmFtZV8xIGluIGZvcm1hdFNldHRpbmdzKSB7XG4gICAgICAgICAgICBpZiAobmFtZV8xIGluIEVYVEVOREVEX1NFVFRJTkdTX0FORF9TRVZFUklUSUVTKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5kZWRTZXR0aW5nc1tuYW1lXzFdID0gZm9ybWF0U2V0dGluZ3NbbmFtZV8xXTtcbiAgICAgICAgICAgICAgICBzZXZlcml0eSA9IE1hdGgubWF4KEVYVEVOREVEX1NFVFRJTkdTX0FORF9TRVZFUklUSUVTW25hbWVfMV0sIHNldmVyaXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkRGF0ZVByb3BzW25hbWVfMV0gPSBmb3JtYXRTZXR0aW5nc1tuYW1lXzFdO1xuICAgICAgICAgICAgICAgIGlmIChuYW1lXzEgaW4gU1RBTkRBUkRfREFURV9QUk9QX1NFVkVSSVRJRVMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V2ZXJpdHkgPSBNYXRoLm1heChTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFU1tuYW1lXzFdLCBzZXZlcml0eSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RhbmRhcmREYXRlUHJvcHMgPSBzdGFuZGFyZERhdGVQcm9wcztcbiAgICAgICAgdGhpcy5leHRlbmRlZFNldHRpbmdzID0gZXh0ZW5kZWRTZXR0aW5ncztcbiAgICAgICAgdGhpcy5zZXZlcml0eSA9IHNldmVyaXR5O1xuICAgICAgICB0aGlzLmJ1aWxkRm9ybWF0dGluZ0Z1bmMgPSBtZW1vaXplKGJ1aWxkRm9ybWF0dGluZ0Z1bmMpO1xuICAgIH1cbiAgICBOYXRpdmVGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdCA9IGZ1bmN0aW9uIChkYXRlLCBjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkRm9ybWF0dGluZ0Z1bmModGhpcy5zdGFuZGFyZERhdGVQcm9wcywgdGhpcy5leHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KShkYXRlKTtcbiAgICB9O1xuICAgIE5hdGl2ZUZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0UmFuZ2UgPSBmdW5jdGlvbiAoc3RhcnQsIGVuZCwgY29udGV4dCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBzdGFuZGFyZERhdGVQcm9wcyA9IF9hLnN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzID0gX2EuZXh0ZW5kZWRTZXR0aW5ncztcbiAgICAgICAgdmFyIGRpZmZTZXZlcml0eSA9IGNvbXB1dGVNYXJrZXJEaWZmU2V2ZXJpdHkoc3RhcnQubWFya2VyLCBlbmQubWFya2VyLCBjb250ZXh0LmNhbGVuZGFyU3lzdGVtKTtcbiAgICAgICAgaWYgKCFkaWZmU2V2ZXJpdHkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvcm1hdChzdGFydCwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJpZ2dlc3RVbml0Rm9yUGFydGlhbCA9IGRpZmZTZXZlcml0eTtcbiAgICAgICAgaWYgKGJpZ2dlc3RVbml0Rm9yUGFydGlhbCA+IDEgJiYgLy8gdGhlIHR3byBkYXRlcyBhcmUgZGlmZmVyZW50IGluIGEgd2F5IHRoYXQncyBsYXJnZXIgc2NhbGUgdGhhbiB0aW1lXG4gICAgICAgICAgICAoc3RhbmRhcmREYXRlUHJvcHMueWVhciA9PT0gJ251bWVyaWMnIHx8IHN0YW5kYXJkRGF0ZVByb3BzLnllYXIgPT09ICcyLWRpZ2l0JykgJiZcbiAgICAgICAgICAgIChzdGFuZGFyZERhdGVQcm9wcy5tb250aCA9PT0gJ251bWVyaWMnIHx8IHN0YW5kYXJkRGF0ZVByb3BzLm1vbnRoID09PSAnMi1kaWdpdCcpICYmXG4gICAgICAgICAgICAoc3RhbmRhcmREYXRlUHJvcHMuZGF5ID09PSAnbnVtZXJpYycgfHwgc3RhbmRhcmREYXRlUHJvcHMuZGF5ID09PSAnMi1kaWdpdCcpKSB7XG4gICAgICAgICAgICBiaWdnZXN0VW5pdEZvclBhcnRpYWwgPSAxOyAvLyBtYWtlIGl0IGxvb2sgbGlrZSB0aGUgZGF0ZXMgYXJlIG9ubHkgZGlmZmVyZW50IGluIHRlcm1zIG9mIHRpbWVcbiAgICAgICAgfVxuICAgICAgICB2YXIgZnVsbDAgPSB0aGlzLmZvcm1hdChzdGFydCwgY29udGV4dCk7XG4gICAgICAgIHZhciBmdWxsMSA9IHRoaXMuZm9ybWF0KGVuZCwgY29udGV4dCk7XG4gICAgICAgIGlmIChmdWxsMCA9PT0gZnVsbDEpIHtcbiAgICAgICAgICAgIHJldHVybiBmdWxsMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFydGlhbERhdGVQcm9wcyA9IGNvbXB1dGVQYXJ0aWFsRm9ybWF0dGluZ09wdGlvbnMoc3RhbmRhcmREYXRlUHJvcHMsIGJpZ2dlc3RVbml0Rm9yUGFydGlhbCk7XG4gICAgICAgIHZhciBwYXJ0aWFsRm9ybWF0dGluZ0Z1bmMgPSBidWlsZEZvcm1hdHRpbmdGdW5jKHBhcnRpYWxEYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpO1xuICAgICAgICB2YXIgcGFydGlhbDAgPSBwYXJ0aWFsRm9ybWF0dGluZ0Z1bmMoc3RhcnQpO1xuICAgICAgICB2YXIgcGFydGlhbDEgPSBwYXJ0aWFsRm9ybWF0dGluZ0Z1bmMoZW5kKTtcbiAgICAgICAgdmFyIGluc2VydGlvbiA9IGZpbmRDb21tb25JbnNlcnRpb24oZnVsbDAsIHBhcnRpYWwwLCBmdWxsMSwgcGFydGlhbDEpO1xuICAgICAgICB2YXIgc2VwYXJhdG9yID0gZXh0ZW5kZWRTZXR0aW5ncy5zZXBhcmF0b3IgfHwgJyc7XG4gICAgICAgIGlmIChpbnNlcnRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBpbnNlcnRpb24uYmVmb3JlICsgcGFydGlhbDAgKyBzZXBhcmF0b3IgKyBwYXJ0aWFsMSArIGluc2VydGlvbi5hZnRlcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVsbDAgKyBzZXBhcmF0b3IgKyBmdWxsMTtcbiAgICB9O1xuICAgIE5hdGl2ZUZvcm1hdHRlci5wcm90b3R5cGUuZ2V0TGFyZ2VzdFVuaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5zZXZlcml0eSkge1xuICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgIHJldHVybiAneWVhcic7XG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuICdtb250aCc7XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgcmV0dXJuICd3ZWVrJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkYXknO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gTmF0aXZlRm9ybWF0dGVyO1xufSgpKTtcbmZ1bmN0aW9uIGJ1aWxkRm9ybWF0dGluZ0Z1bmMoc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MsIGNvbnRleHQpIHtcbiAgICB2YXIgc3RhbmRhcmREYXRlUHJvcENudCA9IE9iamVjdC5rZXlzKHN0YW5kYXJkRGF0ZVByb3BzKS5sZW5ndGg7XG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BDbnQgPT09IDEgJiYgc3RhbmRhcmREYXRlUHJvcHMudGltZVpvbmVOYW1lID09PSAnc2hvcnQnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdFRpbWVab25lT2Zmc2V0KGRhdGUudGltZVpvbmVPZmZzZXQpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoc3RhbmRhcmREYXRlUHJvcENudCA9PT0gMCAmJiBleHRlbmRlZFNldHRpbmdzLndlZWspIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0V2Vla051bWJlcihjb250ZXh0LmNvbXB1dGVXZWVrTnVtYmVyKGRhdGUubWFya2VyKSwgY29udGV4dC53ZWVrTGFiZWwsIGNvbnRleHQubG9jYWxlLCBleHRlbmRlZFNldHRpbmdzLndlZWspO1xuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gYnVpbGROYXRpdmVGb3JtYXR0aW5nRnVuYyhzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG59XG5mdW5jdGlvbiBidWlsZE5hdGl2ZUZvcm1hdHRpbmdGdW5jKHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgc3RhbmRhcmREYXRlUHJvcHMgPSBfX2Fzc2lnbih7fSwgc3RhbmRhcmREYXRlUHJvcHMpOyAvLyBjb3B5XG4gICAgZXh0ZW5kZWRTZXR0aW5ncyA9IF9fYXNzaWduKHt9LCBleHRlbmRlZFNldHRpbmdzKTsgLy8gY29weVxuICAgIHNhbml0aXplU2V0dGluZ3Moc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MpO1xuICAgIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lID0gJ1VUQyc7IC8vIHdlIGxldmVyYWdlIHRoZSBvbmx5IGd1YXJhbnRlZWQgdGltZVpvbmUgZm9yIG91ciBVVEMgbWFya2Vyc1xuICAgIHZhciBub3JtYWxGb3JtYXQgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChjb250ZXh0LmxvY2FsZS5jb2Rlcywgc3RhbmRhcmREYXRlUHJvcHMpO1xuICAgIHZhciB6ZXJvRm9ybWF0OyAvLyBuZWVkZWQ/XG4gICAgaWYgKGV4dGVuZGVkU2V0dGluZ3Mub21pdFplcm9NaW51dGUpIHtcbiAgICAgICAgdmFyIHplcm9Qcm9wcyA9IF9fYXNzaWduKHt9LCBzdGFuZGFyZERhdGVQcm9wcyk7XG4gICAgICAgIGRlbGV0ZSB6ZXJvUHJvcHMubWludXRlOyAvLyBzZWNvbmRzIGFuZCBtcyB3ZXJlIGFscmVhZHkgY29uc2lkZXJlZCBpbiBzYW5pdGl6ZVNldHRpbmdzXG4gICAgICAgIHplcm9Gb3JtYXQgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChjb250ZXh0LmxvY2FsZS5jb2RlcywgemVyb1Byb3BzKTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgIHZhciBtYXJrZXIgPSBkYXRlLm1hcmtlcjtcbiAgICAgICAgdmFyIGZvcm1hdDtcbiAgICAgICAgaWYgKHplcm9Gb3JtYXQgJiYgIW1hcmtlci5nZXRVVENNaW51dGVzKCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IHplcm9Gb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBub3JtYWxGb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHMgPSBmb3JtYXQuZm9ybWF0KG1hcmtlcik7XG4gICAgICAgIHJldHVybiBwb3N0UHJvY2VzcyhzLCBkYXRlLCBzdGFuZGFyZERhdGVQcm9wcywgZXh0ZW5kZWRTZXR0aW5ncywgY29udGV4dCk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHNhbml0aXplU2V0dGluZ3Moc3RhbmRhcmREYXRlUHJvcHMsIGV4dGVuZGVkU2V0dGluZ3MpIHtcbiAgICAvLyBkZWFsIHdpdGggYSBicm93c2VyIGluY29uc2lzdGVuY3kgd2hlcmUgZm9ybWF0dGluZyB0aGUgdGltZXpvbmVcbiAgICAvLyByZXF1aXJlcyB0aGF0IHRoZSBob3VyL21pbnV0ZSBiZSBwcmVzZW50LlxuICAgIGlmIChzdGFuZGFyZERhdGVQcm9wcy50aW1lWm9uZU5hbWUpIHtcbiAgICAgICAgaWYgKCFzdGFuZGFyZERhdGVQcm9wcy5ob3VyKSB7XG4gICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy5ob3VyID0gJzItZGlnaXQnO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3RhbmRhcmREYXRlUHJvcHMubWludXRlKSB7XG4gICAgICAgICAgICBzdGFuZGFyZERhdGVQcm9wcy5taW51dGUgPSAnMi1kaWdpdCc7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gb25seSBzdXBwb3J0IHNob3J0IHRpbWV6b25lIG5hbWVzXG4gICAgaWYgKHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9PT0gJ2xvbmcnKSB7XG4gICAgICAgIHN0YW5kYXJkRGF0ZVByb3BzLnRpbWVab25lTmFtZSA9ICdzaG9ydCc7XG4gICAgfVxuICAgIC8vIGlmIHJlcXVlc3RpbmcgdG8gZGlzcGxheSBzZWNvbmRzLCBNVVNUIGRpc3BsYXkgbWludXRlc1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlICYmIChzdGFuZGFyZERhdGVQcm9wcy5zZWNvbmQgfHwgc3RhbmRhcmREYXRlUHJvcHMubWlsbGlzZWNvbmQpKSB7XG4gICAgICAgIGRlbGV0ZSBleHRlbmRlZFNldHRpbmdzLm9taXRaZXJvTWludXRlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHBvc3RQcm9jZXNzKHMsIGRhdGUsIHN0YW5kYXJkRGF0ZVByb3BzLCBleHRlbmRlZFNldHRpbmdzLCBjb250ZXh0KSB7XG4gICAgcyA9IHMucmVwbGFjZShMVFJfUkUsICcnKTsgLy8gcmVtb3ZlIGxlZnQtdG8tcmlnaHQgY29udHJvbCBjaGFycy4gZG8gZmlyc3QuIGdvb2QgZm9yIG90aGVyIHJlZ2V4ZXNcbiAgICBpZiAoc3RhbmRhcmREYXRlUHJvcHMudGltZVpvbmVOYW1lID09PSAnc2hvcnQnKSB7XG4gICAgICAgIHMgPSBpbmplY3RUem9TdHIocywgKGNvbnRleHQudGltZVpvbmUgPT09ICdVVEMnIHx8IGRhdGUudGltZVpvbmVPZmZzZXQgPT0gbnVsbCkgP1xuICAgICAgICAgICAgJ1VUQycgOiAvLyBpbXBvcnRhbnQgdG8gbm9ybWFsaXplIGZvciBJRSwgd2hpY2ggZG9lcyBcIkdNVFwiXG4gICAgICAgICAgICBmb3JtYXRUaW1lWm9uZU9mZnNldChkYXRlLnRpbWVab25lT2Zmc2V0KSk7XG4gICAgfVxuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm9taXRDb21tYXMpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZShDT01NQV9SRSwgJycpLnRyaW0oKTtcbiAgICB9XG4gICAgaWYgKGV4dGVuZGVkU2V0dGluZ3Mub21pdFplcm9NaW51dGUpIHtcbiAgICAgICAgcyA9IHMucmVwbGFjZSgnOjAwJywgJycpOyAvLyB6ZXJvRm9ybWF0IGRvZXNuJ3QgYWx3YXlzIGFjaGlldmUgdGhpc1xuICAgIH1cbiAgICAvLyBeIGRvIGFueXRoaW5nIHRoYXQgbWlnaHQgY3JlYXRlIGFkamFjZW50IHNwYWNlcyBiZWZvcmUgdGhpcyBwb2ludCxcbiAgICAvLyBiZWNhdXNlIE1FUklESUVNX1JFIGxpa2VzIHRvIGVhdCB1cCBsb2FkaW5nIHNwYWNlc1xuICAgIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSBmYWxzZSkge1xuICAgICAgICBzID0gcy5yZXBsYWNlKE1FUklESUVNX1JFLCAnJykudHJpbSgpO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSAnbmFycm93JykgeyAvLyBhL3BcbiAgICAgICAgcyA9IHMucmVwbGFjZShNRVJJRElFTV9SRSwgZnVuY3Rpb24gKG0wLCBtMSkge1xuICAgICAgICAgICAgcmV0dXJuIG0xLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHRlbmRlZFNldHRpbmdzLm1lcmlkaWVtID09PSAnc2hvcnQnKSB7IC8vIGFtL3BtXG4gICAgICAgIHMgPSBzLnJlcGxhY2UoTUVSSURJRU1fUkUsIGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgICAgIHJldHVybiBtMS50b0xvY2FsZUxvd2VyQ2FzZSgpICsgJ20nO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXh0ZW5kZWRTZXR0aW5ncy5tZXJpZGllbSA9PT0gJ2xvd2VyY2FzZScpIHsgLy8gb3RoZXIgbWVyaWRpZW0gdHJhbnNmb3JtZXJzIGFscmVhZHkgY29udmVydGVkIHRvIGxvd2VyY2FzZVxuICAgICAgICBzID0gcy5yZXBsYWNlKE1FUklESUVNX1JFLCBmdW5jdGlvbiAobTApIHtcbiAgICAgICAgICAgIHJldHVybiBtMC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcyA9IHMucmVwbGFjZShNVUxUSV9TUEFDRV9SRSwgJyAnKTtcbiAgICBzID0gcy50cmltKCk7XG4gICAgcmV0dXJuIHM7XG59XG5mdW5jdGlvbiBpbmplY3RUem9TdHIocywgdHpvU3RyKSB7XG4gICAgdmFyIHJlcGxhY2VkID0gZmFsc2U7XG4gICAgcyA9IHMucmVwbGFjZShVVENfUkUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVwbGFjZWQgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdHpvU3RyO1xuICAgIH0pO1xuICAgIC8vIElFMTEgZG9lc24ndCBpbmNsdWRlIFVUQy9HTVQgaW4gdGhlIG9yaWdpbmFsIHN0cmluZywgc28gYXBwZW5kIHRvIGVuZFxuICAgIGlmICghcmVwbGFjZWQpIHtcbiAgICAgICAgcyArPSAnICcgKyB0em9TdHI7XG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuZnVuY3Rpb24gZm9ybWF0V2Vla051bWJlcihudW0sIHdlZWtMYWJlbCwgbG9jYWxlLCBkaXNwbGF5KSB7XG4gICAgdmFyIHBhcnRzID0gW107XG4gICAgaWYgKGRpc3BsYXkgPT09ICduYXJyb3cnKSB7XG4gICAgICAgIHBhcnRzLnB1c2god2Vla0xhYmVsKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZGlzcGxheSA9PT0gJ3Nob3J0Jykge1xuICAgICAgICBwYXJ0cy5wdXNoKHdlZWtMYWJlbCwgJyAnKTtcbiAgICB9XG4gICAgLy8gb3RoZXJ3aXNlLCBjb25zaWRlcmVkICdudW1lcmljJ1xuICAgIHBhcnRzLnB1c2gobG9jYWxlLnNpbXBsZU51bWJlckZvcm1hdC5mb3JtYXQobnVtKSk7XG4gICAgaWYgKGxvY2FsZS5vcHRpb25zLmlzUnRsKSB7IC8vIFRPRE86IHVzZSBjb250cm9sIGNoYXJhY3RlcnMgaW5zdGVhZD9cbiAgICAgICAgcGFydHMucmV2ZXJzZSgpO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHMuam9pbignJyk7XG59XG4vLyBSYW5nZSBGb3JtYXR0aW5nIFV0aWxzXG4vLyAwID0gZXhhY3RseSB0aGUgc2FtZVxuLy8gMSA9IGRpZmZlcmVudCBieSB0aW1lXG4vLyBhbmQgYmlnZ2VyXG5mdW5jdGlvbiBjb21wdXRlTWFya2VyRGlmZlNldmVyaXR5KGQwLCBkMSwgY2EpIHtcbiAgICBpZiAoY2EuZ2V0TWFya2VyWWVhcihkMCkgIT09IGNhLmdldE1hcmtlclllYXIoZDEpKSB7XG4gICAgICAgIHJldHVybiA1O1xuICAgIH1cbiAgICBpZiAoY2EuZ2V0TWFya2VyTW9udGgoZDApICE9PSBjYS5nZXRNYXJrZXJNb250aChkMSkpIHtcbiAgICAgICAgcmV0dXJuIDQ7XG4gICAgfVxuICAgIGlmIChjYS5nZXRNYXJrZXJEYXkoZDApICE9PSBjYS5nZXRNYXJrZXJEYXkoZDEpKSB7XG4gICAgICAgIHJldHVybiAyO1xuICAgIH1cbiAgICBpZiAodGltZUFzTXMoZDApICE9PSB0aW1lQXNNcyhkMSkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIHJldHVybiAwO1xufVxuZnVuY3Rpb24gY29tcHV0ZVBhcnRpYWxGb3JtYXR0aW5nT3B0aW9ucyhvcHRpb25zLCBiaWdnZXN0VW5pdCkge1xuICAgIHZhciBwYXJ0aWFsT3B0aW9ucyA9IHt9O1xuICAgIGZvciAodmFyIG5hbWVfMiBpbiBvcHRpb25zKSB7XG4gICAgICAgIGlmICghKG5hbWVfMiBpbiBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFUykgfHwgLy8gbm90IGEgZGF0ZSBwYXJ0IHByb3AgKGxpa2UgdGltZVpvbmUpXG4gICAgICAgICAgICBTVEFOREFSRF9EQVRFX1BST1BfU0VWRVJJVElFU1tuYW1lXzJdIDw9IGJpZ2dlc3RVbml0KSB7XG4gICAgICAgICAgICBwYXJ0aWFsT3B0aW9uc1tuYW1lXzJdID0gb3B0aW9uc1tuYW1lXzJdO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJ0aWFsT3B0aW9ucztcbn1cbmZ1bmN0aW9uIGZpbmRDb21tb25JbnNlcnRpb24oZnVsbDAsIHBhcnRpYWwwLCBmdWxsMSwgcGFydGlhbDEpIHtcbiAgICB2YXIgaTAgPSAwO1xuICAgIHdoaWxlIChpMCA8IGZ1bGwwLmxlbmd0aCkge1xuICAgICAgICB2YXIgZm91bmQwID0gZnVsbDAuaW5kZXhPZihwYXJ0aWFsMCwgaTApO1xuICAgICAgICBpZiAoZm91bmQwID09PSAtMSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJlZm9yZTAgPSBmdWxsMC5zdWJzdHIoMCwgZm91bmQwKTtcbiAgICAgICAgaTAgPSBmb3VuZDAgKyBwYXJ0aWFsMC5sZW5ndGg7XG4gICAgICAgIHZhciBhZnRlcjAgPSBmdWxsMC5zdWJzdHIoaTApO1xuICAgICAgICB2YXIgaTEgPSAwO1xuICAgICAgICB3aGlsZSAoaTEgPCBmdWxsMS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBmb3VuZDEgPSBmdWxsMS5pbmRleE9mKHBhcnRpYWwxLCBpMSk7XG4gICAgICAgICAgICBpZiAoZm91bmQxID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGJlZm9yZTEgPSBmdWxsMS5zdWJzdHIoMCwgZm91bmQxKTtcbiAgICAgICAgICAgIGkxID0gZm91bmQxICsgcGFydGlhbDEubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGFmdGVyMSA9IGZ1bGwxLnN1YnN0cihpMSk7XG4gICAgICAgICAgICBpZiAoYmVmb3JlMCA9PT0gYmVmb3JlMSAmJiBhZnRlcjAgPT09IGFmdGVyMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGJlZm9yZTogYmVmb3JlMCxcbiAgICAgICAgICAgICAgICAgICAgYWZ0ZXI6IGFmdGVyMFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbi8qXG5UT0RPOiBmaXggdGhlIHRlcm1pbm9sb2d5IG9mIFwiZm9ybWF0dGVyXCIgdnMgXCJmb3JtYXR0aW5nIGZ1bmNcIlxuKi9cbi8qXG5BdCB0aGUgdGltZSBvZiBpbnN0YW50aWF0aW9uLCB0aGlzIG9iamVjdCBkb2VzIG5vdCBrbm93IHdoaWNoIGNtZC1mb3JtYXR0aW5nIHN5c3RlbSBpdCB3aWxsIHVzZS5cbkl0IHJlY2VpdmVzIHRoaXMgYXQgdGhlIHRpbWUgb2YgZm9ybWF0dGluZywgYXMgYSBzZXR0aW5nLlxuKi9cbnZhciBDbWRGb3JtYXR0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ21kRm9ybWF0dGVyKGNtZFN0ciwgc2VwYXJhdG9yKSB7XG4gICAgICAgIHRoaXMuY21kU3RyID0gY21kU3RyO1xuICAgICAgICB0aGlzLnNlcGFyYXRvciA9IHNlcGFyYXRvcjtcbiAgICB9XG4gICAgQ21kRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAoZGF0ZSwgY29udGV4dCkge1xuICAgICAgICByZXR1cm4gY29udGV4dC5jbWRGb3JtYXR0ZXIodGhpcy5jbWRTdHIsIGNyZWF0ZVZlcmJvc2VGb3JtYXR0aW5nQXJnKGRhdGUsIG51bGwsIGNvbnRleHQsIHRoaXMuc2VwYXJhdG9yKSk7XG4gICAgfTtcbiAgICBDbWRGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIGNvbnRleHQuY21kRm9ybWF0dGVyKHRoaXMuY21kU3RyLCBjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhzdGFydCwgZW5kLCBjb250ZXh0LCB0aGlzLnNlcGFyYXRvcikpO1xuICAgIH07XG4gICAgcmV0dXJuIENtZEZvcm1hdHRlcjtcbn0oKSk7XG5cbnZhciBGdW5jRm9ybWF0dGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZ1bmNGb3JtYXR0ZXIoZnVuYykge1xuICAgICAgICB0aGlzLmZ1bmMgPSBmdW5jO1xuICAgIH1cbiAgICBGdW5jRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAoZGF0ZSwgY29udGV4dCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mdW5jKGNyZWF0ZVZlcmJvc2VGb3JtYXR0aW5nQXJnKGRhdGUsIG51bGwsIGNvbnRleHQpKTtcbiAgICB9O1xuICAgIEZ1bmNGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuYyhjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhzdGFydCwgZW5kLCBjb250ZXh0KSk7XG4gICAgfTtcbiAgICByZXR1cm4gRnVuY0Zvcm1hdHRlcjtcbn0oKSk7XG5cbi8vIEZvcm1hdHRlciBPYmplY3QgQ3JlYXRpb25cbmZ1bmN0aW9uIGNyZWF0ZUZvcm1hdHRlcihpbnB1dCwgZGVmYXVsdFNlcGFyYXRvcikge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmIGlucHV0KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICBpZiAodHlwZW9mIGRlZmF1bHRTZXBhcmF0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpbnB1dCA9IF9fYXNzaWduKHsgc2VwYXJhdG9yOiBkZWZhdWx0U2VwYXJhdG9yIH0sIGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZUZvcm1hdHRlcihpbnB1dCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDbWRGb3JtYXR0ZXIoaW5wdXQsIGRlZmF1bHRTZXBhcmF0b3IpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBGdW5jRm9ybWF0dGVyKGlucHV0KTtcbiAgICB9XG59XG4vLyBTdHJpbmcgVXRpbHNcbi8vIHRpbWVab25lT2Zmc2V0IGlzIGluIG1pbnV0ZXNcbmZ1bmN0aW9uIGJ1aWxkSXNvU3RyaW5nKG1hcmtlciwgdGltZVpvbmVPZmZzZXQsIHN0cmlwWmVyb1RpbWUpIHtcbiAgICBpZiAoc3RyaXBaZXJvVGltZSA9PT0gdm9pZCAwKSB7IHN0cmlwWmVyb1RpbWUgPSBmYWxzZTsgfVxuICAgIHZhciBzID0gbWFya2VyLnRvSVNPU3RyaW5nKCk7XG4gICAgcyA9IHMucmVwbGFjZSgnLjAwMCcsICcnKTtcbiAgICBpZiAoc3RyaXBaZXJvVGltZSkge1xuICAgICAgICBzID0gcy5yZXBsYWNlKCdUMDA6MDA6MDBaJywgJycpO1xuICAgIH1cbiAgICBpZiAocy5sZW5ndGggPiAxMCkgeyAvLyB0aW1lIHBhcnQgd2Fzbid0IHN0cmlwcGVkLCBjYW4gYWRkIHRpbWV6b25lIGluZm9cbiAgICAgICAgaWYgKHRpbWVab25lT2Zmc2V0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJ1onLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGltZVpvbmVPZmZzZXQgIT09IDApIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJ1onLCBmb3JtYXRUaW1lWm9uZU9mZnNldCh0aW1lWm9uZU9mZnNldCwgdHJ1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG90aGVyd2lzZSwgaXRzIFVUQy0wIGFuZCB3ZSB3YW50IHRvIGtlZXAgdGhlIFpcbiAgICB9XG4gICAgcmV0dXJuIHM7XG59XG5mdW5jdGlvbiBmb3JtYXRJc29UaW1lU3RyaW5nKG1hcmtlcikge1xuICAgIHJldHVybiBwYWRTdGFydChtYXJrZXIuZ2V0VVRDSG91cnMoKSwgMikgKyAnOicgK1xuICAgICAgICBwYWRTdGFydChtYXJrZXIuZ2V0VVRDTWludXRlcygpLCAyKSArICc6JyArXG4gICAgICAgIHBhZFN0YXJ0KG1hcmtlci5nZXRVVENTZWNvbmRzKCksIDIpO1xufVxuZnVuY3Rpb24gZm9ybWF0VGltZVpvbmVPZmZzZXQobWludXRlcywgZG9Jc28pIHtcbiAgICBpZiAoZG9Jc28gPT09IHZvaWQgMCkgeyBkb0lzbyA9IGZhbHNlOyB9XG4gICAgdmFyIHNpZ24gPSBtaW51dGVzIDwgMCA/ICctJyA6ICcrJztcbiAgICB2YXIgYWJzID0gTWF0aC5hYnMobWludXRlcyk7XG4gICAgdmFyIGhvdXJzID0gTWF0aC5mbG9vcihhYnMgLyA2MCk7XG4gICAgdmFyIG1pbnMgPSBNYXRoLnJvdW5kKGFicyAlIDYwKTtcbiAgICBpZiAoZG9Jc28pIHtcbiAgICAgICAgcmV0dXJuIHNpZ24gKyBwYWRTdGFydChob3VycywgMikgKyAnOicgKyBwYWRTdGFydChtaW5zLCAyKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiAnR01UJyArIHNpZ24gKyBob3VycyArIChtaW5zID8gJzonICsgcGFkU3RhcnQobWlucywgMikgOiAnJyk7XG4gICAgfVxufVxuLy8gQXJnIFV0aWxzXG5mdW5jdGlvbiBjcmVhdGVWZXJib3NlRm9ybWF0dGluZ0FyZyhzdGFydCwgZW5kLCBjb250ZXh0LCBzZXBhcmF0b3IpIHtcbiAgICB2YXIgc3RhcnRJbmZvID0gZXhwYW5kWm9uZWRNYXJrZXIoc3RhcnQsIGNvbnRleHQuY2FsZW5kYXJTeXN0ZW0pO1xuICAgIHZhciBlbmRJbmZvID0gZW5kID8gZXhwYW5kWm9uZWRNYXJrZXIoZW5kLCBjb250ZXh0LmNhbGVuZGFyU3lzdGVtKSA6IG51bGw7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGF0ZTogc3RhcnRJbmZvLFxuICAgICAgICBzdGFydDogc3RhcnRJbmZvLFxuICAgICAgICBlbmQ6IGVuZEluZm8sXG4gICAgICAgIHRpbWVab25lOiBjb250ZXh0LnRpbWVab25lLFxuICAgICAgICBsb2NhbGVDb2RlczogY29udGV4dC5sb2NhbGUuY29kZXMsXG4gICAgICAgIHNlcGFyYXRvcjogc2VwYXJhdG9yXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGV4cGFuZFpvbmVkTWFya2VyKGRhdGVJbmZvLCBjYWxlbmRhclN5c3RlbSkge1xuICAgIHZhciBhID0gY2FsZW5kYXJTeXN0ZW0ubWFya2VyVG9BcnJheShkYXRlSW5mby5tYXJrZXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIG1hcmtlcjogZGF0ZUluZm8ubWFya2VyLFxuICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZUluZm8udGltZVpvbmVPZmZzZXQsXG4gICAgICAgIGFycmF5OiBhLFxuICAgICAgICB5ZWFyOiBhWzBdLFxuICAgICAgICBtb250aDogYVsxXSxcbiAgICAgICAgZGF5OiBhWzJdLFxuICAgICAgICBob3VyOiBhWzNdLFxuICAgICAgICBtaW51dGU6IGFbNF0sXG4gICAgICAgIHNlY29uZDogYVs1XSxcbiAgICAgICAgbWlsbGlzZWNvbmQ6IGFbNl1cbiAgICB9O1xufVxuXG52YXIgRXZlbnRTb3VyY2VBcGkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRXZlbnRTb3VyY2VBcGkoY2FsZW5kYXIsIGludGVybmFsRXZlbnRTb3VyY2UpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLmludGVybmFsRXZlbnRTb3VyY2UgPSBpbnRlcm5hbEV2ZW50U291cmNlO1xuICAgIH1cbiAgICBFdmVudFNvdXJjZUFwaS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRfU09VUkNFJyxcbiAgICAgICAgICAgIHNvdXJjZUlkOiB0aGlzLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWRcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBFdmVudFNvdXJjZUFwaS5wcm90b3R5cGUucmVmZXRjaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnRkVUQ0hfRVZFTlRfU09VUkNFUycsXG4gICAgICAgICAgICBzb3VyY2VJZHM6IFt0aGlzLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWRdXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50U291cmNlQXBpLnByb3RvdHlwZSwgXCJpZFwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5wdWJsaWNJZDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50U291cmNlQXBpLnByb3RvdHlwZSwgXCJ1cmxcIiwge1xuICAgICAgICAvLyBvbmx5IHJlbGV2YW50IHRvIGpzb24tZmVlZCBldmVudCBzb3VyY2VzXG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFNvdXJjZS5tZXRhLnVybDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIEV2ZW50U291cmNlQXBpO1xufSgpKTtcblxudmFyIEV2ZW50QXBpID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEV2ZW50QXBpKGNhbGVuZGFyLCBkZWYsIGluc3RhbmNlKSB7XG4gICAgICAgIHRoaXMuX2NhbGVuZGFyID0gY2FsZW5kYXI7XG4gICAgICAgIHRoaXMuX2RlZiA9IGRlZjtcbiAgICAgICAgdGhpcy5faW5zdGFuY2UgPSBpbnN0YW5jZSB8fCBudWxsO1xuICAgIH1cbiAgICAvKlxuICAgIFRPRE86IG1ha2UgZXZlbnQgc3RydWN0IG1vcmUgcmVzcG9uc2libGUgZm9yIHRoaXNcbiAgICAqL1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRQcm9wID0gZnVuY3Rpb24gKG5hbWUsIHZhbCkge1xuICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICBpZiAobmFtZSBpbiBEQVRFX1BST1BTKSA7XG4gICAgICAgIGVsc2UgaWYgKG5hbWUgaW4gTk9OX0RBVEVfUFJPUFMpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgTk9OX0RBVEVfUFJPUFNbbmFtZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB2YWwgPSBOT05fREFURV9QUk9QU1tuYW1lXSh2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tdXRhdGUoe1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHM6IChfYSA9IHt9LCBfYVtuYW1lXSA9IHZhbCwgX2EpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuYW1lIGluIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTKSB7XG4gICAgICAgICAgICB2YXIgdWkgPSB2b2lkIDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTW25hbWVdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gVU5TQ09QRURfRVZFTlRfVUlfUFJPUFNbbmFtZV0odmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuYW1lID09PSAnY29sb3InKSB7XG4gICAgICAgICAgICAgICAgdWkgPSB7IGJhY2tncm91bmRDb2xvcjogdmFsLCBib3JkZXJDb2xvcjogdmFsIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChuYW1lID09PSAnZWRpdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgdWkgPSB7IHN0YXJ0RWRpdGFibGU6IHZhbCwgZHVyYXRpb25FZGl0YWJsZTogdmFsIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB1aSA9IChfYiA9IHt9LCBfYltuYW1lXSA9IHZhbCwgX2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tdXRhdGUoe1xuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHM6IHsgdWk6IHVpIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0RXh0ZW5kZWRQcm9wID0gZnVuY3Rpb24gKG5hbWUsIHZhbCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHRoaXMubXV0YXRlKHtcbiAgICAgICAgICAgIGV4dGVuZGVkUHJvcHM6IChfYSA9IHt9LCBfYVtuYW1lXSA9IHZhbCwgX2EpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLnNldFN0YXJ0ID0gZnVuY3Rpb24gKHN0YXJ0SW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgc3RhcnQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihzdGFydElucHV0KTtcbiAgICAgICAgaWYgKHN0YXJ0ICYmIHRoaXMuX2luc3RhbmNlKSB7IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICAgICAgdmFyIGluc3RhbmNlUmFuZ2UgPSB0aGlzLl9pbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgICAgIHZhciBzdGFydERlbHRhID0gZGlmZkRhdGVzKGluc3RhbmNlUmFuZ2Uuc3RhcnQsIHN0YXJ0LCBkYXRlRW52LCBvcHRpb25zLmdyYW51bGFyaXR5KTsgLy8gd2hhdCBpZiBwYXJzZWQgYmFkIT9cbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1haW50YWluRHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IGRhdGVzRGVsdGE6IHN0YXJ0RGVsdGEgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YXJ0RGVsdGE6IHN0YXJ0RGVsdGEgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRFbmQgPSBmdW5jdGlvbiAoZW5kSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgZW5kO1xuICAgICAgICBpZiAoZW5kSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoZW5kSW5wdXQpO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIFRPRE86IHdhcm5pbmcgaWYgcGFyc2VkIGJhZFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnN0YW5jZSkge1xuICAgICAgICAgICAgaWYgKGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciBlbmREZWx0YSA9IGRpZmZEYXRlcyh0aGlzLl9pbnN0YW5jZS5yYW5nZS5lbmQsIGVuZCwgZGF0ZUVudiwgb3B0aW9ucy5ncmFudWxhcml0eSk7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBlbmREZWx0YTogZW5kRGVsdGEgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YW5kYXJkUHJvcHM6IHsgaGFzRW5kOiBmYWxzZSB9IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuc2V0RGF0ZXMgPSBmdW5jdGlvbiAoc3RhcnRJbnB1dCwgZW5kSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgc3RhbmRhcmRQcm9wcyA9IHsgYWxsRGF5OiBvcHRpb25zLmFsbERheSB9O1xuICAgICAgICB2YXIgc3RhcnQgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihzdGFydElucHV0KTtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgaWYgKCFzdGFydCkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5kSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5jcmVhdGVNYXJrZXIoZW5kSW5wdXQpO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHsgLy8gVE9ETzogd2FybmluZyBpZiBwYXJzZWQgYmFkXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnN0YW5jZSkge1xuICAgICAgICAgICAgdmFyIGluc3RhbmNlUmFuZ2UgPSB0aGlzLl9pbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgICAgIC8vIHdoZW4gY29tcHV0aW5nIHRoZSBkaWZmIGZvciBhbiBldmVudCBiZWluZyBjb252ZXJ0ZWQgdG8gYWxsLWRheSxcbiAgICAgICAgICAgIC8vIGNvbXB1dGUgZGlmZiBvZmYgb2YgdGhlIGFsbC1kYXkgdmFsdWVzIHRoZSB3YXkgZXZlbnQtbXV0YXRpb24gZG9lcy5cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFsbERheSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGluc3RhbmNlUmFuZ2UgPSBjb21wdXRlQWxpZ25lZERheVJhbmdlKGluc3RhbmNlUmFuZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHN0YXJ0RGVsdGEgPSBkaWZmRGF0ZXMoaW5zdGFuY2VSYW5nZS5zdGFydCwgc3RhcnQsIGRhdGVFbnYsIG9wdGlvbnMuZ3JhbnVsYXJpdHkpO1xuICAgICAgICAgICAgaWYgKGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciBlbmREZWx0YSA9IGRpZmZEYXRlcyhpbnN0YW5jZVJhbmdlLmVuZCwgZW5kLCBkYXRlRW52LCBvcHRpb25zLmdyYW51bGFyaXR5KTtcbiAgICAgICAgICAgICAgICBpZiAoZHVyYXRpb25zRXF1YWwoc3RhcnREZWx0YSwgZW5kRGVsdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZGF0ZXNEZWx0YTogc3RhcnREZWx0YSwgc3RhbmRhcmRQcm9wczogc3RhbmRhcmRQcm9wcyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgc3RhcnREZWx0YTogc3RhcnREZWx0YSwgZW5kRGVsdGE6IGVuZERlbHRhLCBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgeyAvLyBtZWFucyBcImNsZWFyIHRoZSBlbmRcIlxuICAgICAgICAgICAgICAgIHN0YW5kYXJkUHJvcHMuaGFzRW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRhdGUoeyBkYXRlc0RlbHRhOiBzdGFydERlbHRhLCBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUubW92ZVN0YXJ0ID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgc3RhcnREZWx0YTogZGVsdGEgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5tb3ZlRW5kID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZW5kRGVsdGE6IGRlbHRhIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUubW92ZURhdGVzID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBUT0RPOiB3YXJuaW5nIGlmIHBhcnNlZCBiYWRcbiAgICAgICAgICAgIHRoaXMubXV0YXRlKHsgZGF0ZXNEZWx0YTogZGVsdGEgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50QXBpLnByb3RvdHlwZS5zZXRBbGxEYXkgPSBmdW5jdGlvbiAoYWxsRGF5LCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciBzdGFuZGFyZFByb3BzID0geyBhbGxEYXk6IGFsbERheSB9O1xuICAgICAgICB2YXIgbWFpbnRhaW5EdXJhdGlvbiA9IG9wdGlvbnMubWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgaWYgKG1haW50YWluRHVyYXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgbWFpbnRhaW5EdXJhdGlvbiA9IHRoaXMuX2NhbGVuZGFyLm9wdCgnYWxsRGF5TWFpbnRhaW5EdXJhdGlvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9kZWYuYWxsRGF5ICE9PSBhbGxEYXkpIHtcbiAgICAgICAgICAgIHN0YW5kYXJkUHJvcHMuaGFzRW5kID0gbWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm11dGF0ZSh7IHN0YW5kYXJkUHJvcHM6IHN0YW5kYXJkUHJvcHMgfSk7XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUuZm9ybWF0UmFuZ2UgPSBmdW5jdGlvbiAoZm9ybWF0SW5wdXQpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLl9jYWxlbmRhci5kYXRlRW52O1xuICAgICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgdmFyIGZvcm1hdHRlciA9IGNyZWF0ZUZvcm1hdHRlcihmb3JtYXRJbnB1dCwgdGhpcy5fY2FsZW5kYXIub3B0KCdkZWZhdWx0UmFuZ2VTZXBhcmF0b3InKSk7XG4gICAgICAgIGlmICh0aGlzLl9kZWYuaGFzRW5kKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXRSYW5nZShpbnN0YW5jZS5yYW5nZS5zdGFydCwgaW5zdGFuY2UucmFuZ2UuZW5kLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICBmb3JjZWRTdGFydFR6bzogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICAgICAgZm9yY2VkRW5kVHpvOiBpbnN0YW5jZS5mb3JjZWRFbmRUem9cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0KGluc3RhbmNlLnJhbmdlLnN0YXJ0LCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgICAgICAgICBmb3JjZWRUem86IGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRBcGkucHJvdG90eXBlLm11dGF0ZSA9IGZ1bmN0aW9uIChtdXRhdGlvbikge1xuICAgICAgICB2YXIgZGVmID0gdGhpcy5fZGVmO1xuICAgICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLl9pbnN0YW5jZTtcbiAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ01VVEFURV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlSWQ6IGluc3RhbmNlLmluc3RhbmNlSWQsXG4gICAgICAgICAgICAgICAgbXV0YXRpb246IG11dGF0aW9uLFxuICAgICAgICAgICAgICAgIGZyb21BcGk6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGV2ZW50U3RvcmUgPSB0aGlzLl9jYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlO1xuICAgICAgICAgICAgdGhpcy5fZGVmID0gZXZlbnRTdG9yZS5kZWZzW2RlZi5kZWZJZF07XG4gICAgICAgICAgICB0aGlzLl9pbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlLmluc3RhbmNlSWRdO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudEFwaS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9jYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnUkVNT1ZFX0VWRU5UX0RFRicsXG4gICAgICAgICAgICBkZWZJZDogdGhpcy5fZGVmLmRlZklkXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJzb3VyY2VcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2VJZCA9IHRoaXMuX2RlZi5zb3VyY2VJZDtcbiAgICAgICAgICAgIGlmIChzb3VyY2VJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZlbnRTb3VyY2VBcGkodGhpcy5fY2FsZW5kYXIsIHRoaXMuX2NhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlc1tzb3VyY2VJZF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwic3RhcnRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pbnN0YW5jZSA/XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FsZW5kYXIuZGF0ZUVudi50b0RhdGUodGhpcy5faW5zdGFuY2UucmFuZ2Uuc3RhcnQpIDpcbiAgICAgICAgICAgICAgICBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImVuZFwiLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLl9pbnN0YW5jZSAmJiB0aGlzLl9kZWYuaGFzRW5kKSA/XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FsZW5kYXIuZGF0ZUVudi50b0RhdGUodGhpcy5faW5zdGFuY2UucmFuZ2UuZW5kKSA6XG4gICAgICAgICAgICAgICAgbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJpZFwiLCB7XG4gICAgICAgIC8vIGNvbXB1dGFibGUgcHJvcHMgdGhhdCBhbGwgYWNjZXNzIHRoZSBkZWZcbiAgICAgICAgLy8gVE9ETzogZmluZCBhIFR5cGVTY3JpcHQtY29tcGF0aWJsZSB3YXkgdG8gZG8gdGhpcyBhdCBzY2FsZVxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi5wdWJsaWNJZDsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJncm91cElkXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYuZ3JvdXBJZDsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJhbGxEYXlcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi5hbGxEYXk7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwidGl0bGVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi50aXRsZTsgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50QXBpLnByb3RvdHlwZSwgXCJ1cmxcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51cmw7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwicmVuZGVyaW5nXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYucmVuZGVyaW5nOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcInN0YXJ0RWRpdGFibGVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5zdGFydEVkaXRhYmxlOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImR1cmF0aW9uRWRpdGFibGVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5kdXJhdGlvbkVkaXRhYmxlOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImNvbnN0cmFpbnRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5jb25zdHJhaW50c1swXSB8fCBudWxsOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcIm92ZXJsYXBcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5vdmVybGFwOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImFsbG93XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYWxsb3dzWzBdIHx8IG51bGw7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwiYmFja2dyb3VuZENvbG9yXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYmFja2dyb3VuZENvbG9yOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImJvcmRlckNvbG9yXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkuYm9yZGVyQ29sb3I7IH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEFwaS5wcm90b3R5cGUsIFwidGV4dENvbG9yXCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kZWYudWkudGV4dENvbG9yOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImNsYXNzTmFtZXNcIiwge1xuICAgICAgICAvLyBOT1RFOiB1c2VyIGNhbid0IG1vZGlmeSB0aGVzZSBiZWNhdXNlIE9iamVjdC5mcmVlemUgd2FzIGNhbGxlZCBpbiBldmVudC1kZWYgcGFyc2luZ1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi51aS5jbGFzc05hbWVzOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRBcGkucHJvdG90eXBlLCBcImV4dGVuZGVkUHJvcHNcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2RlZi5leHRlbmRlZFByb3BzOyB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICByZXR1cm4gRXZlbnRBcGk7XG59KCkpO1xuXG4vKlxuU3BlY2lmeWluZyBuZXh0RGF5VGhyZXNob2xkIHNpZ25hbHMgdGhhdCBhbGwtZGF5IHJhbmdlcyBzaG91bGQgYmUgc2xpY2VkLlxuKi9cbmZ1bmN0aW9uIHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGZyYW1pbmdSYW5nZSwgbmV4dERheVRocmVzaG9sZCkge1xuICAgIHZhciBpbnZlcnNlQmdCeUdyb3VwSWQgPSB7fTtcbiAgICB2YXIgaW52ZXJzZUJnQnlEZWZJZCA9IHt9O1xuICAgIHZhciBkZWZCeUdyb3VwSWQgPSB7fTtcbiAgICB2YXIgYmdSYW5nZXMgPSBbXTtcbiAgICB2YXIgZmdSYW5nZXMgPSBbXTtcbiAgICB2YXIgZXZlbnRVaXMgPSBjb21waWxlRXZlbnRVaXMoZXZlbnRTdG9yZS5kZWZzLCBldmVudFVpQmFzZXMpO1xuICAgIGZvciAodmFyIGRlZklkIGluIGV2ZW50U3RvcmUuZGVmcykge1xuICAgICAgICB2YXIgZGVmID0gZXZlbnRTdG9yZS5kZWZzW2RlZklkXTtcbiAgICAgICAgaWYgKGRlZi5yZW5kZXJpbmcgPT09ICdpbnZlcnNlLWJhY2tncm91bmQnKSB7XG4gICAgICAgICAgICBpZiAoZGVmLmdyb3VwSWQpIHtcbiAgICAgICAgICAgICAgICBpbnZlcnNlQmdCeUdyb3VwSWRbZGVmLmdyb3VwSWRdID0gW107XG4gICAgICAgICAgICAgICAgaWYgKCFkZWZCeUdyb3VwSWRbZGVmLmdyb3VwSWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlZkJ5R3JvdXBJZFtkZWYuZ3JvdXBJZF0gPSBkZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlEZWZJZFtkZWZJZF0gPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBpbnN0YW5jZUlkIGluIGV2ZW50U3RvcmUuaW5zdGFuY2VzKSB7XG4gICAgICAgIHZhciBpbnN0YW5jZSA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzW2luc3RhbmNlSWRdO1xuICAgICAgICB2YXIgZGVmID0gZXZlbnRTdG9yZS5kZWZzW2luc3RhbmNlLmRlZklkXTtcbiAgICAgICAgdmFyIHVpID0gZXZlbnRVaXNbZGVmLmRlZklkXTtcbiAgICAgICAgdmFyIG9yaWdSYW5nZSA9IGluc3RhbmNlLnJhbmdlO1xuICAgICAgICB2YXIgbm9ybWFsUmFuZ2UgPSAoIWRlZi5hbGxEYXkgJiYgbmV4dERheVRocmVzaG9sZCkgP1xuICAgICAgICAgICAgY29tcHV0ZVZpc2libGVEYXlSYW5nZShvcmlnUmFuZ2UsIG5leHREYXlUaHJlc2hvbGQpIDpcbiAgICAgICAgICAgIG9yaWdSYW5nZTtcbiAgICAgICAgdmFyIHNsaWNlZFJhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKG5vcm1hbFJhbmdlLCBmcmFtaW5nUmFuZ2UpO1xuICAgICAgICBpZiAoc2xpY2VkUmFuZ2UpIHtcbiAgICAgICAgICAgIGlmIChkZWYucmVuZGVyaW5nID09PSAnaW52ZXJzZS1iYWNrZ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIGlmIChkZWYuZ3JvdXBJZCkge1xuICAgICAgICAgICAgICAgICAgICBpbnZlcnNlQmdCeUdyb3VwSWRbZGVmLmdyb3VwSWRdLnB1c2goc2xpY2VkUmFuZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW52ZXJzZUJnQnlEZWZJZFtpbnN0YW5jZS5kZWZJZF0ucHVzaChzbGljZWRSYW5nZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgKGRlZi5yZW5kZXJpbmcgPT09ICdiYWNrZ3JvdW5kJyA/IGJnUmFuZ2VzIDogZmdSYW5nZXMpLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBkZWY6IGRlZixcbiAgICAgICAgICAgICAgICAgICAgdWk6IHVpLFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2UsXG4gICAgICAgICAgICAgICAgICAgIHJhbmdlOiBzbGljZWRSYW5nZSxcbiAgICAgICAgICAgICAgICAgICAgaXNTdGFydDogbm9ybWFsUmFuZ2Uuc3RhcnQgJiYgbm9ybWFsUmFuZ2Uuc3RhcnQudmFsdWVPZigpID09PSBzbGljZWRSYW5nZS5zdGFydC52YWx1ZU9mKCksXG4gICAgICAgICAgICAgICAgICAgIGlzRW5kOiBub3JtYWxSYW5nZS5lbmQgJiYgbm9ybWFsUmFuZ2UuZW5kLnZhbHVlT2YoKSA9PT0gc2xpY2VkUmFuZ2UuZW5kLnZhbHVlT2YoKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAodmFyIGdyb3VwSWQgaW4gaW52ZXJzZUJnQnlHcm91cElkKSB7IC8vIEJZIEdST1VQXG4gICAgICAgIHZhciByYW5nZXMgPSBpbnZlcnNlQmdCeUdyb3VwSWRbZ3JvdXBJZF07XG4gICAgICAgIHZhciBpbnZlcnRlZFJhbmdlcyA9IGludmVydFJhbmdlcyhyYW5nZXMsIGZyYW1pbmdSYW5nZSk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgaW52ZXJ0ZWRSYW5nZXNfMSA9IGludmVydGVkUmFuZ2VzOyBfaSA8IGludmVydGVkUmFuZ2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgaW52ZXJ0ZWRSYW5nZSA9IGludmVydGVkUmFuZ2VzXzFbX2ldO1xuICAgICAgICAgICAgdmFyIGRlZiA9IGRlZkJ5R3JvdXBJZFtncm91cElkXTtcbiAgICAgICAgICAgIHZhciB1aSA9IGV2ZW50VWlzW2RlZi5kZWZJZF07XG4gICAgICAgICAgICBiZ1Jhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBkZWY6IGRlZixcbiAgICAgICAgICAgICAgICB1aTogdWksXG4gICAgICAgICAgICAgICAgaW5zdGFuY2U6IG51bGwsXG4gICAgICAgICAgICAgICAgcmFuZ2U6IGludmVydGVkUmFuZ2UsXG4gICAgICAgICAgICAgICAgaXNTdGFydDogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNFbmQ6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBkZWZJZCBpbiBpbnZlcnNlQmdCeURlZklkKSB7XG4gICAgICAgIHZhciByYW5nZXMgPSBpbnZlcnNlQmdCeURlZklkW2RlZklkXTtcbiAgICAgICAgdmFyIGludmVydGVkUmFuZ2VzID0gaW52ZXJ0UmFuZ2VzKHJhbmdlcywgZnJhbWluZ1JhbmdlKTtcbiAgICAgICAgZm9yICh2YXIgX2EgPSAwLCBpbnZlcnRlZFJhbmdlc18yID0gaW52ZXJ0ZWRSYW5nZXM7IF9hIDwgaW52ZXJ0ZWRSYW5nZXNfMi5sZW5ndGg7IF9hKyspIHtcbiAgICAgICAgICAgIHZhciBpbnZlcnRlZFJhbmdlID0gaW52ZXJ0ZWRSYW5nZXNfMltfYV07XG4gICAgICAgICAgICBiZ1Jhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBkZWY6IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF0sXG4gICAgICAgICAgICAgICAgdWk6IGV2ZW50VWlzW2RlZklkXSxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZTogbnVsbCxcbiAgICAgICAgICAgICAgICByYW5nZTogaW52ZXJ0ZWRSYW5nZSxcbiAgICAgICAgICAgICAgICBpc1N0YXJ0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc0VuZDogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGJnOiBiZ1JhbmdlcywgZmc6IGZnUmFuZ2VzIH07XG59XG5mdW5jdGlvbiBoYXNCZ1JlbmRlcmluZyhkZWYpIHtcbiAgICByZXR1cm4gZGVmLnJlbmRlcmluZyA9PT0gJ2JhY2tncm91bmQnIHx8IGRlZi5yZW5kZXJpbmcgPT09ICdpbnZlcnNlLWJhY2tncm91bmQnO1xufVxuZnVuY3Rpb24gZmlsdGVyU2Vnc1ZpYUVscyhjb250ZXh0LCBzZWdzLCBpc01pcnJvcikge1xuICAgIHZhciBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXIsIHZpZXcgPSBjb250ZXh0LnZpZXc7XG4gICAgaWYgKGNhbGVuZGFyLmhhc1B1YmxpY0hhbmRsZXJzKCdldmVudFJlbmRlcicpKSB7XG4gICAgICAgIHNlZ3MgPSBzZWdzLmZpbHRlcihmdW5jdGlvbiAoc2VnKSB7XG4gICAgICAgICAgICB2YXIgY3VzdG9tID0gY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlbmRlcicsIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIHNlZy5ldmVudFJhbmdlLmRlZiwgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBpc01pcnJvcjogaXNNaXJyb3IsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IHNlZy5pc1N0YXJ0LFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogc2VnLmlzRW5kLFxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBpbmNsdWRlIHNlZy5yYW5nZSBvbmNlIGFsbCBjb21wb25lbnRzIGNvbnNpc3RlbnRseSBnZW5lcmF0ZSBpdFxuICAgICAgICAgICAgICAgICAgICBlbDogc2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICBpZiAoY3VzdG9tID09PSBmYWxzZSkgeyAvLyBtZWFucyBkb24ndCByZW5kZXIgYXQgYWxsXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY3VzdG9tICYmIGN1c3RvbSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHNlZy5lbCA9IGN1c3RvbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZm9yICh2YXIgX2kgPSAwLCBzZWdzXzEgPSBzZWdzOyBfaSA8IHNlZ3NfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHNlZyA9IHNlZ3NfMVtfaV07XG4gICAgICAgIHNldEVsU2VnKHNlZy5lbCwgc2VnKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlZ3M7XG59XG5mdW5jdGlvbiBzZXRFbFNlZyhlbCwgc2VnKSB7XG4gICAgZWwuZmNTZWcgPSBzZWc7XG59XG5mdW5jdGlvbiBnZXRFbFNlZyhlbCkge1xuICAgIHJldHVybiBlbC5mY1NlZyB8fCBudWxsO1xufVxuLy8gZXZlbnQgdWkgY29tcHV0YXRpb25cbmZ1bmN0aW9uIGNvbXBpbGVFdmVudFVpcyhldmVudERlZnMsIGV2ZW50VWlCYXNlcykge1xuICAgIHJldHVybiBtYXBIYXNoKGV2ZW50RGVmcywgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgIHJldHVybiBjb21waWxlRXZlbnRVaShldmVudERlZiwgZXZlbnRVaUJhc2VzKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGNvbXBpbGVFdmVudFVpKGV2ZW50RGVmLCBldmVudFVpQmFzZXMpIHtcbiAgICB2YXIgdWlzID0gW107XG4gICAgaWYgKGV2ZW50VWlCYXNlc1snJ10pIHtcbiAgICAgICAgdWlzLnB1c2goZXZlbnRVaUJhc2VzWycnXSk7XG4gICAgfVxuICAgIGlmIChldmVudFVpQmFzZXNbZXZlbnREZWYuZGVmSWRdKSB7XG4gICAgICAgIHVpcy5wdXNoKGV2ZW50VWlCYXNlc1tldmVudERlZi5kZWZJZF0pO1xuICAgIH1cbiAgICB1aXMucHVzaChldmVudERlZi51aSk7XG4gICAgcmV0dXJuIGNvbWJpbmVFdmVudFVpcyh1aXMpO1xufVxuLy8gdHJpZ2dlcnNcbmZ1bmN0aW9uIHRyaWdnZXJSZW5kZXJlZFNlZ3MoY29udGV4dCwgc2VncywgaXNNaXJyb3JzKSB7XG4gICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhciwgdmlldyA9IGNvbnRleHQudmlldztcbiAgICBpZiAoY2FsZW5kYXIuaGFzUHVibGljSGFuZGxlcnMoJ2V2ZW50UG9zaXRpb25lZCcpKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18yID0gc2VnczsgX2kgPCBzZWdzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18yW19pXTtcbiAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlckFmdGVyU2l6aW5nKCdldmVudFBvc2l0aW9uZWQnLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgaXNNaXJyb3I6IGlzTWlycm9ycyxcbiAgICAgICAgICAgICAgICAgICAgaXNTdGFydDogc2VnLmlzU3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIGlzRW5kOiBzZWcuaXNFbmQsXG4gICAgICAgICAgICAgICAgICAgIGVsOiBzZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWNhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlTG9hZGluZ0xldmVsKSB7IC8vIGF2b2lkIGluaXRpYWwgZW1wdHkgc3RhdGUgd2hpbGUgcGVuZGluZ1xuICAgICAgICBjYWxlbmRhci5hZnRlclNpemluZ1RyaWdnZXJzLl9ldmVudHNQb3NpdGlvbmVkID0gW251bGxdOyAvLyBmaXJlIG9uY2VcbiAgICB9XG59XG5mdW5jdGlvbiB0cmlnZ2VyV2lsbFJlbW92ZVNlZ3MoY29udGV4dCwgc2VncywgaXNNaXJyb3JzKSB7XG4gICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhciwgdmlldyA9IGNvbnRleHQudmlldztcbiAgICBmb3IgKHZhciBfaSA9IDAsIHNlZ3NfMyA9IHNlZ3M7IF9pIDwgc2Vnc18zLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc2VnID0gc2Vnc18zW19pXTtcbiAgICAgICAgY2FsZW5kYXIudHJpZ2dlcignZXZlbnRFbFJlbW92ZScsIHNlZy5lbCk7XG4gICAgfVxuICAgIGlmIChjYWxlbmRhci5oYXNQdWJsaWNIYW5kbGVycygnZXZlbnREZXN0cm95JykpIHtcbiAgICAgICAgZm9yICh2YXIgX2EgPSAwLCBzZWdzXzQgPSBzZWdzOyBfYSA8IHNlZ3NfNC5sZW5ndGg7IF9hKyspIHtcbiAgICAgICAgICAgIHZhciBzZWcgPSBzZWdzXzRbX2FdO1xuICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudERlc3Ryb3knLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzZWcuZXZlbnRSYW5nZS5kZWYsIHNlZy5ldmVudFJhbmdlLmluc3RhbmNlKSxcbiAgICAgICAgICAgICAgICAgICAgaXNNaXJyb3I6IGlzTWlycm9ycyxcbiAgICAgICAgICAgICAgICAgICAgZWw6IHNlZy5lbCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfVxufVxuLy8gaXMtaW50ZXJhY3RhYmxlXG5mdW5jdGlvbiBjb21wdXRlRXZlbnREcmFnZ2FibGUoY29udGV4dCwgZXZlbnREZWYsIGV2ZW50VWkpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBjb250ZXh0LmNhbGVuZGFyLCB2aWV3ID0gY29udGV4dC52aWV3O1xuICAgIHZhciB0cmFuc2Zvcm1lcnMgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnM7XG4gICAgdmFyIHZhbCA9IGV2ZW50VWkuc3RhcnRFZGl0YWJsZTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHRyYW5zZm9ybWVyc18xID0gdHJhbnNmb3JtZXJzOyBfaSA8IHRyYW5zZm9ybWVyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtZXIgPSB0cmFuc2Zvcm1lcnNfMVtfaV07XG4gICAgICAgIHZhbCA9IHRyYW5zZm9ybWVyKHZhbCwgZXZlbnREZWYsIGV2ZW50VWksIHZpZXcpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsO1xufVxuZnVuY3Rpb24gY29tcHV0ZUV2ZW50U3RhcnRSZXNpemFibGUoY29udGV4dCwgZXZlbnREZWYsIGV2ZW50VWkpIHtcbiAgICByZXR1cm4gZXZlbnRVaS5kdXJhdGlvbkVkaXRhYmxlICYmIGNvbnRleHQub3B0aW9ucy5ldmVudFJlc2l6YWJsZUZyb21TdGFydDtcbn1cbmZ1bmN0aW9uIGNvbXB1dGVFdmVudEVuZFJlc2l6YWJsZShjb250ZXh0LCBldmVudERlZiwgZXZlbnRVaSkge1xuICAgIHJldHVybiBldmVudFVpLmR1cmF0aW9uRWRpdGFibGU7XG59XG5cbi8vIGFwcGxpZXMgdGhlIG11dGF0aW9uIHRvIEFMTCBkZWZzL2luc3RhbmNlcyB3aXRoaW4gdGhlIGV2ZW50IHN0b3JlXG5mdW5jdGlvbiBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlKGV2ZW50U3RvcmUsIGV2ZW50Q29uZmlnQmFzZSwgbXV0YXRpb24sIGNhbGVuZGFyKSB7XG4gICAgdmFyIGV2ZW50Q29uZmlncyA9IGNvbXBpbGVFdmVudFVpcyhldmVudFN0b3JlLmRlZnMsIGV2ZW50Q29uZmlnQmFzZSk7XG4gICAgdmFyIGRlc3QgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICBmb3IgKHZhciBkZWZJZCBpbiBldmVudFN0b3JlLmRlZnMpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50U3RvcmUuZGVmc1tkZWZJZF07XG4gICAgICAgIGRlc3QuZGVmc1tkZWZJZF0gPSBhcHBseU11dGF0aW9uVG9FdmVudERlZihkZWYsIGV2ZW50Q29uZmlnc1tkZWZJZF0sIG11dGF0aW9uLCBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzLCBjYWxlbmRhcik7XG4gICAgfVxuICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gZXZlbnRTdG9yZS5pbnN0YW5jZXMpIHtcbiAgICAgICAgdmFyIGluc3RhbmNlID0gZXZlbnRTdG9yZS5pbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgIHZhciBkZWYgPSBkZXN0LmRlZnNbaW5zdGFuY2UuZGVmSWRdOyAvLyBpbXBvcnRhbnQgdG8gZ3JhYiB0aGUgbmV3bHkgbW9kaWZpZWQgZGVmXG4gICAgICAgIGRlc3QuaW5zdGFuY2VzW2luc3RhbmNlSWRdID0gYXBwbHlNdXRhdGlvblRvRXZlbnRJbnN0YW5jZShpbnN0YW5jZSwgZGVmLCBldmVudENvbmZpZ3NbaW5zdGFuY2UuZGVmSWRdLCBtdXRhdGlvbiwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn1cbmZ1bmN0aW9uIGFwcGx5TXV0YXRpb25Ub0V2ZW50RGVmKGV2ZW50RGVmLCBldmVudENvbmZpZywgbXV0YXRpb24sIGFwcGxpZXJzLCBjYWxlbmRhcikge1xuICAgIHZhciBzdGFuZGFyZFByb3BzID0gbXV0YXRpb24uc3RhbmRhcmRQcm9wcyB8fCB7fTtcbiAgICAvLyBpZiBoYXNFbmQgaGFzIG5vdCBiZWVuIHNwZWNpZmllZCwgZ3Vlc3MgYSBnb29kIHZhbHVlIGJhc2VkIG9uIGRlbHRhcy5cbiAgICAvLyBpZiBkdXJhdGlvbiB3aWxsIGNoYW5nZSwgdGhlcmUncyBubyB3YXkgdGhlIGRlZmF1bHQgZHVyYXRpb24gd2lsbCBwZXJzaXN0LFxuICAgIC8vIGFuZCB0aHVzLCB3ZSBuZWVkIHRvIG1hcmsgdGhlIGV2ZW50IGFzIGhhdmluZyBhIHJlYWwgZW5kXG4gICAgaWYgKHN0YW5kYXJkUHJvcHMuaGFzRW5kID09IG51bGwgJiZcbiAgICAgICAgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSAmJlxuICAgICAgICAobXV0YXRpb24uc3RhcnREZWx0YSB8fCBtdXRhdGlvbi5lbmREZWx0YSkpIHtcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5oYXNFbmQgPSB0cnVlOyAvLyBUT0RPOiBpcyB0aGlzIG11dGF0aW9uIG9rYXk/XG4gICAgfVxuICAgIHZhciBjb3B5ID0gX19hc3NpZ24oe30sIGV2ZW50RGVmLCBzdGFuZGFyZFByb3BzLCB7IHVpOiBfX2Fzc2lnbih7fSwgZXZlbnREZWYudWksIHN0YW5kYXJkUHJvcHMudWkpIH0pO1xuICAgIGlmIChtdXRhdGlvbi5leHRlbmRlZFByb3BzKSB7XG4gICAgICAgIGNvcHkuZXh0ZW5kZWRQcm9wcyA9IF9fYXNzaWduKHt9LCBjb3B5LmV4dGVuZGVkUHJvcHMsIG11dGF0aW9uLmV4dGVuZGVkUHJvcHMpO1xuICAgIH1cbiAgICBmb3IgKHZhciBfaSA9IDAsIGFwcGxpZXJzXzEgPSBhcHBsaWVyczsgX2kgPCBhcHBsaWVyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgYXBwbGllciA9IGFwcGxpZXJzXzFbX2ldO1xuICAgICAgICBhcHBsaWVyKGNvcHksIG11dGF0aW9uLCBjYWxlbmRhcik7XG4gICAgfVxuICAgIGlmICghY29weS5oYXNFbmQgJiYgY2FsZW5kYXIub3B0KCdmb3JjZUV2ZW50RHVyYXRpb24nKSkge1xuICAgICAgICBjb3B5Lmhhc0VuZCA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xufVxuZnVuY3Rpb24gYXBwbHlNdXRhdGlvblRvRXZlbnRJbnN0YW5jZShldmVudEluc3RhbmNlLCBldmVudERlZiwgLy8gbXVzdCBmaXJzdCBiZSBtb2RpZmllZCBieSBhcHBseU11dGF0aW9uVG9FdmVudERlZlxuZXZlbnRDb25maWcsIG11dGF0aW9uLCBjYWxlbmRhcikge1xuICAgIHZhciBkYXRlRW52ID0gY2FsZW5kYXIuZGF0ZUVudjtcbiAgICB2YXIgZm9yY2VBbGxEYXkgPSBtdXRhdGlvbi5zdGFuZGFyZFByb3BzICYmIG11dGF0aW9uLnN0YW5kYXJkUHJvcHMuYWxsRGF5ID09PSB0cnVlO1xuICAgIHZhciBjbGVhckVuZCA9IG11dGF0aW9uLnN0YW5kYXJkUHJvcHMgJiYgbXV0YXRpb24uc3RhbmRhcmRQcm9wcy5oYXNFbmQgPT09IGZhbHNlO1xuICAgIHZhciBjb3B5ID0gX19hc3NpZ24oe30sIGV2ZW50SW5zdGFuY2UpO1xuICAgIGlmIChmb3JjZUFsbERheSkge1xuICAgICAgICBjb3B5LnJhbmdlID0gY29tcHV0ZUFsaWduZWREYXlSYW5nZShjb3B5LnJhbmdlKTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLmRhdGVzRGVsdGEgJiYgZXZlbnRDb25maWcuc3RhcnRFZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2Uuc3RhcnQsIG11dGF0aW9uLmRhdGVzRGVsdGEpLFxuICAgICAgICAgICAgZW5kOiBkYXRlRW52LmFkZChjb3B5LnJhbmdlLmVuZCwgbXV0YXRpb24uZGF0ZXNEZWx0YSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG11dGF0aW9uLnN0YXJ0RGVsdGEgJiYgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2Uuc3RhcnQsIG11dGF0aW9uLnN0YXJ0RGVsdGEpLFxuICAgICAgICAgICAgZW5kOiBjb3B5LnJhbmdlLmVuZFxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24uZW5kRGVsdGEgJiYgZXZlbnRDb25maWcuZHVyYXRpb25FZGl0YWJsZSkge1xuICAgICAgICBjb3B5LnJhbmdlID0ge1xuICAgICAgICAgICAgc3RhcnQ6IGNvcHkucmFuZ2Uuc3RhcnQsXG4gICAgICAgICAgICBlbmQ6IGRhdGVFbnYuYWRkKGNvcHkucmFuZ2UuZW5kLCBtdXRhdGlvbi5lbmREZWx0YSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKGNsZWFyRW5kKSB7XG4gICAgICAgIGNvcHkucmFuZ2UgPSB7XG4gICAgICAgICAgICBzdGFydDogY29weS5yYW5nZS5zdGFydCxcbiAgICAgICAgICAgIGVuZDogY2FsZW5kYXIuZ2V0RGVmYXVsdEV2ZW50RW5kKGV2ZW50RGVmLmFsbERheSwgY29weS5yYW5nZS5zdGFydClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gaW4gY2FzZSBldmVudCB3YXMgYWxsLWRheSBidXQgdGhlIHN1cHBsaWVkIGRlbHRhcyB3ZXJlIG5vdFxuICAgIC8vIGJldHRlciB1dGlsIGZvciB0aGlzP1xuICAgIGlmIChldmVudERlZi5hbGxEYXkpIHtcbiAgICAgICAgY29weS5yYW5nZSA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBzdGFydE9mRGF5KGNvcHkucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kOiBzdGFydE9mRGF5KGNvcHkucmFuZ2UuZW5kKVxuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBoYW5kbGUgaW52YWxpZCBkdXJhdGlvbnNcbiAgICBpZiAoY29weS5yYW5nZS5lbmQgPCBjb3B5LnJhbmdlLnN0YXJ0KSB7XG4gICAgICAgIGNvcHkucmFuZ2UuZW5kID0gY2FsZW5kYXIuZ2V0RGVmYXVsdEV2ZW50RW5kKGV2ZW50RGVmLmFsbERheSwgY29weS5yYW5nZS5zdGFydCk7XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xufVxuXG5mdW5jdGlvbiByZWR1Y2VFdmVudFN0b3JlIChldmVudFN0b3JlLCBhY3Rpb24sIGV2ZW50U291cmNlcywgZGF0ZVByb2ZpbGUsIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdSRUNFSVZFX0VWRU5UUyc6IC8vIHJhd1xuICAgICAgICAgICAgcmV0dXJuIHJlY2VpdmVSYXdFdmVudHMoZXZlbnRTdG9yZSwgZXZlbnRTb3VyY2VzW2FjdGlvbi5zb3VyY2VJZF0sIGFjdGlvbi5mZXRjaElkLCBhY3Rpb24uZmV0Y2hSYW5nZSwgYWN0aW9uLnJhd0V2ZW50cywgY2FsZW5kYXIpO1xuICAgICAgICBjYXNlICdBRERfRVZFTlRTJzogLy8gYWxyZWFkeSBwYXJzZWQsIGJ1dCBub3QgZXhwYW5kZWRcbiAgICAgICAgICAgIHJldHVybiBhZGRFdmVudChldmVudFN0b3JlLCBhY3Rpb24uZXZlbnRTdG9yZSwgLy8gbmV3IG9uZXNcbiAgICAgICAgICAgIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ01FUkdFX0VWRU5UUyc6IC8vIGFscmVhZHkgcGFyc2VkIGFuZCBleHBhbmRlZFxuICAgICAgICAgICAgcmV0dXJuIG1lcmdlRXZlbnRTdG9yZXMoZXZlbnRTdG9yZSwgYWN0aW9uLmV2ZW50U3RvcmUpO1xuICAgICAgICBjYXNlICdQUkVWJzogLy8gVE9ETzogaG93IGRvIHdlIHRyYWNrIGFsbCBhY3Rpb25zIHRoYXQgYWZmZWN0IGRhdGVQcm9maWxlIDooXG4gICAgICAgIGNhc2UgJ05FWFQnOlxuICAgICAgICBjYXNlICdTRVRfREFURSc6XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgaWYgKGRhdGVQcm9maWxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4cGFuZFJlY3VycmluZyhldmVudFN0b3JlLCBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmU7XG4gICAgICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9USU1FWk9ORSc6XG4gICAgICAgICAgICByZXR1cm4gcmV6b25lRGF0ZXMoZXZlbnRTdG9yZSwgYWN0aW9uLm9sZERhdGVFbnYsIGNhbGVuZGFyLmRhdGVFbnYpO1xuICAgICAgICBjYXNlICdNVVRBVEVfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiBhcHBseU11dGF0aW9uVG9SZWxhdGVkKGV2ZW50U3RvcmUsIGFjdGlvbi5pbnN0YW5jZUlkLCBhY3Rpb24ubXV0YXRpb24sIGFjdGlvbi5mcm9tQXBpLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9JTlNUQU5DRVMnOlxuICAgICAgICAgICAgcmV0dXJuIGV4Y2x1ZGVJbnN0YW5jZXMoZXZlbnRTdG9yZSwgYWN0aW9uLmluc3RhbmNlcyk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9ERUYnOlxuICAgICAgICAgICAgcmV0dXJuIGZpbHRlckV2ZW50U3RvcmVEZWZzKGV2ZW50U3RvcmUsIGZ1bmN0aW9uIChldmVudERlZikge1xuICAgICAgICAgICAgICAgIHJldHVybiBldmVudERlZi5kZWZJZCAhPT0gYWN0aW9uLmRlZklkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9TT1VSQ0UnOlxuICAgICAgICAgICAgcmV0dXJuIGV4Y2x1ZGVFdmVudHNCeVNvdXJjZUlkKGV2ZW50U3RvcmUsIGFjdGlvbi5zb3VyY2VJZCk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9BTExfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyRXZlbnRTdG9yZURlZnMoZXZlbnRTdG9yZSwgZnVuY3Rpb24gKGV2ZW50RGVmKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICFldmVudERlZi5zb3VyY2VJZDsgLy8gb25seSBrZWVwIGV2ZW50cyB3aXRoIG5vIHNvdXJjZSBpZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9BTExfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgY2FzZSAnUkVTRVRfRVZFTlRTJzpcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZGVmczogZXZlbnRTdG9yZS5kZWZzLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlczogZXZlbnRTdG9yZS5pbnN0YW5jZXNcbiAgICAgICAgICAgIH07XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZXZlbnRTdG9yZTtcbiAgICB9XG59XG5mdW5jdGlvbiByZWNlaXZlUmF3RXZlbnRzKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlLCBmZXRjaElkLCBmZXRjaFJhbmdlLCByYXdFdmVudHMsIGNhbGVuZGFyKSB7XG4gICAgaWYgKGV2ZW50U291cmNlICYmIC8vIG5vdCBhbHJlYWR5IHJlbW92ZWRcbiAgICAgICAgZmV0Y2hJZCA9PT0gZXZlbnRTb3VyY2UubGF0ZXN0RmV0Y2hJZCAvLyBUT0RPOiB3aXNoIHRoaXMgbG9naWMgd2FzIGFsd2F5cyBpbiBldmVudC1zb3VyY2VzXG4gICAgKSB7XG4gICAgICAgIHZhciBzdWJzZXQgPSBwYXJzZUV2ZW50cyh0cmFuc2Zvcm1SYXdFdmVudHMocmF3RXZlbnRzLCBldmVudFNvdXJjZSwgY2FsZW5kYXIpLCBldmVudFNvdXJjZS5zb3VyY2VJZCwgY2FsZW5kYXIpO1xuICAgICAgICBpZiAoZmV0Y2hSYW5nZSkge1xuICAgICAgICAgICAgc3Vic2V0ID0gZXhwYW5kUmVjdXJyaW5nKHN1YnNldCwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXJnZUV2ZW50U3RvcmVzKGV4Y2x1ZGVFdmVudHNCeVNvdXJjZUlkKGV2ZW50U3RvcmUsIGV2ZW50U291cmNlLnNvdXJjZUlkKSwgc3Vic2V0KTtcbiAgICB9XG4gICAgcmV0dXJuIGV2ZW50U3RvcmU7XG59XG5mdW5jdGlvbiBhZGRFdmVudChldmVudFN0b3JlLCBzdWJzZXQsIGV4cGFuZFJhbmdlLCBjYWxlbmRhcikge1xuICAgIGlmIChleHBhbmRSYW5nZSkge1xuICAgICAgICBzdWJzZXQgPSBleHBhbmRSZWN1cnJpbmcoc3Vic2V0LCBleHBhbmRSYW5nZSwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICByZXR1cm4gbWVyZ2VFdmVudFN0b3JlcyhldmVudFN0b3JlLCBzdWJzZXQpO1xufVxuZnVuY3Rpb24gcmV6b25lRGF0ZXMoZXZlbnRTdG9yZSwgb2xkRGF0ZUVudiwgbmV3RGF0ZUVudikge1xuICAgIHZhciBkZWZzID0gZXZlbnRTdG9yZS5kZWZzO1xuICAgIHZhciBpbnN0YW5jZXMgPSBtYXBIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgdmFyIGRlZiA9IGRlZnNbaW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICBpZiAoZGVmLmFsbERheSB8fCBkZWYucmVjdXJyaW5nRGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7IC8vIGlzbid0IGRlcGVuZGVudCBvbiB0aW1lem9uZVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXNzaWduKHt9LCBpbnN0YW5jZSwgeyByYW5nZToge1xuICAgICAgICAgICAgICAgICAgICBzdGFydDogbmV3RGF0ZUVudi5jcmVhdGVNYXJrZXIob2xkRGF0ZUVudi50b0RhdGUoaW5zdGFuY2UucmFuZ2Uuc3RhcnQsIGluc3RhbmNlLmZvcmNlZFN0YXJ0VHpvKSksXG4gICAgICAgICAgICAgICAgICAgIGVuZDogbmV3RGF0ZUVudi5jcmVhdGVNYXJrZXIob2xkRGF0ZUVudi50b0RhdGUoaW5zdGFuY2UucmFuZ2UuZW5kLCBpbnN0YW5jZS5mb3JjZWRFbmRUem8pKVxuICAgICAgICAgICAgICAgIH0sIGZvcmNlZFN0YXJ0VHpvOiBuZXdEYXRlRW52LmNhbkNvbXB1dGVPZmZzZXQgPyBudWxsIDogaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sIGZvcmNlZEVuZFR6bzogbmV3RGF0ZUVudi5jYW5Db21wdXRlT2Zmc2V0ID8gbnVsbCA6IGluc3RhbmNlLmZvcmNlZEVuZFR6byB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7IGRlZnM6IGRlZnMsIGluc3RhbmNlczogaW5zdGFuY2VzIH07XG59XG5mdW5jdGlvbiBhcHBseU11dGF0aW9uVG9SZWxhdGVkKGV2ZW50U3RvcmUsIGluc3RhbmNlSWQsIG11dGF0aW9uLCBmcm9tQXBpLCBjYWxlbmRhcikge1xuICAgIHZhciByZWxldmFudCA9IGdldFJlbGV2YW50RXZlbnRzKGV2ZW50U3RvcmUsIGluc3RhbmNlSWQpO1xuICAgIHZhciBldmVudENvbmZpZ0Jhc2UgPSBmcm9tQXBpID9cbiAgICAgICAgeyAnJzoge1xuICAgICAgICAgICAgICAgIHN0YXJ0RWRpdGFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjb25zdHJhaW50czogW10sXG4gICAgICAgICAgICAgICAgb3ZlcmxhcDogbnVsbCxcbiAgICAgICAgICAgICAgICBhbGxvd3M6IFtdLFxuICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJycsXG4gICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6ICcnLFxuICAgICAgICAgICAgICAgIHRleHRDb2xvcjogJycsXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lczogW11cbiAgICAgICAgICAgIH0gfSA6XG4gICAgICAgIGNhbGVuZGFyLmV2ZW50VWlCYXNlcztcbiAgICByZWxldmFudCA9IGFwcGx5TXV0YXRpb25Ub0V2ZW50U3RvcmUocmVsZXZhbnQsIGV2ZW50Q29uZmlnQmFzZSwgbXV0YXRpb24sIGNhbGVuZGFyKTtcbiAgICByZXR1cm4gbWVyZ2VFdmVudFN0b3JlcyhldmVudFN0b3JlLCByZWxldmFudCk7XG59XG5mdW5jdGlvbiBleGNsdWRlRXZlbnRzQnlTb3VyY2VJZChldmVudFN0b3JlLCBzb3VyY2VJZCkge1xuICAgIHJldHVybiBmaWx0ZXJFdmVudFN0b3JlRGVmcyhldmVudFN0b3JlLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50RGVmLnNvdXJjZUlkICE9PSBzb3VyY2VJZDtcbiAgICB9KTtcbn1cbi8vIFFVRVNUSU9OOiB3aHkgbm90IGp1c3QgcmV0dXJuIGluc3RhbmNlcz8gZG8gYSBnZW5lcmFsIG9iamVjdC1wcm9wZXJ0eS1leGNsdXNpb24gdXRpbFxuZnVuY3Rpb24gZXhjbHVkZUluc3RhbmNlcyhldmVudFN0b3JlLCByZW1vdmFscykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGRlZnM6IGV2ZW50U3RvcmUuZGVmcyxcbiAgICAgICAgaW5zdGFuY2VzOiBmaWx0ZXJIYXNoKGV2ZW50U3RvcmUuaW5zdGFuY2VzLCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHJldHVybiAhcmVtb3ZhbHNbaW5zdGFuY2UuaW5zdGFuY2VJZF07XG4gICAgICAgIH0pXG4gICAgfTtcbn1cblxuLy8gaGlnaC1sZXZlbCBzZWdtZW50aW5nLWF3YXJlIHRlc3RlciBmdW5jdGlvbnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gaXNJbnRlcmFjdGlvblZhbGlkKGludGVyYWN0aW9uLCBjYWxlbmRhcikge1xuICAgIHJldHVybiBpc05ld1Byb3BzVmFsaWQoeyBldmVudERyYWc6IGludGVyYWN0aW9uIH0sIGNhbGVuZGFyKTsgLy8gSEFDSzogdGhlIGV2ZW50RHJhZyBwcm9wcyBpcyB1c2VkIGZvciBBTEwgaW50ZXJhY3Rpb25zXG59XG5mdW5jdGlvbiBpc0RhdGVTZWxlY3Rpb25WYWxpZChkYXRlU2VsZWN0aW9uLCBjYWxlbmRhcikge1xuICAgIHJldHVybiBpc05ld1Byb3BzVmFsaWQoeyBkYXRlU2VsZWN0aW9uOiBkYXRlU2VsZWN0aW9uIH0sIGNhbGVuZGFyKTtcbn1cbmZ1bmN0aW9uIGlzTmV3UHJvcHNWYWxpZChuZXdQcm9wcywgY2FsZW5kYXIpIHtcbiAgICB2YXIgdmlldyA9IGNhbGVuZGFyLnZpZXc7XG4gICAgdmFyIHByb3BzID0gX19hc3NpZ24oeyBidXNpbmVzc0hvdXJzOiB2aWV3ID8gdmlldy5wcm9wcy5idXNpbmVzc0hvdXJzIDogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksIGRhdGVTZWxlY3Rpb246ICcnLCBldmVudFN0b3JlOiBjYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlLCBldmVudFVpQmFzZXM6IGNhbGVuZGFyLmV2ZW50VWlCYXNlcywgZXZlbnRTZWxlY3Rpb246ICcnLCBldmVudERyYWc6IG51bGwsIGV2ZW50UmVzaXplOiBudWxsIH0sIG5ld1Byb3BzKTtcbiAgICByZXR1cm4gKGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5pc1Byb3BzVmFsaWQgfHwgaXNQcm9wc1ZhbGlkKShwcm9wcywgY2FsZW5kYXIpO1xufVxuZnVuY3Rpb24gaXNQcm9wc1ZhbGlkKHN0YXRlLCBjYWxlbmRhciwgZGF0ZVNwYW5NZXRhLCBmaWx0ZXJDb25maWcpIHtcbiAgICBpZiAoZGF0ZVNwYW5NZXRhID09PSB2b2lkIDApIHsgZGF0ZVNwYW5NZXRhID0ge307IH1cbiAgICBpZiAoc3RhdGUuZXZlbnREcmFnICYmICFpc0ludGVyYWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChzdGF0ZS5kYXRlU2VsZWN0aW9uICYmICFpc0RhdGVTZWxlY3Rpb25Qcm9wc1ZhbGlkKHN0YXRlLCBjYWxlbmRhciwgZGF0ZVNwYW5NZXRhLCBmaWx0ZXJDb25maWcpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG4vLyBNb3ZpbmcgRXZlbnQgVmFsaWRhdGlvblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBpc0ludGVyYWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgdmFyIGludGVyYWN0aW9uID0gc3RhdGUuZXZlbnREcmFnOyAvLyBIQUNLOiB0aGUgZXZlbnREcmFnIHByb3BzIGlzIHVzZWQgZm9yIEFMTCBpbnRlcmFjdGlvbnNcbiAgICB2YXIgc3ViamVjdEV2ZW50U3RvcmUgPSBpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzO1xuICAgIHZhciBzdWJqZWN0RGVmcyA9IHN1YmplY3RFdmVudFN0b3JlLmRlZnM7XG4gICAgdmFyIHN1YmplY3RJbnN0YW5jZXMgPSBzdWJqZWN0RXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIHN1YmplY3RDb25maWdzID0gY29tcGlsZUV2ZW50VWlzKHN1YmplY3REZWZzLCBpbnRlcmFjdGlvbi5pc0V2ZW50ID9cbiAgICAgICAgc3RhdGUuZXZlbnRVaUJhc2VzIDpcbiAgICAgICAgeyAnJzogY2FsZW5kYXIuc2VsZWN0aW9uQ29uZmlnIH0gLy8gaWYgbm90IGEgcmVhbCBldmVudCwgdmFsaWRhdGUgYXMgYSBzZWxlY3Rpb25cbiAgICApO1xuICAgIGlmIChmaWx0ZXJDb25maWcpIHtcbiAgICAgICAgc3ViamVjdENvbmZpZ3MgPSBtYXBIYXNoKHN1YmplY3RDb25maWdzLCBmaWx0ZXJDb25maWcpO1xuICAgIH1cbiAgICB2YXIgb3RoZXJFdmVudFN0b3JlID0gZXhjbHVkZUluc3RhbmNlcyhzdGF0ZS5ldmVudFN0b3JlLCBpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cy5pbnN0YW5jZXMpOyAvLyBleGNsdWRlIHRoZSBzdWJqZWN0IGV2ZW50cy4gVE9ETzogZXhjbHVkZSBkZWZzIHRvbz9cbiAgICB2YXIgb3RoZXJEZWZzID0gb3RoZXJFdmVudFN0b3JlLmRlZnM7XG4gICAgdmFyIG90aGVySW5zdGFuY2VzID0gb3RoZXJFdmVudFN0b3JlLmluc3RhbmNlcztcbiAgICB2YXIgb3RoZXJDb25maWdzID0gY29tcGlsZUV2ZW50VWlzKG90aGVyRGVmcywgc3RhdGUuZXZlbnRVaUJhc2VzKTtcbiAgICBmb3IgKHZhciBzdWJqZWN0SW5zdGFuY2VJZCBpbiBzdWJqZWN0SW5zdGFuY2VzKSB7XG4gICAgICAgIHZhciBzdWJqZWN0SW5zdGFuY2UgPSBzdWJqZWN0SW5zdGFuY2VzW3N1YmplY3RJbnN0YW5jZUlkXTtcbiAgICAgICAgdmFyIHN1YmplY3RSYW5nZSA9IHN1YmplY3RJbnN0YW5jZS5yYW5nZTtcbiAgICAgICAgdmFyIHN1YmplY3RDb25maWcgPSBzdWJqZWN0Q29uZmlnc1tzdWJqZWN0SW5zdGFuY2UuZGVmSWRdO1xuICAgICAgICB2YXIgc3ViamVjdERlZiA9IHN1YmplY3REZWZzW3N1YmplY3RJbnN0YW5jZS5kZWZJZF07XG4gICAgICAgIC8vIGNvbnN0cmFpbnRcbiAgICAgICAgaWYgKCFhbGxDb25zdHJhaW50c1Bhc3Moc3ViamVjdENvbmZpZy5jb25zdHJhaW50cywgc3ViamVjdFJhbmdlLCBvdGhlckV2ZW50U3RvcmUsIHN0YXRlLmJ1c2luZXNzSG91cnMsIGNhbGVuZGFyKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIG92ZXJsYXBcbiAgICAgICAgdmFyIG92ZXJsYXBGdW5jID0gY2FsZW5kYXIub3B0KCdldmVudE92ZXJsYXAnKTtcbiAgICAgICAgaWYgKHR5cGVvZiBvdmVybGFwRnVuYyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgb3ZlcmxhcEZ1bmMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIG90aGVySW5zdGFuY2VJZCBpbiBvdGhlckluc3RhbmNlcykge1xuICAgICAgICAgICAgdmFyIG90aGVySW5zdGFuY2UgPSBvdGhlckluc3RhbmNlc1tvdGhlckluc3RhbmNlSWRdO1xuICAgICAgICAgICAgLy8gaW50ZXJzZWN0ISBldmFsdWF0ZVxuICAgICAgICAgICAgaWYgKHJhbmdlc0ludGVyc2VjdChzdWJqZWN0UmFuZ2UsIG90aGVySW5zdGFuY2UucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgdmFyIG90aGVyT3ZlcmxhcCA9IG90aGVyQ29uZmlnc1tvdGhlckluc3RhbmNlLmRlZklkXS5vdmVybGFwO1xuICAgICAgICAgICAgICAgIC8vIGNvbnNpZGVyIHRoZSBvdGhlciBldmVudCdzIG92ZXJsYXAuIG9ubHkgZG8gdGhpcyBpZiB0aGUgc3ViamVjdCBldmVudCBpcyBhIFwicmVhbFwiIGV2ZW50XG4gICAgICAgICAgICAgICAgaWYgKG90aGVyT3ZlcmxhcCA9PT0gZmFsc2UgJiYgaW50ZXJhY3Rpb24uaXNFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdWJqZWN0Q29uZmlnLm92ZXJsYXAgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG92ZXJsYXBGdW5jICYmICFvdmVybGFwRnVuYyhuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIG90aGVyRGVmc1tvdGhlckluc3RhbmNlLmRlZklkXSwgb3RoZXJJbnN0YW5jZSksIC8vIHN0aWxsIGV2ZW50XG4gICAgICAgICAgICAgICAgbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzdWJqZWN0RGVmLCBzdWJqZWN0SW5zdGFuY2UpIC8vIG1vdmluZyBldmVudFxuICAgICAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBhbGxvdyAoYSBmdW5jdGlvbilcbiAgICAgICAgdmFyIGNhbGVuZGFyRXZlbnRTdG9yZSA9IGNhbGVuZGFyLnN0YXRlLmV2ZW50U3RvcmU7IC8vIG5lZWQgZ2xvYmFsLXRvLWNhbGVuZGFyLCBub3QgbG9jYWwgdG8gY29tcG9uZW50IChzcGxpdHRhYmxlKXN0YXRlXG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBzdWJqZWN0Q29uZmlnLmFsbG93czsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzdWJqZWN0QWxsb3cgPSBfYVtfaV07XG4gICAgICAgICAgICB2YXIgc3ViamVjdERhdGVTcGFuID0gX19hc3NpZ24oe30sIGRhdGVTcGFuTWV0YSwgeyByYW5nZTogc3ViamVjdEluc3RhbmNlLnJhbmdlLCBhbGxEYXk6IHN1YmplY3REZWYuYWxsRGF5IH0pO1xuICAgICAgICAgICAgdmFyIG9yaWdEZWYgPSBjYWxlbmRhckV2ZW50U3RvcmUuZGVmc1tzdWJqZWN0RGVmLmRlZklkXTtcbiAgICAgICAgICAgIHZhciBvcmlnSW5zdGFuY2UgPSBjYWxlbmRhckV2ZW50U3RvcmUuaW5zdGFuY2VzW3N1YmplY3RJbnN0YW5jZUlkXTtcbiAgICAgICAgICAgIHZhciBldmVudEFwaSA9IHZvaWQgMDtcbiAgICAgICAgICAgIGlmIChvcmlnRGVmKSB7IC8vIHdhcyBwcmV2aW91c2x5IGluIHRoZSBjYWxlbmRhclxuICAgICAgICAgICAgICAgIGV2ZW50QXBpID0gbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBvcmlnRGVmLCBvcmlnSW5zdGFuY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7IC8vIHdhcyBhbiBleHRlcm5hbCBldmVudFxuICAgICAgICAgICAgICAgIGV2ZW50QXBpID0gbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBzdWJqZWN0RGVmKTsgLy8gbm8gaW5zdGFuY2UsIGJlY2F1c2UgaGFkIG5vIGRhdGVzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXN1YmplY3RBbGxvdyhjYWxlbmRhci5idWlsZERhdGVTcGFuQXBpKHN1YmplY3REYXRlU3BhbiksIGV2ZW50QXBpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8vIERhdGUgU2VsZWN0aW9uIFZhbGlkYXRpb25cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gaXNEYXRlU2VsZWN0aW9uUHJvcHNWYWxpZChzdGF0ZSwgY2FsZW5kYXIsIGRhdGVTcGFuTWV0YSwgZmlsdGVyQ29uZmlnKSB7XG4gICAgdmFyIHJlbGV2YW50RXZlbnRTdG9yZSA9IHN0YXRlLmV2ZW50U3RvcmU7XG4gICAgdmFyIHJlbGV2YW50RGVmcyA9IHJlbGV2YW50RXZlbnRTdG9yZS5kZWZzO1xuICAgIHZhciByZWxldmFudEluc3RhbmNlcyA9IHJlbGV2YW50RXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIHNlbGVjdGlvbiA9IHN0YXRlLmRhdGVTZWxlY3Rpb247XG4gICAgdmFyIHNlbGVjdGlvblJhbmdlID0gc2VsZWN0aW9uLnJhbmdlO1xuICAgIHZhciBzZWxlY3Rpb25Db25maWcgPSBjYWxlbmRhci5zZWxlY3Rpb25Db25maWc7XG4gICAgaWYgKGZpbHRlckNvbmZpZykge1xuICAgICAgICBzZWxlY3Rpb25Db25maWcgPSBmaWx0ZXJDb25maWcoc2VsZWN0aW9uQ29uZmlnKTtcbiAgICB9XG4gICAgLy8gY29uc3RyYWludFxuICAgIGlmICghYWxsQ29uc3RyYWludHNQYXNzKHNlbGVjdGlvbkNvbmZpZy5jb25zdHJhaW50cywgc2VsZWN0aW9uUmFuZ2UsIHJlbGV2YW50RXZlbnRTdG9yZSwgc3RhdGUuYnVzaW5lc3NIb3VycywgY2FsZW5kYXIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gb3ZlcmxhcFxuICAgIHZhciBvdmVybGFwRnVuYyA9IGNhbGVuZGFyLm9wdCgnc2VsZWN0T3ZlcmxhcCcpO1xuICAgIGlmICh0eXBlb2Ygb3ZlcmxhcEZ1bmMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgb3ZlcmxhcEZ1bmMgPSBudWxsO1xuICAgIH1cbiAgICBmb3IgKHZhciByZWxldmFudEluc3RhbmNlSWQgaW4gcmVsZXZhbnRJbnN0YW5jZXMpIHtcbiAgICAgICAgdmFyIHJlbGV2YW50SW5zdGFuY2UgPSByZWxldmFudEluc3RhbmNlc1tyZWxldmFudEluc3RhbmNlSWRdO1xuICAgICAgICAvLyBpbnRlcnNlY3QhIGV2YWx1YXRlXG4gICAgICAgIGlmIChyYW5nZXNJbnRlcnNlY3Qoc2VsZWN0aW9uUmFuZ2UsIHJlbGV2YW50SW5zdGFuY2UucmFuZ2UpKSB7XG4gICAgICAgICAgICBpZiAoc2VsZWN0aW9uQ29uZmlnLm92ZXJsYXAgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG92ZXJsYXBGdW5jICYmICFvdmVybGFwRnVuYyhuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIHJlbGV2YW50RGVmc1tyZWxldmFudEluc3RhbmNlLmRlZklkXSwgcmVsZXZhbnRJbnN0YW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGFsbG93IChhIGZ1bmN0aW9uKVxuICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBzZWxlY3Rpb25Db25maWcuYWxsb3dzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc2VsZWN0aW9uQWxsb3cgPSBfYVtfaV07XG4gICAgICAgIHZhciBmdWxsRGF0ZVNwYW4gPSBfX2Fzc2lnbih7fSwgZGF0ZVNwYW5NZXRhLCBzZWxlY3Rpb24pO1xuICAgICAgICBpZiAoIXNlbGVjdGlvbkFsbG93KGNhbGVuZGFyLmJ1aWxkRGF0ZVNwYW5BcGkoZnVsbERhdGVTcGFuKSwgbnVsbCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8vIENvbnN0cmFpbnQgVXRpbHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYWxsQ29uc3RyYWludHNQYXNzKGNvbnN0cmFpbnRzLCBzdWJqZWN0UmFuZ2UsIG90aGVyRXZlbnRTdG9yZSwgYnVzaW5lc3NIb3Vyc1VuZXhwYW5kZWQsIGNhbGVuZGFyKSB7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBjb25zdHJhaW50c18xID0gY29uc3RyYWludHM7IF9pIDwgY29uc3RyYWludHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSBjb25zdHJhaW50c18xW19pXTtcbiAgICAgICAgaWYgKCFhbnlSYW5nZXNDb250YWluUmFuZ2UoY29uc3RyYWludFRvUmFuZ2VzKGNvbnN0cmFpbnQsIHN1YmplY3RSYW5nZSwgb3RoZXJFdmVudFN0b3JlLCBidXNpbmVzc0hvdXJzVW5leHBhbmRlZCwgY2FsZW5kYXIpLCBzdWJqZWN0UmFuZ2UpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBjb25zdHJhaW50VG9SYW5nZXMoY29uc3RyYWludCwgc3ViamVjdFJhbmdlLCAvLyBmb3IgZXhwYW5kaW5nIGEgcmVjdXJyaW5nIGNvbnN0cmFpbnQsIG9yIGV4cGFuZGluZyBidXNpbmVzcyBob3Vyc1xub3RoZXJFdmVudFN0b3JlLCAvLyBmb3IgaWYgY29uc3RyYWludCBpcyBhbiBldmVuIGdyb3VwIElEXG5idXNpbmVzc0hvdXJzVW5leHBhbmRlZCwgLy8gZm9yIGlmIGNvbnN0cmFpbnQgaXMgJ2J1c2luZXNzSG91cnMnXG5jYWxlbmRhciAvLyBmb3IgZXhwYW5kaW5nIGJ1c2luZXNzaG91cnNcbikge1xuICAgIGlmIChjb25zdHJhaW50ID09PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50U3RvcmVUb1JhbmdlcyhleHBhbmRSZWN1cnJpbmcoYnVzaW5lc3NIb3Vyc1VuZXhwYW5kZWQsIHN1YmplY3RSYW5nZSwgY2FsZW5kYXIpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGNvbnN0cmFpbnQgPT09ICdzdHJpbmcnKSB7IC8vIGFuIGdyb3VwIElEXG4gICAgICAgIHJldHVybiBldmVudFN0b3JlVG9SYW5nZXMoZmlsdGVyRXZlbnRTdG9yZURlZnMob3RoZXJFdmVudFN0b3JlLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBldmVudERlZi5ncm91cElkID09PSBjb25zdHJhaW50O1xuICAgICAgICB9KSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBjb25zdHJhaW50ID09PSAnb2JqZWN0JyAmJiBjb25zdHJhaW50KSB7IC8vIG5vbi1udWxsIG9iamVjdFxuICAgICAgICByZXR1cm4gZXZlbnRTdG9yZVRvUmFuZ2VzKGV4cGFuZFJlY3VycmluZyhjb25zdHJhaW50LCBzdWJqZWN0UmFuZ2UsIGNhbGVuZGFyKSk7XG4gICAgfVxuICAgIHJldHVybiBbXTsgLy8gaWYgaXQncyBmYWxzZVxufVxuLy8gVE9ETzogbW92ZSB0byBldmVudC1zdG9yZSBmaWxlP1xuZnVuY3Rpb24gZXZlbnRTdG9yZVRvUmFuZ2VzKGV2ZW50U3RvcmUpIHtcbiAgICB2YXIgaW5zdGFuY2VzID0gZXZlbnRTdG9yZS5pbnN0YW5jZXM7XG4gICAgdmFyIHJhbmdlcyA9IFtdO1xuICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgIHJhbmdlcy5wdXNoKGluc3RhbmNlc1tpbnN0YW5jZUlkXS5yYW5nZSk7XG4gICAgfVxuICAgIHJldHVybiByYW5nZXM7XG59XG4vLyBUT0RPOiBtb3ZlIHRvIGdlb20gZmlsZT9cbmZ1bmN0aW9uIGFueVJhbmdlc0NvbnRhaW5SYW5nZShvdXRlclJhbmdlcywgaW5uZXJSYW5nZSkge1xuICAgIGZvciAodmFyIF9pID0gMCwgb3V0ZXJSYW5nZXNfMSA9IG91dGVyUmFuZ2VzOyBfaSA8IG91dGVyUmFuZ2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBvdXRlclJhbmdlID0gb3V0ZXJSYW5nZXNfMVtfaV07XG4gICAgICAgIGlmIChyYW5nZUNvbnRhaW5zUmFuZ2Uob3V0ZXJSYW5nZSwgaW5uZXJSYW5nZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8vIFBhcnNpbmdcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gbm9ybWFsaXplQ29uc3RyYWludChpbnB1dCwgY2FsZW5kYXIpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlRXZlbnRzKGlucHV0LCAnJywgY2FsZW5kYXIsIHRydWUpOyAvLyBhbGxvd09wZW5SYW5nZT10cnVlXG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgaW5wdXQpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgIHJldHVybiBwYXJzZUV2ZW50cyhbaW5wdXRdLCAnJywgY2FsZW5kYXIsIHRydWUpOyAvLyBhbGxvd09wZW5SYW5nZT10cnVlXG4gICAgfVxuICAgIGVsc2UgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyhpbnB1dCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGh0bWxFc2NhcGUocykge1xuICAgIHJldHVybiAocyArICcnKS5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gICAgICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JylcbiAgICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKVxuICAgICAgICAucmVwbGFjZSgvJy9nLCAnJiMwMzk7JylcbiAgICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxuICAgICAgICAucmVwbGFjZSgvXFxuL2csICc8YnIgLz4nKTtcbn1cbi8vIEdpdmVuIGEgaGFzaCBvZiBDU1MgcHJvcGVydGllcywgcmV0dXJucyBhIHN0cmluZyBvZiBDU1MuXG4vLyBVc2VzIHByb3BlcnR5IG5hbWVzIGFzLWlzIChubyBjYW1lbC1jYXNlIGNvbnZlcnNpb24pLiBXaWxsIG5vdCBtYWtlIHN0YXRlbWVudHMgZm9yIG51bGwvdW5kZWZpbmVkIHZhbHVlcy5cbmZ1bmN0aW9uIGNzc1RvU3RyKGNzc1Byb3BzKSB7XG4gICAgdmFyIHN0YXRlbWVudHMgPSBbXTtcbiAgICBmb3IgKHZhciBuYW1lXzEgaW4gY3NzUHJvcHMpIHtcbiAgICAgICAgdmFyIHZhbCA9IGNzc1Byb3BzW25hbWVfMV07XG4gICAgICAgIGlmICh2YWwgIT0gbnVsbCAmJiB2YWwgIT09ICcnKSB7XG4gICAgICAgICAgICBzdGF0ZW1lbnRzLnB1c2gobmFtZV8xICsgJzonICsgdmFsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3RhdGVtZW50cy5qb2luKCc7Jyk7XG59XG4vLyBHaXZlbiBhbiBvYmplY3QgaGFzaCBvZiBIVE1MIGF0dHJpYnV0ZSBuYW1lcyB0byB2YWx1ZXMsXG4vLyBnZW5lcmF0ZXMgYSBzdHJpbmcgdGhhdCBjYW4gYmUgaW5qZWN0ZWQgYmV0d2VlbiA8ID4gaW4gSFRNTFxuZnVuY3Rpb24gYXR0cnNUb1N0cihhdHRycykge1xuICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgIGZvciAodmFyIG5hbWVfMiBpbiBhdHRycykge1xuICAgICAgICB2YXIgdmFsID0gYXR0cnNbbmFtZV8yXTtcbiAgICAgICAgaWYgKHZhbCAhPSBudWxsKSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKG5hbWVfMiArICc9XCInICsgaHRtbEVzY2FwZSh2YWwpICsgJ1wiJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBhcnRzLmpvaW4oJyAnKTtcbn1cbmZ1bmN0aW9uIHBhcnNlQ2xhc3NOYW1lKHJhdykge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHtcbiAgICAgICAgcmV0dXJuIHJhdztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHJhdyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHJhdy5zcGxpdCgvXFxzKy8pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbn1cblxudmFyIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTID0ge1xuICAgIGVkaXRhYmxlOiBCb29sZWFuLFxuICAgIHN0YXJ0RWRpdGFibGU6IEJvb2xlYW4sXG4gICAgZHVyYXRpb25FZGl0YWJsZTogQm9vbGVhbixcbiAgICBjb25zdHJhaW50OiBudWxsLFxuICAgIG92ZXJsYXA6IG51bGwsXG4gICAgYWxsb3c6IG51bGwsXG4gICAgY2xhc3NOYW1lOiBwYXJzZUNsYXNzTmFtZSxcbiAgICBjbGFzc05hbWVzOiBwYXJzZUNsYXNzTmFtZSxcbiAgICBjb2xvcjogU3RyaW5nLFxuICAgIGJhY2tncm91bmRDb2xvcjogU3RyaW5nLFxuICAgIGJvcmRlckNvbG9yOiBTdHJpbmcsXG4gICAgdGV4dENvbG9yOiBTdHJpbmdcbn07XG5mdW5jdGlvbiBwcm9jZXNzVW5zY29wZWRVaVByb3BzKHJhd1Byb3BzLCBjYWxlbmRhciwgbGVmdG92ZXJzKSB7XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3UHJvcHMsIFVOU0NPUEVEX0VWRU5UX1VJX1BST1BTLCB7fSwgbGVmdG92ZXJzKTtcbiAgICB2YXIgY29uc3RyYWludCA9IG5vcm1hbGl6ZUNvbnN0cmFpbnQocHJvcHMuY29uc3RyYWludCwgY2FsZW5kYXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0RWRpdGFibGU6IHByb3BzLnN0YXJ0RWRpdGFibGUgIT0gbnVsbCA/IHByb3BzLnN0YXJ0RWRpdGFibGUgOiBwcm9wcy5lZGl0YWJsZSxcbiAgICAgICAgZHVyYXRpb25FZGl0YWJsZTogcHJvcHMuZHVyYXRpb25FZGl0YWJsZSAhPSBudWxsID8gcHJvcHMuZHVyYXRpb25FZGl0YWJsZSA6IHByb3BzLmVkaXRhYmxlLFxuICAgICAgICBjb25zdHJhaW50czogY29uc3RyYWludCAhPSBudWxsID8gW2NvbnN0cmFpbnRdIDogW10sXG4gICAgICAgIG92ZXJsYXA6IHByb3BzLm92ZXJsYXAsXG4gICAgICAgIGFsbG93czogcHJvcHMuYWxsb3cgIT0gbnVsbCA/IFtwcm9wcy5hbGxvd10gOiBbXSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBwcm9wcy5iYWNrZ3JvdW5kQ29sb3IgfHwgcHJvcHMuY29sb3IsXG4gICAgICAgIGJvcmRlckNvbG9yOiBwcm9wcy5ib3JkZXJDb2xvciB8fCBwcm9wcy5jb2xvcixcbiAgICAgICAgdGV4dENvbG9yOiBwcm9wcy50ZXh0Q29sb3IsXG4gICAgICAgIGNsYXNzTmFtZXM6IHByb3BzLmNsYXNzTmFtZXMuY29uY2F0KHByb3BzLmNsYXNzTmFtZSlcbiAgICB9O1xufVxuZnVuY3Rpb24gcHJvY2Vzc1Njb3BlZFVpUHJvcHMocHJlZml4LCByYXdTY29wZWQsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMpIHtcbiAgICB2YXIgcmF3VW5zY29wZWQgPSB7fTtcbiAgICB2YXIgd2FzRm91bmQgPSB7fTtcbiAgICBmb3IgKHZhciBrZXkgaW4gVU5TQ09QRURfRVZFTlRfVUlfUFJPUFMpIHtcbiAgICAgICAgdmFyIHNjb3BlZEtleSA9IHByZWZpeCArIGNhcGl0YWxpc2VGaXJzdExldHRlcihrZXkpO1xuICAgICAgICByYXdVbnNjb3BlZFtrZXldID0gcmF3U2NvcGVkW3Njb3BlZEtleV07XG4gICAgICAgIHdhc0ZvdW5kW3Njb3BlZEtleV0gPSB0cnVlO1xuICAgIH1cbiAgICBpZiAocHJlZml4ID09PSAnZXZlbnQnKSB7XG4gICAgICAgIHJhd1Vuc2NvcGVkLmVkaXRhYmxlID0gcmF3U2NvcGVkLmVkaXRhYmxlOyAvLyBzcGVjaWFsIGNhc2UuIHRoZXJlIGlzIG5vICdldmVudEVkaXRhYmxlJywganVzdCAnZWRpdGFibGUnXG4gICAgfVxuICAgIGlmIChsZWZ0b3ZlcnMpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHJhd1Njb3BlZCkge1xuICAgICAgICAgICAgaWYgKCF3YXNGb3VuZFtrZXldKSB7XG4gICAgICAgICAgICAgICAgbGVmdG92ZXJzW2tleV0gPSByYXdTY29wZWRba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcHJvY2Vzc1Vuc2NvcGVkVWlQcm9wcyhyYXdVbnNjb3BlZCwgY2FsZW5kYXIpO1xufVxudmFyIEVNUFRZX0VWRU5UX1VJID0ge1xuICAgIHN0YXJ0RWRpdGFibGU6IG51bGwsXG4gICAgZHVyYXRpb25FZGl0YWJsZTogbnVsbCxcbiAgICBjb25zdHJhaW50czogW10sXG4gICAgb3ZlcmxhcDogbnVsbCxcbiAgICBhbGxvd3M6IFtdLFxuICAgIGJhY2tncm91bmRDb2xvcjogJycsXG4gICAgYm9yZGVyQ29sb3I6ICcnLFxuICAgIHRleHRDb2xvcjogJycsXG4gICAgY2xhc3NOYW1lczogW11cbn07XG4vLyBwcmV2ZW50IGFnYWluc3QgcHJvYmxlbXMgd2l0aCA8MiBhcmdzIVxuZnVuY3Rpb24gY29tYmluZUV2ZW50VWlzKHVpcykge1xuICAgIHJldHVybiB1aXMucmVkdWNlKGNvbWJpbmVUd29FdmVudFVpcywgRU1QVFlfRVZFTlRfVUkpO1xufVxuZnVuY3Rpb24gY29tYmluZVR3b0V2ZW50VWlzKGl0ZW0wLCBpdGVtMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0RWRpdGFibGU6IGl0ZW0xLnN0YXJ0RWRpdGFibGUgIT0gbnVsbCA/IGl0ZW0xLnN0YXJ0RWRpdGFibGUgOiBpdGVtMC5zdGFydEVkaXRhYmxlLFxuICAgICAgICBkdXJhdGlvbkVkaXRhYmxlOiBpdGVtMS5kdXJhdGlvbkVkaXRhYmxlICE9IG51bGwgPyBpdGVtMS5kdXJhdGlvbkVkaXRhYmxlIDogaXRlbTAuZHVyYXRpb25FZGl0YWJsZSxcbiAgICAgICAgY29uc3RyYWludHM6IGl0ZW0wLmNvbnN0cmFpbnRzLmNvbmNhdChpdGVtMS5jb25zdHJhaW50cyksXG4gICAgICAgIG92ZXJsYXA6IHR5cGVvZiBpdGVtMS5vdmVybGFwID09PSAnYm9vbGVhbicgPyBpdGVtMS5vdmVybGFwIDogaXRlbTAub3ZlcmxhcCxcbiAgICAgICAgYWxsb3dzOiBpdGVtMC5hbGxvd3MuY29uY2F0KGl0ZW0xLmFsbG93cyksXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogaXRlbTEuYmFja2dyb3VuZENvbG9yIHx8IGl0ZW0wLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgYm9yZGVyQ29sb3I6IGl0ZW0xLmJvcmRlckNvbG9yIHx8IGl0ZW0wLmJvcmRlckNvbG9yLFxuICAgICAgICB0ZXh0Q29sb3I6IGl0ZW0xLnRleHRDb2xvciB8fCBpdGVtMC50ZXh0Q29sb3IsXG4gICAgICAgIGNsYXNzTmFtZXM6IGl0ZW0wLmNsYXNzTmFtZXMuY29uY2F0KGl0ZW0xLmNsYXNzTmFtZXMpXG4gICAgfTtcbn1cblxudmFyIE5PTl9EQVRFX1BST1BTID0ge1xuICAgIGlkOiBTdHJpbmcsXG4gICAgZ3JvdXBJZDogU3RyaW5nLFxuICAgIHRpdGxlOiBTdHJpbmcsXG4gICAgdXJsOiBTdHJpbmcsXG4gICAgcmVuZGVyaW5nOiBTdHJpbmcsXG4gICAgZXh0ZW5kZWRQcm9wczogbnVsbFxufTtcbnZhciBEQVRFX1BST1BTID0ge1xuICAgIHN0YXJ0OiBudWxsLFxuICAgIGRhdGU6IG51bGwsXG4gICAgZW5kOiBudWxsLFxuICAgIGFsbERheTogbnVsbFxufTtcbnZhciB1aWQgPSAwO1xuZnVuY3Rpb24gcGFyc2VFdmVudChyYXcsIHNvdXJjZUlkLCBjYWxlbmRhciwgYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICB2YXIgYWxsRGF5RGVmYXVsdCA9IGNvbXB1dGVJc0FsbERheURlZmF1bHQoc291cmNlSWQsIGNhbGVuZGFyKTtcbiAgICB2YXIgbGVmdG92ZXJzMCA9IHt9O1xuICAgIHZhciByZWN1cnJpbmdSZXMgPSBwYXJzZVJlY3VycmluZyhyYXcsIC8vIHJhdywgYnV0IHdpdGggc2luZ2xlLWV2ZW50IHN0dWZmIHN0cmlwcGVkIG91dFxuICAgIGFsbERheURlZmF1bHQsIGNhbGVuZGFyLmRhdGVFbnYsIGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5yZWN1cnJpbmdUeXBlcywgbGVmdG92ZXJzMCAvLyB3aWxsIHBvcHVsYXRlIHdpdGggbm9uLXJlY3VycmluZyBwcm9wc1xuICAgICk7XG4gICAgaWYgKHJlY3VycmluZ1Jlcykge1xuICAgICAgICB2YXIgZGVmID0gcGFyc2VFdmVudERlZihsZWZ0b3ZlcnMwLCBzb3VyY2VJZCwgcmVjdXJyaW5nUmVzLmFsbERheSwgQm9vbGVhbihyZWN1cnJpbmdSZXMuZHVyYXRpb24pLCBjYWxlbmRhcik7XG4gICAgICAgIGRlZi5yZWN1cnJpbmdEZWYgPSB7XG4gICAgICAgICAgICB0eXBlSWQ6IHJlY3VycmluZ1Jlcy50eXBlSWQsXG4gICAgICAgICAgICB0eXBlRGF0YTogcmVjdXJyaW5nUmVzLnR5cGVEYXRhLFxuICAgICAgICAgICAgZHVyYXRpb246IHJlY3VycmluZ1Jlcy5kdXJhdGlvblxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4geyBkZWY6IGRlZiwgaW5zdGFuY2U6IG51bGwgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBsZWZ0b3ZlcnMxID0ge307XG4gICAgICAgIHZhciBzaW5nbGVSZXMgPSBwYXJzZVNpbmdsZShyYXcsIGFsbERheURlZmF1bHQsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMxLCBhbGxvd09wZW5SYW5nZSk7XG4gICAgICAgIGlmIChzaW5nbGVSZXMpIHtcbiAgICAgICAgICAgIHZhciBkZWYgPSBwYXJzZUV2ZW50RGVmKGxlZnRvdmVyczEsIHNvdXJjZUlkLCBzaW5nbGVSZXMuYWxsRGF5LCBzaW5nbGVSZXMuaGFzRW5kLCBjYWxlbmRhcik7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBjcmVhdGVFdmVudEluc3RhbmNlKGRlZi5kZWZJZCwgc2luZ2xlUmVzLnJhbmdlLCBzaW5nbGVSZXMuZm9yY2VkU3RhcnRUem8sIHNpbmdsZVJlcy5mb3JjZWRFbmRUem8pO1xuICAgICAgICAgICAgcmV0dXJuIHsgZGVmOiBkZWYsIGluc3RhbmNlOiBpbnN0YW5jZSB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuLypcbldpbGwgTk9UIHBvcHVsYXRlIGV4dGVuZGVkUHJvcHMgd2l0aCB0aGUgbGVmdG92ZXIgcHJvcGVydGllcy5cbldpbGwgTk9UIHBvcHVsYXRlIGRhdGUtcmVsYXRlZCBwcm9wcy5cblRoZSBFdmVudE5vbkRhdGVJbnB1dCBoYXMgYmVlbiBub3JtYWxpemVkIChpZCA9PiBwdWJsaWNJZCwgZXRjKS5cbiovXG5mdW5jdGlvbiBwYXJzZUV2ZW50RGVmKHJhdywgc291cmNlSWQsIGFsbERheSwgaGFzRW5kLCBjYWxlbmRhcikge1xuICAgIHZhciBsZWZ0b3ZlcnMgPSB7fTtcbiAgICB2YXIgZGVmID0gcGx1Y2tOb25EYXRlUHJvcHMocmF3LCBjYWxlbmRhciwgbGVmdG92ZXJzKTtcbiAgICBkZWYuZGVmSWQgPSBTdHJpbmcodWlkKyspO1xuICAgIGRlZi5zb3VyY2VJZCA9IHNvdXJjZUlkO1xuICAgIGRlZi5hbGxEYXkgPSBhbGxEYXk7XG4gICAgZGVmLmhhc0VuZCA9IGhhc0VuZDtcbiAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50RGVmUGFyc2VyczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIGV2ZW50RGVmUGFyc2VyID0gX2FbX2ldO1xuICAgICAgICB2YXIgbmV3TGVmdG92ZXJzID0ge307XG4gICAgICAgIGV2ZW50RGVmUGFyc2VyKGRlZiwgbGVmdG92ZXJzLCBuZXdMZWZ0b3ZlcnMpO1xuICAgICAgICBsZWZ0b3ZlcnMgPSBuZXdMZWZ0b3ZlcnM7XG4gICAgfVxuICAgIGRlZi5leHRlbmRlZFByb3BzID0gX19hc3NpZ24obGVmdG92ZXJzLCBkZWYuZXh0ZW5kZWRQcm9wcyB8fCB7fSk7XG4gICAgLy8gaGVscCBvdXQgRXZlbnRBcGkgZnJvbSBoYXZpbmcgdXNlciBtb2RpZnkgcHJvcHNcbiAgICBPYmplY3QuZnJlZXplKGRlZi51aS5jbGFzc05hbWVzKTtcbiAgICBPYmplY3QuZnJlZXplKGRlZi5leHRlbmRlZFByb3BzKTtcbiAgICByZXR1cm4gZGVmO1xufVxuZnVuY3Rpb24gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWZJZCwgcmFuZ2UsIGZvcmNlZFN0YXJ0VHpvLCBmb3JjZWRFbmRUem8pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBpbnN0YW5jZUlkOiBTdHJpbmcodWlkKyspLFxuICAgICAgICBkZWZJZDogZGVmSWQsXG4gICAgICAgIHJhbmdlOiByYW5nZSxcbiAgICAgICAgZm9yY2VkU3RhcnRUem86IGZvcmNlZFN0YXJ0VHpvID09IG51bGwgPyBudWxsIDogZm9yY2VkU3RhcnRUem8sXG4gICAgICAgIGZvcmNlZEVuZFR6bzogZm9yY2VkRW5kVHpvID09IG51bGwgPyBudWxsIDogZm9yY2VkRW5kVHpvXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlU2luZ2xlKHJhdywgYWxsRGF5RGVmYXVsdCwgY2FsZW5kYXIsIGxlZnRvdmVycywgYWxsb3dPcGVuUmFuZ2UpIHtcbiAgICB2YXIgcHJvcHMgPSBwbHVja0RhdGVQcm9wcyhyYXcsIGxlZnRvdmVycyk7XG4gICAgdmFyIGFsbERheSA9IHByb3BzLmFsbERheTtcbiAgICB2YXIgc3RhcnRNZXRhO1xuICAgIHZhciBzdGFydE1hcmtlciA9IG51bGw7XG4gICAgdmFyIGhhc0VuZCA9IGZhbHNlO1xuICAgIHZhciBlbmRNZXRhO1xuICAgIHZhciBlbmRNYXJrZXIgPSBudWxsO1xuICAgIHN0YXJ0TWV0YSA9IGNhbGVuZGFyLmRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShwcm9wcy5zdGFydCk7XG4gICAgaWYgKHN0YXJ0TWV0YSkge1xuICAgICAgICBzdGFydE1hcmtlciA9IHN0YXJ0TWV0YS5tYXJrZXI7XG4gICAgfVxuICAgIGVsc2UgaWYgKCFhbGxvd09wZW5SYW5nZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHByb3BzLmVuZCAhPSBudWxsKSB7XG4gICAgICAgIGVuZE1ldGEgPSBjYWxlbmRhci5kYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEocHJvcHMuZW5kKTtcbiAgICB9XG4gICAgaWYgKGFsbERheSA9PSBudWxsKSB7XG4gICAgICAgIGlmIChhbGxEYXlEZWZhdWx0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGFsbERheSA9IGFsbERheURlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBmYWxsIGJhY2sgdG8gdGhlIGRhdGUgcHJvcHMgTEFTVFxuICAgICAgICAgICAgYWxsRGF5ID0gKCFzdGFydE1ldGEgfHwgc3RhcnRNZXRhLmlzVGltZVVuc3BlY2lmaWVkKSAmJlxuICAgICAgICAgICAgICAgICghZW5kTWV0YSB8fCBlbmRNZXRhLmlzVGltZVVuc3BlY2lmaWVkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYWxsRGF5ICYmIHN0YXJ0TWFya2VyKSB7XG4gICAgICAgIHN0YXJ0TWFya2VyID0gc3RhcnRPZkRheShzdGFydE1hcmtlcik7XG4gICAgfVxuICAgIGlmIChlbmRNZXRhKSB7XG4gICAgICAgIGVuZE1hcmtlciA9IGVuZE1ldGEubWFya2VyO1xuICAgICAgICBpZiAoYWxsRGF5KSB7XG4gICAgICAgICAgICBlbmRNYXJrZXIgPSBzdGFydE9mRGF5KGVuZE1hcmtlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXJ0TWFya2VyICYmIGVuZE1hcmtlciA8PSBzdGFydE1hcmtlcikge1xuICAgICAgICAgICAgZW5kTWFya2VyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZW5kTWFya2VyKSB7XG4gICAgICAgIGhhc0VuZCA9IHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYgKCFhbGxvd09wZW5SYW5nZSkge1xuICAgICAgICBoYXNFbmQgPSBjYWxlbmRhci5vcHQoJ2ZvcmNlRXZlbnREdXJhdGlvbicpIHx8IGZhbHNlO1xuICAgICAgICBlbmRNYXJrZXIgPSBjYWxlbmRhci5kYXRlRW52LmFkZChzdGFydE1hcmtlciwgYWxsRGF5ID9cbiAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uIDpcbiAgICAgICAgICAgIGNhbGVuZGFyLmRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBhbGxEYXk6IGFsbERheSxcbiAgICAgICAgaGFzRW5kOiBoYXNFbmQsXG4gICAgICAgIHJhbmdlOiB7IHN0YXJ0OiBzdGFydE1hcmtlciwgZW5kOiBlbmRNYXJrZXIgfSxcbiAgICAgICAgZm9yY2VkU3RhcnRUem86IHN0YXJ0TWV0YSA/IHN0YXJ0TWV0YS5mb3JjZWRUem8gOiBudWxsLFxuICAgICAgICBmb3JjZWRFbmRUem86IGVuZE1ldGEgPyBlbmRNZXRhLmZvcmNlZFR6byA6IG51bGxcbiAgICB9O1xufVxuZnVuY3Rpb24gcGx1Y2tEYXRlUHJvcHMocmF3LCBsZWZ0b3ZlcnMpIHtcbiAgICB2YXIgcHJvcHMgPSByZWZpbmVQcm9wcyhyYXcsIERBVEVfUFJPUFMsIHt9LCBsZWZ0b3ZlcnMpO1xuICAgIHByb3BzLnN0YXJ0ID0gKHByb3BzLnN0YXJ0ICE9PSBudWxsKSA/IHByb3BzLnN0YXJ0IDogcHJvcHMuZGF0ZTtcbiAgICBkZWxldGUgcHJvcHMuZGF0ZTtcbiAgICByZXR1cm4gcHJvcHM7XG59XG5mdW5jdGlvbiBwbHVja05vbkRhdGVQcm9wcyhyYXcsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMpIHtcbiAgICB2YXIgcHJlTGVmdG92ZXJzID0ge307XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3LCBOT05fREFURV9QUk9QUywge30sIHByZUxlZnRvdmVycyk7XG4gICAgdmFyIHVpID0gcHJvY2Vzc1Vuc2NvcGVkVWlQcm9wcyhwcmVMZWZ0b3ZlcnMsIGNhbGVuZGFyLCBsZWZ0b3ZlcnMpO1xuICAgIHByb3BzLnB1YmxpY0lkID0gcHJvcHMuaWQ7XG4gICAgZGVsZXRlIHByb3BzLmlkO1xuICAgIHByb3BzLnVpID0gdWk7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuZnVuY3Rpb24gY29tcHV0ZUlzQWxsRGF5RGVmYXVsdChzb3VyY2VJZCwgY2FsZW5kYXIpIHtcbiAgICB2YXIgcmVzID0gbnVsbDtcbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGNhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlc1tzb3VyY2VJZF07XG4gICAgICAgIHJlcyA9IHNvdXJjZS5hbGxEYXlEZWZhdWx0O1xuICAgIH1cbiAgICBpZiAocmVzID09IG51bGwpIHtcbiAgICAgICAgcmVzID0gY2FsZW5kYXIub3B0KCdhbGxEYXlEZWZhdWx0Jyk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5cbnZhciBERUZfREVGQVVMVFMgPSB7XG4gICAgc3RhcnRUaW1lOiAnMDk6MDAnLFxuICAgIGVuZFRpbWU6ICcxNzowMCcsXG4gICAgZGF5c09mV2VlazogWzEsIDIsIDMsIDQsIDVdLFxuICAgIHJlbmRlcmluZzogJ2ludmVyc2UtYmFja2dyb3VuZCcsXG4gICAgY2xhc3NOYW1lczogJ2ZjLW5vbmJ1c2luZXNzJyxcbiAgICBncm91cElkOiAnX2J1c2luZXNzSG91cnMnIC8vIHNvIG11bHRpcGxlIGRlZnMgZ2V0IGdyb3VwZWRcbn07XG4vKlxuVE9ETzogcGFzcyBhcm91bmQgYXMgRXZlbnREZWZIYXNoISEhXG4qL1xuZnVuY3Rpb24gcGFyc2VCdXNpbmVzc0hvdXJzKGlucHV0LCBjYWxlbmRhcikge1xuICAgIHJldHVybiBwYXJzZUV2ZW50cyhyZWZpbmVJbnB1dHMoaW5wdXQpLCAnJywgY2FsZW5kYXIpO1xufVxuZnVuY3Rpb24gcmVmaW5lSW5wdXRzKGlucHV0KSB7XG4gICAgdmFyIHJhd0RlZnM7XG4gICAgaWYgKGlucHV0ID09PSB0cnVlKSB7XG4gICAgICAgIHJhd0RlZnMgPSBbe31dOyAvLyB3aWxsIGdldCBERUZfREVGQVVMVFMgdmVyYmF0aW1cbiAgICB9XG4gICAgZWxzZSBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgLy8gaWYgc3BlY2lmeWluZyBhbiBhcnJheSwgZXZlcnkgc3ViLWRlZmluaXRpb24gTkVFRFMgYSBkYXktb2Ytd2Vla1xuICAgICAgICByYXdEZWZzID0gaW5wdXQuZmlsdGVyKGZ1bmN0aW9uIChyYXdEZWYpIHtcbiAgICAgICAgICAgIHJldHVybiByYXdEZWYuZGF5c09mV2VlaztcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgaW5wdXQpIHsgLy8gbm9uLW51bGwgb2JqZWN0XG4gICAgICAgIHJhd0RlZnMgPSBbaW5wdXRdO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gaXMgcHJvYmFibHkgZmFsc2VcbiAgICAgICAgcmF3RGVmcyA9IFtdO1xuICAgIH1cbiAgICByYXdEZWZzID0gcmF3RGVmcy5tYXAoZnVuY3Rpb24gKHJhd0RlZikge1xuICAgICAgICByZXR1cm4gX19hc3NpZ24oe30sIERFRl9ERUZBVUxUUywgcmF3RGVmKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmF3RGVmcztcbn1cblxuZnVuY3Rpb24gbWVtb2l6ZVJlbmRlcmluZyhyZW5kZXJGdW5jLCB1bnJlbmRlckZ1bmMsIGRlcGVuZGVuY2llcykge1xuICAgIGlmIChkZXBlbmRlbmNpZXMgPT09IHZvaWQgMCkgeyBkZXBlbmRlbmNpZXMgPSBbXTsgfVxuICAgIHZhciBkZXBlbmRlbnRzID0gW107XG4gICAgdmFyIHRoaXNDb250ZXh0O1xuICAgIHZhciBwcmV2QXJncztcbiAgICBmdW5jdGlvbiB1bnJlbmRlcigpIHtcbiAgICAgICAgaWYgKHByZXZBcmdzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIGRlcGVuZGVudHNfMSA9IGRlcGVuZGVudHM7IF9pIDwgZGVwZW5kZW50c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBkZXBlbmRlbnQgPSBkZXBlbmRlbnRzXzFbX2ldO1xuICAgICAgICAgICAgICAgIGRlcGVuZGVudC51bnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVucmVuZGVyRnVuYykge1xuICAgICAgICAgICAgICAgIHVucmVuZGVyRnVuYy5hcHBseSh0aGlzQ29udGV4dCwgcHJldkFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJldkFyZ3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlcygpIHtcbiAgICAgICAgaWYgKCFwcmV2QXJncyB8fCAhaXNBcnJheXNFcXVhbChwcmV2QXJncywgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgdW5yZW5kZXIoKTtcbiAgICAgICAgICAgIHRoaXNDb250ZXh0ID0gdGhpcztcbiAgICAgICAgICAgIHByZXZBcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgcmVuZGVyRnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlcy5kZXBlbmRlbnRzID0gZGVwZW5kZW50cztcbiAgICByZXMudW5yZW5kZXIgPSB1bnJlbmRlcjtcbiAgICBmb3IgKHZhciBfaSA9IDAsIGRlcGVuZGVuY2llc18xID0gZGVwZW5kZW5jaWVzOyBfaSA8IGRlcGVuZGVuY2llc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgZGVwZW5kZW5jeSA9IGRlcGVuZGVuY2llc18xW19pXTtcbiAgICAgICAgZGVwZW5kZW5jeS5kZXBlbmRlbnRzLnB1c2gocmVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxudmFyIEVNUFRZX0VWRU5UX1NUT1JFID0gY3JlYXRlRW1wdHlFdmVudFN0b3JlKCk7IC8vIGZvciBwdXJlY29tcG9uZW50cy4gVE9ETzoga2VlcCBlbHNld2hlcmVcbnZhciBTcGxpdHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTcGxpdHRlcigpIHtcbiAgICAgICAgdGhpcy5nZXRLZXlzRm9yRXZlbnREZWZzID0gbWVtb2l6ZSh0aGlzLl9nZXRLZXlzRm9yRXZlbnREZWZzKTtcbiAgICAgICAgdGhpcy5zcGxpdERhdGVTZWxlY3Rpb24gPSBtZW1vaXplKHRoaXMuX3NwbGl0RGF0ZVNwYW4pO1xuICAgICAgICB0aGlzLnNwbGl0RXZlbnRTdG9yZSA9IG1lbW9pemUodGhpcy5fc3BsaXRFdmVudFN0b3JlKTtcbiAgICAgICAgdGhpcy5zcGxpdEluZGl2aWR1YWxVaSA9IG1lbW9pemUodGhpcy5fc3BsaXRJbmRpdmlkdWFsVWkpO1xuICAgICAgICB0aGlzLnNwbGl0RXZlbnREcmFnID0gbWVtb2l6ZSh0aGlzLl9zcGxpdEludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5zcGxpdEV2ZW50UmVzaXplID0gbWVtb2l6ZSh0aGlzLl9zcGxpdEludGVyYWN0aW9uKTtcbiAgICAgICAgdGhpcy5ldmVudFVpQnVpbGRlcnMgPSB7fTsgLy8gVE9ETzogdHlwZXNjcmlwdCBwcm90ZWN0aW9uXG4gICAgfVxuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5zcGxpdFByb3BzID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBrZXlJbmZvcyA9IHRoaXMuZ2V0S2V5SW5mbyhwcm9wcyk7XG4gICAgICAgIHZhciBkZWZLZXlzID0gdGhpcy5nZXRLZXlzRm9yRXZlbnREZWZzKHByb3BzLmV2ZW50U3RvcmUpO1xuICAgICAgICB2YXIgZGF0ZVNlbGVjdGlvbnMgPSB0aGlzLnNwbGl0RGF0ZVNlbGVjdGlvbihwcm9wcy5kYXRlU2VsZWN0aW9uKTtcbiAgICAgICAgdmFyIGluZGl2aWR1YWxVaSA9IHRoaXMuc3BsaXRJbmRpdmlkdWFsVWkocHJvcHMuZXZlbnRVaUJhc2VzLCBkZWZLZXlzKTsgLy8gdGhlIGluZGl2aWR1YWwgKmJhc2VzKlxuICAgICAgICB2YXIgZXZlbnRTdG9yZXMgPSB0aGlzLnNwbGl0RXZlbnRTdG9yZShwcm9wcy5ldmVudFN0b3JlLCBkZWZLZXlzKTtcbiAgICAgICAgdmFyIGV2ZW50RHJhZ3MgPSB0aGlzLnNwbGl0RXZlbnREcmFnKHByb3BzLmV2ZW50RHJhZyk7XG4gICAgICAgIHZhciBldmVudFJlc2l6ZXMgPSB0aGlzLnNwbGl0RXZlbnRSZXNpemUocHJvcHMuZXZlbnRSZXNpemUpO1xuICAgICAgICB2YXIgc3BsaXRQcm9wcyA9IHt9O1xuICAgICAgICB0aGlzLmV2ZW50VWlCdWlsZGVycyA9IG1hcEhhc2goa2V5SW5mb3MsIGZ1bmN0aW9uIChpbmZvLCBrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5ldmVudFVpQnVpbGRlcnNba2V5XSB8fCBtZW1vaXplKGJ1aWxkRXZlbnRVaUZvcktleSk7XG4gICAgICAgIH0pO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4ga2V5SW5mb3MpIHtcbiAgICAgICAgICAgIHZhciBrZXlJbmZvID0ga2V5SW5mb3Nba2V5XTtcbiAgICAgICAgICAgIHZhciBldmVudFN0b3JlID0gZXZlbnRTdG9yZXNba2V5XSB8fCBFTVBUWV9FVkVOVF9TVE9SRTtcbiAgICAgICAgICAgIHZhciBidWlsZEV2ZW50VWkgPSB0aGlzLmV2ZW50VWlCdWlsZGVyc1trZXldO1xuICAgICAgICAgICAgc3BsaXRQcm9wc1trZXldID0ge1xuICAgICAgICAgICAgICAgIGJ1c2luZXNzSG91cnM6IGtleUluZm8uYnVzaW5lc3NIb3VycyB8fCBwcm9wcy5idXNpbmVzc0hvdXJzLFxuICAgICAgICAgICAgICAgIGRhdGVTZWxlY3Rpb246IGRhdGVTZWxlY3Rpb25zW2tleV0gfHwgbnVsbCxcbiAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFN0b3JlLFxuICAgICAgICAgICAgICAgIGV2ZW50VWlCYXNlczogYnVpbGRFdmVudFVpKHByb3BzLmV2ZW50VWlCYXNlc1snJ10sIGtleUluZm8udWksIGluZGl2aWR1YWxVaVtrZXldKSxcbiAgICAgICAgICAgICAgICBldmVudFNlbGVjdGlvbjogZXZlbnRTdG9yZS5pbnN0YW5jZXNbcHJvcHMuZXZlbnRTZWxlY3Rpb25dID8gcHJvcHMuZXZlbnRTZWxlY3Rpb24gOiAnJyxcbiAgICAgICAgICAgICAgICBldmVudERyYWc6IGV2ZW50RHJhZ3Nba2V5XSB8fCBudWxsLFxuICAgICAgICAgICAgICAgIGV2ZW50UmVzaXplOiBldmVudFJlc2l6ZXNba2V5XSB8fCBudWxsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdFByb3BzO1xuICAgIH07XG4gICAgU3BsaXR0ZXIucHJvdG90eXBlLl9zcGxpdERhdGVTcGFuID0gZnVuY3Rpb24gKGRhdGVTcGFuKSB7XG4gICAgICAgIHZhciBkYXRlU3BhbnMgPSB7fTtcbiAgICAgICAgaWYgKGRhdGVTcGFuKSB7XG4gICAgICAgICAgICB2YXIga2V5cyA9IHRoaXMuZ2V0S2V5c0ZvckRhdGVTcGFuKGRhdGVTcGFuKTtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwga2V5c18xID0ga2V5czsgX2kgPCBrZXlzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGtleXNfMVtfaV07XG4gICAgICAgICAgICAgICAgZGF0ZVNwYW5zW2tleV0gPSBkYXRlU3BhbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZVNwYW5zO1xuICAgIH07XG4gICAgU3BsaXR0ZXIucHJvdG90eXBlLl9nZXRLZXlzRm9yRXZlbnREZWZzID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIG1hcEhhc2goZXZlbnRTdG9yZS5kZWZzLCBmdW5jdGlvbiAoZXZlbnREZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5nZXRLZXlzRm9yRXZlbnREZWYoZXZlbnREZWYpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fc3BsaXRFdmVudFN0b3JlID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUsIGRlZktleXMpIHtcbiAgICAgICAgdmFyIGRlZnMgPSBldmVudFN0b3JlLmRlZnMsIGluc3RhbmNlcyA9IGV2ZW50U3RvcmUuaW5zdGFuY2VzO1xuICAgICAgICB2YXIgc3BsaXRTdG9yZXMgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgZGVmSWQgaW4gZGVmcykge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGRlZktleXNbZGVmSWRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKCFzcGxpdFN0b3Jlc1trZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwbGl0U3RvcmVzW2tleV0gPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3BsaXRTdG9yZXNba2V5XS5kZWZzW2RlZklkXSA9IGRlZnNbZGVmSWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGluc3RhbmNlSWQgaW4gaW5zdGFuY2VzKSB7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5zdGFuY2VJZF07XG4gICAgICAgICAgICBmb3IgKHZhciBfYiA9IDAsIF9jID0gZGVmS2V5c1tpbnN0YW5jZS5kZWZJZF07IF9iIDwgX2MubGVuZ3RoOyBfYisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IF9jW19iXTtcbiAgICAgICAgICAgICAgICBpZiAoc3BsaXRTdG9yZXNba2V5XSkgeyAvLyBtdXN0IGhhdmUgYWxyZWFkeSBiZWVuIGNyZWF0ZWRcbiAgICAgICAgICAgICAgICAgICAgc3BsaXRTdG9yZXNba2V5XS5pbnN0YW5jZXNbaW5zdGFuY2VJZF0gPSBpbnN0YW5jZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwbGl0U3RvcmVzO1xuICAgIH07XG4gICAgU3BsaXR0ZXIucHJvdG90eXBlLl9zcGxpdEluZGl2aWR1YWxVaSA9IGZ1bmN0aW9uIChldmVudFVpQmFzZXMsIGRlZktleXMpIHtcbiAgICAgICAgdmFyIHNwbGl0SGFzaGVzID0ge307XG4gICAgICAgIGZvciAodmFyIGRlZklkIGluIGV2ZW50VWlCYXNlcykge1xuICAgICAgICAgICAgaWYgKGRlZklkKSB7IC8vIG5vdCB0aGUgJycga2V5XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGRlZktleXNbZGVmSWRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNwbGl0SGFzaGVzW2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwbGl0SGFzaGVzW2tleV0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzcGxpdEhhc2hlc1trZXldW2RlZklkXSA9IGV2ZW50VWlCYXNlc1tkZWZJZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcGxpdEhhc2hlcztcbiAgICB9O1xuICAgIFNwbGl0dGVyLnByb3RvdHlwZS5fc3BsaXRJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbikge1xuICAgICAgICB2YXIgc3BsaXRTdGF0ZXMgPSB7fTtcbiAgICAgICAgaWYgKGludGVyYWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgYWZmZWN0ZWRTdG9yZXNfMSA9IHRoaXMuX3NwbGl0RXZlbnRTdG9yZShpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cywgdGhpcy5fZ2V0S2V5c0ZvckV2ZW50RGVmcyhpbnRlcmFjdGlvbi5hZmZlY3RlZEV2ZW50cykgLy8gY2FuJ3QgdXNlIGNhY2hlZC4gbWlnaHQgYmUgZXZlbnRzIGZyb20gb3RoZXIgY2FsZW5kYXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICAvLyBjYW4ndCByZWx5IG9uIGRlZktleXMgYmVjYXVzZSBldmVudCBkYXRhIGlzIG11dGF0ZWRcbiAgICAgICAgICAgIHZhciBtdXRhdGVkS2V5c0J5RGVmSWQgPSB0aGlzLl9nZXRLZXlzRm9yRXZlbnREZWZzKGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMpO1xuICAgICAgICAgICAgdmFyIG11dGF0ZWRTdG9yZXNfMSA9IHRoaXMuX3NwbGl0RXZlbnRTdG9yZShpbnRlcmFjdGlvbi5tdXRhdGVkRXZlbnRzLCBtdXRhdGVkS2V5c0J5RGVmSWQpO1xuICAgICAgICAgICAgdmFyIHBvcHVsYXRlID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgIGlmICghc3BsaXRTdGF0ZXNba2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBzcGxpdFN0YXRlc1trZXldID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IGFmZmVjdGVkU3RvcmVzXzFba2V5XSB8fCBFTVBUWV9FVkVOVF9TVE9SRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZWRFdmVudHM6IG11dGF0ZWRTdG9yZXNfMVtrZXldIHx8IEVNUFRZX0VWRU5UX1NUT1JFLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNFdmVudDogaW50ZXJhY3Rpb24uaXNFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdTZWc6IGludGVyYWN0aW9uLm9yaWdTZWdcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGFmZmVjdGVkU3RvcmVzXzEpIHtcbiAgICAgICAgICAgICAgICBwb3B1bGF0ZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG11dGF0ZWRTdG9yZXNfMSkge1xuICAgICAgICAgICAgICAgIHBvcHVsYXRlKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwbGl0U3RhdGVzO1xuICAgIH07XG4gICAgcmV0dXJuIFNwbGl0dGVyO1xufSgpKTtcbmZ1bmN0aW9uIGJ1aWxkRXZlbnRVaUZvcktleShhbGxVaSwgZXZlbnRVaUZvcktleSwgaW5kaXZpZHVhbFVpKSB7XG4gICAgdmFyIGJhc2VQYXJ0cyA9IFtdO1xuICAgIGlmIChhbGxVaSkge1xuICAgICAgICBiYXNlUGFydHMucHVzaChhbGxVaSk7XG4gICAgfVxuICAgIGlmIChldmVudFVpRm9yS2V5KSB7XG4gICAgICAgIGJhc2VQYXJ0cy5wdXNoKGV2ZW50VWlGb3JLZXkpO1xuICAgIH1cbiAgICB2YXIgc3R1ZmYgPSB7XG4gICAgICAgICcnOiBjb21iaW5lRXZlbnRVaXMoYmFzZVBhcnRzKVxuICAgIH07XG4gICAgaWYgKGluZGl2aWR1YWxVaSkge1xuICAgICAgICBfX2Fzc2lnbihzdHVmZiwgaW5kaXZpZHVhbFVpKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0dWZmO1xufVxuXG4vLyBHZW5lcmF0ZXMgSFRNTCBmb3IgYW4gYW5jaG9yIHRvIGFub3RoZXIgdmlldyBpbnRvIHRoZSBjYWxlbmRhci5cbi8vIFdpbGwgZWl0aGVyIGdlbmVyYXRlIGFuIDxhPiB0YWcgb3IgYSBub24tY2xpY2thYmxlIDxzcGFuPiB0YWcsIGRlcGVuZGluZyBvbiBlbmFibGVkIHNldHRpbmdzLlxuLy8gYGdvdG9PcHRpb25zYCBjYW4gZWl0aGVyIGJlIGEgRGF0ZU1hcmtlciwgb3IgYW4gb2JqZWN0IHdpdGggdGhlIGZvcm06XG4vLyB7IGRhdGUsIHR5cGUsIGZvcmNlT2ZmIH1cbi8vIGB0eXBlYCBpcyBhIHZpZXctdHlwZSBsaWtlIFwiZGF5XCIgb3IgXCJ3ZWVrXCIuIGRlZmF1bHQgdmFsdWUgaXMgXCJkYXlcIi5cbi8vIGBhdHRyc2AgYW5kIGBpbm5lckh0bWxgIGFyZSB1c2UgdG8gZ2VuZXJhdGUgdGhlIHJlc3Qgb2YgdGhlIEhUTUwgdGFnLlxuZnVuY3Rpb24gYnVpbGRHb3RvQW5jaG9ySHRtbChhbGxPcHRpb25zLCBkYXRlRW52LCBnb3RvT3B0aW9ucywgYXR0cnMsIGlubmVySHRtbCkge1xuICAgIHZhciBkYXRlO1xuICAgIHZhciB0eXBlO1xuICAgIHZhciBmb3JjZU9mZjtcbiAgICB2YXIgZmluYWxPcHRpb25zO1xuICAgIGlmIChnb3RvT3B0aW9ucyBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgZGF0ZSA9IGdvdG9PcHRpb25zOyAvLyBhIHNpbmdsZSBkYXRlLWxpa2UgaW5wdXRcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGRhdGUgPSBnb3RvT3B0aW9ucy5kYXRlO1xuICAgICAgICB0eXBlID0gZ290b09wdGlvbnMudHlwZTtcbiAgICAgICAgZm9yY2VPZmYgPSBnb3RvT3B0aW9ucy5mb3JjZU9mZjtcbiAgICB9XG4gICAgZmluYWxPcHRpb25zID0ge1xuICAgICAgICBkYXRlOiBkYXRlRW52LmZvcm1hdElzbyhkYXRlLCB7IG9taXRUaW1lOiB0cnVlIH0pLFxuICAgICAgICB0eXBlOiB0eXBlIHx8ICdkYXknXG4gICAgfTtcbiAgICBpZiAodHlwZW9mIGF0dHJzID09PSAnc3RyaW5nJykge1xuICAgICAgICBpbm5lckh0bWwgPSBhdHRycztcbiAgICAgICAgYXR0cnMgPSBudWxsO1xuICAgIH1cbiAgICBhdHRycyA9IGF0dHJzID8gJyAnICsgYXR0cnNUb1N0cihhdHRycykgOiAnJzsgLy8gd2lsbCBoYXZlIGEgbGVhZGluZyBzcGFjZVxuICAgIGlubmVySHRtbCA9IGlubmVySHRtbCB8fCAnJztcbiAgICBpZiAoIWZvcmNlT2ZmICYmIGFsbE9wdGlvbnMubmF2TGlua3MpIHtcbiAgICAgICAgcmV0dXJuICc8YScgKyBhdHRycyArXG4gICAgICAgICAgICAnIGRhdGEtZ290bz1cIicgKyBodG1sRXNjYXBlKEpTT04uc3RyaW5naWZ5KGZpbmFsT3B0aW9ucykpICsgJ1wiPicgK1xuICAgICAgICAgICAgaW5uZXJIdG1sICtcbiAgICAgICAgICAgICc8L2E+JztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiAnPHNwYW4nICsgYXR0cnMgKyAnPicgK1xuICAgICAgICAgICAgaW5uZXJIdG1sICtcbiAgICAgICAgICAgICc8L3NwYW4+JztcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRBbGxEYXlIdG1sKGFsbE9wdGlvbnMpIHtcbiAgICByZXR1cm4gYWxsT3B0aW9ucy5hbGxEYXlIdG1sIHx8IGh0bWxFc2NhcGUoYWxsT3B0aW9ucy5hbGxEYXlUZXh0KTtcbn1cbi8vIENvbXB1dGVzIEhUTUwgY2xhc3NOYW1lcyBmb3IgYSBzaW5nbGUtZGF5IGVsZW1lbnRcbmZ1bmN0aW9uIGdldERheUNsYXNzZXMoZGF0ZSwgZGF0ZVByb2ZpbGUsIGNvbnRleHQsIG5vVGhlbWVIaWdobGlnaHQpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBjb250ZXh0LmNhbGVuZGFyLCBvcHRpb25zID0gY29udGV4dC5vcHRpb25zLCB0aGVtZSA9IGNvbnRleHQudGhlbWUsIGRhdGVFbnYgPSBjb250ZXh0LmRhdGVFbnY7XG4gICAgdmFyIGNsYXNzZXMgPSBbXTtcbiAgICB2YXIgdG9kYXlTdGFydDtcbiAgICB2YXIgdG9kYXlFbmQ7XG4gICAgaWYgKCFyYW5nZUNvbnRhaW5zTWFya2VyKGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBkYXRlKSkge1xuICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLWRpc2FibGVkLWRheScpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy0nICsgREFZX0lEU1tkYXRlLmdldFVUQ0RheSgpXSk7XG4gICAgICAgIGlmIChvcHRpb25zLm1vbnRoTW9kZSAmJlxuICAgICAgICAgICAgZGF0ZUVudi5nZXRNb250aChkYXRlKSAhPT0gZGF0ZUVudi5nZXRNb250aChkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2Uuc3RhcnQpKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLW90aGVyLW1vbnRoJyk7XG4gICAgICAgIH1cbiAgICAgICAgdG9kYXlTdGFydCA9IHN0YXJ0T2ZEYXkoY2FsZW5kYXIuZ2V0Tm93KCkpO1xuICAgICAgICB0b2RheUVuZCA9IGFkZERheXModG9kYXlTdGFydCwgMSk7XG4gICAgICAgIGlmIChkYXRlIDwgdG9kYXlTdGFydCkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1wYXN0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZGF0ZSA+PSB0b2RheUVuZCkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1mdXR1cmUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtdG9kYXknKTtcbiAgICAgICAgICAgIGlmIChub1RoZW1lSGlnaGxpZ2h0ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHRoZW1lLmdldENsYXNzKCd0b2RheScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xhc3Nlcztcbn1cblxuLy8gZ2l2ZW4gYSBmdW5jdGlvbiB0aGF0IHJlc29sdmVzIGEgcmVzdWx0IGFzeW5jaHJvbm91c2x5LlxuLy8gdGhlIGZ1bmN0aW9uIGNhbiBlaXRoZXIgY2FsbCBwYXNzZWQtaW4gc3VjY2VzcyBhbmQgZmFpbHVyZSBjYWxsYmFja3MsXG4vLyBvciBpdCBjYW4gcmV0dXJuIGEgcHJvbWlzZS5cbi8vIGlmIHlvdSBuZWVkIHRvIHBhc3MgYWRkaXRpb25hbCBwYXJhbXMgdG8gZnVuYywgYmluZCB0aGVtIGZpcnN0LlxuZnVuY3Rpb24gdW5wcm9taXNpZnkoZnVuYywgc3VjY2VzcywgZmFpbHVyZSkge1xuICAgIC8vIGd1YXJkIGFnYWluc3Qgc3VjY2Vzcy9mYWlsdXJlIGNhbGxiYWNrcyBiZWluZyBjYWxsZWQgbW9yZSB0aGFuIG9uY2VcbiAgICAvLyBhbmQgZ3VhcmQgYWdhaW5zdCBhIHByb21pc2UgQU5EIGNhbGxiYWNrIGJlaW5nIHVzZWQgdG9nZXRoZXIuXG4gICAgdmFyIGlzUmVzb2x2ZWQgPSBmYWxzZTtcbiAgICB2YXIgd3JhcHBlZFN1Y2Nlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghaXNSZXNvbHZlZCkge1xuICAgICAgICAgICAgaXNSZXNvbHZlZCA9IHRydWU7XG4gICAgICAgICAgICBzdWNjZXNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHZhciB3cmFwcGVkRmFpbHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFpc1Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpc1Jlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChmYWlsdXJlKSB7XG4gICAgICAgICAgICAgICAgZmFpbHVyZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICB2YXIgcmVzID0gZnVuYyh3cmFwcGVkU3VjY2Vzcywgd3JhcHBlZEZhaWx1cmUpO1xuICAgIGlmIChyZXMgJiYgdHlwZW9mIHJlcy50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJlcy50aGVuKHdyYXBwZWRTdWNjZXNzLCB3cmFwcGVkRmFpbHVyZSk7XG4gICAgfVxufVxuXG52YXIgTWl4aW4gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTWl4aW4oKSB7XG4gICAgfVxuICAgIC8vIG1peCBpbnRvIGEgQ0xBU1NcbiAgICBNaXhpbi5taXhJbnRvID0gZnVuY3Rpb24gKGRlc3RDbGFzcykge1xuICAgICAgICB0aGlzLm1peEludG9PYmooZGVzdENsYXNzLnByb3RvdHlwZSk7XG4gICAgfTtcbiAgICAvLyBtaXggaW50byBBTlkgb2JqZWN0XG4gICAgTWl4aW4ubWl4SW50b09iaiA9IGZ1bmN0aW9uIChkZXN0T2JqKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICBpZiAoIWRlc3RPYmpbbmFtZV0pIHsgLy8gaWYgZGVzdGluYXRpb24gZG9lc24ndCBhbHJlYWR5IGRlZmluZSBpdFxuICAgICAgICAgICAgICAgIGRlc3RPYmpbbmFtZV0gPSBfdGhpcy5wcm90b3R5cGVbbmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLypcbiAgICB3aWxsIG92ZXJyaWRlIGV4aXN0aW5nIG1ldGhvZHNcbiAgICBUT0RPOiByZW1vdmUhIG5vdCB1c2VkIGFueW1vcmVcbiAgICAqL1xuICAgIE1peGluLm1peE92ZXIgPSBmdW5jdGlvbiAoZGVzdENsYXNzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICBkZXN0Q2xhc3MucHJvdG90eXBlW25hbWVdID0gX3RoaXMucHJvdG90eXBlW25hbWVdO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBNaXhpbjtcbn0oKSk7XG5cbi8qXG5VU0FHRTpcbiAgaW1wb3J0IHsgZGVmYXVsdCBhcyBFbWl0dGVyTWl4aW4sIEVtaXR0ZXJJbnRlcmZhY2UgfSBmcm9tICcuL0VtaXR0ZXJNaXhpbidcbmluIGNsYXNzOlxuICBvbjogRW1pdHRlckludGVyZmFjZVsnb24nXVxuICBvbmU6IEVtaXR0ZXJJbnRlcmZhY2VbJ29uZSddXG4gIG9mZjogRW1pdHRlckludGVyZmFjZVsnb2ZmJ11cbiAgdHJpZ2dlcjogRW1pdHRlckludGVyZmFjZVsndHJpZ2dlciddXG4gIHRyaWdnZXJXaXRoOiBFbWl0dGVySW50ZXJmYWNlWyd0cmlnZ2VyV2l0aCddXG4gIGhhc0hhbmRsZXJzOiBFbWl0dGVySW50ZXJmYWNlWydoYXNIYW5kbGVycyddXG5hZnRlciBjbGFzczpcbiAgRW1pdHRlck1peGluLm1peEludG8oVGhlQ2xhc3MpXG4qL1xudmFyIEVtaXR0ZXJNaXhpbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRW1pdHRlck1peGluLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEVtaXR0ZXJNaXhpbigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBFbWl0dGVyTWl4aW4ucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgYWRkVG9IYXNoKHRoaXMuX2hhbmRsZXJzIHx8ICh0aGlzLl9oYW5kbGVycyA9IHt9KSwgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIHJldHVybiB0aGlzOyAvLyBmb3IgY2hhaW5pbmdcbiAgICB9O1xuICAgIC8vIHRvZG86IGFkZCBjb21tZW50c1xuICAgIEVtaXR0ZXJNaXhpbi5wcm90b3R5cGUub25lID0gZnVuY3Rpb24gKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgYWRkVG9IYXNoKHRoaXMuX29uZUhhbmRsZXJzIHx8ICh0aGlzLl9vbmVIYW5kbGVycyA9IHt9KSwgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIHJldHVybiB0aGlzOyAvLyBmb3IgY2hhaW5pbmdcbiAgICB9O1xuICAgIEVtaXR0ZXJNaXhpbi5wcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKHR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuX2hhbmRsZXJzKSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tSGFzaCh0aGlzLl9oYW5kbGVycywgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX29uZUhhbmRsZXJzKSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tSGFzaCh0aGlzLl9vbmVIYW5kbGVycywgdHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGZvciBjaGFpbmluZ1xuICAgIH07XG4gICAgRW1pdHRlck1peGluLnByb3RvdHlwZS50cmlnZ2VyID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAxOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGFyZ3NbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50cmlnZ2VyV2l0aCh0eXBlLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGZvciBjaGFpbmluZ1xuICAgIH07XG4gICAgRW1pdHRlck1peGluLnByb3RvdHlwZS50cmlnZ2VyV2l0aCA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0LCBhcmdzKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYW5kbGVycykge1xuICAgICAgICAgICAgYXBwbHlBbGwodGhpcy5faGFuZGxlcnNbdHlwZV0sIGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9vbmVIYW5kbGVycykge1xuICAgICAgICAgICAgYXBwbHlBbGwodGhpcy5fb25lSGFuZGxlcnNbdHlwZV0sIGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX29uZUhhbmRsZXJzW3R5cGVdOyAvLyB3aWxsIG5ldmVyIGZpcmUgYWdhaW5cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpczsgLy8gZm9yIGNoYWluaW5nXG4gICAgfTtcbiAgICBFbWl0dGVyTWl4aW4ucHJvdG90eXBlLmhhc0hhbmRsZXJzID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9oYW5kbGVycyAmJiB0aGlzLl9oYW5kbGVyc1t0eXBlXSAmJiB0aGlzLl9oYW5kbGVyc1t0eXBlXS5sZW5ndGgpIHx8XG4gICAgICAgICAgICAodGhpcy5fb25lSGFuZGxlcnMgJiYgdGhpcy5fb25lSGFuZGxlcnNbdHlwZV0gJiYgdGhpcy5fb25lSGFuZGxlcnNbdHlwZV0ubGVuZ3RoKTtcbiAgICB9O1xuICAgIHJldHVybiBFbWl0dGVyTWl4aW47XG59KE1peGluKSk7XG5mdW5jdGlvbiBhZGRUb0hhc2goaGFzaCwgdHlwZSwgaGFuZGxlcikge1xuICAgIChoYXNoW3R5cGVdIHx8IChoYXNoW3R5cGVdID0gW10pKVxuICAgICAgICAucHVzaChoYW5kbGVyKTtcbn1cbmZ1bmN0aW9uIHJlbW92ZUZyb21IYXNoKGhhc2gsIHR5cGUsIGhhbmRsZXIpIHtcbiAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICBpZiAoaGFzaFt0eXBlXSkge1xuICAgICAgICAgICAgaGFzaFt0eXBlXSA9IGhhc2hbdHlwZV0uZmlsdGVyKGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmMgIT09IGhhbmRsZXI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZGVsZXRlIGhhc2hbdHlwZV07IC8vIHJlbW92ZSBhbGwgaGFuZGxlciBmdW5jcyBmb3IgdGhpcyB0eXBlXG4gICAgfVxufVxuXG4vKlxuUmVjb3JkcyBvZmZzZXQgaW5mb3JtYXRpb24gZm9yIGEgc2V0IG9mIGVsZW1lbnRzLCByZWxhdGl2ZSB0byBhbiBvcmlnaW4gZWxlbWVudC5cbkNhbiByZWNvcmQgdGhlIGxlZnQvcmlnaHQgT1IgdGhlIHRvcC9ib3R0b20gT1IgYm90aC5cblByb3ZpZGVzIG1ldGhvZHMgZm9yIHF1ZXJ5aW5nIHRoZSBjYWNoZSBieSBwb3NpdGlvbi5cbiovXG52YXIgUG9zaXRpb25DYWNoZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQb3NpdGlvbkNhY2hlKG9yaWdpbkVsLCBlbHMsIGlzSG9yaXpvbnRhbCwgaXNWZXJ0aWNhbCkge1xuICAgICAgICB0aGlzLm9yaWdpbkVsID0gb3JpZ2luRWw7XG4gICAgICAgIHRoaXMuZWxzID0gZWxzO1xuICAgICAgICB0aGlzLmlzSG9yaXpvbnRhbCA9IGlzSG9yaXpvbnRhbDtcbiAgICAgICAgdGhpcy5pc1ZlcnRpY2FsID0gaXNWZXJ0aWNhbDtcbiAgICB9XG4gICAgLy8gUXVlcmllcyB0aGUgZWxzIGZvciBjb29yZGluYXRlcyBhbmQgc3RvcmVzIHRoZW0uXG4gICAgLy8gQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgdXNpbmcgYW5kIG9mIHRoZSBnZXQqIG1ldGhvZHMgYmVsb3cuXG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuYnVpbGQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvcmlnaW5FbCA9IHRoaXMub3JpZ2luRWw7XG4gICAgICAgIHZhciBvcmlnaW5DbGllbnRSZWN0ID0gdGhpcy5vcmlnaW5DbGllbnRSZWN0ID1cbiAgICAgICAgICAgIG9yaWdpbkVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyByZWxhdGl2ZSB0byB2aWV3cG9ydCB0b3AtbGVmdFxuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgIHRoaXMuYnVpbGRFbEhvcml6b250YWxzKG9yaWdpbkNsaWVudFJlY3QubGVmdCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNWZXJ0aWNhbCkge1xuICAgICAgICAgICAgdGhpcy5idWlsZEVsVmVydGljYWxzKG9yaWdpbkNsaWVudFJlY3QudG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gUG9wdWxhdGVzIHRoZSBsZWZ0L3JpZ2h0IGludGVybmFsIGNvb3JkaW5hdGUgYXJyYXlzXG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuYnVpbGRFbEhvcml6b250YWxzID0gZnVuY3Rpb24gKG9yaWdpbkNsaWVudExlZnQpIHtcbiAgICAgICAgdmFyIGxlZnRzID0gW107XG4gICAgICAgIHZhciByaWdodHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZWxzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGVsID0gX2FbX2ldO1xuICAgICAgICAgICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGxlZnRzLnB1c2gocmVjdC5sZWZ0IC0gb3JpZ2luQ2xpZW50TGVmdCk7XG4gICAgICAgICAgICByaWdodHMucHVzaChyZWN0LnJpZ2h0IC0gb3JpZ2luQ2xpZW50TGVmdCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sZWZ0cyA9IGxlZnRzO1xuICAgICAgICB0aGlzLnJpZ2h0cyA9IHJpZ2h0cztcbiAgICB9O1xuICAgIC8vIFBvcHVsYXRlcyB0aGUgdG9wL2JvdHRvbSBpbnRlcm5hbCBjb29yZGluYXRlIGFycmF5c1xuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmJ1aWxkRWxWZXJ0aWNhbHMgPSBmdW5jdGlvbiAob3JpZ2luQ2xpZW50VG9wKSB7XG4gICAgICAgIHZhciB0b3BzID0gW107XG4gICAgICAgIHZhciBib3R0b21zID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmVsczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBlbCA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB0b3BzLnB1c2gocmVjdC50b3AgLSBvcmlnaW5DbGllbnRUb3ApO1xuICAgICAgICAgICAgYm90dG9tcy5wdXNoKHJlY3QuYm90dG9tIC0gb3JpZ2luQ2xpZW50VG9wKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRvcHMgPSB0b3BzO1xuICAgICAgICB0aGlzLmJvdHRvbXMgPSBib3R0b21zO1xuICAgIH07XG4gICAgLy8gR2l2ZW4gYSBsZWZ0IG9mZnNldCAoZnJvbSBkb2N1bWVudCBsZWZ0KSwgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGVsIHRoYXQgaXQgaG9yaXpvbnRhbGx5IGludGVyc2VjdHMuXG4gICAgLy8gSWYgbm8gaW50ZXJzZWN0aW9uIGlzIG1hZGUsIHJldHVybnMgdW5kZWZpbmVkLlxuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLmxlZnRUb0luZGV4ID0gZnVuY3Rpb24gKGxlZnRQb3NpdGlvbikge1xuICAgICAgICB2YXIgbGVmdHMgPSB0aGlzLmxlZnRzO1xuICAgICAgICB2YXIgcmlnaHRzID0gdGhpcy5yaWdodHM7XG4gICAgICAgIHZhciBsZW4gPSBsZWZ0cy5sZW5ndGg7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChsZWZ0UG9zaXRpb24gPj0gbGVmdHNbaV0gJiYgbGVmdFBvc2l0aW9uIDwgcmlnaHRzW2ldKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgdG9wIG9mZnNldCAoZnJvbSBkb2N1bWVudCB0b3ApLCByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZWwgdGhhdCBpdCB2ZXJ0aWNhbGx5IGludGVyc2VjdHMuXG4gICAgLy8gSWYgbm8gaW50ZXJzZWN0aW9uIGlzIG1hZGUsIHJldHVybnMgdW5kZWZpbmVkLlxuICAgIFBvc2l0aW9uQ2FjaGUucHJvdG90eXBlLnRvcFRvSW5kZXggPSBmdW5jdGlvbiAodG9wUG9zaXRpb24pIHtcbiAgICAgICAgdmFyIHRvcHMgPSB0aGlzLnRvcHM7XG4gICAgICAgIHZhciBib3R0b21zID0gdGhpcy5ib3R0b21zO1xuICAgICAgICB2YXIgbGVuID0gdG9wcy5sZW5ndGg7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0b3BQb3NpdGlvbiA+PSB0b3BzW2ldICYmIHRvcFBvc2l0aW9uIDwgYm90dG9tc1tpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgZWxlbWVudCBhdCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICBQb3NpdGlvbkNhY2hlLnByb3RvdHlwZS5nZXRXaWR0aCA9IGZ1bmN0aW9uIChsZWZ0SW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmlnaHRzW2xlZnRJbmRleF0gLSB0aGlzLmxlZnRzW2xlZnRJbmRleF07XG4gICAgfTtcbiAgICAvLyBHZXRzIHRoZSBoZWlnaHQgb2YgdGhlIGVsZW1lbnQgYXQgdGhlIGdpdmVuIGluZGV4XG4gICAgUG9zaXRpb25DYWNoZS5wcm90b3R5cGUuZ2V0SGVpZ2h0ID0gZnVuY3Rpb24gKHRvcEluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvdHRvbXNbdG9wSW5kZXhdIC0gdGhpcy50b3BzW3RvcEluZGV4XTtcbiAgICB9O1xuICAgIHJldHVybiBQb3NpdGlvbkNhY2hlO1xufSgpKTtcblxuLypcbkFuIG9iamVjdCBmb3IgZ2V0dGluZy9zZXR0aW5nIHNjcm9sbC1yZWxhdGVkIGluZm9ybWF0aW9uIGZvciBhbiBlbGVtZW50LlxuSW50ZXJuYWxseSwgdGhpcyBpcyBkb25lIHZlcnkgZGlmZmVyZW50bHkgZm9yIHdpbmRvdyB2ZXJzdXMgRE9NIGVsZW1lbnQsXG5zbyB0aGlzIG9iamVjdCBzZXJ2ZXMgYXMgYSBjb21tb24gaW50ZXJmYWNlLlxuKi9cbnZhciBTY3JvbGxDb250cm9sbGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNjcm9sbENvbnRyb2xsZXIoKSB7XG4gICAgfVxuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldE1heFNjcm9sbFRvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KCkgLSB0aGlzLmdldENsaWVudEhlaWdodCgpO1xuICAgIH07XG4gICAgU2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0TWF4U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Nyb2xsV2lkdGgoKSAtIHRoaXMuZ2V0Q2xpZW50V2lkdGgoKTtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbFZlcnRpY2FsbHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE1heFNjcm9sbFRvcCgpID4gMDtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbEhvcml6b250YWxseSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWF4U2Nyb2xsTGVmdCgpID4gMDtcbiAgICB9O1xuICAgIFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmNhblNjcm9sbFVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxUb3AoKSA+IDA7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxUb3AoKSA8IHRoaXMuZ2V0TWF4U2Nyb2xsVG9wKCk7XG4gICAgfTtcbiAgICBTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5jYW5TY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxMZWZ0KCkgPiAwO1xuICAgIH07XG4gICAgU2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuY2FuU2Nyb2xsUmlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFNjcm9sbExlZnQoKSA8IHRoaXMuZ2V0TWF4U2Nyb2xsTGVmdCgpO1xuICAgIH07XG4gICAgcmV0dXJuIFNjcm9sbENvbnRyb2xsZXI7XG59KCkpO1xudmFyIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhFbGVtZW50U2Nyb2xsQ29udHJvbGxlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbGVtZW50U2Nyb2xsQ29udHJvbGxlcihlbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbCA9IGVsO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbFRvcDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5zY3JvbGxMZWZ0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLnNldFNjcm9sbFRvcCA9IGZ1bmN0aW9uICh0b3ApIHtcbiAgICAgICAgdGhpcy5lbC5zY3JvbGxUb3AgPSB0b3A7XG4gICAgfTtcbiAgICBFbGVtZW50U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uIChsZWZ0KSB7XG4gICAgICAgIHRoaXMuZWwuc2Nyb2xsTGVmdCA9IGxlZnQ7XG4gICAgfTtcbiAgICBFbGVtZW50U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLnNjcm9sbFdpZHRoO1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuc2Nyb2xsSGVpZ2h0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldENsaWVudEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuY2xpZW50SGVpZ2h0O1xuICAgIH07XG4gICAgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldENsaWVudFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbC5jbGllbnRXaWR0aDtcbiAgICB9O1xuICAgIHJldHVybiBFbGVtZW50U2Nyb2xsQ29udHJvbGxlcjtcbn0oU2Nyb2xsQ29udHJvbGxlcikpO1xudmFyIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFdpbmRvd1Njcm9sbENvbnRyb2xsZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gV2luZG93U2Nyb2xsQ29udHJvbGxlcigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cucGFnZVlPZmZzZXQ7XG4gICAgfTtcbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnBhZ2VYT2Zmc2V0O1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuc2V0U2Nyb2xsVG9wID0gZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgd2luZG93LnNjcm9sbCh3aW5kb3cucGFnZVhPZmZzZXQsIG4pO1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uIChuKSB7XG4gICAgICAgIHdpbmRvdy5zY3JvbGwobiwgd2luZG93LnBhZ2VZT2Zmc2V0KTtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNjcm9sbFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFdpZHRoO1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0U2Nyb2xsSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICB9O1xuICAgIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIucHJvdG90eXBlLmdldENsaWVudEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgfTtcbiAgICBXaW5kb3dTY3JvbGxDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDbGllbnRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aDtcbiAgICB9O1xuICAgIHJldHVybiBXaW5kb3dTY3JvbGxDb250cm9sbGVyO1xufShTY3JvbGxDb250cm9sbGVyKSk7XG5cbi8qXG5FbWJvZGllcyBhIGRpdiB0aGF0IGhhcyBwb3RlbnRpYWwgc2Nyb2xsYmFyc1xuKi9cbnZhciBTY3JvbGxDb21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNjcm9sbENvbXBvbmVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTY3JvbGxDb21wb25lbnQob3ZlcmZsb3dYLCBvdmVyZmxvd1kpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY3JlYXRlRWxlbWVudCgnZGl2Jywge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnZmMtc2Nyb2xsZXInXG4gICAgICAgIH0pKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5vdmVyZmxvd1ggPSBvdmVyZmxvd1g7XG4gICAgICAgIF90aGlzLm92ZXJmbG93WSA9IG92ZXJmbG93WTtcbiAgICAgICAgX3RoaXMuYXBwbHlPdmVyZmxvdygpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIC8vIHNldHMgdG8gbmF0dXJhbCBoZWlnaHQsIHVubG9ja3Mgb3ZlcmZsb3dcbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldEhlaWdodCgnYXV0bycpO1xuICAgICAgICB0aGlzLmFwcGx5T3ZlcmZsb3coKTtcbiAgICB9O1xuICAgIFNjcm9sbENvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmVsKTtcbiAgICB9O1xuICAgIC8vIE92ZXJmbG93XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmFwcGx5T3ZlcmZsb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFwcGx5U3R5bGUodGhpcy5lbCwge1xuICAgICAgICAgICAgb3ZlcmZsb3dYOiB0aGlzLm92ZXJmbG93WCxcbiAgICAgICAgICAgIG92ZXJmbG93WTogdGhpcy5vdmVyZmxvd1lcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBDYXVzZXMgYW55ICdhdXRvJyBvdmVyZmxvdyB2YWx1ZXMgdG8gcmVzb2x2ZXMgdG8gJ3Njcm9sbCcgb3IgJ2hpZGRlbicuXG4gICAgLy8gVXNlZnVsIGZvciBwcmVzZXJ2aW5nIHNjcm9sbGJhciB3aWR0aHMgcmVnYXJkbGVzcyBvZiBmdXR1cmUgcmVzaXplcy5cbiAgICAvLyBDYW4gcGFzcyBpbiBzY3JvbGxiYXJXaWR0aHMgZm9yIG9wdGltaXphdGlvbi5cbiAgICBTY3JvbGxDb21wb25lbnQucHJvdG90eXBlLmxvY2tPdmVyZmxvdyA9IGZ1bmN0aW9uIChzY3JvbGxiYXJXaWR0aHMpIHtcbiAgICAgICAgdmFyIG92ZXJmbG93WCA9IHRoaXMub3ZlcmZsb3dYO1xuICAgICAgICB2YXIgb3ZlcmZsb3dZID0gdGhpcy5vdmVyZmxvd1k7XG4gICAgICAgIHNjcm9sbGJhcldpZHRocyA9IHNjcm9sbGJhcldpZHRocyB8fCB0aGlzLmdldFNjcm9sbGJhcldpZHRocygpO1xuICAgICAgICBpZiAob3ZlcmZsb3dYID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIG92ZXJmbG93WCA9IChzY3JvbGxiYXJXaWR0aHMuYm90dG9tIHx8IC8vIGhvcml6b250YWwgc2Nyb2xsYmFycz9cbiAgICAgICAgICAgICAgICB0aGlzLmNhblNjcm9sbEhvcml6b250YWxseSgpIC8vIE9SIHNjcm9sbGluZyBwYW5lIHdpdGggbWFzc2xlc3Mgc2Nyb2xsYmFycz9cbiAgICAgICAgICAgICkgPyAnc2Nyb2xsJyA6ICdoaWRkZW4nO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvdmVyZmxvd1kgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgb3ZlcmZsb3dZID0gKHNjcm9sbGJhcldpZHRocy5sZWZ0IHx8IHNjcm9sbGJhcldpZHRocy5yaWdodCB8fCAvLyBob3Jpem9udGFsIHNjcm9sbGJhcnM/XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5TY3JvbGxWZXJ0aWNhbGx5KCkgLy8gT1Igc2Nyb2xsaW5nIHBhbmUgd2l0aCBtYXNzbGVzcyBzY3JvbGxiYXJzP1xuICAgICAgICAgICAgKSA/ICdzY3JvbGwnIDogJ2hpZGRlbic7XG4gICAgICAgIH1cbiAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmVsLCB7IG92ZXJmbG93WDogb3ZlcmZsb3dYLCBvdmVyZmxvd1k6IG92ZXJmbG93WSB9KTtcbiAgICB9O1xuICAgIFNjcm9sbENvbXBvbmVudC5wcm90b3R5cGUuc2V0SGVpZ2h0ID0gZnVuY3Rpb24gKGhlaWdodCkge1xuICAgICAgICBhcHBseVN0eWxlUHJvcCh0aGlzLmVsLCAnaGVpZ2h0JywgaGVpZ2h0KTtcbiAgICB9O1xuICAgIFNjcm9sbENvbXBvbmVudC5wcm90b3R5cGUuZ2V0U2Nyb2xsYmFyV2lkdGhzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZWRnZXMgPSBjb21wdXRlRWRnZXModGhpcy5lbCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsZWZ0OiBlZGdlcy5zY3JvbGxiYXJMZWZ0LFxuICAgICAgICAgICAgcmlnaHQ6IGVkZ2VzLnNjcm9sbGJhclJpZ2h0LFxuICAgICAgICAgICAgYm90dG9tOiBlZGdlcy5zY3JvbGxiYXJCb3R0b21cbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBTY3JvbGxDb21wb25lbnQ7XG59KEVsZW1lbnRTY3JvbGxDb250cm9sbGVyKSk7XG5cbnZhciBUaGVtZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUaGVtZShjYWxlbmRhck9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhck9wdGlvbnMgPSBjYWxlbmRhck9wdGlvbnM7XG4gICAgICAgIHRoaXMucHJvY2Vzc0ljb25PdmVycmlkZSgpO1xuICAgIH1cbiAgICBUaGVtZS5wcm90b3R5cGUucHJvY2Vzc0ljb25PdmVycmlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWNvbk92ZXJyaWRlT3B0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnNldEljb25PdmVycmlkZSh0aGlzLmNhbGVuZGFyT3B0aW9uc1t0aGlzLmljb25PdmVycmlkZU9wdGlvbl0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUaGVtZS5wcm90b3R5cGUuc2V0SWNvbk92ZXJyaWRlID0gZnVuY3Rpb24gKGljb25PdmVycmlkZUhhc2gpIHtcbiAgICAgICAgdmFyIGljb25DbGFzc2VzQ29weTtcbiAgICAgICAgdmFyIGJ1dHRvbk5hbWU7XG4gICAgICAgIGlmICh0eXBlb2YgaWNvbk92ZXJyaWRlSGFzaCA9PT0gJ29iamVjdCcgJiYgaWNvbk92ZXJyaWRlSGFzaCkgeyAvLyBub24tbnVsbCBvYmplY3RcbiAgICAgICAgICAgIGljb25DbGFzc2VzQ29weSA9IF9fYXNzaWduKHt9LCB0aGlzLmljb25DbGFzc2VzKTtcbiAgICAgICAgICAgIGZvciAoYnV0dG9uTmFtZSBpbiBpY29uT3ZlcnJpZGVIYXNoKSB7XG4gICAgICAgICAgICAgICAgaWNvbkNsYXNzZXNDb3B5W2J1dHRvbk5hbWVdID0gdGhpcy5hcHBseUljb25PdmVycmlkZVByZWZpeChpY29uT3ZlcnJpZGVIYXNoW2J1dHRvbk5hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaWNvbkNsYXNzZXMgPSBpY29uQ2xhc3Nlc0NvcHk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaWNvbk92ZXJyaWRlSGFzaCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMuaWNvbkNsYXNzZXMgPSB7fTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVGhlbWUucHJvdG90eXBlLmFwcGx5SWNvbk92ZXJyaWRlUHJlZml4ID0gZnVuY3Rpb24gKGNsYXNzTmFtZSkge1xuICAgICAgICB2YXIgcHJlZml4ID0gdGhpcy5pY29uT3ZlcnJpZGVQcmVmaXg7XG4gICAgICAgIGlmIChwcmVmaXggJiYgY2xhc3NOYW1lLmluZGV4T2YocHJlZml4KSAhPT0gMCkgeyAvLyBpZiBub3QgYWxyZWFkeSBwcmVzZW50XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBwcmVmaXggKyBjbGFzc05hbWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNsYXNzTmFtZTtcbiAgICB9O1xuICAgIFRoZW1lLnByb3RvdHlwZS5nZXRDbGFzcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xhc3Nlc1trZXldIHx8ICcnO1xuICAgIH07XG4gICAgVGhlbWUucHJvdG90eXBlLmdldEljb25DbGFzcyA9IGZ1bmN0aW9uIChidXR0b25OYW1lKSB7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSB0aGlzLmljb25DbGFzc2VzW2J1dHRvbk5hbWVdO1xuICAgICAgICBpZiAoY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iYXNlSWNvbkNsYXNzICsgJyAnICsgY2xhc3NOYW1lO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuICAgIFRoZW1lLnByb3RvdHlwZS5nZXRDdXN0b21CdXR0b25JY29uQ2xhc3MgPSBmdW5jdGlvbiAoY3VzdG9tQnV0dG9uUHJvcHMpIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZTtcbiAgICAgICAgaWYgKHRoaXMuaWNvbk92ZXJyaWRlQ3VzdG9tQnV0dG9uT3B0aW9uKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgPSBjdXN0b21CdXR0b25Qcm9wc1t0aGlzLmljb25PdmVycmlkZUN1c3RvbUJ1dHRvbk9wdGlvbl07XG4gICAgICAgICAgICBpZiAoY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmFzZUljb25DbGFzcyArICcgJyArIHRoaXMuYXBwbHlJY29uT3ZlcnJpZGVQcmVmaXgoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfTtcbiAgICByZXR1cm4gVGhlbWU7XG59KCkpO1xuVGhlbWUucHJvdG90eXBlLmNsYXNzZXMgPSB7fTtcblRoZW1lLnByb3RvdHlwZS5pY29uQ2xhc3NlcyA9IHt9O1xuVGhlbWUucHJvdG90eXBlLmJhc2VJY29uQ2xhc3MgPSAnJztcblRoZW1lLnByb3RvdHlwZS5pY29uT3ZlcnJpZGVQcmVmaXggPSAnJztcblxudmFyIGd1aWQgPSAwO1xudmFyIENvbXBvbmVudENvbnRleHQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29tcG9uZW50Q29udGV4dChjYWxlbmRhciwgdGhlbWUsIGRhdGVFbnYsIG9wdGlvbnMsIHZpZXcpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLnRoZW1lID0gdGhlbWU7XG4gICAgICAgIHRoaXMuZGF0ZUVudiA9IGRhdGVFbnY7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIHRoaXMudmlldyA9IHZpZXc7XG4gICAgICAgIHRoaXMuaXNSdGwgPSBvcHRpb25zLmRpciA9PT0gJ3J0bCc7XG4gICAgICAgIHRoaXMuZXZlbnRPcmRlclNwZWNzID0gcGFyc2VGaWVsZFNwZWNzKG9wdGlvbnMuZXZlbnRPcmRlcik7XG4gICAgICAgIHRoaXMubmV4dERheVRocmVzaG9sZCA9IGNyZWF0ZUR1cmF0aW9uKG9wdGlvbnMubmV4dERheVRocmVzaG9sZCk7XG4gICAgfVxuICAgIENvbXBvbmVudENvbnRleHQucHJvdG90eXBlLmV4dGVuZCA9IGZ1bmN0aW9uIChvcHRpb25zLCB2aWV3KSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29tcG9uZW50Q29udGV4dCh0aGlzLmNhbGVuZGFyLCB0aGlzLnRoZW1lLCB0aGlzLmRhdGVFbnYsIG9wdGlvbnMgfHwgdGhpcy5vcHRpb25zLCB2aWV3IHx8IHRoaXMudmlldyk7XG4gICAgfTtcbiAgICByZXR1cm4gQ29tcG9uZW50Q29udGV4dDtcbn0oKSk7XG52YXIgQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgICAgICAgdGhpcy5ldmVyUmVuZGVyZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy51aWQgPSBTdHJpbmcoZ3VpZCsrKTtcbiAgICB9XG4gICAgQ29tcG9uZW50LmFkZEVxdWFsaXR5RnVuY3MgPSBmdW5jdGlvbiAobmV3RnVuY3MpIHtcbiAgICAgICAgdGhpcy5wcm90b3R5cGUuZXF1YWxpdHlGdW5jcyA9IF9fYXNzaWduKHt9LCB0aGlzLnByb3RvdHlwZS5lcXVhbGl0eUZ1bmNzLCBuZXdGdW5jcyk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnJlY2VpdmVQcm9wcyA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgICAgICB0aGlzLnJlY2VpdmVDb250ZXh0KGNvbnRleHQpO1xuICAgICAgICB2YXIgX2EgPSByZWN5Y2xlUHJvcHModGhpcy5wcm9wcyB8fCB7fSwgcHJvcHMsIHRoaXMuZXF1YWxpdHlGdW5jcyksIGFueUNoYW5nZXMgPSBfYS5hbnlDaGFuZ2VzLCBjb21ib1Byb3BzID0gX2EuY29tYm9Qcm9wcztcbiAgICAgICAgdGhpcy5wcm9wcyA9IGNvbWJvUHJvcHM7XG4gICAgICAgIGlmIChhbnlDaGFuZ2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVyUmVuZGVyZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJlZm9yZVVwZGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZW5kZXIoY29tYm9Qcm9wcywgY29udGV4dCk7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVyUmVuZGVyZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFmdGVyVXBkYXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmVyUmVuZGVyZWQgPSB0cnVlO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5yZWNlaXZlQ29udGV4dCA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgIHZhciBvbGRDb250ZXh0ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICBpZiAoIW9sZENvbnRleHQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyc3RDb250ZXh0KGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5maXJzdENvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5iZWZvcmVVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmFmdGVyVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgLy8gYWZ0ZXIgZGVzdHJveSBpcyBjYWxsZWQsIHRoaXMgY29tcG9uZW50IHdvbid0IGV2ZXIgYmUgdXNlZCBhZ2FpblxuICAgIENvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIHJldHVybiBDb21wb25lbnQ7XG59KCkpO1xuQ29tcG9uZW50LnByb3RvdHlwZS5lcXVhbGl0eUZ1bmNzID0ge307XG4vKlxuUmV1c2VzIG9sZCB2YWx1ZXMgd2hlbiBlcXVhbC4gSWYgYW55dGhpbmcgaXMgdW5lcXVhbCwgcmV0dXJucyBuZXdQcm9wcyBhcy1pcy5cbkdyZWF0IGZvciBQdXJlQ29tcG9uZW50LCBidXQgd29uJ3QgYmUgZmVhc2libGUgd2l0aCBSZWFjdCwgc28ganVzdCBlbGltaW5hdGUgYW5kIHVzZSBSZWFjdCdzIERPTSBkaWZmaW5nLlxuKi9cbmZ1bmN0aW9uIHJlY3ljbGVQcm9wcyhvbGRQcm9wcywgbmV3UHJvcHMsIGVxdWFsaXR5RnVuY3MpIHtcbiAgICB2YXIgY29tYm9Qcm9wcyA9IHt9OyAvLyBzb21lIG9sZCwgc29tZSBuZXdcbiAgICB2YXIgYW55Q2hhbmdlcyA9IGZhbHNlO1xuICAgIGZvciAodmFyIGtleSBpbiBuZXdQcm9wcykge1xuICAgICAgICBpZiAoa2V5IGluIG9sZFByb3BzICYmIChvbGRQcm9wc1trZXldID09PSBuZXdQcm9wc1trZXldIHx8XG4gICAgICAgICAgICAoZXF1YWxpdHlGdW5jc1trZXldICYmIGVxdWFsaXR5RnVuY3Nba2V5XShvbGRQcm9wc1trZXldLCBuZXdQcm9wc1trZXldKSkpKSB7XG4gICAgICAgICAgICAvLyBlcXVhbCB0byBvbGQ/IHVzZSBvbGQgcHJvcFxuICAgICAgICAgICAgY29tYm9Qcm9wc1trZXldID0gb2xkUHJvcHNba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbWJvUHJvcHNba2V5XSA9IG5ld1Byb3BzW2tleV07XG4gICAgICAgICAgICBhbnlDaGFuZ2VzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBrZXkgaW4gb2xkUHJvcHMpIHtcbiAgICAgICAgaWYgKCEoa2V5IGluIG5ld1Byb3BzKSkge1xuICAgICAgICAgICAgYW55Q2hhbmdlcyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBhbnlDaGFuZ2VzOiBhbnlDaGFuZ2VzLCBjb21ib1Byb3BzOiBjb21ib1Byb3BzIH07XG59XG5cbi8qXG5QVVJQT1NFUzpcbi0gaG9vayB1cCB0byBmZywgZmlsbCwgYW5kIG1pcnJvciByZW5kZXJlcnNcbi0gaW50ZXJmYWNlIGZvciBkcmFnZ2luZyBhbmQgaGl0c1xuKi9cbnZhciBEYXRlQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXRlQ29tcG9uZW50LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERhdGVDb21wb25lbnQoZWwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZWwgPSBlbDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmVsKTtcbiAgICB9O1xuICAgIC8vIEhpdCBTeXN0ZW1cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmJ1aWxkUG9zaXRpb25DYWNoZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5xdWVyeUhpdCA9IGZ1bmN0aW9uIChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wLCBlbFdpZHRoLCBlbEhlaWdodCkge1xuICAgICAgICByZXR1cm4gbnVsbDsgLy8gdGhpcyBzaG91bGQgYmUgYWJzdHJhY3RcbiAgICB9O1xuICAgIC8vIFZhbGlkYXRpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzSW50ZXJhY3Rpb25WYWxpZCA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbikge1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzLmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBkYXRlUHJvZmlsZSA9IHRoaXMucHJvcHMuZGF0ZVByb2ZpbGU7IC8vIEhBQ0tcbiAgICAgICAgdmFyIGluc3RhbmNlcyA9IGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMuaW5zdGFuY2VzO1xuICAgICAgICBpZiAoZGF0ZVByb2ZpbGUpIHsgLy8gSEFDSyBmb3IgRGF5VGlsZVxuICAgICAgICAgICAgZm9yICh2YXIgaW5zdGFuY2VJZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXJhbmdlQ29udGFpbnNSYW5nZShkYXRlUHJvZmlsZS52YWxpZFJhbmdlLCBpbnN0YW5jZXNbaW5zdGFuY2VJZF0ucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbiwgY2FsZW5kYXIpO1xuICAgIH07XG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuaXNEYXRlU2VsZWN0aW9uVmFsaWQgPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXMuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgdmFyIGRhdGVQcm9maWxlID0gdGhpcy5wcm9wcy5kYXRlUHJvZmlsZTsgLy8gSEFDS1xuICAgICAgICBpZiAoZGF0ZVByb2ZpbGUgJiYgLy8gSEFDSyBmb3IgRGF5VGlsZVxuICAgICAgICAgICAgIXJhbmdlQ29udGFpbnNSYW5nZShkYXRlUHJvZmlsZS52YWxpZFJhbmdlLCBzZWxlY3Rpb24ucmFuZ2UpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzRGF0ZVNlbGVjdGlvblZhbGlkKHNlbGVjdGlvbiwgY2FsZW5kYXIpO1xuICAgIH07XG4gICAgLy8gUG9pbnRlciBJbnRlcmFjdGlvbiBVdGlsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuaXNWYWxpZFNlZ0Rvd25FbCA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gIXRoaXMucHJvcHMuZXZlbnREcmFnICYmIC8vIEhBQ0tcbiAgICAgICAgICAgICF0aGlzLnByb3BzLmV2ZW50UmVzaXplICYmIC8vIEhBQ0tcbiAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1taXJyb3InKSAmJlxuICAgICAgICAgICAgKHRoaXMuaXNQb3BvdmVyKCkgfHwgIXRoaXMuaXNJblBvcG92ZXIoZWwpKTtcbiAgICAgICAgLy8gXmFib3ZlIGxpbmUgZW5zdXJlcyB3ZSBkb24ndCBkZXRlY3QgYSBzZWcgaW50ZXJhY3Rpb24gd2l0aGluIGEgbmVzdGVkIGNvbXBvbmVudC5cbiAgICAgICAgLy8gaXQncyBhIEhBQ0sgYmVjYXVzZSBpdCBvbmx5IHN1cHBvcnRzIGEgcG9wb3ZlciBhcyB0aGUgbmVzdGVkIGNvbXBvbmVudC5cbiAgICB9O1xuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzVmFsaWREYXRlRG93bkVsID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBzZWdFbCA9IGVsZW1lbnRDbG9zZXN0KGVsLCB0aGlzLmZnU2VnU2VsZWN0b3IpO1xuICAgICAgICByZXR1cm4gKCFzZWdFbCB8fCBzZWdFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLW1pcnJvcicpKSAmJlxuICAgICAgICAgICAgIWVsZW1lbnRDbG9zZXN0KGVsLCAnLmZjLW1vcmUnKSAmJiAvLyBhIFwibW9yZS4uXCIgbGlua1xuICAgICAgICAgICAgIWVsZW1lbnRDbG9zZXN0KGVsLCAnYVtkYXRhLWdvdG9dJykgJiYgLy8gYSBjbGlja2FibGUgbmF2IGxpbmtcbiAgICAgICAgICAgICF0aGlzLmlzSW5Qb3BvdmVyKGVsKTtcbiAgICB9O1xuICAgIERhdGVDb21wb25lbnQucHJvdG90eXBlLmlzUG9wb3ZlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYy1wb3BvdmVyJyk7XG4gICAgfTtcbiAgICBEYXRlQ29tcG9uZW50LnByb3RvdHlwZS5pc0luUG9wb3ZlciA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gQm9vbGVhbihlbGVtZW50Q2xvc2VzdChlbCwgJy5mYy1wb3BvdmVyJykpO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVDb21wb25lbnQ7XG59KENvbXBvbmVudCkpO1xuRGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuZmdTZWdTZWxlY3RvciA9ICcuZmMtZXZlbnQtY29udGFpbmVyID4gKic7XG5EYXRlQ29tcG9uZW50LnByb3RvdHlwZS5iZ1NlZ1NlbGVjdG9yID0gJy5mYy1iZ2V2ZW50Om5vdCguZmMtbm9uYnVzaW5lc3MpJztcblxudmFyIHVpZCQxID0gMDtcbmZ1bmN0aW9uIGNyZWF0ZVBsdWdpbihpbnB1dCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGlkOiBTdHJpbmcodWlkJDErKyksXG4gICAgICAgIGRlcHM6IGlucHV0LmRlcHMgfHwgW10sXG4gICAgICAgIHJlZHVjZXJzOiBpbnB1dC5yZWR1Y2VycyB8fCBbXSxcbiAgICAgICAgZXZlbnREZWZQYXJzZXJzOiBpbnB1dC5ldmVudERlZlBhcnNlcnMgfHwgW10sXG4gICAgICAgIGlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzOiBpbnB1dC5pc0RyYWdnYWJsZVRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnM6IGlucHV0LmV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzIHx8IFtdLFxuICAgICAgICBldmVudERlZk11dGF0aW9uQXBwbGllcnM6IGlucHV0LmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycyB8fCBbXSxcbiAgICAgICAgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyczogaW5wdXQuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgZGF0ZVBvaW50VHJhbnNmb3JtczogaW5wdXQuZGF0ZVBvaW50VHJhbnNmb3JtcyB8fCBbXSxcbiAgICAgICAgZGF0ZVNwYW5UcmFuc2Zvcm1zOiBpbnB1dC5kYXRlU3BhblRyYW5zZm9ybXMgfHwgW10sXG4gICAgICAgIHZpZXdzOiBpbnB1dC52aWV3cyB8fCB7fSxcbiAgICAgICAgdmlld1Byb3BzVHJhbnNmb3JtZXJzOiBpbnB1dC52aWV3UHJvcHNUcmFuc2Zvcm1lcnMgfHwgW10sXG4gICAgICAgIGlzUHJvcHNWYWxpZDogaW5wdXQuaXNQcm9wc1ZhbGlkIHx8IG51bGwsXG4gICAgICAgIGV4dGVybmFsRGVmVHJhbnNmb3JtczogaW5wdXQuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zIHx8IFtdLFxuICAgICAgICBldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zOiBpbnB1dC5ldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zIHx8IFtdLFxuICAgICAgICB2aWV3Q29udGFpbmVyTW9kaWZpZXJzOiBpbnB1dC52aWV3Q29udGFpbmVyTW9kaWZpZXJzIHx8IFtdLFxuICAgICAgICBldmVudERyb3BUcmFuc2Zvcm1lcnM6IGlucHV0LmV2ZW50RHJvcFRyYW5zZm9ybWVycyB8fCBbXSxcbiAgICAgICAgY29tcG9uZW50SW50ZXJhY3Rpb25zOiBpbnB1dC5jb21wb25lbnRJbnRlcmFjdGlvbnMgfHwgW10sXG4gICAgICAgIGNhbGVuZGFySW50ZXJhY3Rpb25zOiBpbnB1dC5jYWxlbmRhckludGVyYWN0aW9ucyB8fCBbXSxcbiAgICAgICAgdGhlbWVDbGFzc2VzOiBpbnB1dC50aGVtZUNsYXNzZXMgfHwge30sXG4gICAgICAgIGV2ZW50U291cmNlRGVmczogaW5wdXQuZXZlbnRTb3VyY2VEZWZzIHx8IFtdLFxuICAgICAgICBjbWRGb3JtYXR0ZXI6IGlucHV0LmNtZEZvcm1hdHRlcixcbiAgICAgICAgcmVjdXJyaW5nVHlwZXM6IGlucHV0LnJlY3VycmluZ1R5cGVzIHx8IFtdLFxuICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IGlucHV0Lm5hbWVkVGltZVpvbmVkSW1wbCxcbiAgICAgICAgZGVmYXVsdFZpZXc6IGlucHV0LmRlZmF1bHRWaWV3IHx8ICcnLFxuICAgICAgICBlbGVtZW50RHJhZ2dpbmdJbXBsOiBpbnB1dC5lbGVtZW50RHJhZ2dpbmdJbXBsLFxuICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczogaW5wdXQub3B0aW9uQ2hhbmdlSGFuZGxlcnMgfHwge31cbiAgICB9O1xufVxudmFyIFBsdWdpblN5c3RlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQbHVnaW5TeXN0ZW0oKSB7XG4gICAgICAgIHRoaXMuaG9va3MgPSB7XG4gICAgICAgICAgICByZWR1Y2VyczogW10sXG4gICAgICAgICAgICBldmVudERlZlBhcnNlcnM6IFtdLFxuICAgICAgICAgICAgaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREZWZNdXRhdGlvbkFwcGxpZXJzOiBbXSxcbiAgICAgICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IFtdLFxuICAgICAgICAgICAgZGF0ZVBvaW50VHJhbnNmb3JtczogW10sXG4gICAgICAgICAgICBkYXRlU3BhblRyYW5zZm9ybXM6IFtdLFxuICAgICAgICAgICAgdmlld3M6IHt9LFxuICAgICAgICAgICAgdmlld1Byb3BzVHJhbnNmb3JtZXJzOiBbXSxcbiAgICAgICAgICAgIGlzUHJvcHNWYWxpZDogbnVsbCxcbiAgICAgICAgICAgIGV4dGVybmFsRGVmVHJhbnNmb3JtczogW10sXG4gICAgICAgICAgICBldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zOiBbXSxcbiAgICAgICAgICAgIHZpZXdDb250YWluZXJNb2RpZmllcnM6IFtdLFxuICAgICAgICAgICAgZXZlbnREcm9wVHJhbnNmb3JtZXJzOiBbXSxcbiAgICAgICAgICAgIGNvbXBvbmVudEludGVyYWN0aW9uczogW10sXG4gICAgICAgICAgICBjYWxlbmRhckludGVyYWN0aW9uczogW10sXG4gICAgICAgICAgICB0aGVtZUNsYXNzZXM6IHt9LFxuICAgICAgICAgICAgZXZlbnRTb3VyY2VEZWZzOiBbXSxcbiAgICAgICAgICAgIGNtZEZvcm1hdHRlcjogbnVsbCxcbiAgICAgICAgICAgIHJlY3VycmluZ1R5cGVzOiBbXSxcbiAgICAgICAgICAgIG5hbWVkVGltZVpvbmVkSW1wbDogbnVsbCxcbiAgICAgICAgICAgIGRlZmF1bHRWaWV3OiAnJyxcbiAgICAgICAgICAgIGVsZW1lbnREcmFnZ2luZ0ltcGw6IG51bGwsXG4gICAgICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczoge31cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRlZEhhc2ggPSB7fTtcbiAgICB9XG4gICAgUGx1Z2luU3lzdGVtLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAocGx1Z2luKSB7XG4gICAgICAgIGlmICghdGhpcy5hZGRlZEhhc2hbcGx1Z2luLmlkXSkge1xuICAgICAgICAgICAgdGhpcy5hZGRlZEhhc2hbcGx1Z2luLmlkXSA9IHRydWU7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gcGx1Z2luLmRlcHM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRlcCA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZChkZXApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5ob29rcyA9IGNvbWJpbmVIb29rcyh0aGlzLmhvb2tzLCBwbHVnaW4pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gUGx1Z2luU3lzdGVtO1xufSgpKTtcbmZ1bmN0aW9uIGNvbWJpbmVIb29rcyhob29rczAsIGhvb2tzMSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHJlZHVjZXJzOiBob29rczAucmVkdWNlcnMuY29uY2F0KGhvb2tzMS5yZWR1Y2VycyksXG4gICAgICAgIGV2ZW50RGVmUGFyc2VyczogaG9va3MwLmV2ZW50RGVmUGFyc2Vycy5jb25jYXQoaG9va3MxLmV2ZW50RGVmUGFyc2VycyksXG4gICAgICAgIGlzRHJhZ2dhYmxlVHJhbnNmb3JtZXJzOiBob29rczAuaXNEcmFnZ2FibGVUcmFuc2Zvcm1lcnMuY29uY2F0KGhvb2tzMS5pc0RyYWdnYWJsZVRyYW5zZm9ybWVycyksXG4gICAgICAgIGV2ZW50RHJhZ011dGF0aW9uTWFzc2FnZXJzOiBob29rczAuZXZlbnREcmFnTXV0YXRpb25NYXNzYWdlcnMuY29uY2F0KGhvb2tzMS5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2VycyksXG4gICAgICAgIGV2ZW50RGVmTXV0YXRpb25BcHBsaWVyczogaG9va3MwLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycy5jb25jYXQoaG9va3MxLmV2ZW50RGVmTXV0YXRpb25BcHBsaWVycyksXG4gICAgICAgIGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnM6IGhvb2tzMC5kYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEuZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycyksXG4gICAgICAgIGRhdGVQb2ludFRyYW5zZm9ybXM6IGhvb2tzMC5kYXRlUG9pbnRUcmFuc2Zvcm1zLmNvbmNhdChob29rczEuZGF0ZVBvaW50VHJhbnNmb3JtcyksXG4gICAgICAgIGRhdGVTcGFuVHJhbnNmb3JtczogaG9va3MwLmRhdGVTcGFuVHJhbnNmb3Jtcy5jb25jYXQoaG9va3MxLmRhdGVTcGFuVHJhbnNmb3JtcyksXG4gICAgICAgIHZpZXdzOiBfX2Fzc2lnbih7fSwgaG9va3MwLnZpZXdzLCBob29rczEudmlld3MpLFxuICAgICAgICB2aWV3UHJvcHNUcmFuc2Zvcm1lcnM6IGhvb2tzMC52aWV3UHJvcHNUcmFuc2Zvcm1lcnMuY29uY2F0KGhvb2tzMS52aWV3UHJvcHNUcmFuc2Zvcm1lcnMpLFxuICAgICAgICBpc1Byb3BzVmFsaWQ6IGhvb2tzMS5pc1Byb3BzVmFsaWQgfHwgaG9va3MwLmlzUHJvcHNWYWxpZCxcbiAgICAgICAgZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zOiBob29rczAuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zLmNvbmNhdChob29rczEuZXh0ZXJuYWxEZWZUcmFuc2Zvcm1zKSxcbiAgICAgICAgZXZlbnRSZXNpemVKb2luVHJhbnNmb3JtczogaG9va3MwLmV2ZW50UmVzaXplSm9pblRyYW5zZm9ybXMuY29uY2F0KGhvb2tzMS5ldmVudFJlc2l6ZUpvaW5UcmFuc2Zvcm1zKSxcbiAgICAgICAgdmlld0NvbnRhaW5lck1vZGlmaWVyczogaG9va3MwLnZpZXdDb250YWluZXJNb2RpZmllcnMuY29uY2F0KGhvb2tzMS52aWV3Q29udGFpbmVyTW9kaWZpZXJzKSxcbiAgICAgICAgZXZlbnREcm9wVHJhbnNmb3JtZXJzOiBob29rczAuZXZlbnREcm9wVHJhbnNmb3JtZXJzLmNvbmNhdChob29rczEuZXZlbnREcm9wVHJhbnNmb3JtZXJzKSxcbiAgICAgICAgY2FsZW5kYXJJbnRlcmFjdGlvbnM6IGhvb2tzMC5jYWxlbmRhckludGVyYWN0aW9ucy5jb25jYXQoaG9va3MxLmNhbGVuZGFySW50ZXJhY3Rpb25zKSxcbiAgICAgICAgY29tcG9uZW50SW50ZXJhY3Rpb25zOiBob29rczAuY29tcG9uZW50SW50ZXJhY3Rpb25zLmNvbmNhdChob29rczEuY29tcG9uZW50SW50ZXJhY3Rpb25zKSxcbiAgICAgICAgdGhlbWVDbGFzc2VzOiBfX2Fzc2lnbih7fSwgaG9va3MwLnRoZW1lQ2xhc3NlcywgaG9va3MxLnRoZW1lQ2xhc3NlcyksXG4gICAgICAgIGV2ZW50U291cmNlRGVmczogaG9va3MwLmV2ZW50U291cmNlRGVmcy5jb25jYXQoaG9va3MxLmV2ZW50U291cmNlRGVmcyksXG4gICAgICAgIGNtZEZvcm1hdHRlcjogaG9va3MxLmNtZEZvcm1hdHRlciB8fCBob29rczAuY21kRm9ybWF0dGVyLFxuICAgICAgICByZWN1cnJpbmdUeXBlczogaG9va3MwLnJlY3VycmluZ1R5cGVzLmNvbmNhdChob29rczEucmVjdXJyaW5nVHlwZXMpLFxuICAgICAgICBuYW1lZFRpbWVab25lZEltcGw6IGhvb2tzMS5uYW1lZFRpbWVab25lZEltcGwgfHwgaG9va3MwLm5hbWVkVGltZVpvbmVkSW1wbCxcbiAgICAgICAgZGVmYXVsdFZpZXc6IGhvb2tzMC5kZWZhdWx0VmlldyB8fCBob29rczEuZGVmYXVsdFZpZXcsXG4gICAgICAgIGVsZW1lbnREcmFnZ2luZ0ltcGw6IGhvb2tzMC5lbGVtZW50RHJhZ2dpbmdJbXBsIHx8IGhvb2tzMS5lbGVtZW50RHJhZ2dpbmdJbXBsLFxuICAgICAgICBvcHRpb25DaGFuZ2VIYW5kbGVyczogX19hc3NpZ24oe30sIGhvb2tzMC5vcHRpb25DaGFuZ2VIYW5kbGVycywgaG9va3MxLm9wdGlvbkNoYW5nZUhhbmRsZXJzKVxuICAgIH07XG59XG5cbnZhciBldmVudFNvdXJjZURlZiA9IHtcbiAgICBpZ25vcmVSYW5nZTogdHJ1ZSxcbiAgICBwYXJzZU1ldGE6IGZ1bmN0aW9uIChyYXcpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmF3KSkgeyAvLyBzaG9ydCBmb3JtXG4gICAgICAgICAgICByZXR1cm4gcmF3O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocmF3LmV2ZW50cykpIHtcbiAgICAgICAgICAgIHJldHVybiByYXcuZXZlbnRzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgZmV0Y2g6IGZ1bmN0aW9uIChhcmcsIHN1Y2Nlc3MpIHtcbiAgICAgICAgc3VjY2Vzcyh7XG4gICAgICAgICAgICByYXdFdmVudHM6IGFyZy5ldmVudFNvdXJjZS5tZXRhXG4gICAgICAgIH0pO1xuICAgIH1cbn07XG52YXIgQXJyYXlFdmVudFNvdXJjZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgZXZlbnRTb3VyY2VEZWZzOiBbZXZlbnRTb3VyY2VEZWZdXG59KTtcblxudmFyIGV2ZW50U291cmNlRGVmJDEgPSB7XG4gICAgcGFyc2VNZXRhOiBmdW5jdGlvbiAocmF3KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmF3ID09PSAnZnVuY3Rpb24nKSB7IC8vIHNob3J0IGZvcm1cbiAgICAgICAgICAgIHJldHVybiByYXc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHJhdy5ldmVudHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiByYXcuZXZlbnRzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgZmV0Y2g6IGZ1bmN0aW9uIChhcmcsIHN1Y2Nlc3MsIGZhaWx1cmUpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSBhcmcuY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdmFyIGZ1bmMgPSBhcmcuZXZlbnRTb3VyY2UubWV0YTtcbiAgICAgICAgdW5wcm9taXNpZnkoZnVuYy5iaW5kKG51bGwsIHtcbiAgICAgICAgICAgIHN0YXJ0OiBkYXRlRW52LnRvRGF0ZShhcmcucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kOiBkYXRlRW52LnRvRGF0ZShhcmcucmFuZ2UuZW5kKSxcbiAgICAgICAgICAgIHN0YXJ0U3RyOiBkYXRlRW52LmZvcm1hdElzbyhhcmcucmFuZ2Uuc3RhcnQpLFxuICAgICAgICAgICAgZW5kU3RyOiBkYXRlRW52LmZvcm1hdElzbyhhcmcucmFuZ2UuZW5kKSxcbiAgICAgICAgICAgIHRpbWVab25lOiBkYXRlRW52LnRpbWVab25lXG4gICAgICAgIH0pLCBmdW5jdGlvbiAocmF3RXZlbnRzKSB7XG4gICAgICAgICAgICBzdWNjZXNzKHsgcmF3RXZlbnRzOiByYXdFdmVudHMgfSk7IC8vIG5lZWRzIGFuIG9iamVjdCByZXNwb25zZVxuICAgICAgICB9LCBmYWlsdXJlIC8vIHNlbmQgZXJyb3JPYmogZGlyZWN0bHkgdG8gZmFpbHVyZSBjYWxsYmFja1xuICAgICAgICApO1xuICAgIH1cbn07XG52YXIgRnVuY0V2ZW50U291cmNlUGx1Z2luID0gY3JlYXRlUGx1Z2luKHtcbiAgICBldmVudFNvdXJjZURlZnM6IFtldmVudFNvdXJjZURlZiQxXVxufSk7XG5cbmZ1bmN0aW9uIHJlcXVlc3RKc29uKG1ldGhvZCwgdXJsLCBwYXJhbXMsIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgbWV0aG9kID0gbWV0aG9kLnRvVXBwZXJDYXNlKCk7XG4gICAgdmFyIGJvZHkgPSBudWxsO1xuICAgIGlmIChtZXRob2QgPT09ICdHRVQnKSB7XG4gICAgICAgIHVybCA9IGluamVjdFF1ZXJ5U3RyaW5nUGFyYW1zKHVybCwgcGFyYW1zKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGJvZHkgPSBlbmNvZGVQYXJhbXMocGFyYW1zKTtcbiAgICB9XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKG1ldGhvZCwgdXJsLCB0cnVlKTtcbiAgICBpZiAobWV0aG9kICE9PSAnR0VUJykge1xuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpO1xuICAgIH1cbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDQwMCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gSlNPTi5wYXJzZSh4aHIucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2socmVzLCB4aHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjaygnRmFpbHVyZSBwYXJzaW5nIEpTT04nLCB4aHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZmFpbHVyZUNhbGxiYWNrKCdSZXF1ZXN0IGZhaWxlZCcsIHhocik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmYWlsdXJlQ2FsbGJhY2soJ1JlcXVlc3QgZmFpbGVkJywgeGhyKTtcbiAgICB9O1xuICAgIHhoci5zZW5kKGJvZHkpO1xufVxuZnVuY3Rpb24gaW5qZWN0UXVlcnlTdHJpbmdQYXJhbXModXJsLCBwYXJhbXMpIHtcbiAgICByZXR1cm4gdXJsICtcbiAgICAgICAgKHVybC5pbmRleE9mKCc/JykgPT09IC0xID8gJz8nIDogJyYnKSArXG4gICAgICAgIGVuY29kZVBhcmFtcyhwYXJhbXMpO1xufVxuZnVuY3Rpb24gZW5jb2RlUGFyYW1zKHBhcmFtcykge1xuICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBwYXJhbXMpIHtcbiAgICAgICAgcGFydHMucHVzaChlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChwYXJhbXNba2V5XSkpO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHMuam9pbignJicpO1xufVxuXG52YXIgZXZlbnRTb3VyY2VEZWYkMiA9IHtcbiAgICBwYXJzZU1ldGE6IGZ1bmN0aW9uIChyYXcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7IC8vIHNob3J0IGZvcm1cbiAgICAgICAgICAgIHJhdyA9IHsgdXJsOiByYXcgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghcmF3IHx8IHR5cGVvZiByYXcgIT09ICdvYmplY3QnIHx8ICFyYXcudXJsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdXJsOiByYXcudXJsLFxuICAgICAgICAgICAgbWV0aG9kOiAocmF3Lm1ldGhvZCB8fCAnR0VUJykudG9VcHBlckNhc2UoKSxcbiAgICAgICAgICAgIGV4dHJhUGFyYW1zOiByYXcuZXh0cmFQYXJhbXMsXG4gICAgICAgICAgICBzdGFydFBhcmFtOiByYXcuc3RhcnRQYXJhbSxcbiAgICAgICAgICAgIGVuZFBhcmFtOiByYXcuZW5kUGFyYW0sXG4gICAgICAgICAgICB0aW1lWm9uZVBhcmFtOiByYXcudGltZVpvbmVQYXJhbVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgZmV0Y2g6IGZ1bmN0aW9uIChhcmcsIHN1Y2Nlc3MsIGZhaWx1cmUpIHtcbiAgICAgICAgdmFyIG1ldGEgPSBhcmcuZXZlbnRTb3VyY2UubWV0YTtcbiAgICAgICAgdmFyIHJlcXVlc3RQYXJhbXMgPSBidWlsZFJlcXVlc3RQYXJhbXMobWV0YSwgYXJnLnJhbmdlLCBhcmcuY2FsZW5kYXIpO1xuICAgICAgICByZXF1ZXN0SnNvbihtZXRhLm1ldGhvZCwgbWV0YS51cmwsIHJlcXVlc3RQYXJhbXMsIGZ1bmN0aW9uIChyYXdFdmVudHMsIHhocikge1xuICAgICAgICAgICAgc3VjY2Vzcyh7IHJhd0V2ZW50czogcmF3RXZlbnRzLCB4aHI6IHhociB9KTtcbiAgICAgICAgfSwgZnVuY3Rpb24gKGVycm9yTWVzc2FnZSwgeGhyKSB7XG4gICAgICAgICAgICBmYWlsdXJlKHsgbWVzc2FnZTogZXJyb3JNZXNzYWdlLCB4aHI6IHhociB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxufTtcbnZhciBKc29uRmVlZEV2ZW50U291cmNlUGx1Z2luID0gY3JlYXRlUGx1Z2luKHtcbiAgICBldmVudFNvdXJjZURlZnM6IFtldmVudFNvdXJjZURlZiQyXVxufSk7XG5mdW5jdGlvbiBidWlsZFJlcXVlc3RQYXJhbXMobWV0YSwgcmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRhdGVFbnYgPSBjYWxlbmRhci5kYXRlRW52O1xuICAgIHZhciBzdGFydFBhcmFtO1xuICAgIHZhciBlbmRQYXJhbTtcbiAgICB2YXIgdGltZVpvbmVQYXJhbTtcbiAgICB2YXIgY3VzdG9tUmVxdWVzdFBhcmFtcztcbiAgICB2YXIgcGFyYW1zID0ge307XG4gICAgc3RhcnRQYXJhbSA9IG1ldGEuc3RhcnRQYXJhbTtcbiAgICBpZiAoc3RhcnRQYXJhbSA9PSBudWxsKSB7XG4gICAgICAgIHN0YXJ0UGFyYW0gPSBjYWxlbmRhci5vcHQoJ3N0YXJ0UGFyYW0nKTtcbiAgICB9XG4gICAgZW5kUGFyYW0gPSBtZXRhLmVuZFBhcmFtO1xuICAgIGlmIChlbmRQYXJhbSA9PSBudWxsKSB7XG4gICAgICAgIGVuZFBhcmFtID0gY2FsZW5kYXIub3B0KCdlbmRQYXJhbScpO1xuICAgIH1cbiAgICB0aW1lWm9uZVBhcmFtID0gbWV0YS50aW1lWm9uZVBhcmFtO1xuICAgIGlmICh0aW1lWm9uZVBhcmFtID09IG51bGwpIHtcbiAgICAgICAgdGltZVpvbmVQYXJhbSA9IGNhbGVuZGFyLm9wdCgndGltZVpvbmVQYXJhbScpO1xuICAgIH1cbiAgICAvLyByZXRyaWV2ZSBhbnkgb3V0Ym91bmQgR0VUL1BPU1QgZGF0YSBmcm9tIHRoZSBvcHRpb25zXG4gICAgaWYgKHR5cGVvZiBtZXRhLmV4dHJhUGFyYW1zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIHN1cHBsaWVkIGFzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEga2V5L3ZhbHVlIG9iamVjdFxuICAgICAgICBjdXN0b21SZXF1ZXN0UGFyYW1zID0gbWV0YS5leHRyYVBhcmFtcygpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gcHJvYmFibHkgc3VwcGxpZWQgYXMgYSBzdHJhaWdodCBrZXkvdmFsdWUgb2JqZWN0XG4gICAgICAgIGN1c3RvbVJlcXVlc3RQYXJhbXMgPSBtZXRhLmV4dHJhUGFyYW1zIHx8IHt9O1xuICAgIH1cbiAgICBfX2Fzc2lnbihwYXJhbXMsIGN1c3RvbVJlcXVlc3RQYXJhbXMpO1xuICAgIHBhcmFtc1tzdGFydFBhcmFtXSA9IGRhdGVFbnYuZm9ybWF0SXNvKHJhbmdlLnN0YXJ0KTtcbiAgICBwYXJhbXNbZW5kUGFyYW1dID0gZGF0ZUVudi5mb3JtYXRJc28ocmFuZ2UuZW5kKTtcbiAgICBpZiAoZGF0ZUVudi50aW1lWm9uZSAhPT0gJ2xvY2FsJykge1xuICAgICAgICBwYXJhbXNbdGltZVpvbmVQYXJhbV0gPSBkYXRlRW52LnRpbWVab25lO1xuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xufVxuXG52YXIgcmVjdXJyaW5nID0ge1xuICAgIHBhcnNlOiBmdW5jdGlvbiAocmF3RXZlbnQsIGxlZnRvdmVyUHJvcHMsIGRhdGVFbnYpIHtcbiAgICAgICAgdmFyIGNyZWF0ZU1hcmtlciA9IGRhdGVFbnYuY3JlYXRlTWFya2VyLmJpbmQoZGF0ZUVudik7XG4gICAgICAgIHZhciBwcm9jZXNzb3JzID0ge1xuICAgICAgICAgICAgZGF5c09mV2VlazogbnVsbCxcbiAgICAgICAgICAgIHN0YXJ0VGltZTogY3JlYXRlRHVyYXRpb24sXG4gICAgICAgICAgICBlbmRUaW1lOiBjcmVhdGVEdXJhdGlvbixcbiAgICAgICAgICAgIHN0YXJ0UmVjdXI6IGNyZWF0ZU1hcmtlcixcbiAgICAgICAgICAgIGVuZFJlY3VyOiBjcmVhdGVNYXJrZXJcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMocmF3RXZlbnQsIHByb2Nlc3NvcnMsIHt9LCBsZWZ0b3ZlclByb3BzKTtcbiAgICAgICAgdmFyIGFueVZhbGlkID0gZmFsc2U7XG4gICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICBpZiAocHJvcHNbcHJvcE5hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhbnlWYWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFueVZhbGlkKSB7XG4gICAgICAgICAgICB2YXIgZHVyYXRpb24gPSBudWxsO1xuICAgICAgICAgICAgaWYgKCdkdXJhdGlvbicgaW4gbGVmdG92ZXJQcm9wcykge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24obGVmdG92ZXJQcm9wcy5kdXJhdGlvbik7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGxlZnRvdmVyUHJvcHMuZHVyYXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWR1cmF0aW9uICYmIHByb3BzLnN0YXJ0VGltZSAmJiBwcm9wcy5lbmRUaW1lKSB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb24gPSBzdWJ0cmFjdER1cmF0aW9ucyhwcm9wcy5lbmRUaW1lLCBwcm9wcy5zdGFydFRpbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhbGxEYXlHdWVzczogQm9vbGVhbighcHJvcHMuc3RhcnRUaW1lICYmICFwcm9wcy5lbmRUaW1lKSxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24sXG4gICAgICAgICAgICAgICAgdHlwZURhdGE6IHByb3BzIC8vIGRvZXNuJ3QgbmVlZCBlbmRUaW1lIGFueW1vcmUgYnV0IG9oIHdlbGxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSxcbiAgICBleHBhbmQ6IGZ1bmN0aW9uICh0eXBlRGF0YSwgZnJhbWluZ1JhbmdlLCBkYXRlRW52KSB7XG4gICAgICAgIHZhciBjbGlwcGVkRnJhbWluZ1JhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKGZyYW1pbmdSYW5nZSwgeyBzdGFydDogdHlwZURhdGEuc3RhcnRSZWN1ciwgZW5kOiB0eXBlRGF0YS5lbmRSZWN1ciB9KTtcbiAgICAgICAgaWYgKGNsaXBwZWRGcmFtaW5nUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBleHBhbmRSYW5nZXModHlwZURhdGEuZGF5c09mV2VlaywgdHlwZURhdGEuc3RhcnRUaW1lLCBjbGlwcGVkRnJhbWluZ1JhbmdlLCBkYXRlRW52KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgIH1cbn07XG52YXIgU2ltcGxlUmVjdXJyZW5jZVBsdWdpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgcmVjdXJyaW5nVHlwZXM6IFtyZWN1cnJpbmddXG59KTtcbmZ1bmN0aW9uIGV4cGFuZFJhbmdlcyhkYXlzT2ZXZWVrLCBzdGFydFRpbWUsIGZyYW1pbmdSYW5nZSwgZGF0ZUVudikge1xuICAgIHZhciBkb3dIYXNoID0gZGF5c09mV2VlayA/IGFycmF5VG9IYXNoKGRheXNPZldlZWspIDogbnVsbDtcbiAgICB2YXIgZGF5TWFya2VyID0gc3RhcnRPZkRheShmcmFtaW5nUmFuZ2Uuc3RhcnQpO1xuICAgIHZhciBlbmRNYXJrZXIgPSBmcmFtaW5nUmFuZ2UuZW5kO1xuICAgIHZhciBpbnN0YW5jZVN0YXJ0cyA9IFtdO1xuICAgIHdoaWxlIChkYXlNYXJrZXIgPCBlbmRNYXJrZXIpIHtcbiAgICAgICAgdmFyIGluc3RhbmNlU3RhcnQgXG4gICAgICAgIC8vIGlmIGV2ZXJ5ZGF5LCBvciB0aGlzIHBhcnRpY3VsYXIgZGF5LW9mLXdlZWtcbiAgICAgICAgPSB2b2lkIDA7XG4gICAgICAgIC8vIGlmIGV2ZXJ5ZGF5LCBvciB0aGlzIHBhcnRpY3VsYXIgZGF5LW9mLXdlZWtcbiAgICAgICAgaWYgKCFkb3dIYXNoIHx8IGRvd0hhc2hbZGF5TWFya2VyLmdldFVUQ0RheSgpXSkge1xuICAgICAgICAgICAgaWYgKHN0YXJ0VGltZSkge1xuICAgICAgICAgICAgICAgIGluc3RhbmNlU3RhcnQgPSBkYXRlRW52LmFkZChkYXlNYXJrZXIsIHN0YXJ0VGltZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnN0YW5jZVN0YXJ0ID0gZGF5TWFya2VyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5zdGFuY2VTdGFydHMucHVzaChpbnN0YW5jZVN0YXJ0KTtcbiAgICAgICAgfVxuICAgICAgICBkYXlNYXJrZXIgPSBhZGREYXlzKGRheU1hcmtlciwgMSk7XG4gICAgfVxuICAgIHJldHVybiBpbnN0YW5jZVN0YXJ0cztcbn1cblxudmFyIERlZmF1bHRPcHRpb25DaGFuZ2VIYW5kbGVycyA9IGNyZWF0ZVBsdWdpbih7XG4gICAgb3B0aW9uQ2hhbmdlSGFuZGxlcnM6IHtcbiAgICAgICAgZXZlbnRzOiBmdW5jdGlvbiAoZXZlbnRzLCBjYWxlbmRhciwgZGVlcEVxdWFsKSB7XG4gICAgICAgICAgICBoYW5kbGVFdmVudFNvdXJjZXMoW2V2ZW50c10sIGNhbGVuZGFyLCBkZWVwRXF1YWwpO1xuICAgICAgICB9LFxuICAgICAgICBldmVudFNvdXJjZXM6IGhhbmRsZUV2ZW50U291cmNlcyxcbiAgICAgICAgcGx1Z2luczogaGFuZGxlUGx1Z2luc1xuICAgIH1cbn0pO1xuZnVuY3Rpb24gaGFuZGxlRXZlbnRTb3VyY2VzKGlucHV0cywgY2FsZW5kYXIsIGRlZXBFcXVhbCkge1xuICAgIHZhciB1bmZvdW5kU291cmNlcyA9IGhhc2hWYWx1ZXNUb0FycmF5KGNhbGVuZGFyLnN0YXRlLmV2ZW50U291cmNlcyk7XG4gICAgdmFyIG5ld0lucHV0cyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMCwgaW5wdXRzXzEgPSBpbnB1dHM7IF9pIDwgaW5wdXRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBpbnB1dCA9IGlucHV0c18xW19pXTtcbiAgICAgICAgdmFyIGlucHV0Rm91bmQgPSBmYWxzZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1bmZvdW5kU291cmNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGRlZXBFcXVhbCh1bmZvdW5kU291cmNlc1tpXS5fcmF3LCBpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICB1bmZvdW5kU291cmNlcy5zcGxpY2UoaSwgMSk7IC8vIGRlbGV0ZVxuICAgICAgICAgICAgICAgIGlucHV0Rm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghaW5wdXRGb3VuZCkge1xuICAgICAgICAgICAgbmV3SW5wdXRzLnB1c2goaW5wdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAodmFyIF9hID0gMCwgdW5mb3VuZFNvdXJjZXNfMSA9IHVuZm91bmRTb3VyY2VzOyBfYSA8IHVuZm91bmRTb3VyY2VzXzEubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgIHZhciB1bmZvdW5kU291cmNlID0gdW5mb3VuZFNvdXJjZXNfMVtfYV07XG4gICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRU1PVkVfRVZFTlRfU09VUkNFJyxcbiAgICAgICAgICAgIHNvdXJjZUlkOiB1bmZvdW5kU291cmNlLnNvdXJjZUlkXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBmb3IgKHZhciBfYiA9IDAsIG5ld0lucHV0c18xID0gbmV3SW5wdXRzOyBfYiA8IG5ld0lucHV0c18xLmxlbmd0aDsgX2IrKykge1xuICAgICAgICB2YXIgbmV3SW5wdXQgPSBuZXdJbnB1dHNfMVtfYl07XG4gICAgICAgIGNhbGVuZGFyLmFkZEV2ZW50U291cmNlKG5ld0lucHV0KTtcbiAgICB9XG59XG4vLyBzaG9ydGNvbWluZzogd29uJ3QgcmVtb3ZlIHBsdWdpbnNcbmZ1bmN0aW9uIGhhbmRsZVBsdWdpbnMoaW5wdXRzLCBjYWxlbmRhcikge1xuICAgIGNhbGVuZGFyLmFkZFBsdWdpbklucHV0cyhpbnB1dHMpOyAvLyB3aWxsIGdyYWNlZnVsbHkgaGFuZGxlIGR1cGxpY2F0ZXNcbn1cblxudmFyIGNvbmZpZyA9IHt9OyAvLyBUT0RPOiBtYWtlIHRoZXNlIG9wdGlvbnNcbnZhciBnbG9iYWxEZWZhdWx0cyA9IHtcbiAgICBkZWZhdWx0UmFuZ2VTZXBhcmF0b3I6ICcgLSAnLFxuICAgIHRpdGxlUmFuZ2VTZXBhcmF0b3I6ICcgXFx1MjAxMyAnLFxuICAgIGRlZmF1bHRUaW1lZEV2ZW50RHVyYXRpb246ICcwMTowMDowMCcsXG4gICAgZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb246IHsgZGF5OiAxIH0sXG4gICAgZm9yY2VFdmVudER1cmF0aW9uOiBmYWxzZSxcbiAgICBuZXh0RGF5VGhyZXNob2xkOiAnMDA6MDA6MDAnLFxuICAgIC8vIGRpc3BsYXlcbiAgICBjb2x1bW5IZWFkZXI6IHRydWUsXG4gICAgZGVmYXVsdFZpZXc6ICcnLFxuICAgIGFzcGVjdFJhdGlvOiAxLjM1LFxuICAgIGhlYWRlcjoge1xuICAgICAgICBsZWZ0OiAndGl0bGUnLFxuICAgICAgICBjZW50ZXI6ICcnLFxuICAgICAgICByaWdodDogJ3RvZGF5IHByZXYsbmV4dCdcbiAgICB9LFxuICAgIHdlZWtlbmRzOiB0cnVlLFxuICAgIHdlZWtOdW1iZXJzOiBmYWxzZSxcbiAgICB3ZWVrTnVtYmVyQ2FsY3VsYXRpb246ICdsb2NhbCcsXG4gICAgZWRpdGFibGU6IGZhbHNlLFxuICAgIC8vIG5vd0luZGljYXRvcjogZmFsc2UsXG4gICAgc2Nyb2xsVGltZTogJzA2OjAwOjAwJyxcbiAgICBtaW5UaW1lOiAnMDA6MDA6MDAnLFxuICAgIG1heFRpbWU6ICcyNDowMDowMCcsXG4gICAgc2hvd05vbkN1cnJlbnREYXRlczogdHJ1ZSxcbiAgICAvLyBldmVudCBhamF4XG4gICAgbGF6eUZldGNoaW5nOiB0cnVlLFxuICAgIHN0YXJ0UGFyYW06ICdzdGFydCcsXG4gICAgZW5kUGFyYW06ICdlbmQnLFxuICAgIHRpbWVab25lUGFyYW06ICd0aW1lWm9uZScsXG4gICAgdGltZVpvbmU6ICdsb2NhbCcsXG4gICAgLy8gYWxsRGF5RGVmYXVsdDogdW5kZWZpbmVkLFxuICAgIC8vIGxvY2FsZVxuICAgIGxvY2FsZXM6IFtdLFxuICAgIGxvY2FsZTogJycsXG4gICAgLy8gZGlyOiB3aWxsIGdldCB0aGlzIGZyb20gdGhlIGRlZmF1bHQgbG9jYWxlXG4gICAgLy8gYnV0dG9uSWNvbnM6IG51bGwsXG4gICAgLy8gYWxsb3dzIHNldHRpbmcgYSBtaW4taGVpZ2h0IHRvIHRoZSBldmVudCBzZWdtZW50IHRvIHByZXZlbnQgc2hvcnQgZXZlbnRzIG92ZXJsYXBwaW5nIGVhY2ggb3RoZXJcbiAgICB0aW1lR3JpZEV2ZW50TWluSGVpZ2h0OiAwLFxuICAgIHRoZW1lU3lzdGVtOiAnc3RhbmRhcmQnLFxuICAgIC8vIGV2ZW50UmVzaXphYmxlRnJvbVN0YXJ0OiBmYWxzZSxcbiAgICBkcmFnUmV2ZXJ0RHVyYXRpb246IDUwMCxcbiAgICBkcmFnU2Nyb2xsOiB0cnVlLFxuICAgIGFsbERheU1haW50YWluRHVyYXRpb246IGZhbHNlLFxuICAgIC8vIHNlbGVjdGFibGU6IGZhbHNlLFxuICAgIHVuc2VsZWN0QXV0bzogdHJ1ZSxcbiAgICAvLyBzZWxlY3RNaW5EaXN0YW5jZTogMCxcbiAgICBkcm9wQWNjZXB0OiAnKicsXG4gICAgZXZlbnRPcmRlcjogJ3N0YXJ0LC1kdXJhdGlvbixhbGxEYXksdGl0bGUnLFxuICAgIC8vIF4gaWYgc3RhcnQgdGllLCBsb25nZXIgZXZlbnRzIGdvIGJlZm9yZSBzaG9ydGVyLiBmaW5hbCB0aWUtYnJlYWtlciBpcyB0aXRsZSB0ZXh0XG4gICAgLy8gcmVyZW5kZXJEZWxheTogbnVsbCxcbiAgICBldmVudExpbWl0OiBmYWxzZSxcbiAgICBldmVudExpbWl0Q2xpY2s6ICdwb3BvdmVyJyxcbiAgICBkYXlQb3BvdmVyRm9ybWF0OiB7IG1vbnRoOiAnbG9uZycsIGRheTogJ251bWVyaWMnLCB5ZWFyOiAnbnVtZXJpYycgfSxcbiAgICBoYW5kbGVXaW5kb3dSZXNpemU6IHRydWUsXG4gICAgd2luZG93UmVzaXplRGVsYXk6IDEwMCxcbiAgICBsb25nUHJlc3NEZWxheTogMTAwMCxcbiAgICBldmVudERyYWdNaW5EaXN0YW5jZTogNSAvLyBvbmx5IGFwcGxpZXMgdG8gbW91c2Vcbn07XG52YXIgcnRsRGVmYXVsdHMgPSB7XG4gICAgaGVhZGVyOiB7XG4gICAgICAgIGxlZnQ6ICduZXh0LHByZXYgdG9kYXknLFxuICAgICAgICBjZW50ZXI6ICcnLFxuICAgICAgICByaWdodDogJ3RpdGxlJ1xuICAgIH0sXG4gICAgYnV0dG9uSWNvbnM6IHtcbiAgICAgICAgLy8gVE9ETzogbWFrZSBSVEwgc3VwcG9ydCB0aGUgcmVzcG9uaWJpbGl0eSBvZiB0aGUgdGhlbWVcbiAgICAgICAgcHJldjogJ2ZjLWljb24tY2hldnJvbi1yaWdodCcsXG4gICAgICAgIG5leHQ6ICdmYy1pY29uLWNoZXZyb24tbGVmdCcsXG4gICAgICAgIHByZXZZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1yaWdodCcsXG4gICAgICAgIG5leHRZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1sZWZ0J1xuICAgIH1cbn07XG52YXIgY29tcGxleE9wdGlvbnMgPSBbXG4gICAgJ2hlYWRlcicsXG4gICAgJ2Zvb3RlcicsXG4gICAgJ2J1dHRvblRleHQnLFxuICAgICdidXR0b25JY29ucydcbl07XG4vLyBNZXJnZXMgYW4gYXJyYXkgb2Ygb3B0aW9uIG9iamVjdHMgaW50byBhIHNpbmdsZSBvYmplY3RcbmZ1bmN0aW9uIG1lcmdlT3B0aW9ucyhvcHRpb25PYmpzKSB7XG4gICAgcmV0dXJuIG1lcmdlUHJvcHMob3B0aW9uT2JqcywgY29tcGxleE9wdGlvbnMpO1xufVxuLy8gVE9ETzogbW92ZSB0aGlzIHN0dWZmIHRvIGEgXCJwbHVnaW5cIi1yZWxhdGVkIGZpbGUuLi5cbnZhciBJTlRFUk5BTF9QTFVHSU5TID0gW1xuICAgIEFycmF5RXZlbnRTb3VyY2VQbHVnaW4sXG4gICAgRnVuY0V2ZW50U291cmNlUGx1Z2luLFxuICAgIEpzb25GZWVkRXZlbnRTb3VyY2VQbHVnaW4sXG4gICAgU2ltcGxlUmVjdXJyZW5jZVBsdWdpbixcbiAgICBEZWZhdWx0T3B0aW9uQ2hhbmdlSGFuZGxlcnNcbl07XG5mdW5jdGlvbiByZWZpbmVQbHVnaW5EZWZzKHBsdWdpbklucHV0cykge1xuICAgIHZhciBwbHVnaW5zID0gW107XG4gICAgZm9yICh2YXIgX2kgPSAwLCBwbHVnaW5JbnB1dHNfMSA9IHBsdWdpbklucHV0czsgX2kgPCBwbHVnaW5JbnB1dHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHBsdWdpbklucHV0ID0gcGx1Z2luSW5wdXRzXzFbX2ldO1xuICAgICAgICBpZiAodHlwZW9mIHBsdWdpbklucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdmFyIGdsb2JhbE5hbWUgPSAnRnVsbENhbGVuZGFyJyArIGNhcGl0YWxpc2VGaXJzdExldHRlcihwbHVnaW5JbnB1dCk7XG4gICAgICAgICAgICBpZiAoIXdpbmRvd1tnbG9iYWxOYW1lXSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUGx1Z2luIGZpbGUgbm90IGxvYWRlZCBmb3IgJyArIHBsdWdpbklucHV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHBsdWdpbnMucHVzaCh3aW5kb3dbZ2xvYmFsTmFtZV0uZGVmYXVsdCk7IC8vIGlzIGFuIEVTNiBtb2R1bGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBsdWdpbnMucHVzaChwbHVnaW5JbnB1dCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIElOVEVSTkFMX1BMVUdJTlMuY29uY2F0KHBsdWdpbnMpO1xufVxuXG52YXIgUkFXX0VOX0xPQ0FMRSA9IHtcbiAgICBjb2RlOiAnZW4nLFxuICAgIHdlZWs6IHtcbiAgICAgICAgZG93OiAwLFxuICAgICAgICBkb3k6IDQgLy8gNCBkYXlzIG5lZWQgdG8gYmUgd2l0aGluIHRoZSB5ZWFyIHRvIGJlIGNvbnNpZGVyZWQgdGhlIGZpcnN0IHdlZWtcbiAgICB9LFxuICAgIGRpcjogJ2x0cicsXG4gICAgYnV0dG9uVGV4dDoge1xuICAgICAgICBwcmV2OiAncHJldicsXG4gICAgICAgIG5leHQ6ICduZXh0JyxcbiAgICAgICAgcHJldlllYXI6ICdwcmV2IHllYXInLFxuICAgICAgICBuZXh0WWVhcjogJ25leHQgeWVhcicsXG4gICAgICAgIHllYXI6ICd5ZWFyJyxcbiAgICAgICAgdG9kYXk6ICd0b2RheScsXG4gICAgICAgIG1vbnRoOiAnbW9udGgnLFxuICAgICAgICB3ZWVrOiAnd2VlaycsXG4gICAgICAgIGRheTogJ2RheScsXG4gICAgICAgIGxpc3Q6ICdsaXN0J1xuICAgIH0sXG4gICAgd2Vla0xhYmVsOiAnVycsXG4gICAgYWxsRGF5VGV4dDogJ2FsbC1kYXknLFxuICAgIGV2ZW50TGltaXRUZXh0OiAnbW9yZScsXG4gICAgbm9FdmVudHNNZXNzYWdlOiAnTm8gZXZlbnRzIHRvIGRpc3BsYXknXG59O1xuZnVuY3Rpb24gcGFyc2VSYXdMb2NhbGVzKGV4cGxpY2l0UmF3TG9jYWxlcykge1xuICAgIHZhciBkZWZhdWx0Q29kZSA9IGV4cGxpY2l0UmF3TG9jYWxlcy5sZW5ndGggPiAwID8gZXhwbGljaXRSYXdMb2NhbGVzWzBdLmNvZGUgOiAnZW4nO1xuICAgIHZhciBnbG9iYWxBcnJheSA9IHdpbmRvd1snRnVsbENhbGVuZGFyTG9jYWxlc0FsbCddIHx8IFtdOyAvLyBmcm9tIGxvY2FsZXMtYWxsLmpzXG4gICAgdmFyIGdsb2JhbE9iamVjdCA9IHdpbmRvd1snRnVsbENhbGVuZGFyTG9jYWxlcyddIHx8IHt9OyAvLyBmcm9tIGxvY2FsZXMvKi5qcy4ga2V5cyBhcmUgbWVhbmluZ2xlc3NcbiAgICB2YXIgYWxsUmF3TG9jYWxlcyA9IGdsb2JhbEFycmF5LmNvbmNhdCgvLyBnbG9iYWxBcnJheSBpcyBsb3cgcHJpb1xuICAgIGhhc2hWYWx1ZXNUb0FycmF5KGdsb2JhbE9iamVjdCksIC8vIG1lZGl1bSBwcmlvXG4gICAgZXhwbGljaXRSYXdMb2NhbGVzIC8vIGhpZ2hlc3QgcHJpb1xuICAgICk7XG4gICAgdmFyIHJhd0xvY2FsZU1hcCA9IHtcbiAgICAgICAgZW46IFJBV19FTl9MT0NBTEUgLy8gbmVjZXNzYXJ5P1xuICAgIH07XG4gICAgZm9yICh2YXIgX2kgPSAwLCBhbGxSYXdMb2NhbGVzXzEgPSBhbGxSYXdMb2NhbGVzOyBfaSA8IGFsbFJhd0xvY2FsZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdmFyIHJhd0xvY2FsZSA9IGFsbFJhd0xvY2FsZXNfMVtfaV07XG4gICAgICAgIHJhd0xvY2FsZU1hcFtyYXdMb2NhbGUuY29kZV0gPSByYXdMb2NhbGU7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIG1hcDogcmF3TG9jYWxlTWFwLFxuICAgICAgICBkZWZhdWx0Q29kZTogZGVmYXVsdENvZGVcbiAgICB9O1xufVxuZnVuY3Rpb24gYnVpbGRMb2NhbGUoaW5wdXRTaW5ndWxhciwgYXZhaWxhYmxlKSB7XG4gICAgaWYgKHR5cGVvZiBpbnB1dFNpbmd1bGFyID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShpbnB1dFNpbmd1bGFyKSkge1xuICAgICAgICByZXR1cm4gcGFyc2VMb2NhbGUoaW5wdXRTaW5ndWxhci5jb2RlLCBbaW5wdXRTaW5ndWxhci5jb2RlXSwgaW5wdXRTaW5ndWxhcik7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcXVlcnlMb2NhbGUoaW5wdXRTaW5ndWxhciwgYXZhaWxhYmxlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBxdWVyeUxvY2FsZShjb2RlQXJnLCBhdmFpbGFibGUpIHtcbiAgICB2YXIgY29kZXMgPSBbXS5jb25jYXQoY29kZUFyZyB8fCBbXSk7IC8vIHdpbGwgY29udmVydCB0byBhcnJheVxuICAgIHZhciByYXcgPSBxdWVyeVJhd0xvY2FsZShjb2RlcywgYXZhaWxhYmxlKSB8fCBSQVdfRU5fTE9DQUxFO1xuICAgIHJldHVybiBwYXJzZUxvY2FsZShjb2RlQXJnLCBjb2RlcywgcmF3KTtcbn1cbmZ1bmN0aW9uIHF1ZXJ5UmF3TG9jYWxlKGNvZGVzLCBhdmFpbGFibGUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGNvZGVzW2ldLnRvTG9jYWxlTG93ZXJDYXNlKCkuc3BsaXQoJy0nKTtcbiAgICAgICAgZm9yICh2YXIgaiA9IHBhcnRzLmxlbmd0aDsgaiA+IDA7IGotLSkge1xuICAgICAgICAgICAgdmFyIHNpbXBsZUlkID0gcGFydHMuc2xpY2UoMCwgaikuam9pbignLScpO1xuICAgICAgICAgICAgaWYgKGF2YWlsYWJsZVtzaW1wbGVJZF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXZhaWxhYmxlW3NpbXBsZUlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIHBhcnNlTG9jYWxlKGNvZGVBcmcsIGNvZGVzLCByYXcpIHtcbiAgICB2YXIgbWVyZ2VkID0gbWVyZ2VQcm9wcyhbUkFXX0VOX0xPQ0FMRSwgcmF3XSwgWydidXR0b25UZXh0J10pO1xuICAgIGRlbGV0ZSBtZXJnZWQuY29kZTsgLy8gZG9uJ3Qgd2FudCB0aGlzIHBhcnQgb2YgdGhlIG9wdGlvbnNcbiAgICB2YXIgd2VlayA9IG1lcmdlZC53ZWVrO1xuICAgIGRlbGV0ZSBtZXJnZWQud2VlaztcbiAgICByZXR1cm4ge1xuICAgICAgICBjb2RlQXJnOiBjb2RlQXJnLFxuICAgICAgICBjb2RlczogY29kZXMsXG4gICAgICAgIHdlZWs6IHdlZWssXG4gICAgICAgIHNpbXBsZU51bWJlckZvcm1hdDogbmV3IEludGwuTnVtYmVyRm9ybWF0KGNvZGVBcmcpLFxuICAgICAgICBvcHRpb25zOiBtZXJnZWRcbiAgICB9O1xufVxuXG52YXIgT3B0aW9uc01hbmFnZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT3B0aW9uc01hbmFnZXIob3ZlcnJpZGVzKSB7XG4gICAgICAgIHRoaXMub3ZlcnJpZGVzID0gX19hc3NpZ24oe30sIG92ZXJyaWRlcyk7IC8vIG1ha2UgYSBjb3B5XG4gICAgICAgIHRoaXMuZHluYW1pY092ZXJyaWRlcyA9IHt9O1xuICAgICAgICB0aGlzLmNvbXB1dGUoKTtcbiAgICB9XG4gICAgT3B0aW9uc01hbmFnZXIucHJvdG90eXBlLm11dGF0ZSA9IGZ1bmN0aW9uICh1cGRhdGVzLCByZW1vdmFscywgaXNEeW5hbWljKSB7XG4gICAgICAgIGlmICghT2JqZWN0LmtleXModXBkYXRlcykubGVuZ3RoICYmICFyZW1vdmFscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3ZlcnJpZGVIYXNoID0gaXNEeW5hbWljID8gdGhpcy5keW5hbWljT3ZlcnJpZGVzIDogdGhpcy5vdmVycmlkZXM7XG4gICAgICAgIF9fYXNzaWduKG92ZXJyaWRlSGFzaCwgdXBkYXRlcyk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgcmVtb3ZhbHNfMSA9IHJlbW92YWxzOyBfaSA8IHJlbW92YWxzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSByZW1vdmFsc18xW19pXTtcbiAgICAgICAgICAgIGRlbGV0ZSBvdmVycmlkZUhhc2hbcHJvcE5hbWVdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29tcHV0ZSgpO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgdGhlIGZsYXR0ZW5lZCBvcHRpb25zIGhhc2ggZm9yIHRoZSBjYWxlbmRhciBhbmQgYXNzaWducyB0byBgdGhpcy5vcHRpb25zYC5cbiAgICAvLyBBc3N1bWVzIHRoaXMub3ZlcnJpZGVzIGFuZCB0aGlzLmR5bmFtaWNPdmVycmlkZXMgaGF2ZSBhbHJlYWR5IGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAgT3B0aW9uc01hbmFnZXIucHJvdG90eXBlLmNvbXB1dGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFRPRE86IG5vdCBhIHZlcnkgZWZmaWNpZW50IHN5c3RlbVxuICAgICAgICB2YXIgbG9jYWxlcyA9IGZpcnN0RGVmaW5lZCgvLyBleHBsaWNpdCBsb2NhbGUgb3B0aW9uIGdpdmVuP1xuICAgICAgICB0aGlzLmR5bmFtaWNPdmVycmlkZXMubG9jYWxlcywgdGhpcy5vdmVycmlkZXMubG9jYWxlcywgZ2xvYmFsRGVmYXVsdHMubG9jYWxlcyk7XG4gICAgICAgIHZhciBsb2NhbGUgPSBmaXJzdERlZmluZWQoLy8gZXhwbGljaXQgbG9jYWxlcyBvcHRpb24gZ2l2ZW4/XG4gICAgICAgIHRoaXMuZHluYW1pY092ZXJyaWRlcy5sb2NhbGUsIHRoaXMub3ZlcnJpZGVzLmxvY2FsZSwgZ2xvYmFsRGVmYXVsdHMubG9jYWxlKTtcbiAgICAgICAgdmFyIGF2YWlsYWJsZSA9IHBhcnNlUmF3TG9jYWxlcyhsb2NhbGVzKTtcbiAgICAgICAgdmFyIGxvY2FsZURlZmF1bHRzID0gYnVpbGRMb2NhbGUobG9jYWxlIHx8IGF2YWlsYWJsZS5kZWZhdWx0Q29kZSwgYXZhaWxhYmxlLm1hcCkub3B0aW9ucztcbiAgICAgICAgdmFyIGRpciA9IGZpcnN0RGVmaW5lZCgvLyBiYXNlZCBvbiBvcHRpb25zIGNvbXB1dGVkIHNvIGZhciwgaXMgZGlyZWN0aW9uIFJUTD9cbiAgICAgICAgdGhpcy5keW5hbWljT3ZlcnJpZGVzLmRpciwgdGhpcy5vdmVycmlkZXMuZGlyLCBsb2NhbGVEZWZhdWx0cy5kaXIpO1xuICAgICAgICB2YXIgZGlyRGVmYXVsdHMgPSBkaXIgPT09ICdydGwnID8gcnRsRGVmYXVsdHMgOiB7fTtcbiAgICAgICAgdGhpcy5kaXJEZWZhdWx0cyA9IGRpckRlZmF1bHRzO1xuICAgICAgICB0aGlzLmxvY2FsZURlZmF1bHRzID0gbG9jYWxlRGVmYXVsdHM7XG4gICAgICAgIHRoaXMuY29tcHV0ZWQgPSBtZXJnZU9wdGlvbnMoW1xuICAgICAgICAgICAgZ2xvYmFsRGVmYXVsdHMsXG4gICAgICAgICAgICBkaXJEZWZhdWx0cyxcbiAgICAgICAgICAgIGxvY2FsZURlZmF1bHRzLFxuICAgICAgICAgICAgdGhpcy5vdmVycmlkZXMsXG4gICAgICAgICAgICB0aGlzLmR5bmFtaWNPdmVycmlkZXNcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICByZXR1cm4gT3B0aW9uc01hbmFnZXI7XG59KCkpO1xuXG52YXIgY2FsZW5kYXJTeXN0ZW1DbGFzc01hcCA9IHt9O1xuZnVuY3Rpb24gcmVnaXN0ZXJDYWxlbmRhclN5c3RlbShuYW1lLCB0aGVDbGFzcykge1xuICAgIGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXBbbmFtZV0gPSB0aGVDbGFzcztcbn1cbmZ1bmN0aW9uIGNyZWF0ZUNhbGVuZGFyU3lzdGVtKG5hbWUpIHtcbiAgICByZXR1cm4gbmV3IGNhbGVuZGFyU3lzdGVtQ2xhc3NNYXBbbmFtZV0oKTtcbn1cbnZhciBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbSgpIHtcbiAgICB9XG4gICAgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0ucHJvdG90eXBlLmdldE1hcmtlclllYXIgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICByZXR1cm4gZC5nZXRVVENGdWxsWWVhcigpO1xuICAgIH07XG4gICAgR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW0ucHJvdG90eXBlLmdldE1hcmtlck1vbnRoID0gZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZ2V0VVRDTW9udGgoKTtcbiAgICB9O1xuICAgIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtLnByb3RvdHlwZS5nZXRNYXJrZXJEYXkgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICByZXR1cm4gZC5nZXRVVENEYXRlKCk7XG4gICAgfTtcbiAgICBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbS5wcm90b3R5cGUuYXJyYXlUb01hcmtlciA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGFycik7XG4gICAgfTtcbiAgICBHcmVnb3JpYW5DYWxlbmRhclN5c3RlbS5wcm90b3R5cGUubWFya2VyVG9BcnJheSA9IGZ1bmN0aW9uIChtYXJrZXIpIHtcbiAgICAgICAgcmV0dXJuIGRhdGVUb1V0Y0FycmF5KG1hcmtlcik7XG4gICAgfTtcbiAgICByZXR1cm4gR3JlZ29yaWFuQ2FsZW5kYXJTeXN0ZW07XG59KCkpO1xucmVnaXN0ZXJDYWxlbmRhclN5c3RlbSgnZ3JlZ29yeScsIEdyZWdvcmlhbkNhbGVuZGFyU3lzdGVtKTtcblxudmFyIElTT19SRSA9IC9eXFxzKihcXGR7NH0pKC0oXFxkezJ9KSgtKFxcZHsyfSkoW1QgXShcXGR7Mn0pOihcXGR7Mn0pKDooXFxkezJ9KShcXC4oXFxkKykpPyk/KFp8KChbLStdKShcXGR7Mn0pKDo/KFxcZHsyfSkpPykpPyk/KT8pPyQvO1xuZnVuY3Rpb24gcGFyc2Uoc3RyKSB7XG4gICAgdmFyIG0gPSBJU09fUkUuZXhlYyhzdHIpO1xuICAgIGlmIChtKSB7XG4gICAgICAgIHZhciBtYXJrZXIgPSBuZXcgRGF0ZShEYXRlLlVUQyhOdW1iZXIobVsxXSksIG1bM10gPyBOdW1iZXIobVszXSkgLSAxIDogMCwgTnVtYmVyKG1bNV0gfHwgMSksIE51bWJlcihtWzddIHx8IDApLCBOdW1iZXIobVs4XSB8fCAwKSwgTnVtYmVyKG1bMTBdIHx8IDApLCBtWzEyXSA/IE51bWJlcignMC4nICsgbVsxMl0pICogMTAwMCA6IDApKTtcbiAgICAgICAgaWYgKGlzVmFsaWREYXRlKG1hcmtlcikpIHtcbiAgICAgICAgICAgIHZhciB0aW1lWm9uZU9mZnNldCA9IG51bGw7XG4gICAgICAgICAgICBpZiAobVsxM10pIHtcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldCA9IChtWzE1XSA9PT0gJy0nID8gLTEgOiAxKSAqIChOdW1iZXIobVsxNl0gfHwgMCkgKiA2MCArXG4gICAgICAgICAgICAgICAgICAgIE51bWJlcihtWzE4XSB8fCAwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1hcmtlcjogbWFya2VyLFxuICAgICAgICAgICAgICAgIGlzVGltZVVuc3BlY2lmaWVkOiAhbVs2XSxcbiAgICAgICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogdGltZVpvbmVPZmZzZXRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbnZhciBEYXRlRW52ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIERhdGVFbnYoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIHRpbWVab25lID0gdGhpcy50aW1lWm9uZSA9IHNldHRpbmdzLnRpbWVab25lO1xuICAgICAgICB2YXIgaXNOYW1lZFRpbWVab25lID0gdGltZVpvbmUgIT09ICdsb2NhbCcgJiYgdGltZVpvbmUgIT09ICdVVEMnO1xuICAgICAgICBpZiAoc2V0dGluZ3MubmFtZWRUaW1lWm9uZUltcGwgJiYgaXNOYW1lZFRpbWVab25lKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWVkVGltZVpvbmVJbXBsID0gbmV3IHNldHRpbmdzLm5hbWVkVGltZVpvbmVJbXBsKHRpbWVab25lKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbkNvbXB1dGVPZmZzZXQgPSBCb29sZWFuKCFpc05hbWVkVGltZVpvbmUgfHwgdGhpcy5uYW1lZFRpbWVab25lSW1wbCk7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0gPSBjcmVhdGVDYWxlbmRhclN5c3RlbShzZXR0aW5ncy5jYWxlbmRhclN5c3RlbSk7XG4gICAgICAgIHRoaXMubG9jYWxlID0gc2V0dGluZ3MubG9jYWxlO1xuICAgICAgICB0aGlzLndlZWtEb3cgPSBzZXR0aW5ncy5sb2NhbGUud2Vlay5kb3c7XG4gICAgICAgIHRoaXMud2Vla0RveSA9IHNldHRpbmdzLmxvY2FsZS53ZWVrLmRveTtcbiAgICAgICAgaWYgKHNldHRpbmdzLndlZWtOdW1iZXJDYWxjdWxhdGlvbiA9PT0gJ0lTTycpIHtcbiAgICAgICAgICAgIHRoaXMud2Vla0RvdyA9IDE7XG4gICAgICAgICAgICB0aGlzLndlZWtEb3kgPSA0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0dGluZ3MuZmlyc3REYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLndlZWtEb3cgPSBzZXR0aW5ncy5maXJzdERheTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzLndlZWtOdW1iZXJDYWxjdWxhdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy53ZWVrTnVtYmVyRnVuYyA9IHNldHRpbmdzLndlZWtOdW1iZXJDYWxjdWxhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLndlZWtMYWJlbCA9IHNldHRpbmdzLndlZWtMYWJlbCAhPSBudWxsID8gc2V0dGluZ3Mud2Vla0xhYmVsIDogc2V0dGluZ3MubG9jYWxlLm9wdGlvbnMud2Vla0xhYmVsO1xuICAgICAgICB0aGlzLmNtZEZvcm1hdHRlciA9IHNldHRpbmdzLmNtZEZvcm1hdHRlcjtcbiAgICB9XG4gICAgLy8gQ3JlYXRpbmcgLyBQYXJzaW5nXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY3JlYXRlTWFya2VyID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHZhciBtZXRhID0gdGhpcy5jcmVhdGVNYXJrZXJNZXRhKGlucHV0KTtcbiAgICAgICAgaWYgKG1ldGEgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhLm1hcmtlcjtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmNyZWF0ZU5vd01hcmtlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2FuQ29tcHV0ZU9mZnNldCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGltZXN0YW1wVG9NYXJrZXIobmV3IERhdGUoKS52YWx1ZU9mKCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgd2UgY2FuJ3QgY29tcHV0ZSB0aGUgY3VycmVudCBkYXRlIHZhbCBmb3IgYSB0aW1lem9uZSxcbiAgICAgICAgICAgIC8vIGJldHRlciB0byBnaXZlIHRoZSBjdXJyZW50IGxvY2FsIGRhdGUgdmFscyB0aGFuIFVUQ1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKGRhdGVUb0xvY2FsQXJyYXkobmV3IERhdGUoKSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5jcmVhdGVNYXJrZXJNZXRhID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShpbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hcmtlciA9IG51bGw7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBtYXJrZXIgPSB0aGlzLnRpbWVzdGFtcFRvTWFya2VyKGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpbnB1dCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICAgIGlucHV0ID0gaW5wdXQudmFsdWVPZigpO1xuICAgICAgICAgICAgaWYgKCFpc05hTihpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICBtYXJrZXIgPSB0aGlzLnRpbWVzdGFtcFRvTWFya2VyKGlucHV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICAgICAgbWFya2VyID0gYXJyYXlUb1V0Y0RhdGUoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXJrZXIgPT09IG51bGwgfHwgIWlzVmFsaWREYXRlKG1hcmtlcikpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IG1hcmtlcjogbWFya2VyLCBpc1RpbWVVbnNwZWNpZmllZDogZmFsc2UsIGZvcmNlZFR6bzogbnVsbCB9O1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbiAocykge1xuICAgICAgICB2YXIgcGFydHMgPSBwYXJzZShzKTtcbiAgICAgICAgaWYgKHBhcnRzID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWFya2VyID0gcGFydHMubWFya2VyO1xuICAgICAgICB2YXIgZm9yY2VkVHpvID0gbnVsbDtcbiAgICAgICAgaWYgKHBhcnRzLnRpbWVab25lT2Zmc2V0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jYW5Db21wdXRlT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgbWFya2VyID0gdGhpcy50aW1lc3RhbXBUb01hcmtlcihtYXJrZXIudmFsdWVPZigpIC0gcGFydHMudGltZVpvbmVPZmZzZXQgKiA2MCAqIDEwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yY2VkVHpvID0gcGFydHMudGltZVpvbmVPZmZzZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgbWFya2VyOiBtYXJrZXIsIGlzVGltZVVuc3BlY2lmaWVkOiBwYXJ0cy5pc1RpbWVVbnNwZWNpZmllZCwgZm9yY2VkVHpvOiBmb3JjZWRUem8gfTtcbiAgICB9O1xuICAgIC8vIEFjY2Vzc29yc1xuICAgIERhdGVFbnYucHJvdG90eXBlLmdldFllYXIgPSBmdW5jdGlvbiAobWFya2VyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobWFya2VyKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmdldE1vbnRoID0gZnVuY3Rpb24gKG1hcmtlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtYXJrZXIpO1xuICAgIH07XG4gICAgLy8gQWRkaW5nIC8gU3VidHJhY3RpbmdcbiAgICBEYXRlRW52LnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAobWFya2VyLCBkdXIpIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVswXSArPSBkdXIueWVhcnM7XG4gICAgICAgIGFbMV0gKz0gZHVyLm1vbnRocztcbiAgICAgICAgYVsyXSArPSBkdXIuZGF5cztcbiAgICAgICAgYVs2XSArPSBkdXIubWlsbGlzZWNvbmRzO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuc3VidHJhY3QgPSBmdW5jdGlvbiAobWFya2VyLCBkdXIpIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVswXSAtPSBkdXIueWVhcnM7XG4gICAgICAgIGFbMV0gLT0gZHVyLm1vbnRocztcbiAgICAgICAgYVsyXSAtPSBkdXIuZGF5cztcbiAgICAgICAgYVs2XSAtPSBkdXIubWlsbGlzZWNvbmRzO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuYWRkWWVhcnMgPSBmdW5jdGlvbiAobWFya2VyLCBuKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5jYWxlbmRhclN5c3RlbS5tYXJrZXJUb0FycmF5KG1hcmtlcik7XG4gICAgICAgIGFbMF0gKz0gbjtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihhKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmFkZE1vbnRocyA9IGZ1bmN0aW9uIChtYXJrZXIsIG4pIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmNhbGVuZGFyU3lzdGVtLm1hcmtlclRvQXJyYXkobWFya2VyKTtcbiAgICAgICAgYVsxXSArPSBuO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKGEpO1xuICAgIH07XG4gICAgLy8gRGlmZmluZyBXaG9sZSBVbml0c1xuICAgIERhdGVFbnYucHJvdG90eXBlLmRpZmZXaG9sZVllYXJzID0gZnVuY3Rpb24gKG0wLCBtMSkge1xuICAgICAgICB2YXIgY2FsZW5kYXJTeXN0ZW0gPSB0aGlzLmNhbGVuZGFyU3lzdGVtO1xuICAgICAgICBpZiAodGltZUFzTXMobTApID09PSB0aW1lQXNNcyhtMSkgJiZcbiAgICAgICAgICAgIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlckRheShtMCkgPT09IGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlckRheShtMSkgJiZcbiAgICAgICAgICAgIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0wKSA9PT0gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyTW9udGgobTEpKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtMSkgLSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0wKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmRpZmZXaG9sZU1vbnRocyA9IGZ1bmN0aW9uIChtMCwgbTEpIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyU3lzdGVtID0gdGhpcy5jYWxlbmRhclN5c3RlbTtcbiAgICAgICAgaWYgKHRpbWVBc01zKG0wKSA9PT0gdGltZUFzTXMobTEpICYmXG4gICAgICAgICAgICBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTApID09PSBjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJEYXkobTEpKSB7XG4gICAgICAgICAgICByZXR1cm4gKGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0xKSAtIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlck1vbnRoKG0wKSkgK1xuICAgICAgICAgICAgICAgIChjYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0xKSAtIGNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobTApKSAqIDEyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLy8gUmFuZ2UgLyBEdXJhdGlvblxuICAgIERhdGVFbnYucHJvdG90eXBlLmdyZWF0ZXN0V2hvbGVVbml0ID0gZnVuY3Rpb24gKG0wLCBtMSkge1xuICAgICAgICB2YXIgbiA9IHRoaXMuZGlmZldob2xlWWVhcnMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICd5ZWFyJywgdmFsdWU6IG4gfTtcbiAgICAgICAgfVxuICAgICAgICBuID0gdGhpcy5kaWZmV2hvbGVNb250aHMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdtb250aCcsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZXaG9sZVdlZWtzKG0wLCBtMSk7XG4gICAgICAgIGlmIChuICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnd2VlaycsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZXaG9sZURheXMobTAsIG0xKTtcbiAgICAgICAgaWYgKG4gIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHVuaXQ6ICdkYXknLCB2YWx1ZTogbiB9O1xuICAgICAgICB9XG4gICAgICAgIG4gPSBkaWZmSG91cnMobTAsIG0xKTtcbiAgICAgICAgaWYgKGlzSW50KG4pKSB7XG4gICAgICAgICAgICByZXR1cm4geyB1bml0OiAnaG91cicsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZNaW51dGVzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbnV0ZScsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgbiA9IGRpZmZTZWNvbmRzKG0wLCBtMSk7XG4gICAgICAgIGlmIChpc0ludChuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgdW5pdDogJ3NlY29uZCcsIHZhbHVlOiBuIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdW5pdDogJ21pbGxpc2Vjb25kJywgdmFsdWU6IG0xLnZhbHVlT2YoKSAtIG0wLnZhbHVlT2YoKSB9O1xuICAgIH07XG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY291bnREdXJhdGlvbnNCZXR3ZWVuID0gZnVuY3Rpb24gKG0wLCBtMSwgZCkge1xuICAgICAgICAvLyBUT0RPOiBjYW4gdXNlIGdyZWF0ZXN0V2hvbGVVbml0XG4gICAgICAgIHZhciBkaWZmO1xuICAgICAgICBpZiAoZC55ZWFycykge1xuICAgICAgICAgICAgZGlmZiA9IHRoaXMuZGlmZldob2xlWWVhcnMobTAsIG0xKTtcbiAgICAgICAgICAgIGlmIChkaWZmICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmYgLyBhc1JvdWdoWWVhcnMoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGQubW9udGhzKSB7XG4gICAgICAgICAgICBkaWZmID0gdGhpcy5kaWZmV2hvbGVNb250aHMobTAsIG0xKTtcbiAgICAgICAgICAgIGlmIChkaWZmICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmYgLyBhc1JvdWdoTW9udGhzKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChkLmRheXMpIHtcbiAgICAgICAgICAgIGRpZmYgPSBkaWZmV2hvbGVEYXlzKG0wLCBtMSk7XG4gICAgICAgICAgICBpZiAoZGlmZiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmIC8gYXNSb3VnaERheXMoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChtMS52YWx1ZU9mKCkgLSBtMC52YWx1ZU9mKCkpIC8gYXNSb3VnaE1zKGQpO1xuICAgIH07XG4gICAgLy8gU3RhcnQtT2ZcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mID0gZnVuY3Rpb24gKG0sIHVuaXQpIHtcbiAgICAgICAgaWYgKHVuaXQgPT09ICd5ZWFyJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZlllYXIobSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodW5pdCA9PT0gJ21vbnRoJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZk1vbnRoKG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICd3ZWVrJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZldlZWsobSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodW5pdCA9PT0gJ2RheScpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGFydE9mRGF5KG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICdob3VyJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZIb3VyKG0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHVuaXQgPT09ICdtaW51dGUnKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RhcnRPZk1pbnV0ZShtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1bml0ID09PSAnc2Vjb25kJykge1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0T2ZTZWNvbmQobSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLnN0YXJ0T2ZZZWFyID0gZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTeXN0ZW0uYXJyYXlUb01hcmtlcihbXG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyU3lzdGVtLmdldE1hcmtlclllYXIobSlcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mTW9udGggPSBmdW5jdGlvbiAobSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhclN5c3RlbS5hcnJheVRvTWFya2VyKFtcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyWWVhcihtKSxcbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJTeXN0ZW0uZ2V0TWFya2VyTW9udGgobSlcbiAgICAgICAgXSk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5zdGFydE9mV2VlayA9IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGVuZGFyU3lzdGVtLmFycmF5VG9NYXJrZXIoW1xuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJZZWFyKG0pLFxuICAgICAgICAgICAgdGhpcy5jYWxlbmRhclN5c3RlbS5nZXRNYXJrZXJNb250aChtKSxcbiAgICAgICAgICAgIG0uZ2V0VVRDRGF0ZSgpIC0gKChtLmdldFVUQ0RheSgpIC0gdGhpcy53ZWVrRG93ICsgNykgJSA3KVxuICAgICAgICBdKTtcbiAgICB9O1xuICAgIC8vIFdlZWsgTnVtYmVyXG4gICAgRGF0ZUVudi5wcm90b3R5cGUuY29tcHV0ZVdlZWtOdW1iZXIgPSBmdW5jdGlvbiAobWFya2VyKSB7XG4gICAgICAgIGlmICh0aGlzLndlZWtOdW1iZXJGdW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53ZWVrTnVtYmVyRnVuYyh0aGlzLnRvRGF0ZShtYXJrZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWVrT2ZZZWFyKG1hcmtlciwgdGhpcy53ZWVrRG93LCB0aGlzLndlZWtEb3kpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBUT0RPOiBjaG9rZSBvbiB0aW1lWm9uZU5hbWU6IGxvbmdcbiAgICBEYXRlRW52LnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiAobWFya2VyLCBmb3JtYXR0ZXIsIGRhdGVPcHRpb25zKSB7XG4gICAgICAgIGlmIChkYXRlT3B0aW9ucyA9PT0gdm9pZCAwKSB7IGRhdGVPcHRpb25zID0ge307IH1cbiAgICAgICAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXQoe1xuICAgICAgICAgICAgbWFya2VyOiBtYXJrZXIsXG4gICAgICAgICAgICB0aW1lWm9uZU9mZnNldDogZGF0ZU9wdGlvbnMuZm9yY2VkVHpvICE9IG51bGwgP1xuICAgICAgICAgICAgICAgIGRhdGVPcHRpb25zLmZvcmNlZFR6byA6XG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXRGb3JNYXJrZXIobWFya2VyKVxuICAgICAgICB9LCB0aGlzKTtcbiAgICB9O1xuICAgIERhdGVFbnYucHJvdG90eXBlLmZvcm1hdFJhbmdlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQsIGZvcm1hdHRlciwgZGF0ZU9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGRhdGVPcHRpb25zID09PSB2b2lkIDApIHsgZGF0ZU9wdGlvbnMgPSB7fTsgfVxuICAgICAgICBpZiAoZGF0ZU9wdGlvbnMuaXNFbmRFeGNsdXNpdmUpIHtcbiAgICAgICAgICAgIGVuZCA9IGFkZE1zKGVuZCwgLTEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0UmFuZ2Uoe1xuICAgICAgICAgICAgbWFya2VyOiBzdGFydCxcbiAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0OiBkYXRlT3B0aW9ucy5mb3JjZWRTdGFydFR6byAhPSBudWxsID9cbiAgICAgICAgICAgICAgICBkYXRlT3B0aW9ucy5mb3JjZWRTdGFydFR6byA6XG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXRGb3JNYXJrZXIoc3RhcnQpXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIG1hcmtlcjogZW5kLFxuICAgICAgICAgICAgdGltZVpvbmVPZmZzZXQ6IGRhdGVPcHRpb25zLmZvcmNlZEVuZFR6byAhPSBudWxsID9cbiAgICAgICAgICAgICAgICBkYXRlT3B0aW9ucy5mb3JjZWRFbmRUem8gOlxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0Rm9yTWFya2VyKGVuZClcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5mb3JtYXRJc28gPSBmdW5jdGlvbiAobWFya2VyLCBleHRyYU9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGV4dHJhT3B0aW9ucyA9PT0gdm9pZCAwKSB7IGV4dHJhT3B0aW9ucyA9IHt9OyB9XG4gICAgICAgIHZhciB0aW1lWm9uZU9mZnNldCA9IG51bGw7XG4gICAgICAgIGlmICghZXh0cmFPcHRpb25zLm9taXRUaW1lWm9uZU9mZnNldCkge1xuICAgICAgICAgICAgaWYgKGV4dHJhT3B0aW9ucy5mb3JjZWRUem8gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0ID0gZXh0cmFPcHRpb25zLmZvcmNlZFR6bztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRpbWVab25lT2Zmc2V0ID0gdGhpcy5vZmZzZXRGb3JNYXJrZXIobWFya2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYnVpbGRJc29TdHJpbmcobWFya2VyLCB0aW1lWm9uZU9mZnNldCwgZXh0cmFPcHRpb25zLm9taXRUaW1lKTtcbiAgICB9O1xuICAgIC8vIFRpbWVab25lXG4gICAgRGF0ZUVudi5wcm90b3R5cGUudGltZXN0YW1wVG9NYXJrZXIgPSBmdW5jdGlvbiAobXMpIHtcbiAgICAgICAgaWYgKHRoaXMudGltZVpvbmUgPT09ICdsb2NhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiBhcnJheVRvVXRjRGF0ZShkYXRlVG9Mb2NhbEFycmF5KG5ldyBEYXRlKG1zKSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnIHx8ICF0aGlzLm5hbWVkVGltZVpvbmVJbXBsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9VdGNEYXRlKHRoaXMubmFtZWRUaW1lWm9uZUltcGwudGltZXN0YW1wVG9BcnJheShtcykpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlRW52LnByb3RvdHlwZS5vZmZzZXRGb3JNYXJrZXIgPSBmdW5jdGlvbiAobSkge1xuICAgICAgICBpZiAodGhpcy50aW1lWm9uZSA9PT0gJ2xvY2FsJykge1xuICAgICAgICAgICAgcmV0dXJuIC1hcnJheVRvTG9jYWxEYXRlKGRhdGVUb1V0Y0FycmF5KG0pKS5nZXRUaW1lem9uZU9mZnNldCgpOyAvLyBjb252ZXJ0IFwiaW52ZXJzZVwiIG9mZnNldCB0byBcIm5vcm1hbFwiIG9mZnNldFxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLm5hbWVkVGltZVpvbmVJbXBsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uYW1lZFRpbWVab25lSW1wbC5vZmZzZXRGb3JBcnJheShkYXRlVG9VdGNBcnJheShtKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvLyBDb252ZXJzaW9uXG4gICAgRGF0ZUVudi5wcm90b3R5cGUudG9EYXRlID0gZnVuY3Rpb24gKG0sIGZvcmNlZFR6bykge1xuICAgICAgICBpZiAodGhpcy50aW1lWm9uZSA9PT0gJ2xvY2FsJykge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5VG9Mb2NhbERhdGUoZGF0ZVRvVXRjQXJyYXkobSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVpvbmUgPT09ICdVVEMnKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobS52YWx1ZU9mKCkpOyAvLyBtYWtlIHN1cmUgaXQncyBhIGNvcHlcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghdGhpcy5uYW1lZFRpbWVab25lSW1wbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKG0udmFsdWVPZigpIC0gKGZvcmNlZFR6byB8fCAwKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUobS52YWx1ZU9mKCkgLVxuICAgICAgICAgICAgICAgIHRoaXMubmFtZWRUaW1lWm9uZUltcGwub2Zmc2V0Rm9yQXJyYXkoZGF0ZVRvVXRjQXJyYXkobSkpICogMTAwMCAqIDYwIC8vIGNvbnZlcnQgbWludXRlcyAtPiBtc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERhdGVFbnY7XG59KCkpO1xuXG52YXIgU0lNUExFX1NPVVJDRV9QUk9QUyA9IHtcbiAgICBpZDogU3RyaW5nLFxuICAgIGFsbERheURlZmF1bHQ6IEJvb2xlYW4sXG4gICAgZXZlbnREYXRhVHJhbnNmb3JtOiBGdW5jdGlvbixcbiAgICBzdWNjZXNzOiBGdW5jdGlvbixcbiAgICBmYWlsdXJlOiBGdW5jdGlvblxufTtcbnZhciB1aWQkMiA9IDA7XG5mdW5jdGlvbiBkb2VzU291cmNlTmVlZFJhbmdlKGV2ZW50U291cmNlLCBjYWxlbmRhcikge1xuICAgIHZhciBkZWZzID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50U291cmNlRGVmcztcbiAgICByZXR1cm4gIWRlZnNbZXZlbnRTb3VyY2Uuc291cmNlRGVmSWRdLmlnbm9yZVJhbmdlO1xufVxuZnVuY3Rpb24gcGFyc2VFdmVudFNvdXJjZShyYXcsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRlZnMgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MuZXZlbnRTb3VyY2VEZWZzO1xuICAgIGZvciAodmFyIGkgPSBkZWZzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7IC8vIGxhdGVyLWFkZGVkIHBsdWdpbnMgdGFrZSBwcmVjZWRlbmNlXG4gICAgICAgIHZhciBkZWYgPSBkZWZzW2ldO1xuICAgICAgICB2YXIgbWV0YSA9IGRlZi5wYXJzZU1ldGEocmF3KTtcbiAgICAgICAgaWYgKG1ldGEpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSBwYXJzZUV2ZW50U291cmNlUHJvcHModHlwZW9mIHJhdyA9PT0gJ29iamVjdCcgPyByYXcgOiB7fSwgbWV0YSwgaSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgcmVzLl9yYXcgPSByYXc7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gcGFyc2VFdmVudFNvdXJjZVByb3BzKHJhdywgbWV0YSwgc291cmNlRGVmSWQsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGxlZnRvdmVyczAgPSB7fTtcbiAgICB2YXIgcHJvcHMgPSByZWZpbmVQcm9wcyhyYXcsIFNJTVBMRV9TT1VSQ0VfUFJPUFMsIHt9LCBsZWZ0b3ZlcnMwKTtcbiAgICB2YXIgbGVmdG92ZXJzMSA9IHt9O1xuICAgIHZhciB1aSA9IHByb2Nlc3NVbnNjb3BlZFVpUHJvcHMobGVmdG92ZXJzMCwgY2FsZW5kYXIsIGxlZnRvdmVyczEpO1xuICAgIHByb3BzLmlzRmV0Y2hpbmcgPSBmYWxzZTtcbiAgICBwcm9wcy5sYXRlc3RGZXRjaElkID0gJyc7XG4gICAgcHJvcHMuZmV0Y2hSYW5nZSA9IG51bGw7XG4gICAgcHJvcHMucHVibGljSWQgPSBTdHJpbmcocmF3LmlkIHx8ICcnKTtcbiAgICBwcm9wcy5zb3VyY2VJZCA9IFN0cmluZyh1aWQkMisrKTtcbiAgICBwcm9wcy5zb3VyY2VEZWZJZCA9IHNvdXJjZURlZklkO1xuICAgIHByb3BzLm1ldGEgPSBtZXRhO1xuICAgIHByb3BzLnVpID0gdWk7XG4gICAgcHJvcHMuZXh0ZW5kZWRQcm9wcyA9IGxlZnRvdmVyczE7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuXG5mdW5jdGlvbiByZWR1Y2VFdmVudFNvdXJjZXMgKGV2ZW50U291cmNlcywgYWN0aW9uLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXIpIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ0FERF9FVkVOVF9TT1VSQ0VTJzogLy8gYWxyZWFkeSBwYXJzZWRcbiAgICAgICAgICAgIHJldHVybiBhZGRTb3VyY2VzKGV2ZW50U291cmNlcywgYWN0aW9uLnNvdXJjZXMsIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ1JFTU9WRV9FVkVOVF9TT1VSQ0UnOlxuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZVNvdXJjZShldmVudFNvdXJjZXMsIGFjdGlvbi5zb3VyY2VJZCk7XG4gICAgICAgIGNhc2UgJ1BSRVYnOiAvLyBUT0RPOiBob3cgZG8gd2UgdHJhY2sgYWxsIGFjdGlvbnMgdGhhdCBhZmZlY3QgZGF0ZVByb2ZpbGUgOihcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgIGNhc2UgJ1NFVF9EQVRFJzpcbiAgICAgICAgY2FzZSAnU0VUX1ZJRVdfVFlQRSc6XG4gICAgICAgICAgICBpZiAoZGF0ZVByb2ZpbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmV0Y2hEaXJ0eVNvdXJjZXMoZXZlbnRTb3VyY2VzLCBkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV2ZW50U291cmNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAnRkVUQ0hfRVZFTlRfU09VUkNFUyc6XG4gICAgICAgIGNhc2UgJ0NIQU5HRV9USU1FWk9ORSc6XG4gICAgICAgICAgICByZXR1cm4gZmV0Y2hTb3VyY2VzQnlJZHMoZXZlbnRTb3VyY2VzLCBhY3Rpb24uc291cmNlSWRzID9cbiAgICAgICAgICAgICAgICBhcnJheVRvSGFzaChhY3Rpb24uc291cmNlSWRzKSA6XG4gICAgICAgICAgICAgICAgZXhjbHVkZVN0YXRpY1NvdXJjZXMoZXZlbnRTb3VyY2VzLCBjYWxlbmRhciksIGRhdGVQcm9maWxlID8gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UgOiBudWxsLCBjYWxlbmRhcik7XG4gICAgICAgIGNhc2UgJ1JFQ0VJVkVfRVZFTlRTJzpcbiAgICAgICAgY2FzZSAnUkVDRUlWRV9FVkVOVF9FUlJPUic6XG4gICAgICAgICAgICByZXR1cm4gcmVjZWl2ZVJlc3BvbnNlKGV2ZW50U291cmNlcywgYWN0aW9uLnNvdXJjZUlkLCBhY3Rpb24uZmV0Y2hJZCwgYWN0aW9uLmZldGNoUmFuZ2UpO1xuICAgICAgICBjYXNlICdSRU1PVkVfQUxMX0VWRU5UX1NPVVJDRVMnOlxuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50U291cmNlcztcbiAgICB9XG59XG52YXIgdWlkJDMgPSAwO1xuZnVuY3Rpb24gYWRkU291cmNlcyhldmVudFNvdXJjZUhhc2gsIHNvdXJjZXMsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHNvdXJjZXNfMSA9IHNvdXJjZXM7IF9pIDwgc291cmNlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgc291cmNlID0gc291cmNlc18xW19pXTtcbiAgICAgICAgaGFzaFtzb3VyY2Uuc291cmNlSWRdID0gc291cmNlO1xuICAgIH1cbiAgICBpZiAoZmV0Y2hSYW5nZSkge1xuICAgICAgICBoYXNoID0gZmV0Y2hEaXJ0eVNvdXJjZXMoaGFzaCwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICByZXR1cm4gX19hc3NpZ24oe30sIGV2ZW50U291cmNlSGFzaCwgaGFzaCk7XG59XG5mdW5jdGlvbiByZW1vdmVTb3VyY2UoZXZlbnRTb3VyY2VIYXNoLCBzb3VyY2VJZCkge1xuICAgIHJldHVybiBmaWx0ZXJIYXNoKGV2ZW50U291cmNlSGFzaCwgZnVuY3Rpb24gKGV2ZW50U291cmNlKSB7XG4gICAgICAgIHJldHVybiBldmVudFNvdXJjZS5zb3VyY2VJZCAhPT0gc291cmNlSWQ7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBmZXRjaERpcnR5U291cmNlcyhzb3VyY2VIYXNoLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIHJldHVybiBmZXRjaFNvdXJjZXNCeUlkcyhzb3VyY2VIYXNoLCBmaWx0ZXJIYXNoKHNvdXJjZUhhc2gsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gaXNTb3VyY2VEaXJ0eShldmVudFNvdXJjZSwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpO1xuICAgIH0pLCBmZXRjaFJhbmdlLCBjYWxlbmRhcik7XG59XG5mdW5jdGlvbiBpc1NvdXJjZURpcnR5KGV2ZW50U291cmNlLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIGlmICghZG9lc1NvdXJjZU5lZWRSYW5nZShldmVudFNvdXJjZSwgY2FsZW5kYXIpKSB7XG4gICAgICAgIHJldHVybiAhZXZlbnRTb3VyY2UubGF0ZXN0RmV0Y2hJZDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiAhY2FsZW5kYXIub3B0KCdsYXp5RmV0Y2hpbmcnKSB8fFxuICAgICAgICAgICAgIWV2ZW50U291cmNlLmZldGNoUmFuZ2UgfHxcbiAgICAgICAgICAgIGV2ZW50U291cmNlLmlzRmV0Y2hpbmcgfHwgLy8gYWx3YXlzIGNhbmNlbCBvdXRkYXRlZCBpbi1wcm9ncmVzcyBmZXRjaGVzXG4gICAgICAgICAgICBmZXRjaFJhbmdlLnN0YXJ0IDwgZXZlbnRTb3VyY2UuZmV0Y2hSYW5nZS5zdGFydCB8fFxuICAgICAgICAgICAgZmV0Y2hSYW5nZS5lbmQgPiBldmVudFNvdXJjZS5mZXRjaFJhbmdlLmVuZDtcbiAgICB9XG59XG5mdW5jdGlvbiBmZXRjaFNvdXJjZXNCeUlkcyhwcmV2U291cmNlcywgc291cmNlSWRIYXNoLCBmZXRjaFJhbmdlLCBjYWxlbmRhcikge1xuICAgIHZhciBuZXh0U291cmNlcyA9IHt9O1xuICAgIGZvciAodmFyIHNvdXJjZUlkIGluIHByZXZTb3VyY2VzKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwcmV2U291cmNlc1tzb3VyY2VJZF07XG4gICAgICAgIGlmIChzb3VyY2VJZEhhc2hbc291cmNlSWRdKSB7XG4gICAgICAgICAgICBuZXh0U291cmNlc1tzb3VyY2VJZF0gPSBmZXRjaFNvdXJjZShzb3VyY2UsIGZldGNoUmFuZ2UsIGNhbGVuZGFyKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5leHRTb3VyY2VzW3NvdXJjZUlkXSA9IHNvdXJjZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV4dFNvdXJjZXM7XG59XG5mdW5jdGlvbiBmZXRjaFNvdXJjZShldmVudFNvdXJjZSwgZmV0Y2hSYW5nZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgc291cmNlRGVmID0gY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50U291cmNlRGVmc1tldmVudFNvdXJjZS5zb3VyY2VEZWZJZF07XG4gICAgdmFyIGZldGNoSWQgPSBTdHJpbmcodWlkJDMrKyk7XG4gICAgc291cmNlRGVmLmZldGNoKHtcbiAgICAgICAgZXZlbnRTb3VyY2U6IGV2ZW50U291cmNlLFxuICAgICAgICBjYWxlbmRhcjogY2FsZW5kYXIsXG4gICAgICAgIHJhbmdlOiBmZXRjaFJhbmdlXG4gICAgfSwgZnVuY3Rpb24gKHJlcykge1xuICAgICAgICB2YXIgcmF3RXZlbnRzID0gcmVzLnJhd0V2ZW50cztcbiAgICAgICAgdmFyIGNhbFN1Y2Nlc3MgPSBjYWxlbmRhci5vcHQoJ2V2ZW50U291cmNlU3VjY2VzcycpO1xuICAgICAgICB2YXIgY2FsU3VjY2Vzc1JlcztcbiAgICAgICAgdmFyIHNvdXJjZVN1Y2Nlc3NSZXM7XG4gICAgICAgIGlmIChldmVudFNvdXJjZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICBzb3VyY2VTdWNjZXNzUmVzID0gZXZlbnRTb3VyY2Uuc3VjY2VzcyhyYXdFdmVudHMsIHJlcy54aHIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjYWxTdWNjZXNzKSB7XG4gICAgICAgICAgICBjYWxTdWNjZXNzUmVzID0gY2FsU3VjY2VzcyhyYXdFdmVudHMsIHJlcy54aHIpO1xuICAgICAgICB9XG4gICAgICAgIHJhd0V2ZW50cyA9IHNvdXJjZVN1Y2Nlc3NSZXMgfHwgY2FsU3VjY2Vzc1JlcyB8fCByYXdFdmVudHM7XG4gICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdSRUNFSVZFX0VWRU5UUycsXG4gICAgICAgICAgICBzb3VyY2VJZDogZXZlbnRTb3VyY2Uuc291cmNlSWQsXG4gICAgICAgICAgICBmZXRjaElkOiBmZXRjaElkLFxuICAgICAgICAgICAgZmV0Y2hSYW5nZTogZmV0Y2hSYW5nZSxcbiAgICAgICAgICAgIHJhd0V2ZW50czogcmF3RXZlbnRzXG4gICAgICAgIH0pO1xuICAgIH0sIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICB2YXIgY2FsbEZhaWx1cmUgPSBjYWxlbmRhci5vcHQoJ2V2ZW50U291cmNlRmFpbHVyZScpO1xuICAgICAgICBjb25zb2xlLndhcm4oZXJyb3IubWVzc2FnZSwgZXJyb3IpO1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2UuZmFpbHVyZSkge1xuICAgICAgICAgICAgZXZlbnRTb3VyY2UuZmFpbHVyZShlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNhbGxGYWlsdXJlKSB7XG4gICAgICAgICAgICBjYWxsRmFpbHVyZShlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1JFQ0VJVkVfRVZFTlRfRVJST1InLFxuICAgICAgICAgICAgc291cmNlSWQ6IGV2ZW50U291cmNlLnNvdXJjZUlkLFxuICAgICAgICAgICAgZmV0Y2hJZDogZmV0Y2hJZCxcbiAgICAgICAgICAgIGZldGNoUmFuZ2U6IGZldGNoUmFuZ2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3JcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIF9fYXNzaWduKHt9LCBldmVudFNvdXJjZSwgeyBpc0ZldGNoaW5nOiB0cnVlLCBsYXRlc3RGZXRjaElkOiBmZXRjaElkIH0pO1xufVxuZnVuY3Rpb24gcmVjZWl2ZVJlc3BvbnNlKHNvdXJjZUhhc2gsIHNvdXJjZUlkLCBmZXRjaElkLCBmZXRjaFJhbmdlKSB7XG4gICAgdmFyIF9hO1xuICAgIHZhciBldmVudFNvdXJjZSA9IHNvdXJjZUhhc2hbc291cmNlSWRdO1xuICAgIGlmIChldmVudFNvdXJjZSAmJiAvLyBub3QgYWxyZWFkeSByZW1vdmVkXG4gICAgICAgIGZldGNoSWQgPT09IGV2ZW50U291cmNlLmxhdGVzdEZldGNoSWQpIHtcbiAgICAgICAgcmV0dXJuIF9fYXNzaWduKHt9LCBzb3VyY2VIYXNoLCAoX2EgPSB7fSwgX2Fbc291cmNlSWRdID0gX19hc3NpZ24oe30sIGV2ZW50U291cmNlLCB7IGlzRmV0Y2hpbmc6IGZhbHNlLCBmZXRjaFJhbmdlOiBmZXRjaFJhbmdlIC8vIGFsc28gc2VydmVzIGFzIGEgbWFya2VyIHRoYXQgYXQgbGVhc3Qgb25lIGZldGNoIGhhcyBjb21wbGV0ZWRcbiAgICAgICAgIH0pLCBfYSkpO1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlSGFzaDtcbn1cbmZ1bmN0aW9uIGV4Y2x1ZGVTdGF0aWNTb3VyY2VzKGV2ZW50U291cmNlcywgY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gZmlsdGVySGFzaChldmVudFNvdXJjZXMsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gZG9lc1NvdXJjZU5lZWRSYW5nZShldmVudFNvdXJjZSwgY2FsZW5kYXIpO1xuICAgIH0pO1xufVxuXG52YXIgRGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRGF0ZVByb2ZpbGVHZW5lcmF0b3Iodmlld1NwZWMsIGNhbGVuZGFyKSB7XG4gICAgICAgIHRoaXMudmlld1NwZWMgPSB2aWV3U3BlYztcbiAgICAgICAgdGhpcy5vcHRpb25zID0gdmlld1NwZWMub3B0aW9ucztcbiAgICAgICAgdGhpcy5kYXRlRW52ID0gY2FsZW5kYXIuZGF0ZUVudjtcbiAgICAgICAgdGhpcy5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgICAgICB0aGlzLmluaXRIaWRkZW5EYXlzKCk7XG4gICAgfVxuICAgIC8qIERhdGUgUmFuZ2UgQ29tcHV0YXRpb25cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSB3aXRoIGluZm8gYWJvdXQgd2hhdCB0aGUgZGF0ZXMvcmFuZ2VzIHdpbGwgYmUgZm9yIHRoZSBcInByZXZcIiB2aWV3LlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFByZXYgPSBmdW5jdGlvbiAoY3VycmVudERhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIHByZXZEYXRlID0gZGF0ZUVudi5zdWJ0cmFjdChkYXRlRW52LnN0YXJ0T2YoY3VycmVudERhdGUsIGN1cnJlbnREYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2VVbml0KSwgLy8gaW1wb3J0YW50IGZvciBzdGFydC1vZi1tb250aFxuICAgICAgICBjdXJyZW50RGF0ZVByb2ZpbGUuZGF0ZUluY3JlbWVudCk7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkKHByZXZEYXRlLCAtMSk7XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYSBzdHJ1Y3R1cmUgd2l0aCBpbmZvIGFib3V0IHdoYXQgdGhlIGRhdGVzL3JhbmdlcyB3aWxsIGJlIGZvciB0aGUgXCJuZXh0XCIgdmlldy5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGROZXh0ID0gZnVuY3Rpb24gKGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHZhciBuZXh0RGF0ZSA9IGRhdGVFbnYuYWRkKGRhdGVFbnYuc3RhcnRPZihjdXJyZW50RGF0ZSwgY3VycmVudERhdGVQcm9maWxlLmN1cnJlbnRSYW5nZVVuaXQpLCAvLyBpbXBvcnRhbnQgZm9yIHN0YXJ0LW9mLW1vbnRoXG4gICAgICAgIGN1cnJlbnREYXRlUHJvZmlsZS5kYXRlSW5jcmVtZW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGQobmV4dERhdGUsIDEpO1xuICAgIH07XG4gICAgLy8gQnVpbGRzIGEgc3RydWN0dXJlIGhvbGRpbmcgZGF0ZXMvcmFuZ2VzIGZvciByZW5kZXJpbmcgYXJvdW5kIHRoZSBnaXZlbiBkYXRlLlxuICAgIC8vIE9wdGlvbmFsIGRpcmVjdGlvbiBwYXJhbSBpbmRpY2F0ZXMgd2hldGhlciB0aGUgZGF0ZSBpcyBiZWluZyBpbmNyZW1lbnRlZC9kZWNyZW1lbnRlZFxuICAgIC8vIGZyb20gaXRzIHByZXZpb3VzIHZhbHVlLiBkZWNyZW1lbnRlZCA9IC0xLCBpbmNyZW1lbnRlZCA9IDEgKGRlZmF1bHQpLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZCA9IGZ1bmN0aW9uIChjdXJyZW50RGF0ZSwgZGlyZWN0aW9uLCBmb3JjZVRvVmFsaWQpIHtcbiAgICAgICAgaWYgKGZvcmNlVG9WYWxpZCA9PT0gdm9pZCAwKSB7IGZvcmNlVG9WYWxpZCA9IGZhbHNlOyB9XG4gICAgICAgIHZhciB2YWxpZFJhbmdlO1xuICAgICAgICB2YXIgbWluVGltZSA9IG51bGw7XG4gICAgICAgIHZhciBtYXhUaW1lID0gbnVsbDtcbiAgICAgICAgdmFyIGN1cnJlbnRJbmZvO1xuICAgICAgICB2YXIgaXNSYW5nZUFsbERheTtcbiAgICAgICAgdmFyIHJlbmRlclJhbmdlO1xuICAgICAgICB2YXIgYWN0aXZlUmFuZ2U7XG4gICAgICAgIHZhciBpc1ZhbGlkO1xuICAgICAgICB2YWxpZFJhbmdlID0gdGhpcy5idWlsZFZhbGlkUmFuZ2UoKTtcbiAgICAgICAgdmFsaWRSYW5nZSA9IHRoaXMudHJpbUhpZGRlbkRheXModmFsaWRSYW5nZSk7XG4gICAgICAgIGlmIChmb3JjZVRvVmFsaWQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gY29uc3RyYWluTWFya2VyVG9SYW5nZShjdXJyZW50RGF0ZSwgdmFsaWRSYW5nZSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudEluZm8gPSB0aGlzLmJ1aWxkQ3VycmVudFJhbmdlSW5mbyhjdXJyZW50RGF0ZSwgZGlyZWN0aW9uKTtcbiAgICAgICAgaXNSYW5nZUFsbERheSA9IC9eKHllYXJ8bW9udGh8d2Vla3xkYXkpJC8udGVzdChjdXJyZW50SW5mby51bml0KTtcbiAgICAgICAgcmVuZGVyUmFuZ2UgPSB0aGlzLmJ1aWxkUmVuZGVyUmFuZ2UodGhpcy50cmltSGlkZGVuRGF5cyhjdXJyZW50SW5mby5yYW5nZSksIGN1cnJlbnRJbmZvLnVuaXQsIGlzUmFuZ2VBbGxEYXkpO1xuICAgICAgICByZW5kZXJSYW5nZSA9IHRoaXMudHJpbUhpZGRlbkRheXMocmVuZGVyUmFuZ2UpO1xuICAgICAgICBhY3RpdmVSYW5nZSA9IHJlbmRlclJhbmdlO1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5zaG93Tm9uQ3VycmVudERhdGVzKSB7XG4gICAgICAgICAgICBhY3RpdmVSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhhY3RpdmVSYW5nZSwgY3VycmVudEluZm8ucmFuZ2UpO1xuICAgICAgICB9XG4gICAgICAgIG1pblRpbWUgPSBjcmVhdGVEdXJhdGlvbih0aGlzLm9wdGlvbnMubWluVGltZSk7XG4gICAgICAgIG1heFRpbWUgPSBjcmVhdGVEdXJhdGlvbih0aGlzLm9wdGlvbnMubWF4VGltZSk7XG4gICAgICAgIGFjdGl2ZVJhbmdlID0gdGhpcy5hZGp1c3RBY3RpdmVSYW5nZShhY3RpdmVSYW5nZSwgbWluVGltZSwgbWF4VGltZSk7XG4gICAgICAgIGFjdGl2ZVJhbmdlID0gaW50ZXJzZWN0UmFuZ2VzKGFjdGl2ZVJhbmdlLCB2YWxpZFJhbmdlKTsgLy8gbWlnaHQgcmV0dXJuIG51bGxcbiAgICAgICAgLy8gaXQncyBpbnZhbGlkIGlmIHRoZSBvcmlnaW5hbGx5IHJlcXVlc3RlZCBkYXRlIGlzIG5vdCBjb250YWluZWQsXG4gICAgICAgIC8vIG9yIGlmIHRoZSByYW5nZSBpcyBjb21wbGV0ZWx5IG91dHNpZGUgb2YgdGhlIHZhbGlkIHJhbmdlLlxuICAgICAgICBpc1ZhbGlkID0gcmFuZ2VzSW50ZXJzZWN0KGN1cnJlbnRJbmZvLnJhbmdlLCB2YWxpZFJhbmdlKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC8vIGNvbnN0cmFpbnQgZm9yIHdoZXJlIHByZXYvbmV4dCBvcGVyYXRpb25zIGNhbiBnbyBhbmQgd2hlcmUgZXZlbnRzIGNhbiBiZSBkcmFnZ2VkL3Jlc2l6ZWQgdG8uXG4gICAgICAgICAgICAvLyBhbiBvYmplY3Qgd2l0aCBvcHRpb25hbCBzdGFydCBhbmQgZW5kIHByb3BlcnRpZXMuXG4gICAgICAgICAgICB2YWxpZFJhbmdlOiB2YWxpZFJhbmdlLFxuICAgICAgICAgICAgLy8gcmFuZ2UgdGhlIHZpZXcgaXMgZm9ybWFsbHkgcmVzcG9uc2libGUgZm9yLlxuICAgICAgICAgICAgLy8gZm9yIGV4YW1wbGUsIGEgbW9udGggdmlldyBtaWdodCBoYXZlIDFzdC0zMXN0LCBleGNsdWRpbmcgcGFkZGVkIGRhdGVzXG4gICAgICAgICAgICBjdXJyZW50UmFuZ2U6IGN1cnJlbnRJbmZvLnJhbmdlLFxuICAgICAgICAgICAgLy8gbmFtZSBvZiBsYXJnZXN0IHVuaXQgYmVpbmcgZGlzcGxheWVkLCBsaWtlIFwibW9udGhcIiBvciBcIndlZWtcIlxuICAgICAgICAgICAgY3VycmVudFJhbmdlVW5pdDogY3VycmVudEluZm8udW5pdCxcbiAgICAgICAgICAgIGlzUmFuZ2VBbGxEYXk6IGlzUmFuZ2VBbGxEYXksXG4gICAgICAgICAgICAvLyBkYXRlcyB0aGF0IGRpc3BsYXkgZXZlbnRzIGFuZCBhY2NlcHQgZHJhZy1uLWRyb3BcbiAgICAgICAgICAgIC8vIHdpbGwgYmUgYG51bGxgIGlmIG5vIGRhdGVzIGFjY2VwdCBldmVudHNcbiAgICAgICAgICAgIGFjdGl2ZVJhbmdlOiBhY3RpdmVSYW5nZSxcbiAgICAgICAgICAgIC8vIGRhdGUgcmFuZ2Ugd2l0aCBhIHJlbmRlcmVkIHNrZWxldG9uXG4gICAgICAgICAgICAvLyBpbmNsdWRlcyBub3QtYWN0aXZlIGRheXMgdGhhdCBuZWVkIHNvbWUgc29ydCBvZiBET01cbiAgICAgICAgICAgIHJlbmRlclJhbmdlOiByZW5kZXJSYW5nZSxcbiAgICAgICAgICAgIC8vIER1cmF0aW9uIG9iamVjdCB0aGF0IGRlbm90ZXMgdGhlIGZpcnN0IHZpc2libGUgdGltZSBvZiBhbnkgZ2l2ZW4gZGF5XG4gICAgICAgICAgICBtaW5UaW1lOiBtaW5UaW1lLFxuICAgICAgICAgICAgLy8gRHVyYXRpb24gb2JqZWN0IHRoYXQgZGVub3RlcyB0aGUgZXhjbHVzaXZlIHZpc2libGUgZW5kIHRpbWUgb2YgYW55IGdpdmVuIGRheVxuICAgICAgICAgICAgbWF4VGltZTogbWF4VGltZSxcbiAgICAgICAgICAgIGlzVmFsaWQ6IGlzVmFsaWQsXG4gICAgICAgICAgICAvLyBob3cgZmFyIHRoZSBjdXJyZW50IGRhdGUgd2lsbCBtb3ZlIGZvciBhIHByZXYvbmV4dCBvcGVyYXRpb25cbiAgICAgICAgICAgIGRhdGVJbmNyZW1lbnQ6IHRoaXMuYnVpbGREYXRlSW5jcmVtZW50KGN1cnJlbnRJbmZvLmR1cmF0aW9uKVxuICAgICAgICAgICAgLy8gcGFzcyBhIGZhbGxiYWNrIChtaWdodCBiZSBudWxsKSBeXG4gICAgICAgIH07XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYW4gb2JqZWN0IHdpdGggb3B0aW9uYWwgc3RhcnQvZW5kIHByb3BlcnRpZXMuXG4gICAgLy8gSW5kaWNhdGVzIHRoZSBtaW5pbXVtL21heGltdW0gZGF0ZXMgdG8gZGlzcGxheS5cbiAgICAvLyBub3QgcmVzcG9uc2libGUgZm9yIHRyaW1taW5nIGhpZGRlbiBkYXlzLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFZhbGlkUmFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJhbmdlT3B0aW9uKCd2YWxpZFJhbmdlJywgdGhpcy5jYWxlbmRhci5nZXROb3coKSkgfHxcbiAgICAgICAgICAgIHsgc3RhcnQ6IG51bGwsIGVuZDogbnVsbCB9OyAvLyBjb21wbGV0ZWx5IG9wZW4tZW5kZWRcbiAgICB9O1xuICAgIC8vIEJ1aWxkcyBhIHN0cnVjdHVyZSB3aXRoIGluZm8gYWJvdXQgdGhlIFwiY3VycmVudFwiIHJhbmdlLCB0aGUgcmFuZ2UgdGhhdCBpc1xuICAgIC8vIGhpZ2hsaWdodGVkIGFzIGJlaW5nIHRoZSBjdXJyZW50IG1vbnRoIGZvciBleGFtcGxlLlxuICAgIC8vIFNlZSBidWlsZCgpIGZvciBhIGRlc2NyaXB0aW9uIG9mIGBkaXJlY3Rpb25gLlxuICAgIC8vIEd1YXJhbnRlZWQgdG8gaGF2ZSBgcmFuZ2VgIGFuZCBgdW5pdGAgcHJvcGVydGllcy4gYGR1cmF0aW9uYCBpcyBvcHRpb25hbC5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRDdXJyZW50UmFuZ2VJbmZvID0gZnVuY3Rpb24gKGRhdGUsIGRpcmVjdGlvbikge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCB2aWV3U3BlYyA9IF9hLnZpZXdTcGVjLCBkYXRlRW52ID0gX2EuZGF0ZUVudjtcbiAgICAgICAgdmFyIGR1cmF0aW9uID0gbnVsbDtcbiAgICAgICAgdmFyIHVuaXQgPSBudWxsO1xuICAgICAgICB2YXIgcmFuZ2UgPSBudWxsO1xuICAgICAgICB2YXIgZGF5Q291bnQ7XG4gICAgICAgIGlmICh2aWV3U3BlYy5kdXJhdGlvbikge1xuICAgICAgICAgICAgZHVyYXRpb24gPSB2aWV3U3BlYy5kdXJhdGlvbjtcbiAgICAgICAgICAgIHVuaXQgPSB2aWV3U3BlYy5kdXJhdGlvblVuaXQ7XG4gICAgICAgICAgICByYW5nZSA9IHRoaXMuYnVpbGRSYW5nZUZyb21EdXJhdGlvbihkYXRlLCBkaXJlY3Rpb24sIGR1cmF0aW9uLCB1bml0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgoZGF5Q291bnQgPSB0aGlzLm9wdGlvbnMuZGF5Q291bnQpKSB7XG4gICAgICAgICAgICB1bml0ID0gJ2RheSc7XG4gICAgICAgICAgICByYW5nZSA9IHRoaXMuYnVpbGRSYW5nZUZyb21EYXlDb3VudChkYXRlLCBkaXJlY3Rpb24sIGRheUNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgocmFuZ2UgPSB0aGlzLmJ1aWxkQ3VzdG9tVmlzaWJsZVJhbmdlKGRhdGUpKSkge1xuICAgICAgICAgICAgdW5pdCA9IGRhdGVFbnYuZ3JlYXRlc3RXaG9sZVVuaXQocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCkudW5pdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGR1cmF0aW9uID0gdGhpcy5nZXRGYWxsYmFja0R1cmF0aW9uKCk7XG4gICAgICAgICAgICB1bml0ID0gZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yKGR1cmF0aW9uKS51bml0O1xuICAgICAgICAgICAgcmFuZ2UgPSB0aGlzLmJ1aWxkUmFuZ2VGcm9tRHVyYXRpb24oZGF0ZSwgZGlyZWN0aW9uLCBkdXJhdGlvbiwgdW5pdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZHVyYXRpb246IGR1cmF0aW9uLCB1bml0OiB1bml0LCByYW5nZTogcmFuZ2UgfTtcbiAgICB9O1xuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5nZXRGYWxsYmFja0R1cmF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oeyBkYXk6IDEgfSk7XG4gICAgfTtcbiAgICAvLyBSZXR1cm5zIGEgbmV3IGFjdGl2ZVJhbmdlIHRvIGhhdmUgdGltZSB2YWx1ZXMgKHVuLWFtYmlndWF0ZSlcbiAgICAvLyBtaW5UaW1lIG9yIG1heFRpbWUgY2F1c2VzIHRoZSByYW5nZSB0byBleHBhbmQuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmFkanVzdEFjdGl2ZVJhbmdlID0gZnVuY3Rpb24gKHJhbmdlLCBtaW5UaW1lLCBtYXhUaW1lKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgc3RhcnQgPSByYW5nZS5zdGFydDtcbiAgICAgICAgdmFyIGVuZCA9IHJhbmdlLmVuZDtcbiAgICAgICAgaWYgKHRoaXMudmlld1NwZWMuY2xhc3MucHJvdG90eXBlLnVzZXNNaW5NYXhUaW1lKSB7XG4gICAgICAgICAgICAvLyBleHBhbmQgYWN0aXZlIHJhbmdlIGlmIG1pblRpbWUgaXMgbmVnYXRpdmUgKHdoeSBub3Qgd2hlbiBwb3NpdGl2ZT8pXG4gICAgICAgICAgICBpZiAoYXNSb3VnaERheXMobWluVGltZSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZGF0ZUVudi5hZGQoc3RhcnQsIG1pblRpbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZXhwYW5kIGFjdGl2ZSByYW5nZSBpZiBtYXhUaW1lIGlzIGJleW9uZCBvbmUgZGF5ICh3aHkgbm90IHdoZW4gcG9zaXRpdmU/KVxuICAgICAgICAgICAgaWYgKGFzUm91Z2hEYXlzKG1heFRpbWUpID4gMSkge1xuICAgICAgICAgICAgICAgIGVuZCA9IHN0YXJ0T2ZEYXkoZW5kKTsgLy8gbmVjZXNzYXJ5P1xuICAgICAgICAgICAgICAgIGVuZCA9IGFkZERheXMoZW5kLCAtMSk7XG4gICAgICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoZW5kLCBtYXhUaW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgdGhlIFwiY3VycmVudFwiIHJhbmdlIHdoZW4gaXQgaXMgc3BlY2lmaWVkIGFzIGFuIGV4cGxpY2l0IGR1cmF0aW9uLlxuICAgIC8vIGB1bml0YCBpcyB0aGUgYWxyZWFkeS1jb21wdXRlZCBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IgdW5pdCBvZiBkdXJhdGlvbi5cbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRSYW5nZUZyb21EdXJhdGlvbiA9IGZ1bmN0aW9uIChkYXRlLCBkaXJlY3Rpb24sIGR1cmF0aW9uLCB1bml0KSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgYWxpZ25tZW50ID0gdGhpcy5vcHRpb25zLmRhdGVBbGlnbm1lbnQ7XG4gICAgICAgIHZhciBkYXRlSW5jcmVtZW50SW5wdXQ7XG4gICAgICAgIHZhciBkYXRlSW5jcmVtZW50RHVyYXRpb247XG4gICAgICAgIHZhciBzdGFydDtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgdmFyIHJlcztcbiAgICAgICAgLy8gY29tcHV0ZSB3aGF0IHRoZSBhbGlnbm1lbnQgc2hvdWxkIGJlXG4gICAgICAgIGlmICghYWxpZ25tZW50KSB7XG4gICAgICAgICAgICBkYXRlSW5jcmVtZW50SW5wdXQgPSB0aGlzLm9wdGlvbnMuZGF0ZUluY3JlbWVudDtcbiAgICAgICAgICAgIGlmIChkYXRlSW5jcmVtZW50SW5wdXQpIHtcbiAgICAgICAgICAgICAgICBkYXRlSW5jcmVtZW50RHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbihkYXRlSW5jcmVtZW50SW5wdXQpO1xuICAgICAgICAgICAgICAgIC8vIHVzZSB0aGUgc21hbGxlciBvZiB0aGUgdHdvIHVuaXRzXG4gICAgICAgICAgICAgICAgaWYgKGFzUm91Z2hNcyhkYXRlSW5jcmVtZW50RHVyYXRpb24pIDwgYXNSb3VnaE1zKGR1cmF0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnQgPSBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZGF0ZUluY3JlbWVudER1cmF0aW9uLCAhZ2V0V2Vla3NGcm9tSW5wdXQoZGF0ZUluY3JlbWVudElucHV0KSkudW5pdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFsaWdubWVudCA9IHVuaXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYWxpZ25tZW50ID0gdW5pdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0aGUgdmlldyBkaXNwbGF5cyBhIHNpbmdsZSBkYXkgb3Igc21hbGxlclxuICAgICAgICBpZiAoYXNSb3VnaERheXMoZHVyYXRpb24pIDw9IDEpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzSGlkZGVuRGF5KHN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5za2lwSGlkZGVuRGF5cyhzdGFydCwgZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICBzdGFydCA9IHN0YXJ0T2ZEYXkoc3RhcnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGNvbXB1dGVSZXMoKSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVFbnYuc3RhcnRPZihkYXRlLCBhbGlnbm1lbnQpO1xuICAgICAgICAgICAgZW5kID0gZGF0ZUVudi5hZGQoc3RhcnQsIGR1cmF0aW9uKTtcbiAgICAgICAgICAgIHJlcyA9IHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbXB1dGVSZXMoKTtcbiAgICAgICAgLy8gaWYgcmFuZ2UgaXMgY29tcGxldGVseSBlbnZlbG9wZWQgYnkgaGlkZGVuIGRheXMsIGdvIHBhc3QgdGhlIGhpZGRlbiBkYXlzXG4gICAgICAgIGlmICghdGhpcy50cmltSGlkZGVuRGF5cyhyZXMpKSB7XG4gICAgICAgICAgICBkYXRlID0gdGhpcy5za2lwSGlkZGVuRGF5cyhkYXRlLCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgY29tcHV0ZVJlcygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgdGhlIFwiY3VycmVudFwiIHJhbmdlIHdoZW4gYSBkYXlDb3VudCBpcyBzcGVjaWZpZWQuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkUmFuZ2VGcm9tRGF5Q291bnQgPSBmdW5jdGlvbiAoZGF0ZSwgZGlyZWN0aW9uLCBkYXlDb3VudCkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgdmFyIGN1c3RvbUFsaWdubWVudCA9IHRoaXMub3B0aW9ucy5kYXRlQWxpZ25tZW50O1xuICAgICAgICB2YXIgcnVubmluZ0NvdW50ID0gMDtcbiAgICAgICAgdmFyIHN0YXJ0ID0gZGF0ZTtcbiAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgaWYgKGN1c3RvbUFsaWdubWVudCkge1xuICAgICAgICAgICAgc3RhcnQgPSBkYXRlRW52LnN0YXJ0T2Yoc3RhcnQsIGN1c3RvbUFsaWdubWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhcnQgPSBzdGFydE9mRGF5KHN0YXJ0KTtcbiAgICAgICAgc3RhcnQgPSB0aGlzLnNraXBIaWRkZW5EYXlzKHN0YXJ0LCBkaXJlY3Rpb24pO1xuICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgZW5kID0gYWRkRGF5cyhlbmQsIDEpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzSGlkZGVuRGF5KGVuZCkpIHtcbiAgICAgICAgICAgICAgICBydW5uaW5nQ291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSB3aGlsZSAocnVubmluZ0NvdW50IDwgZGF5Q291bnQpO1xuICAgICAgICByZXR1cm4geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfTtcbiAgICAvLyBCdWlsZHMgYSBub3JtYWxpemVkIHJhbmdlIG9iamVjdCBmb3IgdGhlIFwidmlzaWJsZVwiIHJhbmdlLFxuICAgIC8vIHdoaWNoIGlzIGEgd2F5IHRvIGRlZmluZSB0aGUgY3VycmVudFJhbmdlIGFuZCBhY3RpdmVSYW5nZSBhdCB0aGUgc2FtZSB0aW1lLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZEN1c3RvbVZpc2libGVSYW5nZSA9IGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICB2YXIgdmlzaWJsZVJhbmdlID0gdGhpcy5nZXRSYW5nZU9wdGlvbigndmlzaWJsZVJhbmdlJywgZGF0ZUVudi50b0RhdGUoZGF0ZSkpO1xuICAgICAgICBpZiAodmlzaWJsZVJhbmdlICYmICh2aXNpYmxlUmFuZ2Uuc3RhcnQgPT0gbnVsbCB8fCB2aXNpYmxlUmFuZ2UuZW5kID09IG51bGwpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmlzaWJsZVJhbmdlO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZXMgdGhlIHJhbmdlIHRoYXQgd2lsbCByZXByZXNlbnQgdGhlIGVsZW1lbnQvY2VsbHMgZm9yICpyZW5kZXJpbmcqLFxuICAgIC8vIGJ1dCB3aGljaCBtYXkgaGF2ZSB2b2lkZWQgZGF5cy90aW1lcy5cbiAgICAvLyBub3QgcmVzcG9uc2libGUgZm9yIHRyaW1taW5nIGhpZGRlbiBkYXlzLlxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5idWlsZFJlbmRlclJhbmdlID0gZnVuY3Rpb24gKGN1cnJlbnRSYW5nZSwgY3VycmVudFJhbmdlVW5pdCwgaXNSYW5nZUFsbERheSkge1xuICAgICAgICByZXR1cm4gY3VycmVudFJhbmdlO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZSB0aGUgZHVyYXRpb24gdmFsdWUgdGhhdCBzaG91bGQgYmUgYWRkZWQvc3Vic3RyYWN0ZWQgdG8gdGhlIGN1cnJlbnQgZGF0ZVxuICAgIC8vIHdoZW4gYSBwcmV2L25leHQgb3BlcmF0aW9uIGhhcHBlbnMuXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmJ1aWxkRGF0ZUluY3JlbWVudCA9IGZ1bmN0aW9uIChmYWxsYmFjaykge1xuICAgICAgICB2YXIgZGF0ZUluY3JlbWVudElucHV0ID0gdGhpcy5vcHRpb25zLmRhdGVJbmNyZW1lbnQ7XG4gICAgICAgIHZhciBjdXN0b21BbGlnbm1lbnQ7XG4gICAgICAgIGlmIChkYXRlSW5jcmVtZW50SW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbihkYXRlSW5jcmVtZW50SW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKChjdXN0b21BbGlnbm1lbnQgPSB0aGlzLm9wdGlvbnMuZGF0ZUFsaWdubWVudCkpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbigxLCBjdXN0b21BbGlnbm1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGZhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsbGJhY2s7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oeyBkYXlzOiAxIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBBcmd1bWVudHMgYWZ0ZXIgbmFtZSB3aWxsIGJlIGZvcndhcmRlZCB0byBhIGh5cG90aGV0aWNhbCBmdW5jdGlvbiB2YWx1ZVxuICAgIC8vIFdBUk5JTkc6IHBhc3NlZC1pbiBhcmd1bWVudHMgd2lsbCBiZSBnaXZlbiB0byBnZW5lcmF0b3IgZnVuY3Rpb25zIGFzLWlzIGFuZCBjYW4gY2F1c2Ugc2lkZS1lZmZlY3RzLlxuICAgIC8vIEFsd2F5cyBjbG9uZSB5b3VyIG9iamVjdHMgaWYgeW91IGZlYXIgbXV0YXRpb24uXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmdldFJhbmdlT3B0aW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIG90aGVyQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDE7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgb3RoZXJBcmdzW19pIC0gMV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLm9wdGlvbnNbbmFtZV07XG4gICAgICAgIGlmICh0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB2YWwgPSB2YWwuYXBwbHkobnVsbCwgb3RoZXJBcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsKSB7XG4gICAgICAgICAgICB2YWwgPSBwYXJzZVJhbmdlKHZhbCwgdGhpcy5kYXRlRW52KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsKSB7XG4gICAgICAgICAgICB2YWwgPSBjb21wdXRlVmlzaWJsZURheVJhbmdlKHZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9O1xuICAgIC8qIEhpZGRlbiBEYXlzXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAvLyBJbml0aWFsaXplcyBpbnRlcm5hbCB2YXJpYWJsZXMgcmVsYXRlZCB0byBjYWxjdWxhdGluZyBoaWRkZW4gZGF5cy1vZi13ZWVrXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLmluaXRIaWRkZW5EYXlzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGlkZGVuRGF5cyA9IHRoaXMub3B0aW9ucy5oaWRkZW5EYXlzIHx8IFtdOyAvLyBhcnJheSBvZiBkYXktb2Ytd2VlayBpbmRpY2VzIHRoYXQgYXJlIGhpZGRlblxuICAgICAgICB2YXIgaXNIaWRkZW5EYXlIYXNoID0gW107IC8vIGlzIHRoZSBkYXktb2Ytd2VlayBoaWRkZW4/IChoYXNoIHdpdGggZGF5LW9mLXdlZWstaW5kZXggLT4gYm9vbClcbiAgICAgICAgdmFyIGRheUNudCA9IDA7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLndlZWtlbmRzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgaGlkZGVuRGF5cy5wdXNoKDAsIDYpOyAvLyAwPXN1bmRheSwgNj1zYXR1cmRheVxuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIGlmICghKGlzSGlkZGVuRGF5SGFzaFtpXSA9IGhpZGRlbkRheXMuaW5kZXhPZihpKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAgICAgZGF5Q250Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXlDbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBoaWRkZW5EYXlzJyk7IC8vIGFsbCBkYXlzIHdlcmUgaGlkZGVuPyBiYWQuXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc0hpZGRlbkRheUhhc2ggPSBpc0hpZGRlbkRheUhhc2g7XG4gICAgfTtcbiAgICAvLyBSZW1vdmUgZGF5cyBmcm9tIHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGUgcmFuZ2UgdGhhdCBhcmUgY29tcHV0ZWQgYXMgaGlkZGVuLlxuICAgIC8vIElmIHRoZSB3aG9sZSByYW5nZSBpcyB0cmltbWVkIG9mZiwgcmV0dXJucyBudWxsXG4gICAgRGF0ZVByb2ZpbGVHZW5lcmF0b3IucHJvdG90eXBlLnRyaW1IaWRkZW5EYXlzID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gICAgICAgIHZhciBzdGFydCA9IHJhbmdlLnN0YXJ0O1xuICAgICAgICB2YXIgZW5kID0gcmFuZ2UuZW5kO1xuICAgICAgICBpZiAoc3RhcnQpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5za2lwSGlkZGVuRGF5cyhzdGFydCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVuZCkge1xuICAgICAgICAgICAgZW5kID0gdGhpcy5za2lwSGlkZGVuRGF5cyhlbmQsIC0xLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RhcnQgPT0gbnVsbCB8fCBlbmQgPT0gbnVsbCB8fCBzdGFydCA8IGVuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLy8gSXMgdGhlIGN1cnJlbnQgZGF5IGhpZGRlbj9cbiAgICAvLyBgZGF5YCBpcyBhIGRheS1vZi13ZWVrIGluZGV4ICgwLTYpLCBvciBhIERhdGUgKHVzZWQgZm9yIFVUQylcbiAgICBEYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuaXNIaWRkZW5EYXkgPSBmdW5jdGlvbiAoZGF5KSB7XG4gICAgICAgIGlmIChkYXkgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgICBkYXkgPSBkYXkuZ2V0VVRDRGF5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaXNIaWRkZW5EYXlIYXNoW2RheV07XG4gICAgfTtcbiAgICAvLyBJbmNyZW1lbnRpbmcgdGhlIGN1cnJlbnQgZGF5IHVudGlsIGl0IGlzIG5vIGxvbmdlciBhIGhpZGRlbiBkYXksIHJldHVybmluZyBhIGNvcHkuXG4gICAgLy8gRE9FUyBOT1QgQ09OU0lERVIgdmFsaWRSYW5nZSFcbiAgICAvLyBJZiB0aGUgaW5pdGlhbCB2YWx1ZSBvZiBgZGF0ZWAgaXMgbm90IGEgaGlkZGVuIGRheSwgZG9uJ3QgZG8gYW55dGhpbmcuXG4gICAgLy8gUGFzcyBgaXNFeGNsdXNpdmVgIGFzIGB0cnVlYCBpZiB5b3UgYXJlIGRlYWxpbmcgd2l0aCBhbiBlbmQgZGF0ZS5cbiAgICAvLyBgaW5jYCBkZWZhdWx0cyB0byBgMWAgKGluY3JlbWVudCBvbmUgZGF5IGZvcndhcmQgZWFjaCB0aW1lKVxuICAgIERhdGVQcm9maWxlR2VuZXJhdG9yLnByb3RvdHlwZS5za2lwSGlkZGVuRGF5cyA9IGZ1bmN0aW9uIChkYXRlLCBpbmMsIGlzRXhjbHVzaXZlKSB7XG4gICAgICAgIGlmIChpbmMgPT09IHZvaWQgMCkgeyBpbmMgPSAxOyB9XG4gICAgICAgIGlmIChpc0V4Y2x1c2l2ZSA9PT0gdm9pZCAwKSB7IGlzRXhjbHVzaXZlID0gZmFsc2U7IH1cbiAgICAgICAgd2hpbGUgKHRoaXMuaXNIaWRkZW5EYXlIYXNoWyhkYXRlLmdldFVUQ0RheSgpICsgKGlzRXhjbHVzaXZlID8gaW5jIDogMCkgKyA3KSAlIDddKSB7XG4gICAgICAgICAgICBkYXRlID0gYWRkRGF5cyhkYXRlLCBpbmMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVQcm9maWxlR2VuZXJhdG9yO1xufSgpKTtcbi8vIFRPRE86IGZpbmQgYSB3YXkgdG8gYXZvaWQgY29tcGFyaW5nIERhdGVQcm9maWxlcy4gaXQncyB0ZWRpb3VzXG5mdW5jdGlvbiBpc0RhdGVQcm9maWxlc0VxdWFsKHAwLCBwMSkge1xuICAgIHJldHVybiByYW5nZXNFcXVhbChwMC52YWxpZFJhbmdlLCBwMS52YWxpZFJhbmdlKSAmJlxuICAgICAgICByYW5nZXNFcXVhbChwMC5hY3RpdmVSYW5nZSwgcDEuYWN0aXZlUmFuZ2UpICYmXG4gICAgICAgIHJhbmdlc0VxdWFsKHAwLnJlbmRlclJhbmdlLCBwMS5yZW5kZXJSYW5nZSkgJiZcbiAgICAgICAgZHVyYXRpb25zRXF1YWwocDAubWluVGltZSwgcDEubWluVGltZSkgJiZcbiAgICAgICAgZHVyYXRpb25zRXF1YWwocDAubWF4VGltZSwgcDEubWF4VGltZSk7XG4gICAgLypcbiAgICBUT0RPOiBjb21wYXJlIG1vcmU/XG4gICAgICBjdXJyZW50UmFuZ2U6IERhdGVSYW5nZVxuICAgICAgY3VycmVudFJhbmdlVW5pdDogc3RyaW5nXG4gICAgICBpc1JhbmdlQWxsRGF5OiBib29sZWFuXG4gICAgICBpc1ZhbGlkOiBib29sZWFuXG4gICAgICBkYXRlSW5jcmVtZW50OiBEdXJhdGlvblxuICAgICovXG59XG5cbmZ1bmN0aW9uIHJlZHVjZSAoc3RhdGUsIGFjdGlvbiwgY2FsZW5kYXIpIHtcbiAgICB2YXIgdmlld1R5cGUgPSByZWR1Y2VWaWV3VHlwZShzdGF0ZS52aWV3VHlwZSwgYWN0aW9uKTtcbiAgICB2YXIgZGF0ZVByb2ZpbGUgPSByZWR1Y2VEYXRlUHJvZmlsZShzdGF0ZS5kYXRlUHJvZmlsZSwgYWN0aW9uLCBzdGF0ZS5jdXJyZW50RGF0ZSwgdmlld1R5cGUsIGNhbGVuZGFyKTtcbiAgICB2YXIgZXZlbnRTb3VyY2VzID0gcmVkdWNlRXZlbnRTb3VyY2VzKHN0YXRlLmV2ZW50U291cmNlcywgYWN0aW9uLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXIpO1xuICAgIHZhciBuZXh0U3RhdGUgPSBfX2Fzc2lnbih7fSwgc3RhdGUsIHsgdmlld1R5cGU6IHZpZXdUeXBlLFxuICAgICAgICBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlOiByZWR1Y2VDdXJyZW50RGF0ZShzdGF0ZS5jdXJyZW50RGF0ZSwgYWN0aW9uLCBkYXRlUHJvZmlsZSksIGV2ZW50U291cmNlczogZXZlbnRTb3VyY2VzLCBldmVudFN0b3JlOiByZWR1Y2VFdmVudFN0b3JlKHN0YXRlLmV2ZW50U3RvcmUsIGFjdGlvbiwgZXZlbnRTb3VyY2VzLCBkYXRlUHJvZmlsZSwgY2FsZW5kYXIpLCBkYXRlU2VsZWN0aW9uOiByZWR1Y2VEYXRlU2VsZWN0aW9uKHN0YXRlLmRhdGVTZWxlY3Rpb24sIGFjdGlvbiwgY2FsZW5kYXIpLCBldmVudFNlbGVjdGlvbjogcmVkdWNlU2VsZWN0ZWRFdmVudChzdGF0ZS5ldmVudFNlbGVjdGlvbiwgYWN0aW9uKSwgZXZlbnREcmFnOiByZWR1Y2VFdmVudERyYWcoc3RhdGUuZXZlbnREcmFnLCBhY3Rpb24sIGV2ZW50U291cmNlcywgY2FsZW5kYXIpLCBldmVudFJlc2l6ZTogcmVkdWNlRXZlbnRSZXNpemUoc3RhdGUuZXZlbnRSZXNpemUsIGFjdGlvbiwgZXZlbnRTb3VyY2VzLCBjYWxlbmRhciksIGV2ZW50U291cmNlTG9hZGluZ0xldmVsOiBjb21wdXRlTG9hZGluZ0xldmVsKGV2ZW50U291cmNlcyksIGxvYWRpbmdMZXZlbDogY29tcHV0ZUxvYWRpbmdMZXZlbChldmVudFNvdXJjZXMpIH0pO1xuICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBjYWxlbmRhci5wbHVnaW5TeXN0ZW0uaG9va3MucmVkdWNlcnM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciByZWR1Y2VyRnVuYyA9IF9hW19pXTtcbiAgICAgICAgbmV4dFN0YXRlID0gcmVkdWNlckZ1bmMobmV4dFN0YXRlLCBhY3Rpb24sIGNhbGVuZGFyKTtcbiAgICB9XG4gICAgLy8gY29uc29sZS5sb2coYWN0aW9uLnR5cGUsIG5leHRTdGF0ZSlcbiAgICByZXR1cm4gbmV4dFN0YXRlO1xufVxuZnVuY3Rpb24gcmVkdWNlVmlld1R5cGUoY3VycmVudFZpZXdUeXBlLCBhY3Rpb24pIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbi52aWV3VHlwZTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50Vmlld1R5cGU7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlRGF0ZVByb2ZpbGUoY3VycmVudERhdGVQcm9maWxlLCBhY3Rpb24sIGN1cnJlbnREYXRlLCB2aWV3VHlwZSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgbmV3RGF0ZVByb2ZpbGU7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdQUkVWJzpcbiAgICAgICAgICAgIG5ld0RhdGVQcm9maWxlID0gY2FsZW5kYXIuZGF0ZVByb2ZpbGVHZW5lcmF0b3JzW3ZpZXdUeXBlXS5idWlsZFByZXYoY3VycmVudERhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgICAgICBuZXdEYXRlUHJvZmlsZSA9IGNhbGVuZGFyLmRhdGVQcm9maWxlR2VuZXJhdG9yc1t2aWV3VHlwZV0uYnVpbGROZXh0KGN1cnJlbnREYXRlUHJvZmlsZSwgY3VycmVudERhdGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ1NFVF9EQVRFJzpcbiAgICAgICAgICAgIGlmICghY3VycmVudERhdGVQcm9maWxlLmFjdGl2ZVJhbmdlIHx8XG4gICAgICAgICAgICAgICAgIXJhbmdlQ29udGFpbnNNYXJrZXIoY3VycmVudERhdGVQcm9maWxlLmN1cnJlbnRSYW5nZSwgYWN0aW9uLmRhdGVNYXJrZXIpKSB7XG4gICAgICAgICAgICAgICAgbmV3RGF0ZVByb2ZpbGUgPSBjYWxlbmRhci5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdLmJ1aWxkKGFjdGlvbi5kYXRlTWFya2VyLCB1bmRlZmluZWQsIHRydWUgLy8gZm9yY2VUb1ZhbGlkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdTRVRfVklFV19UWVBFJzpcbiAgICAgICAgICAgIHZhciBnZW5lcmF0b3IgPSBjYWxlbmRhci5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdO1xuICAgICAgICAgICAgaWYgKCFnZW5lcmF0b3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3Iodmlld1R5cGUgP1xuICAgICAgICAgICAgICAgICAgICAnVGhlIEZ1bGxDYWxlbmRhciB2aWV3IFwiJyArIHZpZXdUeXBlICsgJ1wiIGRvZXMgbm90IGV4aXN0LiBNYWtlIHN1cmUgeW91ciBwbHVnaW5zIGFyZSBsb2FkZWQgY29ycmVjdGx5LicgOlxuICAgICAgICAgICAgICAgICAgICAnTm8gYXZhaWxhYmxlIEZ1bGxDYWxlbmRhciB2aWV3IHBsdWdpbnMuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXdEYXRlUHJvZmlsZSA9IGdlbmVyYXRvci5idWlsZChhY3Rpb24uZGF0ZU1hcmtlciB8fCBjdXJyZW50RGF0ZSwgdW5kZWZpbmVkLCB0cnVlIC8vIGZvcmNlVG9WYWxpZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpZiAobmV3RGF0ZVByb2ZpbGUgJiZcbiAgICAgICAgbmV3RGF0ZVByb2ZpbGUuaXNWYWxpZCAmJlxuICAgICAgICAhKGN1cnJlbnREYXRlUHJvZmlsZSAmJiBpc0RhdGVQcm9maWxlc0VxdWFsKGN1cnJlbnREYXRlUHJvZmlsZSwgbmV3RGF0ZVByb2ZpbGUpKSkge1xuICAgICAgICByZXR1cm4gbmV3RGF0ZVByb2ZpbGU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gY3VycmVudERhdGVQcm9maWxlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJlZHVjZUN1cnJlbnREYXRlKGN1cnJlbnREYXRlLCBhY3Rpb24sIGRhdGVQcm9maWxlKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdQUkVWJzpcbiAgICAgICAgY2FzZSAnTkVYVCc6XG4gICAgICAgICAgICBpZiAoIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLCBjdXJyZW50RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnREYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICBjYXNlICdTRVRfREFURSc6XG4gICAgICAgIGNhc2UgJ1NFVF9WSUVXX1RZUEUnOlxuICAgICAgICAgICAgdmFyIG5ld0RhdGUgPSBhY3Rpb24uZGF0ZU1hcmtlciB8fCBjdXJyZW50RGF0ZTtcbiAgICAgICAgICAgIGlmIChkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSAmJiAhcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgbmV3RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld0RhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudERhdGU7XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlRGF0ZVNlbGVjdGlvbihjdXJyZW50U2VsZWN0aW9uLCBhY3Rpb24sIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRUxFQ1RfREFURVMnOlxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbi5zZWxlY3Rpb247XG4gICAgICAgIGNhc2UgJ1VOU0VMRUNUX0RBVEVTJzpcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRTZWxlY3Rpb247XG4gICAgfVxufVxuZnVuY3Rpb24gcmVkdWNlU2VsZWN0ZWRFdmVudChjdXJyZW50SW5zdGFuY2VJZCwgYWN0aW9uKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRUxFQ1RfRVZFTlQnOlxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbi5ldmVudEluc3RhbmNlSWQ7XG4gICAgICAgIGNhc2UgJ1VOU0VMRUNUX0VWRU5UJzpcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50SW5zdGFuY2VJZDtcbiAgICB9XG59XG5mdW5jdGlvbiByZWR1Y2VFdmVudERyYWcoY3VycmVudERyYWcsIGFjdGlvbiwgc291cmNlcywgY2FsZW5kYXIpIHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ1NFVF9FVkVOVF9EUkFHJzpcbiAgICAgICAgICAgIHZhciBuZXdEcmFnID0gYWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogbmV3RHJhZy5hZmZlY3RlZEV2ZW50cyxcbiAgICAgICAgICAgICAgICBtdXRhdGVkRXZlbnRzOiBuZXdEcmFnLm11dGF0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgaXNFdmVudDogbmV3RHJhZy5pc0V2ZW50LFxuICAgICAgICAgICAgICAgIG9yaWdTZWc6IG5ld0RyYWcub3JpZ1NlZ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAnVU5TRVRfRVZFTlRfRFJBRyc6XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50RHJhZztcbiAgICB9XG59XG5mdW5jdGlvbiByZWR1Y2VFdmVudFJlc2l6ZShjdXJyZW50UmVzaXplLCBhY3Rpb24sIHNvdXJjZXMsIGNhbGVuZGFyKSB7XG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlICdTRVRfRVZFTlRfUkVTSVpFJzpcbiAgICAgICAgICAgIHZhciBuZXdSZXNpemUgPSBhY3Rpb24uc3RhdGU7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFmZmVjdGVkRXZlbnRzOiBuZXdSZXNpemUuYWZmZWN0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogbmV3UmVzaXplLm11dGF0ZWRFdmVudHMsXG4gICAgICAgICAgICAgICAgaXNFdmVudDogbmV3UmVzaXplLmlzRXZlbnQsXG4gICAgICAgICAgICAgICAgb3JpZ1NlZzogbmV3UmVzaXplLm9yaWdTZWdcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgJ1VOU0VUX0VWRU5UX1JFU0laRSc6XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50UmVzaXplO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNvbXB1dGVMb2FkaW5nTGV2ZWwoZXZlbnRTb3VyY2VzKSB7XG4gICAgdmFyIGNudCA9IDA7XG4gICAgZm9yICh2YXIgc291cmNlSWQgaW4gZXZlbnRTb3VyY2VzKSB7XG4gICAgICAgIGlmIChldmVudFNvdXJjZXNbc291cmNlSWRdLmlzRmV0Y2hpbmcpIHtcbiAgICAgICAgICAgIGNudCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjbnQ7XG59XG5cbnZhciBTVEFOREFSRF9QUk9QUyA9IHtcbiAgICBzdGFydDogbnVsbCxcbiAgICBlbmQ6IG51bGwsXG4gICAgYWxsRGF5OiBCb29sZWFuXG59O1xuZnVuY3Rpb24gcGFyc2VEYXRlU3BhbihyYXcsIGRhdGVFbnYsIGRlZmF1bHREdXJhdGlvbikge1xuICAgIHZhciBzcGFuID0gcGFyc2VPcGVuRGF0ZVNwYW4ocmF3LCBkYXRlRW52KTtcbiAgICB2YXIgcmFuZ2UgPSBzcGFuLnJhbmdlO1xuICAgIGlmICghcmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICghcmFuZ2UuZW5kKSB7XG4gICAgICAgIGlmIChkZWZhdWx0RHVyYXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByYW5nZS5lbmQgPSBkYXRlRW52LmFkZChyYW5nZS5zdGFydCwgZGVmYXVsdER1cmF0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3Bhbjtcbn1cbi8qXG5UT0RPOiBzb21laG93IGNvbWJpbmUgd2l0aCBwYXJzZVJhbmdlP1xuV2lsbCByZXR1cm4gbnVsbCBpZiB0aGUgc3RhcnQvZW5kIHByb3BzIHdlcmUgcHJlc2VudCBidXQgcGFyc2VkIGludmFsaWRseS5cbiovXG5mdW5jdGlvbiBwYXJzZU9wZW5EYXRlU3BhbihyYXcsIGRhdGVFbnYpIHtcbiAgICB2YXIgbGVmdG92ZXJzID0ge307XG4gICAgdmFyIHN0YW5kYXJkUHJvcHMgPSByZWZpbmVQcm9wcyhyYXcsIFNUQU5EQVJEX1BST1BTLCB7fSwgbGVmdG92ZXJzKTtcbiAgICB2YXIgc3RhcnRNZXRhID0gc3RhbmRhcmRQcm9wcy5zdGFydCA/IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShzdGFuZGFyZFByb3BzLnN0YXJ0KSA6IG51bGw7XG4gICAgdmFyIGVuZE1ldGEgPSBzdGFuZGFyZFByb3BzLmVuZCA/IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShzdGFuZGFyZFByb3BzLmVuZCkgOiBudWxsO1xuICAgIHZhciBhbGxEYXkgPSBzdGFuZGFyZFByb3BzLmFsbERheTtcbiAgICBpZiAoYWxsRGF5ID09IG51bGwpIHtcbiAgICAgICAgYWxsRGF5ID0gKHN0YXJ0TWV0YSAmJiBzdGFydE1ldGEuaXNUaW1lVW5zcGVjaWZpZWQpICYmXG4gICAgICAgICAgICAoIWVuZE1ldGEgfHwgZW5kTWV0YS5pc1RpbWVVbnNwZWNpZmllZCk7XG4gICAgfVxuICAgIC8vIHVzZSB0aGlzIGxlZnRvdmVyIG9iamVjdCBhcyB0aGUgc2VsZWN0aW9uIG9iamVjdFxuICAgIGxlZnRvdmVycy5yYW5nZSA9IHtcbiAgICAgICAgc3RhcnQ6IHN0YXJ0TWV0YSA/IHN0YXJ0TWV0YS5tYXJrZXIgOiBudWxsLFxuICAgICAgICBlbmQ6IGVuZE1ldGEgPyBlbmRNZXRhLm1hcmtlciA6IG51bGxcbiAgICB9O1xuICAgIGxlZnRvdmVycy5hbGxEYXkgPSBhbGxEYXk7XG4gICAgcmV0dXJuIGxlZnRvdmVycztcbn1cbmZ1bmN0aW9uIGlzRGF0ZVNwYW5zRXF1YWwoc3BhbjAsIHNwYW4xKSB7XG4gICAgcmV0dXJuIHJhbmdlc0VxdWFsKHNwYW4wLnJhbmdlLCBzcGFuMS5yYW5nZSkgJiZcbiAgICAgICAgc3BhbjAuYWxsRGF5ID09PSBzcGFuMS5hbGxEYXkgJiZcbiAgICAgICAgaXNTcGFuUHJvcHNFcXVhbChzcGFuMCwgc3BhbjEpO1xufVxuLy8gdGhlIE5PTi1EQVRFLVJFTEFURUQgcHJvcHNcbmZ1bmN0aW9uIGlzU3BhblByb3BzRXF1YWwoc3BhbjAsIHNwYW4xKSB7XG4gICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gc3BhbjEpIHtcbiAgICAgICAgaWYgKHByb3BOYW1lICE9PSAncmFuZ2UnICYmIHByb3BOYW1lICE9PSAnYWxsRGF5Jykge1xuICAgICAgICAgICAgaWYgKHNwYW4wW3Byb3BOYW1lXSAhPT0gc3BhbjFbcHJvcE5hbWVdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGFyZSB0aGVyZSBhbnkgcHJvcHMgdGhhdCBzcGFuMCBoYXMgdGhhdCBzcGFuMSBET0VTTidUIGhhdmU/XG4gICAgLy8gYm90aCBoYXZlIHJhbmdlL2FsbERheSwgc28gbm8gbmVlZCB0byBzcGVjaWFsLWNhc2UuXG4gICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gc3BhbjApIHtcbiAgICAgICAgaWYgKCEocHJvcE5hbWUgaW4gc3BhbjEpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBidWlsZERhdGVTcGFuQXBpKHNwYW4sIGRhdGVFbnYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogZGF0ZUVudi50b0RhdGUoc3Bhbi5yYW5nZS5zdGFydCksXG4gICAgICAgIGVuZDogZGF0ZUVudi50b0RhdGUoc3Bhbi5yYW5nZS5lbmQpLFxuICAgICAgICBzdGFydFN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5zdGFydCwgeyBvbWl0VGltZTogc3Bhbi5hbGxEYXkgfSksXG4gICAgICAgIGVuZFN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5lbmQsIHsgb21pdFRpbWU6IHNwYW4uYWxsRGF5IH0pLFxuICAgICAgICBhbGxEYXk6IHNwYW4uYWxsRGF5XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRGF0ZVBvaW50QXBpKHNwYW4sIGRhdGVFbnYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBkYXRlOiBkYXRlRW52LnRvRGF0ZShzcGFuLnJhbmdlLnN0YXJ0KSxcbiAgICAgICAgZGF0ZVN0cjogZGF0ZUVudi5mb3JtYXRJc28oc3Bhbi5yYW5nZS5zdGFydCwgeyBvbWl0VGltZTogc3Bhbi5hbGxEYXkgfSksXG4gICAgICAgIGFsbERheTogc3Bhbi5hbGxEYXlcbiAgICB9O1xufVxuZnVuY3Rpb24gZmFicmljYXRlRXZlbnRSYW5nZShkYXRlU3BhbiwgZXZlbnRVaUJhc2VzLCBjYWxlbmRhcikge1xuICAgIHZhciBkZWYgPSBwYXJzZUV2ZW50RGVmKHsgZWRpdGFibGU6IGZhbHNlIH0sICcnLCAvLyBzb3VyY2VJZFxuICAgIGRhdGVTcGFuLmFsbERheSwgdHJ1ZSwgLy8gaGFzRW5kXG4gICAgY2FsZW5kYXIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGRlZjogZGVmLFxuICAgICAgICB1aTogY29tcGlsZUV2ZW50VWkoZGVmLCBldmVudFVpQmFzZXMpLFxuICAgICAgICBpbnN0YW5jZTogY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIGRhdGVTcGFuLnJhbmdlKSxcbiAgICAgICAgcmFuZ2U6IGRhdGVTcGFuLnJhbmdlLFxuICAgICAgICBpc1N0YXJ0OiB0cnVlLFxuICAgICAgICBpc0VuZDogdHJ1ZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVWaWV3RGVmcyhkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKSB7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICB2YXIgdmlld1R5cGU7XG4gICAgZm9yICh2aWV3VHlwZSBpbiBkZWZhdWx0Q29uZmlncykge1xuICAgICAgICBlbnN1cmVWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICB9XG4gICAgZm9yICh2aWV3VHlwZSBpbiBvdmVycmlkZUNvbmZpZ3MpIHtcbiAgICAgICAgZW5zdXJlVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgfVxuICAgIHJldHVybiBoYXNoO1xufVxuZnVuY3Rpb24gZW5zdXJlVmlld0RlZih2aWV3VHlwZSwgaGFzaCwgZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncykge1xuICAgIGlmIChoYXNoW3ZpZXdUeXBlXSkge1xuICAgICAgICByZXR1cm4gaGFzaFt2aWV3VHlwZV07XG4gICAgfVxuICAgIHZhciB2aWV3RGVmID0gYnVpbGRWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICBpZiAodmlld0RlZikge1xuICAgICAgICBoYXNoW3ZpZXdUeXBlXSA9IHZpZXdEZWY7XG4gICAgfVxuICAgIHJldHVybiB2aWV3RGVmO1xufVxuZnVuY3Rpb24gYnVpbGRWaWV3RGVmKHZpZXdUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKSB7XG4gICAgdmFyIGRlZmF1bHRDb25maWcgPSBkZWZhdWx0Q29uZmlnc1t2aWV3VHlwZV07XG4gICAgdmFyIG92ZXJyaWRlQ29uZmlnID0gb3ZlcnJpZGVDb25maWdzW3ZpZXdUeXBlXTtcbiAgICB2YXIgcXVlcnlQcm9wID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIChkZWZhdWx0Q29uZmlnICYmIGRlZmF1bHRDb25maWdbbmFtZV0gIT09IG51bGwpID8gZGVmYXVsdENvbmZpZ1tuYW1lXSA6XG4gICAgICAgICAgICAoKG92ZXJyaWRlQ29uZmlnICYmIG92ZXJyaWRlQ29uZmlnW25hbWVdICE9PSBudWxsKSA/IG92ZXJyaWRlQ29uZmlnW25hbWVdIDogbnVsbCk7XG4gICAgfTtcbiAgICB2YXIgdGhlQ2xhc3MgPSBxdWVyeVByb3AoJ2NsYXNzJyk7XG4gICAgdmFyIHN1cGVyVHlwZSA9IHF1ZXJ5UHJvcCgnc3VwZXJUeXBlJyk7XG4gICAgaWYgKCFzdXBlclR5cGUgJiYgdGhlQ2xhc3MpIHtcbiAgICAgICAgc3VwZXJUeXBlID1cbiAgICAgICAgICAgIGZpbmRWaWV3TmFtZUJ5U3ViY2xhc3ModGhlQ2xhc3MsIG92ZXJyaWRlQ29uZmlncykgfHxcbiAgICAgICAgICAgICAgICBmaW5kVmlld05hbWVCeVN1YmNsYXNzKHRoZUNsYXNzLCBkZWZhdWx0Q29uZmlncyk7XG4gICAgfVxuICAgIHZhciBzdXBlckRlZiA9IG51bGw7XG4gICAgaWYgKHN1cGVyVHlwZSkge1xuICAgICAgICBpZiAoc3VwZXJUeXBlID09PSB2aWV3VHlwZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IGhhdmUgYSBjdXN0b20gdmlldyB0eXBlIHRoYXQgcmVmZXJlbmNlcyBpdHNlbGYnKTtcbiAgICAgICAgfVxuICAgICAgICBzdXBlckRlZiA9IGVuc3VyZVZpZXdEZWYoc3VwZXJUeXBlLCBoYXNoLCBkZWZhdWx0Q29uZmlncywgb3ZlcnJpZGVDb25maWdzKTtcbiAgICB9XG4gICAgaWYgKCF0aGVDbGFzcyAmJiBzdXBlckRlZikge1xuICAgICAgICB0aGVDbGFzcyA9IHN1cGVyRGVmLmNsYXNzO1xuICAgIH1cbiAgICBpZiAoIXRoZUNsYXNzKSB7XG4gICAgICAgIHJldHVybiBudWxsOyAvLyBkb24ndCB0aHJvdyBhIHdhcm5pbmcsIG1pZ2h0IGJlIHNldHRpbmdzIGZvciBhIHNpbmdsZS11bml0IHZpZXdcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogdmlld1R5cGUsXG4gICAgICAgIGNsYXNzOiB0aGVDbGFzcyxcbiAgICAgICAgZGVmYXVsdHM6IF9fYXNzaWduKHt9LCAoc3VwZXJEZWYgPyBzdXBlckRlZi5kZWZhdWx0cyA6IHt9KSwgKGRlZmF1bHRDb25maWcgPyBkZWZhdWx0Q29uZmlnLm9wdGlvbnMgOiB7fSkpLFxuICAgICAgICBvdmVycmlkZXM6IF9fYXNzaWduKHt9LCAoc3VwZXJEZWYgPyBzdXBlckRlZi5vdmVycmlkZXMgOiB7fSksIChvdmVycmlkZUNvbmZpZyA/IG92ZXJyaWRlQ29uZmlnLm9wdGlvbnMgOiB7fSkpXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGZpbmRWaWV3TmFtZUJ5U3ViY2xhc3Modmlld1N1YmNsYXNzLCBjb25maWdzKSB7XG4gICAgdmFyIHN1cGVyUHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yodmlld1N1YmNsYXNzLnByb3RvdHlwZSk7XG4gICAgZm9yICh2YXIgdmlld1R5cGUgaW4gY29uZmlncykge1xuICAgICAgICB2YXIgcGFyc2VkID0gY29uZmlnc1t2aWV3VHlwZV07XG4gICAgICAgIC8vIG5lZWQgRElSRUNUIHN1YmNsYXNzLCBzbyBpbnN0YW5jZW9mIHdvbid0IGRvIGl0XG4gICAgICAgIGlmIChwYXJzZWQuY2xhc3MgJiYgcGFyc2VkLmNsYXNzLnByb3RvdHlwZSA9PT0gc3VwZXJQcm90bykge1xuICAgICAgICAgICAgcmV0dXJuIHZpZXdUeXBlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiAnJztcbn1cblxuZnVuY3Rpb24gcGFyc2VWaWV3Q29uZmlncyhpbnB1dHMpIHtcbiAgICByZXR1cm4gbWFwSGFzaChpbnB1dHMsIHBhcnNlVmlld0NvbmZpZyk7XG59XG52YXIgVklFV19ERUZfUFJPUFMgPSB7XG4gICAgdHlwZTogU3RyaW5nLFxuICAgIGNsYXNzOiBudWxsXG59O1xuZnVuY3Rpb24gcGFyc2VWaWV3Q29uZmlnKGlucHV0KSB7XG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBpbnB1dCA9IHsgY2xhc3M6IGlucHV0IH07XG4gICAgfVxuICAgIHZhciBvcHRpb25zID0ge307XG4gICAgdmFyIHByb3BzID0gcmVmaW5lUHJvcHMoaW5wdXQsIFZJRVdfREVGX1BST1BTLCB7fSwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3VwZXJUeXBlOiBwcm9wcy50eXBlLFxuICAgICAgICBjbGFzczogcHJvcHMuY2xhc3MsXG4gICAgICAgIG9wdGlvbnM6IG9wdGlvbnNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZFZpZXdTcGVjcyhkZWZhdWx0SW5wdXRzLCBvcHRpb25zTWFuYWdlcikge1xuICAgIHZhciBkZWZhdWx0Q29uZmlncyA9IHBhcnNlVmlld0NvbmZpZ3MoZGVmYXVsdElucHV0cyk7XG4gICAgdmFyIG92ZXJyaWRlQ29uZmlncyA9IHBhcnNlVmlld0NvbmZpZ3Mob3B0aW9uc01hbmFnZXIub3ZlcnJpZGVzLnZpZXdzKTtcbiAgICB2YXIgdmlld0RlZnMgPSBjb21waWxlVmlld0RlZnMoZGVmYXVsdENvbmZpZ3MsIG92ZXJyaWRlQ29uZmlncyk7XG4gICAgcmV0dXJuIG1hcEhhc2godmlld0RlZnMsIGZ1bmN0aW9uICh2aWV3RGVmKSB7XG4gICAgICAgIHJldHVybiBidWlsZFZpZXdTcGVjKHZpZXdEZWYsIG92ZXJyaWRlQ29uZmlncywgb3B0aW9uc01hbmFnZXIpO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gYnVpbGRWaWV3U3BlYyh2aWV3RGVmLCBvdmVycmlkZUNvbmZpZ3MsIG9wdGlvbnNNYW5hZ2VyKSB7XG4gICAgdmFyIGR1cmF0aW9uSW5wdXQgPSB2aWV3RGVmLm92ZXJyaWRlcy5kdXJhdGlvbiB8fFxuICAgICAgICB2aWV3RGVmLmRlZmF1bHRzLmR1cmF0aW9uIHx8XG4gICAgICAgIG9wdGlvbnNNYW5hZ2VyLmR5bmFtaWNPdmVycmlkZXMuZHVyYXRpb24gfHxcbiAgICAgICAgb3B0aW9uc01hbmFnZXIub3ZlcnJpZGVzLmR1cmF0aW9uO1xuICAgIHZhciBkdXJhdGlvbiA9IG51bGw7XG4gICAgdmFyIGR1cmF0aW9uVW5pdCA9ICcnO1xuICAgIHZhciBzaW5nbGVVbml0ID0gJyc7XG4gICAgdmFyIHNpbmdsZVVuaXRPdmVycmlkZXMgPSB7fTtcbiAgICBpZiAoZHVyYXRpb25JbnB1dCkge1xuICAgICAgICBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKGR1cmF0aW9uSW5wdXQpO1xuICAgICAgICBpZiAoZHVyYXRpb24pIHsgLy8gdmFsaWQ/XG4gICAgICAgICAgICB2YXIgZGVub20gPSBncmVhdGVzdER1cmF0aW9uRGVub21pbmF0b3IoZHVyYXRpb24sICFnZXRXZWVrc0Zyb21JbnB1dChkdXJhdGlvbklucHV0KSk7XG4gICAgICAgICAgICBkdXJhdGlvblVuaXQgPSBkZW5vbS51bml0O1xuICAgICAgICAgICAgaWYgKGRlbm9tLnZhbHVlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlVW5pdCA9IGR1cmF0aW9uVW5pdDtcbiAgICAgICAgICAgICAgICBzaW5nbGVVbml0T3ZlcnJpZGVzID0gb3ZlcnJpZGVDb25maWdzW2R1cmF0aW9uVW5pdF0gPyBvdmVycmlkZUNvbmZpZ3NbZHVyYXRpb25Vbml0XS5vcHRpb25zIDoge307XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIHF1ZXJ5QnV0dG9uVGV4dCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciBidXR0b25UZXh0TWFwID0gb3B0aW9ucy5idXR0b25UZXh0IHx8IHt9O1xuICAgICAgICB2YXIgYnV0dG9uVGV4dEtleSA9IHZpZXdEZWYuZGVmYXVsdHMuYnV0dG9uVGV4dEtleTtcbiAgICAgICAgaWYgKGJ1dHRvblRleHRLZXkgIT0gbnVsbCAmJiBidXR0b25UZXh0TWFwW2J1dHRvblRleHRLZXldICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBidXR0b25UZXh0TWFwW2J1dHRvblRleHRLZXldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChidXR0b25UZXh0TWFwW3ZpZXdEZWYudHlwZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGJ1dHRvblRleHRNYXBbdmlld0RlZi50eXBlXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9uVGV4dE1hcFtzaW5nbGVVbml0XSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYnV0dG9uVGV4dE1hcFtzaW5nbGVVbml0XTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogdmlld0RlZi50eXBlLFxuICAgICAgICBjbGFzczogdmlld0RlZi5jbGFzcyxcbiAgICAgICAgZHVyYXRpb246IGR1cmF0aW9uLFxuICAgICAgICBkdXJhdGlvblVuaXQ6IGR1cmF0aW9uVW5pdCxcbiAgICAgICAgc2luZ2xlVW5pdDogc2luZ2xlVW5pdCxcbiAgICAgICAgb3B0aW9uczogX19hc3NpZ24oe30sIGdsb2JhbERlZmF1bHRzLCB2aWV3RGVmLmRlZmF1bHRzLCBvcHRpb25zTWFuYWdlci5kaXJEZWZhdWx0cywgb3B0aW9uc01hbmFnZXIubG9jYWxlRGVmYXVsdHMsIG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcywgc2luZ2xlVW5pdE92ZXJyaWRlcywgdmlld0RlZi5vdmVycmlkZXMsIG9wdGlvbnNNYW5hZ2VyLmR5bmFtaWNPdmVycmlkZXMpLFxuICAgICAgICBidXR0b25UZXh0T3ZlcnJpZGU6IHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5keW5hbWljT3ZlcnJpZGVzKSB8fFxuICAgICAgICAgICAgcXVlcnlCdXR0b25UZXh0KG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcykgfHwgLy8gY29uc3RydWN0b3Itc3BlY2lmaWVkIGJ1dHRvblRleHQgbG9va3VwIGhhc2ggdGFrZXMgcHJlY2VkZW5jZVxuICAgICAgICAgICAgdmlld0RlZi5vdmVycmlkZXMuYnV0dG9uVGV4dCxcbiAgICAgICAgYnV0dG9uVGV4dERlZmF1bHQ6IHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5sb2NhbGVEZWZhdWx0cykgfHxcbiAgICAgICAgICAgIHF1ZXJ5QnV0dG9uVGV4dChvcHRpb25zTWFuYWdlci5kaXJEZWZhdWx0cykgfHxcbiAgICAgICAgICAgIHZpZXdEZWYuZGVmYXVsdHMuYnV0dG9uVGV4dCB8fFxuICAgICAgICAgICAgcXVlcnlCdXR0b25UZXh0KGdsb2JhbERlZmF1bHRzKSB8fFxuICAgICAgICAgICAgdmlld0RlZi50eXBlIC8vIGZhbGwgYmFjayB0byBnaXZlbiB2aWV3IG5hbWVcbiAgICB9O1xufVxuXG52YXIgVG9vbGJhciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoVG9vbGJhciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBUb29sYmFyKGV4dHJhQ2xhc3NOYW1lKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLl9yZW5kZXJMYXlvdXQgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckxheW91dCwgX3RoaXMudW5yZW5kZXJMYXlvdXQpO1xuICAgICAgICBfdGhpcy5fdXBkYXRlVGl0bGUgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnVwZGF0ZVRpdGxlLCBudWxsLCBbX3RoaXMuX3JlbmRlckxheW91dF0pO1xuICAgICAgICBfdGhpcy5fdXBkYXRlQWN0aXZlQnV0dG9uID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy51cGRhdGVBY3RpdmVCdXR0b24sIG51bGwsIFtfdGhpcy5fcmVuZGVyTGF5b3V0XSk7XG4gICAgICAgIF90aGlzLl91cGRhdGVUb2RheSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMudXBkYXRlVG9kYXksIG51bGwsIFtfdGhpcy5fcmVuZGVyTGF5b3V0XSk7XG4gICAgICAgIF90aGlzLl91cGRhdGVQcmV2ID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy51cGRhdGVQcmV2LCBudWxsLCBbX3RoaXMuX3JlbmRlckxheW91dF0pO1xuICAgICAgICBfdGhpcy5fdXBkYXRlTmV4dCA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMudXBkYXRlTmV4dCwgbnVsbCwgW190aGlzLl9yZW5kZXJMYXlvdXRdKTtcbiAgICAgICAgX3RoaXMuZWwgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLXRvb2xiYXIgJyArIGV4dHJhQ2xhc3NOYW1lIH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFRvb2xiYXIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLl9yZW5kZXJMYXlvdXQudW5yZW5kZXIoKTsgLy8gc2hvdWxkIHVucmVuZGVyIGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICByZW1vdmVFbGVtZW50KHRoaXMuZWwpO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlckxheW91dChwcm9wcy5sYXlvdXQpO1xuICAgICAgICB0aGlzLl91cGRhdGVUaXRsZShwcm9wcy50aXRsZSk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUFjdGl2ZUJ1dHRvbihwcm9wcy5hY3RpdmVCdXR0b24pO1xuICAgICAgICB0aGlzLl91cGRhdGVUb2RheShwcm9wcy5pc1RvZGF5RW5hYmxlZCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZXYocHJvcHMuaXNQcmV2RW5hYmxlZCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZU5leHQocHJvcHMuaXNOZXh0RW5hYmxlZCk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS5yZW5kZXJMYXlvdXQgPSBmdW5jdGlvbiAobGF5b3V0KSB7XG4gICAgICAgIHZhciBlbCA9IHRoaXMuZWw7XG4gICAgICAgIHRoaXMudmlld3NXaXRoQnV0dG9ucyA9IFtdO1xuICAgICAgICBhcHBlbmRUb0VsZW1lbnQoZWwsIHRoaXMucmVuZGVyU2VjdGlvbignbGVmdCcsIGxheW91dC5sZWZ0KSk7XG4gICAgICAgIGFwcGVuZFRvRWxlbWVudChlbCwgdGhpcy5yZW5kZXJTZWN0aW9uKCdjZW50ZXInLCBsYXlvdXQuY2VudGVyKSk7XG4gICAgICAgIGFwcGVuZFRvRWxlbWVudChlbCwgdGhpcy5yZW5kZXJTZWN0aW9uKCdyaWdodCcsIGxheW91dC5yaWdodCkpO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUudW5yZW5kZXJMYXlvdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gJyc7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS5yZW5kZXJTZWN0aW9uID0gZnVuY3Rpb24gKHBvc2l0aW9uLCBidXR0b25TdHIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCB0aGVtZSA9IF9hLnRoZW1lLCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyO1xuICAgICAgICB2YXIgb3B0aW9uc01hbmFnZXIgPSBjYWxlbmRhci5vcHRpb25zTWFuYWdlcjtcbiAgICAgICAgdmFyIHZpZXdTcGVjcyA9IGNhbGVuZGFyLnZpZXdTcGVjcztcbiAgICAgICAgdmFyIHNlY3Rpb25FbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHsgY2xhc3NOYW1lOiAnZmMtJyArIHBvc2l0aW9uIH0pO1xuICAgICAgICB2YXIgY2FsZW5kYXJDdXN0b21CdXR0b25zID0gb3B0aW9uc01hbmFnZXIuY29tcHV0ZWQuY3VzdG9tQnV0dG9ucyB8fCB7fTtcbiAgICAgICAgdmFyIGNhbGVuZGFyQnV0dG9uVGV4dE92ZXJyaWRlcyA9IG9wdGlvbnNNYW5hZ2VyLm92ZXJyaWRlcy5idXR0b25UZXh0IHx8IHt9O1xuICAgICAgICB2YXIgY2FsZW5kYXJCdXR0b25UZXh0ID0gb3B0aW9uc01hbmFnZXIuY29tcHV0ZWQuYnV0dG9uVGV4dCB8fCB7fTtcbiAgICAgICAgaWYgKGJ1dHRvblN0cikge1xuICAgICAgICAgICAgYnV0dG9uU3RyLnNwbGl0KCcgJykuZm9yRWFjaChmdW5jdGlvbiAoYnV0dG9uR3JvdXBTdHIsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBDaGlsZHJlbiA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpc09ubHlCdXR0b25zID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBFbDtcbiAgICAgICAgICAgICAgICBidXR0b25Hcm91cFN0ci5zcGxpdCgnLCcpLmZvckVhY2goZnVuY3Rpb24gKGJ1dHRvbk5hbWUsIGopIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN1c3RvbUJ1dHRvblByb3BzO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmlld1NwZWM7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25DbGljaztcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbkljb247IC8vIG9ubHkgb25lIG9mIHRoZXNlIHdpbGwgYmUgc2V0XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25UZXh0OyAvLyBcIlxuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uSW5uZXJIdG1sO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uQ2xhc3NlcztcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1dHRvbkVsO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnV0dG9uQXJpYUF0dHI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChidXR0b25OYW1lID09PSAndGl0bGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cENoaWxkcmVuLnB1c2goaHRtbFRvRWxlbWVudCgnPGgyPiZuYnNwOzwvaDI+JykpOyAvLyB3ZSBhbHdheXMgd2FudCBpdCB0byB0YWtlIHVwIGhlaWdodFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNPbmx5QnV0dG9ucyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChjdXN0b21CdXR0b25Qcm9wcyA9IGNhbGVuZGFyQ3VzdG9tQnV0dG9uc1tidXR0b25OYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25DbGljayA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VzdG9tQnV0dG9uUHJvcHMuY2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbUJ1dHRvblByb3BzLmNsaWNrLmNhbGwoYnV0dG9uRWwsIGV2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvbkljb24gPSB0aGVtZS5nZXRDdXN0b21CdXR0b25JY29uQ2xhc3MoY3VzdG9tQnV0dG9uUHJvcHMpKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uSWNvbiA9IHRoZW1lLmdldEljb25DbGFzcyhidXR0b25OYW1lKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSBjdXN0b21CdXR0b25Qcm9wcy50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCh2aWV3U3BlYyA9IHZpZXdTcGVjc1tidXR0b25OYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy52aWV3c1dpdGhCdXR0b25zLnB1c2goYnV0dG9uTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQ2xpY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmNoYW5nZVZpZXcoYnV0dG9uTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uVGV4dCA9IHZpZXdTcGVjLmJ1dHRvblRleHRPdmVycmlkZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvbkljb24gPSB0aGVtZS5nZXRJY29uQ2xhc3MoYnV0dG9uTmFtZSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25UZXh0ID0gdmlld1NwZWMuYnV0dG9uVGV4dERlZmF1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY2FsZW5kYXJbYnV0dG9uTmFtZV0pIHsgLy8gYSBjYWxlbmRhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25DbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXJbYnV0dG9uTmFtZV0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChidXR0b25UZXh0ID0gY2FsZW5kYXJCdXR0b25UZXh0T3ZlcnJpZGVzW2J1dHRvbk5hbWVdKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYnV0dG9uSWNvbiA9IHRoZW1lLmdldEljb25DbGFzcyhidXR0b25OYW1lKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJ1dHRvblRleHQgPSBjYWxlbmRhckJ1dHRvblRleHRbYnV0dG9uTmFtZV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgXiBldmVyeXRoaW5nIGVsc2UgaXMgY29uc2lkZXJlZCBkZWZhdWx0XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYnV0dG9uQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25DbGFzc2VzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZmMtJyArIGJ1dHRvbk5hbWUgKyAnLWJ1dHRvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lLmdldENsYXNzKCdidXR0b24nKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJ1dHRvblRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uSW5uZXJIdG1sID0gaHRtbEVzY2FwZShidXR0b25UZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uQXJpYUF0dHIgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYnV0dG9uSWNvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25Jbm5lckh0bWwgPSBcIjxzcGFuIGNsYXNzPSdcIiArIGJ1dHRvbkljb24gKyBcIic+PC9zcGFuPlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25BcmlhQXR0ciA9ICcgYXJpYS1sYWJlbD1cIicgKyBidXR0b25OYW1lICsgJ1wiJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uRWwgPSBodG1sVG9FbGVtZW50KC8vIHR5cGU9XCJidXR0b25cIiBzbyB0aGF0IGl0IGRvZXNuJ3Qgc3VibWl0IGEgZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIicgKyBidXR0b25DbGFzc2VzLmpvaW4oJyAnKSArICdcIicgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25BcmlhQXR0ciArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc+JyArIGJ1dHRvbklubmVySHRtbCArICc8L2J1dHRvbj4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25FbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGJ1dHRvbkNsaWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cENoaWxkcmVuLnB1c2goYnV0dG9uRWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGdyb3VwQ2hpbGRyZW4ubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBncm91cEVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidXR0b25Hcm91cENsYXNzTmFtZSA9IHRoZW1lLmdldENsYXNzKCdidXR0b25Hcm91cCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNPbmx5QnV0dG9ucyAmJiBidXR0b25Hcm91cENsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBFbC5jbGFzc0xpc3QuYWRkKGJ1dHRvbkdyb3VwQ2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQoZ3JvdXBFbCwgZ3JvdXBDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25FbC5hcHBlbmRDaGlsZChncm91cEVsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudChzZWN0aW9uRWwsIGdyb3VwQ2hpbGRyZW4pOyAvLyAxIG9yIDAgY2hpbGRyZW5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VjdGlvbkVsO1xuICAgIH07XG4gICAgVG9vbGJhci5wcm90b3R5cGUudXBkYXRlVG9kYXkgPSBmdW5jdGlvbiAoaXNUb2RheUVuYWJsZWQpIHtcbiAgICAgICAgdGhpcy50b2dnbGVCdXR0b25FbmFibGVkKCd0b2RheScsIGlzVG9kYXlFbmFibGVkKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZVByZXYgPSBmdW5jdGlvbiAoaXNQcmV2RW5hYmxlZCkge1xuICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbkVuYWJsZWQoJ3ByZXYnLCBpc1ByZXZFbmFibGVkKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZU5leHQgPSBmdW5jdGlvbiAoaXNOZXh0RW5hYmxlZCkge1xuICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbkVuYWJsZWQoJ25leHQnLCBpc05leHRFbmFibGVkKTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnVwZGF0ZVRpdGxlID0gZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgZmluZEVsZW1lbnRzKHRoaXMuZWwsICdoMicpLmZvckVhY2goZnVuY3Rpb24gKHRpdGxlRWwpIHtcbiAgICAgICAgICAgIHRpdGxlRWwuaW5uZXJUZXh0ID0gdGV4dDtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBUb29sYmFyLnByb3RvdHlwZS51cGRhdGVBY3RpdmVCdXR0b24gPSBmdW5jdGlvbiAoYnV0dG9uTmFtZSkge1xuICAgICAgICB2YXIgdGhlbWUgPSB0aGlzLmNvbnRleHQudGhlbWU7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSB0aGVtZS5nZXRDbGFzcygnYnV0dG9uQWN0aXZlJyk7XG4gICAgICAgIGZpbmRFbGVtZW50cyh0aGlzLmVsLCAnYnV0dG9uJykuZm9yRWFjaChmdW5jdGlvbiAoYnV0dG9uRWwpIHtcbiAgICAgICAgICAgIGlmIChidXR0b25OYW1lICYmIGJ1dHRvbkVsLmNsYXNzTGlzdC5jb250YWlucygnZmMtJyArIGJ1dHRvbk5hbWUgKyAnLWJ1dHRvbicpKSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uRWwuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uRWwuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFRvb2xiYXIucHJvdG90eXBlLnRvZ2dsZUJ1dHRvbkVuYWJsZWQgPSBmdW5jdGlvbiAoYnV0dG9uTmFtZSwgYm9vbCkge1xuICAgICAgICBmaW5kRWxlbWVudHModGhpcy5lbCwgJy5mYy0nICsgYnV0dG9uTmFtZSArICctYnV0dG9uJykuZm9yRWFjaChmdW5jdGlvbiAoYnV0dG9uRWwpIHtcbiAgICAgICAgICAgIGJ1dHRvbkVsLmRpc2FibGVkID0gIWJvb2w7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIFRvb2xiYXI7XG59KENvbXBvbmVudCkpO1xuXG52YXIgQ2FsZW5kYXJDb21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKENhbGVuZGFyQ29tcG9uZW50LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENhbGVuZGFyQ29tcG9uZW50KGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmVsQ2xhc3NOYW1lcyA9IFtdO1xuICAgICAgICBfdGhpcy5yZW5kZXJTa2VsZXRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclNrZWxldG9uLCBfdGhpcy5fdW5yZW5kZXJTa2VsZXRvbik7XG4gICAgICAgIF90aGlzLnJlbmRlclRvb2xiYXJzID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyVG9vbGJhcnMsIF90aGlzLl91bnJlbmRlclRvb2xiYXJzLCBbX3RoaXMucmVuZGVyU2tlbGV0b25dKTtcbiAgICAgICAgX3RoaXMuYnVpbGRDb21wb25lbnRDb250ZXh0ID0gbWVtb2l6ZShidWlsZENvbXBvbmVudENvbnRleHQpO1xuICAgICAgICBfdGhpcy5idWlsZFZpZXdQcm9wVHJhbnNmb3JtZXJzID0gbWVtb2l6ZShidWlsZFZpZXdQcm9wVHJhbnNmb3JtZXJzKTtcbiAgICAgICAgX3RoaXMuZWwgPSBlbDtcbiAgICAgICAgX3RoaXMuY29tcHV0ZVRpdGxlID0gbWVtb2l6ZShjb21wdXRlVGl0bGUpO1xuICAgICAgICBfdGhpcy5wYXJzZUJ1c2luZXNzSG91cnMgPSBtZW1vaXplKGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIHBhcnNlQnVzaW5lc3NIb3VycyhpbnB1dCwgX3RoaXMuY29udGV4dC5jYWxlbmRhcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5mcmVlemVIZWlnaHQoKTtcbiAgICAgICAgdmFyIHRpdGxlID0gdGhpcy5jb21wdXRlVGl0bGUocHJvcHMuZGF0ZVByb2ZpbGUsIHByb3BzLnZpZXdTcGVjLm9wdGlvbnMpO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uKGNvbnRleHQpO1xuICAgICAgICB0aGlzLnJlbmRlclRvb2xiYXJzKHByb3BzLnZpZXdTcGVjLCBwcm9wcy5kYXRlUHJvZmlsZSwgcHJvcHMuY3VycmVudERhdGUsIHRpdGxlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJWaWV3KHByb3BzLCB0aXRsZSk7XG4gICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICB0aGlzLnRoYXdIZWlnaHQoKTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5mb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uLnVucmVuZGVyKCk7IC8vIHdpbGwgY2FsbCBkZXN0cm95Vmlld1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5fcmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUVsQ2xhc3NOYW1lcyhjb250ZXh0KTtcbiAgICAgICAgcHJlcGVuZFRvRWxlbWVudCh0aGlzLmVsLCB0aGlzLmNvbnRlbnRFbCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIHsgY2xhc3NOYW1lOiAnZmMtdmlldy1jb250YWluZXInIH0pKTtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy52aWV3Q29udGFpbmVyTW9kaWZpZXJzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIG1vZGlmeVZpZXdDb250YWluZXIgPSBfYVtfaV07XG4gICAgICAgICAgICBtb2RpZnlWaWV3Q29udGFpbmVyKHRoaXMuY29udGVudEVsLCBjYWxlbmRhcik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5fdW5yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2VpcmQgdG8gaGF2ZSB0aGlzIGhlcmVcbiAgICAgICAgaWYgKHRoaXMudmlldykge1xuICAgICAgICAgICAgdGhpcy5zYXZlZFNjcm9sbCA9IHRoaXMudmlldy5xdWVyeVNjcm9sbCgpO1xuICAgICAgICAgICAgdGhpcy52aWV3LmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHRoaXMudmlldyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmVtb3ZlRWxlbWVudCh0aGlzLmNvbnRlbnRFbCk7XG4gICAgICAgIHRoaXMucmVtb3ZlRWxDbGFzc05hbWVzKCk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUucmVtb3ZlRWxDbGFzc05hbWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2xhc3NMaXN0ID0gdGhpcy5lbC5jbGFzc0xpc3Q7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmVsQ2xhc3NOYW1lczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBjbGFzc05hbWUgPSBfYVtfaV07XG4gICAgICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbENsYXNzTmFtZXMgPSBbXTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS51cGRhdGVFbENsYXNzTmFtZXMgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB0aGlzLnJlbW92ZUVsQ2xhc3NOYW1lcygpO1xuICAgICAgICB2YXIgdGhlbWUgPSBjb250ZXh0LnRoZW1lLCBvcHRpb25zID0gY29udGV4dC5vcHRpb25zO1xuICAgICAgICB0aGlzLmVsQ2xhc3NOYW1lcyA9IFtcbiAgICAgICAgICAgICdmYycsXG4gICAgICAgICAgICAnZmMtJyArIG9wdGlvbnMuZGlyLFxuICAgICAgICAgICAgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldCcpXG4gICAgICAgIF07XG4gICAgICAgIHZhciBjbGFzc0xpc3QgPSB0aGlzLmVsLmNsYXNzTGlzdDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZWxDbGFzc05hbWVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGNsYXNzTmFtZSA9IF9hW19pXTtcbiAgICAgICAgICAgIGNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLl9yZW5kZXJUb29sYmFycyA9IGZ1bmN0aW9uICh2aWV3U3BlYywgZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlLCB0aXRsZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBjb250ZXh0ID0gX2EuY29udGV4dCwgaGVhZGVyID0gX2EuaGVhZGVyLCBmb290ZXIgPSBfYS5mb290ZXI7XG4gICAgICAgIHZhciBvcHRpb25zID0gY29udGV4dC5vcHRpb25zLCBjYWxlbmRhciA9IGNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBoZWFkZXJMYXlvdXQgPSBvcHRpb25zLmhlYWRlcjtcbiAgICAgICAgdmFyIGZvb3RlckxheW91dCA9IG9wdGlvbnMuZm9vdGVyO1xuICAgICAgICB2YXIgZGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSB0aGlzLnByb3BzLmRhdGVQcm9maWxlR2VuZXJhdG9yO1xuICAgICAgICB2YXIgbm93ID0gY2FsZW5kYXIuZ2V0Tm93KCk7XG4gICAgICAgIHZhciB0b2RheUluZm8gPSBkYXRlUHJvZmlsZUdlbmVyYXRvci5idWlsZChub3cpO1xuICAgICAgICB2YXIgcHJldkluZm8gPSBkYXRlUHJvZmlsZUdlbmVyYXRvci5idWlsZFByZXYoZGF0ZVByb2ZpbGUsIGN1cnJlbnREYXRlKTtcbiAgICAgICAgdmFyIG5leHRJbmZvID0gZGF0ZVByb2ZpbGVHZW5lcmF0b3IuYnVpbGROZXh0KGRhdGVQcm9maWxlLCBjdXJyZW50RGF0ZSk7XG4gICAgICAgIHZhciB0b29sYmFyUHJvcHMgPSB7XG4gICAgICAgICAgICB0aXRsZTogdGl0bGUsXG4gICAgICAgICAgICBhY3RpdmVCdXR0b246IHZpZXdTcGVjLnR5cGUsXG4gICAgICAgICAgICBpc1RvZGF5RW5hYmxlZDogdG9kYXlJbmZvLmlzVmFsaWQgJiYgIXJhbmdlQ29udGFpbnNNYXJrZXIoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLCBub3cpLFxuICAgICAgICAgICAgaXNQcmV2RW5hYmxlZDogcHJldkluZm8uaXNWYWxpZCxcbiAgICAgICAgICAgIGlzTmV4dEVuYWJsZWQ6IG5leHRJbmZvLmlzVmFsaWRcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGhlYWRlckxheW91dCkge1xuICAgICAgICAgICAgaWYgKCFoZWFkZXIpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXIgPSB0aGlzLmhlYWRlciA9IG5ldyBUb29sYmFyKCdmYy1oZWFkZXItdG9vbGJhcicpO1xuICAgICAgICAgICAgICAgIHByZXBlbmRUb0VsZW1lbnQodGhpcy5lbCwgaGVhZGVyLmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhlYWRlci5yZWNlaXZlUHJvcHMoX19hc3NpZ24oeyBsYXlvdXQ6IGhlYWRlckxheW91dCB9LCB0b29sYmFyUHJvcHMpLCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChoZWFkZXIpIHtcbiAgICAgICAgICAgIGhlYWRlci5kZXN0cm95KCk7XG4gICAgICAgICAgICBoZWFkZXIgPSB0aGlzLmhlYWRlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvb3RlckxheW91dCkge1xuICAgICAgICAgICAgaWYgKCFmb290ZXIpIHtcbiAgICAgICAgICAgICAgICBmb290ZXIgPSB0aGlzLmZvb3RlciA9IG5ldyBUb29sYmFyKCdmYy1mb290ZXItdG9vbGJhcicpO1xuICAgICAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudCh0aGlzLmVsLCBmb290ZXIuZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9vdGVyLnJlY2VpdmVQcm9wcyhfX2Fzc2lnbih7IGxheW91dDogZm9vdGVyTGF5b3V0IH0sIHRvb2xiYXJQcm9wcyksIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGZvb3Rlcikge1xuICAgICAgICAgICAgZm9vdGVyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIGZvb3RlciA9IHRoaXMuZm9vdGVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLl91bnJlbmRlclRvb2xiYXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5mb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHRoaXMuZm9vdGVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnJlbmRlclZpZXcgPSBmdW5jdGlvbiAocHJvcHMsIHRpdGxlKSB7XG4gICAgICAgIHZhciB2aWV3ID0gdGhpcy52aWV3O1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIG9wdGlvbnMgPSBfYS5vcHRpb25zO1xuICAgICAgICB2YXIgdmlld1NwZWMgPSBwcm9wcy52aWV3U3BlYywgZGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSBwcm9wcy5kYXRlUHJvZmlsZUdlbmVyYXRvcjtcbiAgICAgICAgaWYgKCF2aWV3IHx8IHZpZXcudmlld1NwZWMgIT09IHZpZXdTcGVjKSB7XG4gICAgICAgICAgICBpZiAodmlldykge1xuICAgICAgICAgICAgICAgIHZpZXcuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmlldyA9IHRoaXMudmlldyA9IG5ldyB2aWV3U3BlY1snY2xhc3MnXSh2aWV3U3BlYywgdGhpcy5jb250ZW50RWwpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc2F2ZWRTY3JvbGwpIHtcbiAgICAgICAgICAgICAgICB2aWV3LmFkZFNjcm9sbCh0aGlzLnNhdmVkU2Nyb2xsLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNhdmVkU2Nyb2xsID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2aWV3LnRpdGxlID0gdGl0bGU7IC8vIGZvciB0aGUgQVBJXG4gICAgICAgIHZhciB2aWV3UHJvcHMgPSB7XG4gICAgICAgICAgICBkYXRlUHJvZmlsZUdlbmVyYXRvcjogZGF0ZVByb2ZpbGVHZW5lcmF0b3IsXG4gICAgICAgICAgICBkYXRlUHJvZmlsZTogcHJvcHMuZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICBidXNpbmVzc0hvdXJzOiB0aGlzLnBhcnNlQnVzaW5lc3NIb3Vycyh2aWV3U3BlYy5vcHRpb25zLmJ1c2luZXNzSG91cnMpLFxuICAgICAgICAgICAgZXZlbnRTdG9yZTogcHJvcHMuZXZlbnRTdG9yZSxcbiAgICAgICAgICAgIGV2ZW50VWlCYXNlczogcHJvcHMuZXZlbnRVaUJhc2VzLFxuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvbjogcHJvcHMuZGF0ZVNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IHByb3BzLmV2ZW50UmVzaXplXG4gICAgICAgIH07XG4gICAgICAgIHZhciB0cmFuc2Zvcm1lcnMgPSB0aGlzLmJ1aWxkVmlld1Byb3BUcmFuc2Zvcm1lcnMoY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLnZpZXdQcm9wc1RyYW5zZm9ybWVycyk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgdHJhbnNmb3JtZXJzXzEgPSB0cmFuc2Zvcm1lcnM7IF9pIDwgdHJhbnNmb3JtZXJzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNmb3JtZXIgPSB0cmFuc2Zvcm1lcnNfMVtfaV07XG4gICAgICAgICAgICBfX2Fzc2lnbih2aWV3UHJvcHMsIHRyYW5zZm9ybWVyLnRyYW5zZm9ybSh2aWV3UHJvcHMsIHZpZXdTcGVjLCBwcm9wcywgb3B0aW9ucykpO1xuICAgICAgICB9XG4gICAgICAgIHZpZXcucmVjZWl2ZVByb3BzKHZpZXdQcm9wcywgdGhpcy5idWlsZENvbXBvbmVudENvbnRleHQodGhpcy5jb250ZXh0LCB2aWV3U3BlYywgdmlldykpO1xuICAgIH07XG4gICAgLy8gU2l6aW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUudXBkYXRlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSkge1xuICAgICAgICBpZiAoaXNSZXNpemUgPT09IHZvaWQgMCkgeyBpc1Jlc2l6ZSA9IGZhbHNlOyB9XG4gICAgICAgIHZhciB2aWV3ID0gdGhpcy52aWV3O1xuICAgICAgICBpZiAoIXZpZXcpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gd2h5P1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Jlc2l6ZSB8fCB0aGlzLmlzSGVpZ2h0QXV0byA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXB1dGVIZWlnaHRWYXJzKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlldy51cGRhdGVTaXplKGlzUmVzaXplLCB0aGlzLnZpZXdIZWlnaHQsIHRoaXMuaXNIZWlnaHRBdXRvKTtcbiAgICAgICAgdmlldy51cGRhdGVOb3dJbmRpY2F0b3IoKTsgLy8gd2UgbmVlZCB0byBndWFyYW50ZWUgdGhpcyB3aWxsIHJ1biBhZnRlciB1cGRhdGVTaXplXG4gICAgICAgIHZpZXcucG9wU2Nyb2xsKGlzUmVzaXplKTtcbiAgICB9O1xuICAgIENhbGVuZGFyQ29tcG9uZW50LnByb3RvdHlwZS5jb21wdXRlSGVpZ2h0VmFycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdGhpcy5jb250ZXh0LmNhbGVuZGFyOyAvLyB5dWNrLiBuZWVkIHRvIGhhbmRsZSBkeW5hbWljIG9wdGlvbnNcbiAgICAgICAgdmFyIGhlaWdodElucHV0ID0gY2FsZW5kYXIub3B0KCdoZWlnaHQnKTtcbiAgICAgICAgdmFyIGNvbnRlbnRIZWlnaHRJbnB1dCA9IGNhbGVuZGFyLm9wdCgnY29udGVudEhlaWdodCcpO1xuICAgICAgICB0aGlzLmlzSGVpZ2h0QXV0byA9IGhlaWdodElucHV0ID09PSAnYXV0bycgfHwgY29udGVudEhlaWdodElucHV0ID09PSAnYXV0byc7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGVudEhlaWdodElucHV0ID09PSAnbnVtYmVyJykgeyAvLyBleGlzdHMgYW5kIG5vdCAnYXV0bydcbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IGNvbnRlbnRIZWlnaHRJbnB1dDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgY29udGVudEhlaWdodElucHV0ID09PSAnZnVuY3Rpb24nKSB7IC8vIGV4aXN0cyBhbmQgaXMgYSBmdW5jdGlvblxuICAgICAgICAgICAgdGhpcy52aWV3SGVpZ2h0ID0gY29udGVudEhlaWdodElucHV0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGhlaWdodElucHV0ID09PSAnbnVtYmVyJykgeyAvLyBleGlzdHMgYW5kIG5vdCAnYXV0bydcbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IGhlaWdodElucHV0IC0gdGhpcy5xdWVyeVRvb2xiYXJzSGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGhlaWdodElucHV0ID09PSAnZnVuY3Rpb24nKSB7IC8vIGV4aXN0cyBhbmQgaXMgYSBmdW5jdGlvblxuICAgICAgICAgICAgdGhpcy52aWV3SGVpZ2h0ID0gaGVpZ2h0SW5wdXQoKSAtIHRoaXMucXVlcnlUb29sYmFyc0hlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGhlaWdodElucHV0ID09PSAncGFyZW50JykgeyAvLyBzZXQgdG8gaGVpZ2h0IG9mIHBhcmVudCBlbGVtZW50XG4gICAgICAgICAgICB2YXIgcGFyZW50RWwgPSB0aGlzLmVsLnBhcmVudE5vZGU7XG4gICAgICAgICAgICB0aGlzLnZpZXdIZWlnaHQgPSBwYXJlbnRFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgLSB0aGlzLnF1ZXJ5VG9vbGJhcnNIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudmlld0hlaWdodCA9IE1hdGgucm91bmQodGhpcy5jb250ZW50RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggL1xuICAgICAgICAgICAgICAgIE1hdGgubWF4KGNhbGVuZGFyLm9wdCgnYXNwZWN0UmF0aW8nKSwgLjUpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXJDb21wb25lbnQucHJvdG90eXBlLnF1ZXJ5VG9vbGJhcnNIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBoZWlnaHQgPSAwO1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIGhlaWdodCArPSBjb21wdXRlSGVpZ2h0QW5kTWFyZ2lucyh0aGlzLmhlYWRlci5lbCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZm9vdGVyKSB7XG4gICAgICAgICAgICBoZWlnaHQgKz0gY29tcHV0ZUhlaWdodEFuZE1hcmdpbnModGhpcy5mb290ZXIuZWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoZWlnaHQ7XG4gICAgfTtcbiAgICAvLyBIZWlnaHQgXCJGcmVlemluZ1wiXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUuZnJlZXplSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBhcHBseVN0eWxlKHRoaXMuZWwsIHtcbiAgICAgICAgICAgIGhlaWdodDogdGhpcy5lbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQsXG4gICAgICAgICAgICBvdmVyZmxvdzogJ2hpZGRlbidcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhckNvbXBvbmVudC5wcm90b3R5cGUudGhhd0hlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmVsLCB7XG4gICAgICAgICAgICBoZWlnaHQ6ICcnLFxuICAgICAgICAgICAgb3ZlcmZsb3c6ICcnXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIENhbGVuZGFyQ29tcG9uZW50O1xufShDb21wb25lbnQpKTtcbi8vIFRpdGxlIGFuZCBEYXRlIEZvcm1hdHRpbmdcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDb21wdXRlcyB3aGF0IHRoZSB0aXRsZSBhdCB0aGUgdG9wIG9mIHRoZSBjYWxlbmRhciBzaG91bGQgYmUgZm9yIHRoaXMgdmlld1xuZnVuY3Rpb24gY29tcHV0ZVRpdGxlKGRhdGVQcm9maWxlLCB2aWV3T3B0aW9ucykge1xuICAgIHZhciByYW5nZTtcbiAgICAvLyBmb3Igdmlld3MgdGhhdCBzcGFuIGEgbGFyZ2UgdW5pdCBvZiB0aW1lLCBzaG93IHRoZSBwcm9wZXIgaW50ZXJ2YWwsIGlnbm9yaW5nIHN0cmF5IGRheXMgYmVmb3JlIGFuZCBhZnRlclxuICAgIGlmICgvXih5ZWFyfG1vbnRoKSQvLnRlc3QoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdCkpIHtcbiAgICAgICAgcmFuZ2UgPSBkYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2U7XG4gICAgfVxuICAgIGVsc2UgeyAvLyBmb3IgZGF5IHVuaXRzIG9yIHNtYWxsZXIsIHVzZSB0aGUgYWN0dWFsIGRheSByYW5nZVxuICAgICAgICByYW5nZSA9IGRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYuZm9ybWF0UmFuZ2UocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCwgY3JlYXRlRm9ybWF0dGVyKHZpZXdPcHRpb25zLnRpdGxlRm9ybWF0IHx8IGNvbXB1dGVUaXRsZUZvcm1hdChkYXRlUHJvZmlsZSksIHZpZXdPcHRpb25zLnRpdGxlUmFuZ2VTZXBhcmF0b3IpLCB7IGlzRW5kRXhjbHVzaXZlOiBkYXRlUHJvZmlsZS5pc1JhbmdlQWxsRGF5IH0pO1xufVxuLy8gR2VuZXJhdGVzIHRoZSBmb3JtYXQgc3RyaW5nIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIHRpdGxlIGZvciB0aGUgY3VycmVudCBkYXRlIHJhbmdlLlxuLy8gQXR0ZW1wdHMgdG8gY29tcHV0ZSB0aGUgbW9zdCBhcHByb3ByaWF0ZSBmb3JtYXQgaWYgbm90IGV4cGxpY2l0bHkgc3BlY2lmaWVkIHdpdGggYHRpdGxlRm9ybWF0YC5cbmZ1bmN0aW9uIGNvbXB1dGVUaXRsZUZvcm1hdChkYXRlUHJvZmlsZSkge1xuICAgIHZhciBjdXJyZW50UmFuZ2VVbml0ID0gZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdDtcbiAgICBpZiAoY3VycmVudFJhbmdlVW5pdCA9PT0gJ3llYXInKSB7XG4gICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJyB9O1xuICAgIH1cbiAgICBlbHNlIGlmIChjdXJyZW50UmFuZ2VVbml0ID09PSAnbW9udGgnKSB7XG4gICAgICAgIHJldHVybiB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICdsb25nJyB9OyAvLyBsaWtlIFwiU2VwdGVtYmVyIDIwMTRcIlxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGRheXMgPSBkaWZmV2hvbGVEYXlzKGRhdGVQcm9maWxlLmN1cnJlbnRSYW5nZS5zdGFydCwgZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLmVuZCk7XG4gICAgICAgIGlmIChkYXlzICE9PSBudWxsICYmIGRheXMgPiAxKSB7XG4gICAgICAgICAgICAvLyBtdWx0aS1kYXkgcmFuZ2UuIHNob3J0ZXIsIGxpa2UgXCJTZXAgOSAtIDEwIDIwMTRcIlxuICAgICAgICAgICAgcmV0dXJuIHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ3Nob3J0JywgZGF5OiAnbnVtZXJpYycgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIG9uZSBkYXkuIGxvbmdlciwgbGlrZSBcIlNlcHRlbWJlciA5IDIwMTRcIlxuICAgICAgICAgICAgcmV0dXJuIHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJyB9O1xuICAgICAgICB9XG4gICAgfVxufVxuLy8gYnVpbGQgYSBjb250ZXh0IHNjb3BlZCB0byB0aGUgdmlld1xuZnVuY3Rpb24gYnVpbGRDb21wb25lbnRDb250ZXh0KGNvbnRleHQsIHZpZXdTcGVjLCB2aWV3KSB7XG4gICAgcmV0dXJuIGNvbnRleHQuZXh0ZW5kKHZpZXdTcGVjLm9wdGlvbnMsIHZpZXcpO1xufVxuLy8gUGx1Z2luXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYnVpbGRWaWV3UHJvcFRyYW5zZm9ybWVycyh0aGVDbGFzc2VzKSB7XG4gICAgcmV0dXJuIHRoZUNsYXNzZXMubWFwKGZ1bmN0aW9uICh0aGVDbGFzcykge1xuICAgICAgICByZXR1cm4gbmV3IHRoZUNsYXNzKCk7XG4gICAgfSk7XG59XG5cbnZhciBJbnRlcmFjdGlvbiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBJbnRlcmFjdGlvbihzZXR0aW5ncykge1xuICAgICAgICB0aGlzLmNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICB9XG4gICAgSW50ZXJhY3Rpb24ucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICByZXR1cm4gSW50ZXJhY3Rpb247XG59KCkpO1xuZnVuY3Rpb24gcGFyc2VJbnRlcmFjdGlvblNldHRpbmdzKGNvbXBvbmVudCwgaW5wdXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCxcbiAgICAgICAgZWw6IGlucHV0LmVsLFxuICAgICAgICB1c2VFdmVudENlbnRlcjogaW5wdXQudXNlRXZlbnRDZW50ZXIgIT0gbnVsbCA/IGlucHV0LnVzZUV2ZW50Q2VudGVyIDogdHJ1ZVxuICAgIH07XG59XG5mdW5jdGlvbiBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykge1xuICAgIHZhciBfYTtcbiAgICByZXR1cm4gX2EgPSB7fSxcbiAgICAgICAgX2Fbc2V0dGluZ3MuY29tcG9uZW50LnVpZF0gPSBzZXR0aW5ncyxcbiAgICAgICAgX2E7XG59XG4vLyBnbG9iYWwgc3RhdGVcbnZhciBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUgPSB7fTtcblxuLypcbkRldGVjdHMgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYW4gZXZlbnQgd2l0aGluIGEgRGF0ZUNvbXBvbmVudFxuKi9cbnZhciBFdmVudENsaWNraW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhFdmVudENsaWNraW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEV2ZW50Q2xpY2tpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmhhbmRsZVNlZ0NsaWNrID0gZnVuY3Rpb24gKGV2LCBzZWdFbCkge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIHZhciBfYSA9IGNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgICAgIHZhciBzZWcgPSBnZXRFbFNlZyhzZWdFbCk7XG4gICAgICAgICAgICBpZiAoc2VnICYmIC8vIG1pZ2h0IGJlIHRoZSA8ZGl2PiBzdXJyb3VuZGluZyB0aGUgbW9yZSBsaW5rXG4gICAgICAgICAgICAgICAgY29tcG9uZW50LmlzVmFsaWRTZWdEb3duRWwoZXYudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgIC8vIG91ciB3YXkgdG8gc2ltdWxhdGUgYSBsaW5rIGNsaWNrIGZvciBlbGVtZW50cyB0aGF0IGNhbid0IGJlIDxhPiB0YWdzXG4gICAgICAgICAgICAgICAgLy8gZ3JhYiBiZWZvcmUgdHJpZ2dlciBmaXJlZCBpbiBjYXNlIHRyaWdnZXIgdHJhc2hlcyBET00gdGhydSByZXJlbmRlcmluZ1xuICAgICAgICAgICAgICAgIHZhciBoYXNVcmxDb250YWluZXIgPSBlbGVtZW50Q2xvc2VzdChldi50YXJnZXQsICcuZmMtaGFzLXVybCcpO1xuICAgICAgICAgICAgICAgIHZhciB1cmwgPSBoYXNVcmxDb250YWluZXIgPyBoYXNVcmxDb250YWluZXIucXVlcnlTZWxlY3RvcignYVtocmVmXScpLmhyZWYgOiAnJztcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50Q2xpY2snLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiBzZWdFbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIsIHNlZy5ldmVudFJhbmdlLmRlZiwgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICBpZiAodXJsICYmICFldi5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgX3RoaXMuZGVzdHJveSA9IGxpc3RlbkJ5U2VsZWN0b3IoY29tcG9uZW50LmVsLCAnY2xpY2snLCBjb21wb25lbnQuZmdTZWdTZWxlY3RvciArICcsJyArIGNvbXBvbmVudC5iZ1NlZ1NlbGVjdG9yLCBfdGhpcy5oYW5kbGVTZWdDbGljayk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIEV2ZW50Q2xpY2tpbmc7XG59KEludGVyYWN0aW9uKSk7XG5cbi8qXG5UcmlnZ2VycyBldmVudHMgYW5kIGFkZHMvcmVtb3ZlcyBjb3JlIGNsYXNzTmFtZXMgd2hlbiB0aGUgdXNlcidzIHBvaW50ZXJcbmVudGVycy9sZWF2ZXMgZXZlbnQtZWxlbWVudHMgb2YgYSBjb21wb25lbnQuXG4qL1xudmFyIEV2ZW50SG92ZXJpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEV2ZW50SG92ZXJpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRXZlbnRIb3ZlcmluZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgLy8gZm9yIHNpbXVsYXRpbmcgYW4gZXZlbnRNb3VzZUxlYXZlIHdoZW4gdGhlIGV2ZW50IGVsIGlzIGRlc3Ryb3llZCB3aGlsZSBtb3VzZSBpcyBvdmVyIGl0XG4gICAgICAgIF90aGlzLmhhbmRsZUV2ZW50RWxSZW1vdmUgPSBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbCA9PT0gX3RoaXMuY3VycmVudFNlZ0VsKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGFuZGxlU2VnTGVhdmUobnVsbCwgX3RoaXMuY3VycmVudFNlZ0VsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlU2VnRW50ZXIgPSBmdW5jdGlvbiAoZXYsIHNlZ0VsKSB7XG4gICAgICAgICAgICBpZiAoZ2V0RWxTZWcoc2VnRWwpKSB7IC8vIFRPRE86IGJldHRlciB3YXkgdG8gbWFrZSBzdXJlIG5vdCBob3ZlcmluZyBvdmVyIG1vcmUrIGxpbmsgb3IgaXRzIHdyYXBwZXJcbiAgICAgICAgICAgICAgICBzZWdFbC5jbGFzc0xpc3QuYWRkKCdmYy1hbGxvdy1tb3VzZS1yZXNpemUnKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jdXJyZW50U2VnRWwgPSBzZWdFbDtcbiAgICAgICAgICAgICAgICBfdGhpcy50cmlnZ2VyRXZlbnQoJ2V2ZW50TW91c2VFbnRlcicsIGV2LCBzZWdFbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVNlZ0xlYXZlID0gZnVuY3Rpb24gKGV2LCBzZWdFbCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmN1cnJlbnRTZWdFbCkge1xuICAgICAgICAgICAgICAgIHNlZ0VsLmNsYXNzTGlzdC5yZW1vdmUoJ2ZjLWFsbG93LW1vdXNlLXJlc2l6ZScpO1xuICAgICAgICAgICAgICAgIF90aGlzLmN1cnJlbnRTZWdFbCA9IG51bGw7XG4gICAgICAgICAgICAgICAgX3RoaXMudHJpZ2dlckV2ZW50KCdldmVudE1vdXNlTGVhdmUnLCBldiwgc2VnRWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gc2V0dGluZ3MuY29tcG9uZW50O1xuICAgICAgICBfdGhpcy5yZW1vdmVIb3Zlckxpc3RlbmVycyA9IGxpc3RlblRvSG92ZXJCeVNlbGVjdG9yKGNvbXBvbmVudC5lbCwgY29tcG9uZW50LmZnU2VnU2VsZWN0b3IgKyAnLCcgKyBjb21wb25lbnQuYmdTZWdTZWxlY3RvciwgX3RoaXMuaGFuZGxlU2VnRW50ZXIsIF90aGlzLmhhbmRsZVNlZ0xlYXZlKTtcbiAgICAgICAgLy8gaG93IHRvIG1ha2Ugc3VyZSBjb21wb25lbnQgYWxyZWFkeSBoYXMgY29udGV4dD9cbiAgICAgICAgY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIub24oJ2V2ZW50RWxSZW1vdmUnLCBfdGhpcy5oYW5kbGVFdmVudEVsUmVtb3ZlKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBFdmVudEhvdmVyaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlbW92ZUhvdmVyTGlzdGVuZXJzKCk7XG4gICAgICAgIHRoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXIub2ZmKCdldmVudEVsUmVtb3ZlJywgdGhpcy5oYW5kbGVFdmVudEVsUmVtb3ZlKTtcbiAgICB9O1xuICAgIEV2ZW50SG92ZXJpbmcucHJvdG90eXBlLnRyaWdnZXJFdmVudCA9IGZ1bmN0aW9uIChwdWJsaWNFdk5hbWUsIGV2LCBzZWdFbCkge1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnQ7XG4gICAgICAgIHZhciBfYSA9IGNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgdmFyIHNlZyA9IGdldEVsU2VnKHNlZ0VsKTtcbiAgICAgICAgaWYgKCFldiB8fCBjb21wb25lbnQuaXNWYWxpZFNlZ0Rvd25FbChldi50YXJnZXQpKSB7XG4gICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIocHVibGljRXZOYW1lLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBlbDogc2VnRWwsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIHNlZy5ldmVudFJhbmdlLmRlZiwgc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gRXZlbnRIb3ZlcmluZztcbn0oSW50ZXJhY3Rpb24pKTtcblxudmFyIFN0YW5kYXJkVGhlbWUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFN0YW5kYXJkVGhlbWUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU3RhbmRhcmRUaGVtZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gU3RhbmRhcmRUaGVtZTtcbn0oVGhlbWUpKTtcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmNsYXNzZXMgPSB7XG4gICAgd2lkZ2V0OiAnZmMtdW50aGVtZWQnLFxuICAgIHdpZGdldEhlYWRlcjogJ2ZjLXdpZGdldC1oZWFkZXInLFxuICAgIHdpZGdldENvbnRlbnQ6ICdmYy13aWRnZXQtY29udGVudCcsXG4gICAgYnV0dG9uR3JvdXA6ICdmYy1idXR0b24tZ3JvdXAnLFxuICAgIGJ1dHRvbjogJ2ZjLWJ1dHRvbiBmYy1idXR0b24tcHJpbWFyeScsXG4gICAgYnV0dG9uQWN0aXZlOiAnZmMtYnV0dG9uLWFjdGl2ZScsXG4gICAgcG9wb3ZlckhlYWRlcjogJ2ZjLXdpZGdldC1oZWFkZXInLFxuICAgIHBvcG92ZXJDb250ZW50OiAnZmMtd2lkZ2V0LWNvbnRlbnQnLFxuICAgIC8vIGRheSBncmlkXG4gICAgaGVhZGVyUm93OiAnZmMtd2lkZ2V0LWhlYWRlcicsXG4gICAgZGF5Um93OiAnZmMtd2lkZ2V0LWNvbnRlbnQnLFxuICAgIC8vIGxpc3Qgdmlld1xuICAgIGxpc3RWaWV3OiAnZmMtd2lkZ2V0LWNvbnRlbnQnXG59O1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuYmFzZUljb25DbGFzcyA9ICdmYy1pY29uJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25DbGFzc2VzID0ge1xuICAgIGNsb3NlOiAnZmMtaWNvbi14JyxcbiAgICBwcmV2OiAnZmMtaWNvbi1jaGV2cm9uLWxlZnQnLFxuICAgIG5leHQ6ICdmYy1pY29uLWNoZXZyb24tcmlnaHQnLFxuICAgIHByZXZZZWFyOiAnZmMtaWNvbi1jaGV2cm9ucy1sZWZ0JyxcbiAgICBuZXh0WWVhcjogJ2ZjLWljb24tY2hldnJvbnMtcmlnaHQnXG59O1xuU3RhbmRhcmRUaGVtZS5wcm90b3R5cGUuaWNvbk92ZXJyaWRlT3B0aW9uID0gJ2J1dHRvbkljb25zJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25PdmVycmlkZUN1c3RvbUJ1dHRvbk9wdGlvbiA9ICdpY29uJztcblN0YW5kYXJkVGhlbWUucHJvdG90eXBlLmljb25PdmVycmlkZVByZWZpeCA9ICdmYy1pY29uLSc7XG5cbnZhciBDYWxlbmRhciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYWxlbmRhcihlbCwgb3ZlcnJpZGVzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYnVpbGRDb21wb25lbnRDb250ZXh0ID0gbWVtb2l6ZShidWlsZENvbXBvbmVudENvbnRleHQkMSk7XG4gICAgICAgIHRoaXMucGFyc2VSYXdMb2NhbGVzID0gbWVtb2l6ZShwYXJzZVJhd0xvY2FsZXMpO1xuICAgICAgICB0aGlzLmJ1aWxkTG9jYWxlID0gbWVtb2l6ZShidWlsZExvY2FsZSk7XG4gICAgICAgIHRoaXMuYnVpbGREYXRlRW52ID0gbWVtb2l6ZShidWlsZERhdGVFbnYpO1xuICAgICAgICB0aGlzLmJ1aWxkVGhlbWUgPSBtZW1vaXplKGJ1aWxkVGhlbWUpO1xuICAgICAgICB0aGlzLmJ1aWxkRXZlbnRVaVNpbmdsZUJhc2UgPSBtZW1vaXplKHRoaXMuX2J1aWxkRXZlbnRVaVNpbmdsZUJhc2UpO1xuICAgICAgICB0aGlzLmJ1aWxkU2VsZWN0aW9uQ29uZmlnID0gbWVtb2l6ZSh0aGlzLl9idWlsZFNlbGVjdGlvbkNvbmZpZyk7XG4gICAgICAgIHRoaXMuYnVpbGRFdmVudFVpQnlTb3VyY2UgPSBtZW1vaXplT3V0cHV0KGJ1aWxkRXZlbnRVaUJ5U291cmNlLCBpc1Byb3BzRXF1YWwpO1xuICAgICAgICB0aGlzLmJ1aWxkRXZlbnRVaUJhc2VzID0gbWVtb2l6ZShidWlsZEV2ZW50VWlCYXNlcyk7XG4gICAgICAgIHRoaXMuaW50ZXJhY3Rpb25zU3RvcmUgPSB7fTtcbiAgICAgICAgdGhpcy5hY3Rpb25RdWV1ZSA9IFtdO1xuICAgICAgICB0aGlzLmlzUmVkdWNpbmcgPSBmYWxzZTtcbiAgICAgICAgLy8gaXNEaXNwbGF5aW5nOiBib29sZWFuID0gZmFsc2UgLy8gaW5zdGFsbGVkIGluIERPTT8gYWNjZXB0aW5nIHJlbmRlcnM/XG4gICAgICAgIHRoaXMubmVlZHNSZXJlbmRlciA9IGZhbHNlOyAvLyBuZWVkcyBhIHJlbmRlcj9cbiAgICAgICAgdGhpcy5pc1JlbmRlcmluZyA9IGZhbHNlOyAvLyBjdXJyZW50bHkgaW4gdGhlIGV4ZWN1dGVSZW5kZXIgZnVuY3Rpb24/XG4gICAgICAgIHRoaXMucmVuZGVyaW5nUGF1c2VEZXB0aCA9IDA7XG4gICAgICAgIHRoaXMuYnVpbGREZWxheWVkUmVyZW5kZXIgPSBtZW1vaXplKGJ1aWxkRGVsYXllZFJlcmVuZGVyKTtcbiAgICAgICAgdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzID0ge307XG4gICAgICAgIHRoaXMuaXNWaWV3VXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzRGF0ZXNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNFdmVudHNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgICAgdGhpcy5vcHRpb25zTWFuYWdlciA9IG5ldyBPcHRpb25zTWFuYWdlcihvdmVycmlkZXMgfHwge30pO1xuICAgICAgICB0aGlzLnBsdWdpblN5c3RlbSA9IG5ldyBQbHVnaW5TeXN0ZW0oKTtcbiAgICAgICAgLy8gb25seSBkbyBvbmNlLiBkb24ndCBkbyBpbiBoYW5kbGVPcHRpb25zLiBiZWNhdXNlIGNhbid0IHJlbW92ZSBwbHVnaW5zXG4gICAgICAgIHRoaXMuYWRkUGx1Z2luSW5wdXRzKHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQucGx1Z2lucyB8fCBbXSk7XG4gICAgICAgIHRoaXMuaGFuZGxlT3B0aW9ucyh0aGlzLm9wdGlvbnNNYW5hZ2VyLmNvbXB1dGVkKTtcbiAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ19pbml0Jyk7IC8vIGZvciB0ZXN0c1xuICAgICAgICB0aGlzLmh5ZHJhdGUoKTtcbiAgICAgICAgdGhpcy5jYWxlbmRhckludGVyYWN0aW9ucyA9IHRoaXMucGx1Z2luU3lzdGVtLmhvb2tzLmNhbGVuZGFySW50ZXJhY3Rpb25zXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChjYWxlbmRhckludGVyYWN0aW9uQ2xhc3MpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgY2FsZW5kYXJJbnRlcmFjdGlvbkNsYXNzKF90aGlzKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5hZGRQbHVnaW5JbnB1dHMgPSBmdW5jdGlvbiAocGx1Z2luSW5wdXRzKSB7XG4gICAgICAgIHZhciBwbHVnaW5EZWZzID0gcmVmaW5lUGx1Z2luRGVmcyhwbHVnaW5JbnB1dHMpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHBsdWdpbkRlZnNfMSA9IHBsdWdpbkRlZnM7IF9pIDwgcGx1Z2luRGVmc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHBsdWdpbkRlZiA9IHBsdWdpbkRlZnNfMVtfaV07XG4gICAgICAgICAgICB0aGlzLnBsdWdpblN5c3RlbS5hZGQocGx1Z2luRGVmKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KENhbGVuZGFyLnByb3RvdHlwZSwgXCJ2aWV3XCIsIHtcbiAgICAgICAgLy8gcHVibGljIEFQSVxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbXBvbmVudCA/IHRoaXMuY29tcG9uZW50LnZpZXcgOiBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICAvLyBQdWJsaWMgQVBJIGZvciByZW5kZXJpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jb21wb25lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50ID0gbmV3IENhbGVuZGFyQ29tcG9uZW50KHRoaXMuZWwpO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJhYmxlRXZlbnRTdG9yZSA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgICAgICAgICAgdGhpcy5iaW5kSGFuZGxlcnMoKTtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZVJlbmRlcigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0UmVyZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCkge1xuICAgICAgICAgICAgdGhpcy51bmJpbmRIYW5kbGVycygpO1xuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQuZGVzdHJveSgpOyAvLyBkb24ndCBudWxsLW91dC4gaW4gY2FzZSBBUEkgbmVlZHMgYWNjZXNzXG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IG51bGw7IC8vIHVtbSA/Pz9cbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmNhbGVuZGFySW50ZXJhY3Rpb25zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5kZXN0cm95KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignX2Rlc3Ryb3llZCcpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBIYW5kbGVyc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmJpbmRIYW5kbGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gZXZlbnQgZGVsZWdhdGlvbiBmb3IgbmF2IGxpbmtzXG4gICAgICAgIHRoaXMucmVtb3ZlTmF2TGlua0xpc3RlbmVyID0gbGlzdGVuQnlTZWxlY3Rvcih0aGlzLmVsLCAnY2xpY2snLCAnYVtkYXRhLWdvdG9dJywgZnVuY3Rpb24gKGV2LCBhbmNob3JFbCkge1xuICAgICAgICAgICAgdmFyIGdvdG9PcHRpb25zID0gYW5jaG9yRWwuZ2V0QXR0cmlidXRlKCdkYXRhLWdvdG8nKTtcbiAgICAgICAgICAgIGdvdG9PcHRpb25zID0gZ290b09wdGlvbnMgPyBKU09OLnBhcnNlKGdvdG9PcHRpb25zKSA6IHt9O1xuICAgICAgICAgICAgdmFyIGRhdGVFbnYgPSBfdGhpcy5kYXRlRW52O1xuICAgICAgICAgICAgdmFyIGRhdGVNYXJrZXIgPSBkYXRlRW52LmNyZWF0ZU1hcmtlcihnb3RvT3B0aW9ucy5kYXRlKTtcbiAgICAgICAgICAgIHZhciB2aWV3VHlwZSA9IGdvdG9PcHRpb25zLnR5cGU7XG4gICAgICAgICAgICAvLyBwcm9wZXJ0eSBsaWtlIFwibmF2TGlua0RheUNsaWNrXCIuIG1pZ2h0IGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb25cbiAgICAgICAgICAgIHZhciBjdXN0b21BY3Rpb24gPSBfdGhpcy52aWV3T3B0KCduYXZMaW5rJyArIGNhcGl0YWxpc2VGaXJzdExldHRlcih2aWV3VHlwZSkgKyAnQ2xpY2snKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3VzdG9tQWN0aW9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgY3VzdG9tQWN0aW9uKGRhdGVFbnYudG9EYXRlKGRhdGVNYXJrZXIpLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1c3RvbUFjdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdmlld1R5cGUgPSBjdXN0b21BY3Rpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnpvb21UbyhkYXRlTWFya2VyLCB2aWV3VHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy5vcHQoJ2hhbmRsZVdpbmRvd1Jlc2l6ZScpKSB7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy53aW5kb3dSZXNpemVQcm94eSA9IGRlYm91bmNlKC8vIHByZXZlbnRzIHJhcGlkIGNhbGxzXG4gICAgICAgICAgICB0aGlzLndpbmRvd1Jlc2l6ZS5iaW5kKHRoaXMpLCB0aGlzLm9wdCgnd2luZG93UmVzaXplRGVsYXknKSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudW5iaW5kSGFuZGxlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTmF2TGlua0xpc3RlbmVyKCk7XG4gICAgICAgIGlmICh0aGlzLndpbmRvd1Jlc2l6ZVByb3h5KSB7XG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy53aW5kb3dSZXNpemVQcm94eSk7XG4gICAgICAgICAgICB0aGlzLndpbmRvd1Jlc2l6ZVByb3h5ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gRGlzcGF0Y2hlclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmh5ZHJhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB0aGlzLmJ1aWxkSW5pdGlhbFN0YXRlKCk7XG4gICAgICAgIHZhciByYXdTb3VyY2VzID0gdGhpcy5vcHQoJ2V2ZW50U291cmNlcycpIHx8IFtdO1xuICAgICAgICB2YXIgc2luZ2xlUmF3U291cmNlID0gdGhpcy5vcHQoJ2V2ZW50cycpO1xuICAgICAgICB2YXIgc291cmNlcyA9IFtdOyAvLyBwYXJzZWRcbiAgICAgICAgaWYgKHNpbmdsZVJhd1NvdXJjZSkge1xuICAgICAgICAgICAgcmF3U291cmNlcy51bnNoaWZ0KHNpbmdsZVJhd1NvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByYXdTb3VyY2VzXzEgPSByYXdTb3VyY2VzOyBfaSA8IHJhd1NvdXJjZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByYXdTb3VyY2UgPSByYXdTb3VyY2VzXzFbX2ldO1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHBhcnNlRXZlbnRTb3VyY2UocmF3U291cmNlLCB0aGlzKTtcbiAgICAgICAgICAgIGlmIChzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VzLnB1c2goc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJhdGNoUmVuZGVyaW5nKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHsgdHlwZTogJ0lOSVQnIH0pOyAvLyBwYXNzIGluIHNvdXJjZXMgaGVyZT9cbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHsgdHlwZTogJ0FERF9FVkVOVF9TT1VSQ0VTJywgc291cmNlczogc291cmNlcyB9KTtcbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX1ZJRVdfVFlQRScsXG4gICAgICAgICAgICAgICAgdmlld1R5cGU6IF90aGlzLm9wdCgnZGVmYXVsdFZpZXcnKSB8fCBfdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3MuZGVmYXVsdFZpZXdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5idWlsZEluaXRpYWxTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZpZXdUeXBlOiBudWxsLFxuICAgICAgICAgICAgbG9hZGluZ0xldmVsOiAwLFxuICAgICAgICAgICAgZXZlbnRTb3VyY2VMb2FkaW5nTGV2ZWw6IDAsXG4gICAgICAgICAgICBjdXJyZW50RGF0ZTogdGhpcy5nZXRJbml0aWFsRGF0ZSgpLFxuICAgICAgICAgICAgZGF0ZVByb2ZpbGU6IG51bGwsXG4gICAgICAgICAgICBldmVudFNvdXJjZXM6IHt9LFxuICAgICAgICAgICAgZXZlbnRTdG9yZTogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICBkYXRlU2VsZWN0aW9uOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246ICcnLFxuICAgICAgICAgICAgZXZlbnREcmFnOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IG51bGxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5kaXNwYXRjaCA9IGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgdGhpcy5hY3Rpb25RdWV1ZS5wdXNoKGFjdGlvbik7XG4gICAgICAgIGlmICghdGhpcy5pc1JlZHVjaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmlzUmVkdWNpbmcgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIG9sZFN0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmFjdGlvblF1ZXVlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSB0aGlzLnJlZHVjZSh0aGlzLnN0YXRlLCB0aGlzLmFjdGlvblF1ZXVlLnNoaWZ0KCksIHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG5ld1N0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgICAgIHRoaXMuaXNSZWR1Y2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKCFvbGRTdGF0ZS5sb2FkaW5nTGV2ZWwgJiYgbmV3U3RhdGUubG9hZGluZ0xldmVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ2xvYWRpbmcnLCBbdHJ1ZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob2xkU3RhdGUubG9hZGluZ0xldmVsICYmICFuZXdTdGF0ZS5sb2FkaW5nTGV2ZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignbG9hZGluZycsIFtmYWxzZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHZpZXcgPSB0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC52aWV3O1xuICAgICAgICAgICAgaWYgKG9sZFN0YXRlLmV2ZW50U3RvcmUgIT09IG5ld1N0YXRlLmV2ZW50U3RvcmUpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkU3RhdGUuZXZlbnRTdG9yZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzRXZlbnRzVXBkYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9sZFN0YXRlLmRhdGVQcm9maWxlICE9PSBuZXdTdGF0ZS5kYXRlUHJvZmlsZSkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRTdGF0ZS5kYXRlUHJvZmlsZSAmJiB2aWV3KSB7IC8vIHdoeSB3b3VsZCB2aWV3IGJlIG51bGwhP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignZGF0ZXNEZXN0cm95JywgW1xuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWw6IHZpZXcuZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaXNEYXRlc1VwZGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9sZFN0YXRlLnZpZXdUeXBlICE9PSBuZXdTdGF0ZS52aWV3VHlwZSkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRTdGF0ZS52aWV3VHlwZSAmJiB2aWV3KSB7IC8vIHdoeSB3b3VsZCB2aWV3IGJlIG51bGwhP1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcigndmlld1NrZWxldG9uRGVzdHJveScsIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsOiB2aWV3LmVsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmlzVmlld1VwZGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0UmVyZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlZHVjZSA9IGZ1bmN0aW9uIChzdGF0ZSwgYWN0aW9uLCBjYWxlbmRhcikge1xuICAgICAgICByZXR1cm4gcmVkdWNlKHN0YXRlLCBhY3Rpb24sIGNhbGVuZGFyKTtcbiAgICB9O1xuICAgIC8vIFJlbmRlciBRdWV1ZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlcXVlc3RSZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5uZWVkc1JlcmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5kZWxheWVkUmVyZW5kZXIoKTsgLy8gd2lsbCBjYWxsIGEgZGVib3VuY2VkLXZlcnNpb24gb2YgdHJ5UmVyZW5kZXJcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50cnlSZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50ICYmIC8vIG11c3QgYmUgYWNjZXB0aW5nIHJlbmRlcnNcbiAgICAgICAgICAgIHRoaXMubmVlZHNSZXJlbmRlciAmJiAvLyBpbmRpY2F0ZXMgdGhhdCBhIHJlcmVuZGVyIHdhcyByZXF1ZXN0ZWRcbiAgICAgICAgICAgICF0aGlzLnJlbmRlcmluZ1BhdXNlRGVwdGggJiYgLy8gbm90IHBhdXNlZFxuICAgICAgICAgICAgIXRoaXMuaXNSZW5kZXJpbmcgLy8gbm90IGN1cnJlbnRseSBpbiB0aGUgcmVuZGVyIGxvb3BcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGVSZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmJhdGNoUmVuZGVyaW5nID0gZnVuY3Rpb24gKGZ1bmMpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJpbmdQYXVzZURlcHRoKys7XG4gICAgICAgIGZ1bmMoKTtcbiAgICAgICAgdGhpcy5yZW5kZXJpbmdQYXVzZURlcHRoLS07XG4gICAgICAgIGlmICh0aGlzLm5lZWRzUmVyZW5kZXIpIHtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdFJlcmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJlbmRlcmluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmV4ZWN1dGVSZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGNsZWFyIHRoZXNlIEJFRk9SRSB0aGUgcmVuZGVyIHNvIHRoYXQgbmV3IHZhbHVlcyB3aWxsIGFjY3VtdWxhdGUgZHVyaW5nIHJlbmRlclxuICAgICAgICB0aGlzLm5lZWRzUmVyZW5kZXIgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1JlbmRlcmluZyA9IHRydWU7XG4gICAgICAgIHRoaXMucmVuZGVyQ29tcG9uZW50KCk7XG4gICAgICAgIHRoaXMuaXNSZW5kZXJpbmcgPSBmYWxzZTtcbiAgICAgICAgLy8gcmVjZWl2ZWQgYSByZXJlbmRlciByZXF1ZXN0IHdoaWxlIHJlbmRlcmluZ1xuICAgICAgICBpZiAodGhpcy5uZWVkc1JlcmVuZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF5ZWRSZXJlbmRlcigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKlxuICAgIGRvbid0IGNhbGwgdGhpcyBkaXJlY3RseS4gdXNlIGV4ZWN1dGVSZW5kZXIgaW5zdGVhZFxuICAgICovXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnJlbmRlckNvbXBvbmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgc3RhdGUgPSBfYS5zdGF0ZSwgY29tcG9uZW50ID0gX2EuY29tcG9uZW50O1xuICAgICAgICB2YXIgdmlld1R5cGUgPSBzdGF0ZS52aWV3VHlwZTtcbiAgICAgICAgdmFyIHZpZXdTcGVjID0gdGhpcy52aWV3U3BlY3Nbdmlld1R5cGVdO1xuICAgICAgICBpZiAoIXZpZXdTcGVjKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJWaWV3IHR5cGUgXFxcIlwiICsgdmlld1R5cGUgKyBcIlxcXCIgaXMgbm90IHZhbGlkXCIpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGV2ZW50IHNvdXJjZXMgYXJlIHN0aWxsIGxvYWRpbmcgYW5kIHByb2dyZXNzaXZlIHJlbmRlcmluZyBoYXNuJ3QgYmVlbiBlbmFibGVkLFxuICAgICAgICAvLyBrZWVwIHJlbmRlcmluZyB0aGUgbGFzdCBmdWxseSBsb2FkZWQgc2V0IG9mIGV2ZW50c1xuICAgICAgICB2YXIgcmVuZGVyYWJsZUV2ZW50U3RvcmUgPSB0aGlzLnJlbmRlcmFibGVFdmVudFN0b3JlID1cbiAgICAgICAgICAgIChzdGF0ZS5ldmVudFNvdXJjZUxvYWRpbmdMZXZlbCAmJiAhdGhpcy5vcHQoJ3Byb2dyZXNzaXZlRXZlbnRSZW5kZXJpbmcnKSkgP1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyYWJsZUV2ZW50U3RvcmUgOlxuICAgICAgICAgICAgICAgIHN0YXRlLmV2ZW50U3RvcmU7XG4gICAgICAgIHZhciBldmVudFVpU2luZ2xlQmFzZSA9IHRoaXMuYnVpbGRFdmVudFVpU2luZ2xlQmFzZSh2aWV3U3BlYy5vcHRpb25zKTtcbiAgICAgICAgdmFyIGV2ZW50VWlCeVNvdXJjZSA9IHRoaXMuYnVpbGRFdmVudFVpQnlTb3VyY2Uoc3RhdGUuZXZlbnRTb3VyY2VzKTtcbiAgICAgICAgdmFyIGV2ZW50VWlCYXNlcyA9IHRoaXMuZXZlbnRVaUJhc2VzID0gdGhpcy5idWlsZEV2ZW50VWlCYXNlcyhyZW5kZXJhYmxlRXZlbnRTdG9yZS5kZWZzLCBldmVudFVpU2luZ2xlQmFzZSwgZXZlbnRVaUJ5U291cmNlKTtcbiAgICAgICAgY29tcG9uZW50LnJlY2VpdmVQcm9wcyhfX2Fzc2lnbih7fSwgc3RhdGUsIHsgdmlld1NwZWM6IHZpZXdTcGVjLCBkYXRlUHJvZmlsZUdlbmVyYXRvcjogdGhpcy5kYXRlUHJvZmlsZUdlbmVyYXRvcnNbdmlld1R5cGVdLCBkYXRlUHJvZmlsZTogc3RhdGUuZGF0ZVByb2ZpbGUsIGV2ZW50U3RvcmU6IHJlbmRlcmFibGVFdmVudFN0b3JlLCBldmVudFVpQmFzZXM6IGV2ZW50VWlCYXNlcywgZGF0ZVNlbGVjdGlvbjogc3RhdGUuZGF0ZVNlbGVjdGlvbiwgZXZlbnRTZWxlY3Rpb246IHN0YXRlLmV2ZW50U2VsZWN0aW9uLCBldmVudERyYWc6IHN0YXRlLmV2ZW50RHJhZywgZXZlbnRSZXNpemU6IHN0YXRlLmV2ZW50UmVzaXplIH0pLCB0aGlzLmJ1aWxkQ29tcG9uZW50Q29udGV4dCh0aGlzLnRoZW1lLCB0aGlzLmRhdGVFbnYsIHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQpKTtcbiAgICAgICAgaWYgKHRoaXMuaXNWaWV3VXBkYXRlZCkge1xuICAgICAgICAgICAgdGhpcy5pc1ZpZXdVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcigndmlld1NrZWxldG9uUmVuZGVyJywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmlldzogY29tcG9uZW50LnZpZXcsXG4gICAgICAgICAgICAgICAgICAgIGVsOiBjb21wb25lbnQudmlldy5lbFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzRGF0ZXNVcGRhdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzRGF0ZXNVcGRhdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignZGF0ZXNSZW5kZXInLCBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB2aWV3OiBjb21wb25lbnQudmlldyxcbiAgICAgICAgICAgICAgICAgICAgZWw6IGNvbXBvbmVudC52aWV3LmVsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNFdmVudHNVcGRhdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzRXZlbnRzVXBkYXRlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVsZWFzZUFmdGVyU2l6aW5nVHJpZ2dlcnMoKTtcbiAgICB9O1xuICAgIC8vIE9wdGlvbnNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5zZXRPcHRpb24gPSBmdW5jdGlvbiAobmFtZSwgdmFsKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdGhpcy5tdXRhdGVPcHRpb25zKChfYSA9IHt9LCBfYVtuYW1lXSA9IHZhbCwgX2EpLCBbXSwgdHJ1ZSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0T3B0aW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWRbbmFtZV07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUub3B0ID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWRbbmFtZV07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudmlld09wdCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdPcHRzKClbbmFtZV07XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudmlld09wdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdTcGVjc1t0aGlzLnN0YXRlLnZpZXdUeXBlXS5vcHRpb25zO1xuICAgIH07XG4gICAgLypcbiAgICBoYW5kbGVzIG9wdGlvbiBjaGFuZ2VzIChsaWtlIGEgZGlmZilcbiAgICAqL1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5tdXRhdGVPcHRpb25zID0gZnVuY3Rpb24gKHVwZGF0ZXMsIHJlbW92YWxzLCBpc0R5bmFtaWMsIGRlZXBFcXVhbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY2hhbmdlSGFuZGxlcnMgPSB0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5vcHRpb25DaGFuZ2VIYW5kbGVycztcbiAgICAgICAgdmFyIG5vcm1hbFVwZGF0ZXMgPSB7fTtcbiAgICAgICAgdmFyIHNwZWNpYWxVcGRhdGVzID0ge307XG4gICAgICAgIHZhciBvbGREYXRlRW52ID0gdGhpcy5kYXRlRW52OyAvLyBkbyB0aGlzIGJlZm9yZSBoYW5kbGVPcHRpb25zXG4gICAgICAgIHZhciBpc1RpbWVab25lRGlydHkgPSBmYWxzZTtcbiAgICAgICAgdmFyIGlzU2l6ZURpcnR5ID0gZmFsc2U7XG4gICAgICAgIHZhciBhbnlEaWZmaWN1bHRPcHRpb25zID0gQm9vbGVhbihyZW1vdmFscy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBuYW1lXzEgaW4gdXBkYXRlcykge1xuICAgICAgICAgICAgaWYgKGNoYW5nZUhhbmRsZXJzW25hbWVfMV0pIHtcbiAgICAgICAgICAgICAgICBzcGVjaWFsVXBkYXRlc1tuYW1lXzFdID0gdXBkYXRlc1tuYW1lXzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9ybWFsVXBkYXRlc1tuYW1lXzFdID0gdXBkYXRlc1tuYW1lXzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIG5hbWVfMiBpbiBub3JtYWxVcGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoL14oaGVpZ2h0fGNvbnRlbnRIZWlnaHR8YXNwZWN0UmF0aW8pJC8udGVzdChuYW1lXzIpKSB7XG4gICAgICAgICAgICAgICAgaXNTaXplRGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoL14oZGVmYXVsdERhdGV8ZGVmYXVsdFZpZXcpJC8udGVzdChuYW1lXzIpKSA7XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbnlEaWZmaWN1bHRPcHRpb25zID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZV8yID09PSAndGltZVpvbmUnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzVGltZVpvbmVEaXJ0eSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMub3B0aW9uc01hbmFnZXIubXV0YXRlKG5vcm1hbFVwZGF0ZXMsIHJlbW92YWxzLCBpc0R5bmFtaWMpO1xuICAgICAgICBpZiAoYW55RGlmZmljdWx0T3B0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVPcHRpb25zKHRoaXMub3B0aW9uc01hbmFnZXIuY29tcHV0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYmF0Y2hSZW5kZXJpbmcoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGFueURpZmZpY3VsdE9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNUaW1lWm9uZURpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdDSEFOR0VfVElNRVpPTkUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZUVudjogb2xkRGF0ZUVudlxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLyogSEFDS1xuICAgICAgICAgICAgICAgIGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgY2FsbGluZyB0aGlzLnJlcXVlc3RSZXJlbmRlcigpXG4gICAgICAgICAgICAgICAgYnV0IHJlY29tcHV0ZXMgdGhlIHN0YXRlJ3MgZGF0ZVByb2ZpbGVcbiAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9WSUVXX1RZUEUnLFxuICAgICAgICAgICAgICAgICAgICB2aWV3VHlwZTogX3RoaXMuc3RhdGUudmlld1R5cGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlzU2l6ZURpcnR5KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gc3BlY2lhbCB1cGRhdGVzXG4gICAgICAgICAgICBpZiAoZGVlcEVxdWFsKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgbmFtZV8zIGluIHNwZWNpYWxVcGRhdGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZUhhbmRsZXJzW25hbWVfM10oc3BlY2lhbFVwZGF0ZXNbbmFtZV8zXSwgX3RoaXMsIGRlZXBFcXVhbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8qXG4gICAgcmVidWlsZHMgdGhpbmdzIGJhc2VkIG9mZiBvZiBhIGNvbXBsZXRlIHNldCBvZiByZWZpbmVkIG9wdGlvbnNcbiAgICAqL1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5oYW5kbGVPcHRpb25zID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHBsdWdpbkhvb2tzID0gdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3M7XG4gICAgICAgIHRoaXMuZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbihvcHRpb25zLmRlZmF1bHRBbGxEYXlFdmVudER1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5kZWZhdWx0VGltZWRFdmVudER1cmF0aW9uID0gY3JlYXRlRHVyYXRpb24ob3B0aW9ucy5kZWZhdWx0VGltZWRFdmVudER1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5kZWxheWVkUmVyZW5kZXIgPSB0aGlzLmJ1aWxkRGVsYXllZFJlcmVuZGVyKG9wdGlvbnMucmVyZW5kZXJEZWxheSk7XG4gICAgICAgIHRoaXMudGhlbWUgPSB0aGlzLmJ1aWxkVGhlbWUob3B0aW9ucyk7XG4gICAgICAgIHZhciBhdmFpbGFibGUgPSB0aGlzLnBhcnNlUmF3TG9jYWxlcyhvcHRpb25zLmxvY2FsZXMpO1xuICAgICAgICB0aGlzLmF2YWlsYWJsZVJhd0xvY2FsZXMgPSBhdmFpbGFibGUubWFwO1xuICAgICAgICB2YXIgbG9jYWxlID0gdGhpcy5idWlsZExvY2FsZShvcHRpb25zLmxvY2FsZSB8fCBhdmFpbGFibGUuZGVmYXVsdENvZGUsIGF2YWlsYWJsZS5tYXApO1xuICAgICAgICB0aGlzLmRhdGVFbnYgPSB0aGlzLmJ1aWxkRGF0ZUVudihsb2NhbGUsIG9wdGlvbnMudGltZVpvbmUsIHBsdWdpbkhvb2tzLm5hbWVkVGltZVpvbmVkSW1wbCwgb3B0aW9ucy5maXJzdERheSwgb3B0aW9ucy53ZWVrTnVtYmVyQ2FsY3VsYXRpb24sIG9wdGlvbnMud2Vla0xhYmVsLCBwbHVnaW5Ib29rcy5jbWRGb3JtYXR0ZXIpO1xuICAgICAgICB0aGlzLnNlbGVjdGlvbkNvbmZpZyA9IHRoaXMuYnVpbGRTZWxlY3Rpb25Db25maWcob3B0aW9ucyk7IC8vIG5lZWRzIGRhdGVFbnYuIGRvIGFmdGVyIDooXG4gICAgICAgIC8vIGluZWZmZWNpZW50IHRvIGRvIGV2ZXJ5IHRpbWU/XG4gICAgICAgIHRoaXMudmlld1NwZWNzID0gYnVpbGRWaWV3U3BlY3MocGx1Z2luSG9va3Mudmlld3MsIHRoaXMub3B0aW9uc01hbmFnZXIpO1xuICAgICAgICAvLyBpbmVmZmVjaWVudCB0byBkbyBldmVyeSB0aW1lP1xuICAgICAgICB0aGlzLmRhdGVQcm9maWxlR2VuZXJhdG9ycyA9IG1hcEhhc2godGhpcy52aWV3U3BlY3MsIGZ1bmN0aW9uICh2aWV3U3BlYykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyB2aWV3U3BlYy5jbGFzcy5wcm90b3R5cGUuZGF0ZVByb2ZpbGVHZW5lcmF0b3JDbGFzcyh2aWV3U3BlYywgX3RoaXMpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRBdmFpbGFibGVMb2NhbGVDb2RlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuYXZhaWxhYmxlUmF3TG9jYWxlcyk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuX2J1aWxkU2VsZWN0aW9uQ29uZmlnID0gZnVuY3Rpb24gKHJhd09wdHMpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NTY29wZWRVaVByb3BzKCdzZWxlY3QnLCByYXdPcHRzLCB0aGlzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5fYnVpbGRFdmVudFVpU2luZ2xlQmFzZSA9IGZ1bmN0aW9uIChyYXdPcHRzKSB7XG4gICAgICAgIGlmIChyYXdPcHRzLmVkaXRhYmxlKSB7IC8vIHNvICdlZGl0YWJsZScgYWZmZWN0ZWQgZXZlbnRzXG4gICAgICAgICAgICByYXdPcHRzID0gX19hc3NpZ24oe30sIHJhd09wdHMsIHsgZXZlbnRFZGl0YWJsZTogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvY2Vzc1Njb3BlZFVpUHJvcHMoJ2V2ZW50JywgcmF3T3B0cywgdGhpcyk7XG4gICAgfTtcbiAgICAvLyBUcmlnZ2VyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuaGFzUHVibGljSGFuZGxlcnMgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNIYW5kbGVycyhuYW1lKSB8fFxuICAgICAgICAgICAgdGhpcy5vcHQobmFtZSk7IC8vIGhhbmRsZXIgc3BlY2lmaWVkIGluIG9wdGlvbnNcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wdWJsaWNseVRyaWdnZXIgPSBmdW5jdGlvbiAobmFtZSwgYXJncykge1xuICAgICAgICB2YXIgb3B0SGFuZGxlciA9IHRoaXMub3B0KG5hbWUpO1xuICAgICAgICB0aGlzLnRyaWdnZXJXaXRoKG5hbWUsIHRoaXMsIGFyZ3MpO1xuICAgICAgICBpZiAob3B0SGFuZGxlcikge1xuICAgICAgICAgICAgcmV0dXJuIG9wdEhhbmRsZXIuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wdWJsaWNseVRyaWdnZXJBZnRlclNpemluZyA9IGZ1bmN0aW9uIChuYW1lLCBhcmdzKSB7XG4gICAgICAgIHZhciBhZnRlclNpemluZ1RyaWdnZXJzID0gdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzO1xuICAgICAgICAoYWZ0ZXJTaXppbmdUcmlnZ2Vyc1tuYW1lXSB8fCAoYWZ0ZXJTaXppbmdUcmlnZ2Vyc1tuYW1lXSA9IFtdKSkucHVzaChhcmdzKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWxlYXNlQWZ0ZXJTaXppbmdUcmlnZ2VycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFmdGVyU2l6aW5nVHJpZ2dlcnMgPSB0aGlzLmFmdGVyU2l6aW5nVHJpZ2dlcnM7XG4gICAgICAgIGZvciAodmFyIG5hbWVfNCBpbiBhZnRlclNpemluZ1RyaWdnZXJzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gYWZ0ZXJTaXppbmdUcmlnZ2Vyc1tuYW1lXzRdOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKG5hbWVfNCwgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZnRlclNpemluZ1RyaWdnZXJzID0ge307XG4gICAgfTtcbiAgICAvLyBWaWV3XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBSZXR1cm5zIGEgYm9vbGVhbiBhYm91dCB3aGV0aGVyIHRoZSB2aWV3IGlzIG9rYXkgdG8gaW5zdGFudGlhdGUgYXQgc29tZSBwb2ludFxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5pc1ZhbGlkVmlld1R5cGUgPSBmdW5jdGlvbiAodmlld1R5cGUpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy52aWV3U3BlY3Nbdmlld1R5cGVdKTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5jaGFuZ2VWaWV3ID0gZnVuY3Rpb24gKHZpZXdUeXBlLCBkYXRlT3JSYW5nZSkge1xuICAgICAgICB2YXIgZGF0ZU1hcmtlciA9IG51bGw7XG4gICAgICAgIGlmIChkYXRlT3JSYW5nZSkge1xuICAgICAgICAgICAgaWYgKGRhdGVPclJhbmdlLnN0YXJ0ICYmIGRhdGVPclJhbmdlLmVuZCkgeyAvLyBhIHJhbmdlXG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zTWFuYWdlci5tdXRhdGUoeyB2aXNpYmxlUmFuZ2U6IGRhdGVPclJhbmdlIH0sIFtdKTsgLy8gd2lsbCBub3QgcmVyZW5kZXJcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZU9wdGlvbnModGhpcy5vcHRpb25zTWFuYWdlci5jb21wdXRlZCk7IC8vIC4uLmJ1dCB5dWNrXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8gYSBkYXRlXG4gICAgICAgICAgICAgICAgZGF0ZU1hcmtlciA9IHRoaXMuZGF0ZUVudi5jcmVhdGVNYXJrZXIoZGF0ZU9yUmFuZ2UpOyAvLyBqdXN0IGxpa2UgZ290b0RhdGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9WSUVXX1RZUEUnLFxuICAgICAgICAgICAgdmlld1R5cGU6IHZpZXdUeXBlLFxuICAgICAgICAgICAgZGF0ZU1hcmtlcjogZGF0ZU1hcmtlclxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIEZvcmNlcyBuYXZpZ2F0aW9uIHRvIGEgdmlldyBmb3IgdGhlIGdpdmVuIGRhdGUuXG4gICAgLy8gYHZpZXdUeXBlYCBjYW4gYmUgYSBzcGVjaWZpYyB2aWV3IG5hbWUgb3IgYSBnZW5lcmljIG9uZSBsaWtlIFwid2Vla1wiIG9yIFwiZGF5XCIuXG4gICAgLy8gbmVlZHMgdG8gY2hhbmdlXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnpvb21UbyA9IGZ1bmN0aW9uIChkYXRlTWFya2VyLCB2aWV3VHlwZSkge1xuICAgICAgICB2YXIgc3BlYztcbiAgICAgICAgdmlld1R5cGUgPSB2aWV3VHlwZSB8fCAnZGF5JzsgLy8gZGF5IGlzIGRlZmF1bHQgem9vbVxuICAgICAgICBzcGVjID0gdGhpcy52aWV3U3BlY3Nbdmlld1R5cGVdIHx8XG4gICAgICAgICAgICB0aGlzLmdldFVuaXRWaWV3U3BlYyh2aWV3VHlwZSk7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgaWYgKHNwZWMpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdTRVRfVklFV19UWVBFJyxcbiAgICAgICAgICAgICAgICB2aWV3VHlwZTogc3BlYy50eXBlLFxuICAgICAgICAgICAgICAgIGRhdGVNYXJrZXI6IGRhdGVNYXJrZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgICAgICBkYXRlTWFya2VyOiBkYXRlTWFya2VyXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gR2l2ZW4gYSBkdXJhdGlvbiBzaW5ndWxhciB1bml0LCBsaWtlIFwid2Vla1wiIG9yIFwiZGF5XCIsIGZpbmRzIGEgbWF0Y2hpbmcgdmlldyBzcGVjLlxuICAgIC8vIFByZWZlcmVuY2UgaXMgZ2l2ZW4gdG8gdmlld3MgdGhhdCBoYXZlIGNvcnJlc3BvbmRpbmcgYnV0dG9ucy5cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0VW5pdFZpZXdTcGVjID0gZnVuY3Rpb24gKHVuaXQpIHtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50O1xuICAgICAgICB2YXIgdmlld1R5cGVzID0gW107XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgc3BlYztcbiAgICAgICAgLy8gcHV0IHZpZXdzIHRoYXQgaGF2ZSBidXR0b25zIGZpcnN0LiB0aGVyZSB3aWxsIGJlIGR1cGxpY2F0ZXMsIGJ1dCBvaFxuICAgICAgICBpZiAoY29tcG9uZW50LmhlYWRlcikge1xuICAgICAgICAgICAgdmlld1R5cGVzLnB1c2guYXBwbHkodmlld1R5cGVzLCBjb21wb25lbnQuaGVhZGVyLnZpZXdzV2l0aEJ1dHRvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb21wb25lbnQuZm9vdGVyKSB7XG4gICAgICAgICAgICB2aWV3VHlwZXMucHVzaC5hcHBseSh2aWV3VHlwZXMsIGNvbXBvbmVudC5mb290ZXIudmlld3NXaXRoQnV0dG9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgdmlld1R5cGUgaW4gdGhpcy52aWV3U3BlY3MpIHtcbiAgICAgICAgICAgIHZpZXdUeXBlcy5wdXNoKHZpZXdUeXBlKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdmlld1R5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzcGVjID0gdGhpcy52aWV3U3BlY3Nbdmlld1R5cGVzW2ldXTtcbiAgICAgICAgICAgIGlmIChzcGVjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNwZWMuc2luZ2xlVW5pdCA9PT0gdW5pdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3BlYztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEN1cnJlbnQgRGF0ZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldEluaXRpYWxEYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGVmYXVsdERhdGVJbnB1dCA9IHRoaXMub3B0KCdkZWZhdWx0RGF0ZScpO1xuICAgICAgICAvLyBjb21wdXRlIHRoZSBpbml0aWFsIGFtYmlnLXRpbWV6b25lIGRhdGVcbiAgICAgICAgaWYgKGRlZmF1bHREYXRlSW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi5jcmVhdGVNYXJrZXIoZGVmYXVsdERhdGVJbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXROb3coKTsgLy8gZ2V0Tm93IGFscmVhZHkgcmV0dXJucyB1bnpvbmVkXG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5wcmV2ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUFJFVicgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUubmV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ05FWFQnIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnByZXZZZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZGF0ZUVudi5hZGRZZWFycyh0aGlzLnN0YXRlLmN1cnJlbnREYXRlLCAtMSlcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUubmV4dFllYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudW5zZWxlY3QoKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiAnU0VUX0RBVEUnLFxuICAgICAgICAgICAgZGF0ZU1hcmtlcjogdGhpcy5kYXRlRW52LmFkZFllYXJzKHRoaXMuc3RhdGUuY3VycmVudERhdGUsIDEpXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnRvZGF5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgdHlwZTogJ1NFVF9EQVRFJyxcbiAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZ2V0Tm93KClcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ290b0RhdGUgPSBmdW5jdGlvbiAoem9uZWREYXRlSW5wdXQpIHtcbiAgICAgICAgdGhpcy51bnNlbGVjdCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdTRVRfREFURScsXG4gICAgICAgICAgICBkYXRlTWFya2VyOiB0aGlzLmRhdGVFbnYuY3JlYXRlTWFya2VyKHpvbmVkRGF0ZUlucHV0KVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5pbmNyZW1lbnREYXRlID0gZnVuY3Rpb24gKGRlbHRhSW5wdXQpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gY3JlYXRlRHVyYXRpb24oZGVsdGFJbnB1dCk7XG4gICAgICAgIGlmIChkZWx0YSkgeyAvLyBlbHNlLCB3YXJuIGFib3V0IGludmFsaWQgaW5wdXQ/XG4gICAgICAgICAgICB0aGlzLnVuc2VsZWN0KCk7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX0RBVEUnLFxuICAgICAgICAgICAgICAgIGRhdGVNYXJrZXI6IHRoaXMuZGF0ZUVudi5hZGQodGhpcy5zdGF0ZS5jdXJyZW50RGF0ZSwgZGVsdGEpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZm9yIGV4dGVybmFsIEFQSVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXREYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRlRW52LnRvRGF0ZSh0aGlzLnN0YXRlLmN1cnJlbnREYXRlKTtcbiAgICB9O1xuICAgIC8vIERhdGUgRm9ybWF0dGluZyBVdGlsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmZvcm1hdERhdGUgPSBmdW5jdGlvbiAoZCwgZm9ybWF0dGVyKSB7XG4gICAgICAgIHZhciBkYXRlRW52ID0gdGhpcy5kYXRlRW52O1xuICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoZGF0ZUVudi5jcmVhdGVNYXJrZXIoZCksIGNyZWF0ZUZvcm1hdHRlcihmb3JtYXR0ZXIpKTtcbiAgICB9O1xuICAgIC8vIGBzZXR0aW5nc2AgaXMgZm9yIGZvcm1hdHRlciBBTkQgaXNFbmRFeGNsdXNpdmVcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZm9ybWF0UmFuZ2UgPSBmdW5jdGlvbiAoZDAsIGQxLCBzZXR0aW5ncykge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2UoZGF0ZUVudi5jcmVhdGVNYXJrZXIoZDApLCBkYXRlRW52LmNyZWF0ZU1hcmtlcihkMSksIGNyZWF0ZUZvcm1hdHRlcihzZXR0aW5ncywgdGhpcy5vcHQoJ2RlZmF1bHRSYW5nZVNlcGFyYXRvcicpKSwgc2V0dGluZ3MpO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmZvcm1hdElzbyA9IGZ1bmN0aW9uIChkLCBvbWl0VGltZSkge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuZGF0ZUVudjtcbiAgICAgICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0SXNvKGRhdGVFbnYuY3JlYXRlTWFya2VyKGQpLCB7IG9taXRUaW1lOiBvbWl0VGltZSB9KTtcbiAgICB9O1xuICAgIC8vIFNpemluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLndpbmRvd1Jlc2l6ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICBpZiAoIXRoaXMuaXNIYW5kbGluZ1dpbmRvd1Jlc2l6ZSAmJlxuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgJiYgLy8gd2h5P1xuICAgICAgICAgICAgZXYudGFyZ2V0ID09PSB3aW5kb3cgLy8gbm90IGEganF1aSByZXNpemUgZXZlbnRcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmlzSGFuZGxpbmdXaW5kb3dSZXNpemUgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVTaXplKCk7XG4gICAgICAgICAgICB0aGlzLnB1YmxpY2x5VHJpZ2dlcignd2luZG93UmVzaXplJywgW3RoaXMudmlld10pO1xuICAgICAgICAgICAgdGhpcy5pc0hhbmRsaW5nV2luZG93UmVzaXplID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5jb21wb25lbnQpIHsgLy8gd2hlbj9cbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LnVwZGF0ZVNpemUodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIENvbXBvbmVudCBSZWdpc3RyYXRpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWdpc3RlckludGVyYWN0aXZlQ29tcG9uZW50ID0gZnVuY3Rpb24gKGNvbXBvbmVudCwgc2V0dGluZ3NJbnB1dCkge1xuICAgICAgICB2YXIgc2V0dGluZ3MgPSBwYXJzZUludGVyYWN0aW9uU2V0dGluZ3MoY29tcG9uZW50LCBzZXR0aW5nc0lucHV0KTtcbiAgICAgICAgdmFyIERFRkFVTFRfSU5URVJBQ1RJT05TID0gW1xuICAgICAgICAgICAgRXZlbnRDbGlja2luZyxcbiAgICAgICAgICAgIEV2ZW50SG92ZXJpbmdcbiAgICAgICAgXTtcbiAgICAgICAgdmFyIGludGVyYWN0aW9uQ2xhc3NlcyA9IERFRkFVTFRfSU5URVJBQ1RJT05TLmNvbmNhdCh0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5jb21wb25lbnRJbnRlcmFjdGlvbnMpO1xuICAgICAgICB2YXIgaW50ZXJhY3Rpb25zID0gaW50ZXJhY3Rpb25DbGFzc2VzLm1hcChmdW5jdGlvbiAoaW50ZXJhY3Rpb25DbGFzcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBpbnRlcmFjdGlvbkNsYXNzKHNldHRpbmdzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW50ZXJhY3Rpb25zU3RvcmVbY29tcG9uZW50LnVpZF0gPSBpbnRlcmFjdGlvbnM7XG4gICAgICAgIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZVtjb21wb25lbnQudWlkXSA9IHNldHRpbmdzO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLnVucmVnaXN0ZXJJbnRlcmFjdGl2ZUNvbXBvbmVudCA9IGZ1bmN0aW9uIChjb21wb25lbnQpIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuaW50ZXJhY3Rpb25zU3RvcmVbY29tcG9uZW50LnVpZF07IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBfYVtfaV07XG4gICAgICAgICAgICBsaXN0ZW5lci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIHRoaXMuaW50ZXJhY3Rpb25zU3RvcmVbY29tcG9uZW50LnVpZF07XG4gICAgICAgIGRlbGV0ZSBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmVbY29tcG9uZW50LnVpZF07XG4gICAgfTtcbiAgICAvLyBEYXRlIFNlbGVjdGlvbiAvIEV2ZW50IFNlbGVjdGlvbiAvIERheUNsaWNrXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyB0aGlzIHB1YmxpYyBtZXRob2QgcmVjZWl2ZXMgc3RhcnQvZW5kIGRhdGVzIGluIGFueSBmb3JtYXQsIHdpdGggYW55IHRpbWV6b25lXG4gICAgLy8gTk9URTogYXJncyB3ZXJlIGNoYW5nZWQgZnJvbSB2M1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5zZWxlY3QgPSBmdW5jdGlvbiAoZGF0ZU9yT2JqLCBlbmREYXRlKSB7XG4gICAgICAgIHZhciBzZWxlY3Rpb25JbnB1dDtcbiAgICAgICAgaWYgKGVuZERhdGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGRhdGVPck9iai5zdGFydCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uSW5wdXQgPSBkYXRlT3JPYmo7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb25JbnB1dCA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IGRhdGVPck9iaixcbiAgICAgICAgICAgICAgICAgICAgZW5kOiBudWxsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbklucHV0ID0ge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBkYXRlT3JPYmosXG4gICAgICAgICAgICAgICAgZW5kOiBlbmREYXRlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBzZWxlY3Rpb24gPSBwYXJzZURhdGVTcGFuKHNlbGVjdGlvbklucHV0LCB0aGlzLmRhdGVFbnYsIGNyZWF0ZUR1cmF0aW9uKHsgZGF5czogMSB9KSAvLyBUT0RPOiBjYWNoZSB0aGlzP1xuICAgICAgICApO1xuICAgICAgICBpZiAoc2VsZWN0aW9uKSB7IC8vIHRocm93IHBhcnNlIGVycm9yIG90aGVyd2lzZT9cbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnU0VMRUNUX0RBVEVTJywgc2VsZWN0aW9uOiBzZWxlY3Rpb24gfSk7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXJEYXRlU2VsZWN0KHNlbGVjdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHB1YmxpYyBtZXRob2RcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudW5zZWxlY3QgPSBmdW5jdGlvbiAocGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmRhdGVTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRUxFQ1RfREFURVMnIH0pO1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyRGF0ZVVuc2VsZWN0KHBldik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50cmlnZ2VyRGF0ZVNlbGVjdCA9IGZ1bmN0aW9uIChzZWxlY3Rpb24sIHBldikge1xuICAgICAgICB2YXIgYXJnID0gX19hc3NpZ24oe30sIHRoaXMuYnVpbGREYXRlU3BhbkFwaShzZWxlY3Rpb24pLCB7IGpzRXZlbnQ6IHBldiA/IHBldi5vcmlnRXZlbnQgOiBudWxsLCB2aWV3OiB0aGlzLnZpZXcgfSk7XG4gICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCdzZWxlY3QnLCBbYXJnXSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUudHJpZ2dlckRhdGVVbnNlbGVjdCA9IGZ1bmN0aW9uIChwZXYpIHtcbiAgICAgICAgdGhpcy5wdWJsaWNseVRyaWdnZXIoJ3Vuc2VsZWN0JywgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGpzRXZlbnQ6IHBldiA/IHBldi5vcmlnRXZlbnQgOiBudWxsLFxuICAgICAgICAgICAgICAgIHZpZXc6IHRoaXMudmlld1xuICAgICAgICAgICAgfVxuICAgICAgICBdKTtcbiAgICB9O1xuICAgIC8vIFRPRE86IHJlY2VpdmUgcGV2P1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS50cmlnZ2VyRGF0ZUNsaWNrID0gZnVuY3Rpb24gKGRhdGVTcGFuLCBkYXlFbCwgdmlldywgZXYpIHtcbiAgICAgICAgdmFyIGFyZyA9IF9fYXNzaWduKHt9LCB0aGlzLmJ1aWxkRGF0ZVBvaW50QXBpKGRhdGVTcGFuKSwgeyBkYXlFbDogZGF5RWwsIGpzRXZlbnQ6IGV2LCAvLyBJcyB0aGlzIGFsd2F5cyBhIG1vdXNlIGV2ZW50PyBTZWUgIzQ2NTVcbiAgICAgICAgICAgIHZpZXc6IHZpZXcgfSk7XG4gICAgICAgIHRoaXMucHVibGljbHlUcmlnZ2VyKCdkYXRlQ2xpY2snLCBbYXJnXSk7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYnVpbGREYXRlUG9pbnRBcGkgPSBmdW5jdGlvbiAoZGF0ZVNwYW4pIHtcbiAgICAgICAgdmFyIHByb3BzID0ge307XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnBsdWdpblN5c3RlbS5ob29rcy5kYXRlUG9pbnRUcmFuc2Zvcm1zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IF9hW19pXTtcbiAgICAgICAgICAgIF9fYXNzaWduKHByb3BzLCB0cmFuc2Zvcm0oZGF0ZVNwYW4sIHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICBfX2Fzc2lnbihwcm9wcywgYnVpbGREYXRlUG9pbnRBcGkoZGF0ZVNwYW4sIHRoaXMuZGF0ZUVudikpO1xuICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYnVpbGREYXRlU3BhbkFwaSA9IGZ1bmN0aW9uIChkYXRlU3Bhbikge1xuICAgICAgICB2YXIgcHJvcHMgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMucGx1Z2luU3lzdGVtLmhvb2tzLmRhdGVTcGFuVHJhbnNmb3JtczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSBfYVtfaV07XG4gICAgICAgICAgICBfX2Fzc2lnbihwcm9wcywgdHJhbnNmb3JtKGRhdGVTcGFuLCB0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgX19hc3NpZ24ocHJvcHMsIGJ1aWxkRGF0ZVNwYW5BcGkoZGF0ZVNwYW4sIHRoaXMuZGF0ZUVudikpO1xuICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgfTtcbiAgICAvLyBEYXRlIFV0aWxzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBSZXR1cm5zIGEgRGF0ZU1hcmtlciBmb3IgdGhlIGN1cnJlbnQgZGF0ZSwgYXMgZGVmaW5lZCBieSB0aGUgY2xpZW50J3MgY29tcHV0ZXIgb3IgZnJvbSB0aGUgYG5vd2Agb3B0aW9uXG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldE5vdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vdyA9IHRoaXMub3B0KCdub3cnKTtcbiAgICAgICAgaWYgKHR5cGVvZiBub3cgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG5vdyA9IG5vdygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub3cgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUVudi5jcmVhdGVOb3dNYXJrZXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5kYXRlRW52LmNyZWF0ZU1hcmtlcihub3cpO1xuICAgIH07XG4gICAgLy8gRXZlbnQtRGF0ZSBVdGlsaXRpZXNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEdpdmVuIGFuIGV2ZW50J3MgYWxsRGF5IHN0YXR1cyBhbmQgc3RhcnQgZGF0ZSwgcmV0dXJuIHdoYXQgaXRzIGZhbGxiYWNrIGVuZCBkYXRlIHNob3VsZCBiZS5cbiAgICAvLyBUT0RPOiByZW5hbWUgdG8gY29tcHV0ZURlZmF1bHRFdmVudEVuZFxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXREZWZhdWx0RXZlbnRFbmQgPSBmdW5jdGlvbiAoYWxsRGF5LCBtYXJrZXIpIHtcbiAgICAgICAgdmFyIGVuZCA9IG1hcmtlcjtcbiAgICAgICAgaWYgKGFsbERheSkge1xuICAgICAgICAgICAgZW5kID0gc3RhcnRPZkRheShlbmQpO1xuICAgICAgICAgICAgZW5kID0gdGhpcy5kYXRlRW52LmFkZChlbmQsIHRoaXMuZGVmYXVsdEFsbERheUV2ZW50RHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZW5kID0gdGhpcy5kYXRlRW52LmFkZChlbmQsIHRoaXMuZGVmYXVsdFRpbWVkRXZlbnREdXJhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVuZDtcbiAgICB9O1xuICAgIC8vIFB1YmxpYyBFdmVudHMgQVBJXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuYWRkRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnRJbnB1dCwgc291cmNlSW5wdXQpIHtcbiAgICAgICAgaWYgKGV2ZW50SW5wdXQgaW5zdGFuY2VvZiBFdmVudEFwaSkge1xuICAgICAgICAgICAgdmFyIGRlZiA9IGV2ZW50SW5wdXQuX2RlZjtcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGV2ZW50SW5wdXQuX2luc3RhbmNlO1xuICAgICAgICAgICAgLy8gbm90IGFscmVhZHkgcHJlc2VudD8gZG9uJ3Qgd2FudCB0byBhZGQgYW4gb2xkIHNuYXBzaG90XG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuZXZlbnRTdG9yZS5kZWZzW2RlZi5kZWZJZF0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ0FERF9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFR1cGxlVG9TdG9yZSh7IGRlZjogZGVmLCBpbnN0YW5jZTogaW5zdGFuY2UgfSkgLy8gVE9ETzogYmV0dGVyIHV0aWwgZm9yIHR3byBhcmdzP1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50SW5wdXQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNvdXJjZUlkO1xuICAgICAgICBpZiAoc291cmNlSW5wdXQgaW5zdGFuY2VvZiBFdmVudFNvdXJjZUFwaSkge1xuICAgICAgICAgICAgc291cmNlSWQgPSBzb3VyY2VJbnB1dC5pbnRlcm5hbEV2ZW50U291cmNlLnNvdXJjZUlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHNvdXJjZUlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2VBcGkgPSB0aGlzLmdldEV2ZW50U291cmNlQnlJZChzb3VyY2VJbnB1dCk7IC8vIFRPRE86IHVzZSBhbiBpbnRlcm5hbCBmdW5jdGlvblxuICAgICAgICAgICAgaWYgKCFzb3VyY2VBcGkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0NvdWxkIG5vdCBmaW5kIGFuIGV2ZW50IHNvdXJjZSB3aXRoIElEIFwiJyArIHNvdXJjZUlucHV0ICsgJ1wiJyk7IC8vIFRPRE86IHRlc3RcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHNvdXJjZUlkID0gc291cmNlQXBpLmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR1cGxlID0gcGFyc2VFdmVudChldmVudElucHV0LCBzb3VyY2VJZCwgdGhpcyk7XG4gICAgICAgIGlmICh0dXBsZSkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ0FERF9FVkVOVFMnLFxuICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50VHVwbGVUb1N0b3JlKHR1cGxlKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50QXBpKHRoaXMsIHR1cGxlLmRlZiwgdHVwbGUuZGVmLnJlY3VycmluZ0RlZiA/IG51bGwgOiB0dXBsZS5pbnN0YW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvLyBUT0RPOiBvcHRpbWl6ZVxuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRFdmVudEJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5zdGF0ZS5ldmVudFN0b3JlLCBkZWZzID0gX2EuZGVmcywgaW5zdGFuY2VzID0gX2EuaW5zdGFuY2VzO1xuICAgICAgICBpZCA9IFN0cmluZyhpZCk7XG4gICAgICAgIGZvciAodmFyIGRlZklkIGluIGRlZnMpIHtcbiAgICAgICAgICAgIHZhciBkZWYgPSBkZWZzW2RlZklkXTtcbiAgICAgICAgICAgIGlmIChkZWYucHVibGljSWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRlZi5yZWN1cnJpbmdEZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudEFwaSh0aGlzLCBkZWYsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaW5zdGFuY2VJZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGluc3RhbmNlc1tpbnN0YW5jZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnN0YW5jZS5kZWZJZCA9PT0gZGVmLmRlZklkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdmVudEFwaSh0aGlzLCBkZWYsIGluc3RhbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5nZXRFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuc3RhdGUuZXZlbnRTdG9yZSwgZGVmcyA9IF9hLmRlZnMsIGluc3RhbmNlcyA9IF9hLmluc3RhbmNlcztcbiAgICAgICAgdmFyIGV2ZW50QXBpcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpZCBpbiBpbnN0YW5jZXMpIHtcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IGluc3RhbmNlc1tpZF07XG4gICAgICAgICAgICB2YXIgZGVmID0gZGVmc1tpbnN0YW5jZS5kZWZJZF07XG4gICAgICAgICAgICBldmVudEFwaXMucHVzaChuZXcgRXZlbnRBcGkodGhpcywgZGVmLCBpbnN0YW5jZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBldmVudEFwaXM7XG4gICAgfTtcbiAgICBDYWxlbmRhci5wcm90b3R5cGUucmVtb3ZlQWxsRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ1JFTU9WRV9BTExfRVZFTlRTJyB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZXJlbmRlckV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdSRVNFVF9FVkVOVFMnIH0pO1xuICAgIH07XG4gICAgLy8gUHVibGljIEV2ZW50IFNvdXJjZXMgQVBJXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuZ2V0RXZlbnRTb3VyY2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc291cmNlSGFzaCA9IHRoaXMuc3RhdGUuZXZlbnRTb3VyY2VzO1xuICAgICAgICB2YXIgc291cmNlQXBpcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpbnRlcm5hbElkIGluIHNvdXJjZUhhc2gpIHtcbiAgICAgICAgICAgIHNvdXJjZUFwaXMucHVzaChuZXcgRXZlbnRTb3VyY2VBcGkodGhpcywgc291cmNlSGFzaFtpbnRlcm5hbElkXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzb3VyY2VBcGlzO1xuICAgIH07XG4gICAgQ2FsZW5kYXIucHJvdG90eXBlLmdldEV2ZW50U291cmNlQnlJZCA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICB2YXIgc291cmNlSGFzaCA9IHRoaXMuc3RhdGUuZXZlbnRTb3VyY2VzO1xuICAgICAgICBpZCA9IFN0cmluZyhpZCk7XG4gICAgICAgIGZvciAodmFyIHNvdXJjZUlkIGluIHNvdXJjZUhhc2gpIHtcbiAgICAgICAgICAgIGlmIChzb3VyY2VIYXNoW3NvdXJjZUlkXS5wdWJsaWNJZCA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlQXBpKHRoaXMsIHNvdXJjZUhhc2hbc291cmNlSWRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5hZGRFdmVudFNvdXJjZSA9IGZ1bmN0aW9uIChzb3VyY2VJbnB1dCkge1xuICAgICAgICBpZiAoc291cmNlSW5wdXQgaW5zdGFuY2VvZiBFdmVudFNvdXJjZUFwaSkge1xuICAgICAgICAgICAgLy8gbm90IGFscmVhZHkgcHJlc2VudD8gZG9uJ3Qgd2FudCB0byBhZGQgYW4gb2xkIHNuYXBzaG90XG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuZXZlbnRTb3VyY2VzW3NvdXJjZUlucHV0LmludGVybmFsRXZlbnRTb3VyY2Uuc291cmNlSWRdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdBRERfRVZFTlRfU09VUkNFUycsXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZXM6IFtzb3VyY2VJbnB1dC5pbnRlcm5hbEV2ZW50U291cmNlXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZUlucHV0O1xuICAgICAgICB9XG4gICAgICAgIHZhciBldmVudFNvdXJjZSA9IHBhcnNlRXZlbnRTb3VyY2Uoc291cmNlSW5wdXQsIHRoaXMpO1xuICAgICAgICBpZiAoZXZlbnRTb3VyY2UpIHsgLy8gVE9ETzogZXJyb3Igb3RoZXJ3aXNlP1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaCh7IHR5cGU6ICdBRERfRVZFTlRfU09VUkNFUycsIHNvdXJjZXM6IFtldmVudFNvdXJjZV0gfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlQXBpKHRoaXMsIGV2ZW50U291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZW1vdmVBbGxFdmVudFNvdXJjZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2goeyB0eXBlOiAnUkVNT1ZFX0FMTF9FVkVOVF9TT1VSQ0VTJyB9KTtcbiAgICB9O1xuICAgIENhbGVuZGFyLnByb3RvdHlwZS5yZWZldGNoRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoKHsgdHlwZTogJ0ZFVENIX0VWRU5UX1NPVVJDRVMnIH0pO1xuICAgIH07XG4gICAgLy8gU2Nyb2xsXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBDYWxlbmRhci5wcm90b3R5cGUuc2Nyb2xsVG9UaW1lID0gZnVuY3Rpb24gKHRpbWVJbnB1dCkge1xuICAgICAgICB2YXIgZHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbih0aW1lSW5wdXQpO1xuICAgICAgICBpZiAoZHVyYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LnZpZXcuc2Nyb2xsVG9EdXJhdGlvbihkdXJhdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBDYWxlbmRhcjtcbn0oKSk7XG5FbWl0dGVyTWl4aW4ubWl4SW50byhDYWxlbmRhcik7XG4vLyBmb3IgbWVtb2l6ZXJzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gYnVpbGRDb21wb25lbnRDb250ZXh0JDEodGhlbWUsIGRhdGVFbnYsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IENvbXBvbmVudENvbnRleHQodGhpcywgdGhlbWUsIGRhdGVFbnYsIG9wdGlvbnMsIG51bGwpO1xufVxuZnVuY3Rpb24gYnVpbGREYXRlRW52KGxvY2FsZSwgdGltZVpvbmUsIG5hbWVkVGltZVpvbmVJbXBsLCBmaXJzdERheSwgd2Vla051bWJlckNhbGN1bGF0aW9uLCB3ZWVrTGFiZWwsIGNtZEZvcm1hdHRlcikge1xuICAgIHJldHVybiBuZXcgRGF0ZUVudih7XG4gICAgICAgIGNhbGVuZGFyU3lzdGVtOiAnZ3JlZ29yeScsXG4gICAgICAgIHRpbWVab25lOiB0aW1lWm9uZSxcbiAgICAgICAgbmFtZWRUaW1lWm9uZUltcGw6IG5hbWVkVGltZVpvbmVJbXBsLFxuICAgICAgICBsb2NhbGU6IGxvY2FsZSxcbiAgICAgICAgd2Vla051bWJlckNhbGN1bGF0aW9uOiB3ZWVrTnVtYmVyQ2FsY3VsYXRpb24sXG4gICAgICAgIGZpcnN0RGF5OiBmaXJzdERheSxcbiAgICAgICAgd2Vla0xhYmVsOiB3ZWVrTGFiZWwsXG4gICAgICAgIGNtZEZvcm1hdHRlcjogY21kRm9ybWF0dGVyXG4gICAgfSk7XG59XG5mdW5jdGlvbiBidWlsZFRoZW1lKGNhbGVuZGFyT3B0aW9ucykge1xuICAgIHZhciB0aGVtZUNsYXNzID0gdGhpcy5wbHVnaW5TeXN0ZW0uaG9va3MudGhlbWVDbGFzc2VzW2NhbGVuZGFyT3B0aW9ucy50aGVtZVN5c3RlbV0gfHwgU3RhbmRhcmRUaGVtZTtcbiAgICByZXR1cm4gbmV3IHRoZW1lQ2xhc3MoY2FsZW5kYXJPcHRpb25zKTtcbn1cbmZ1bmN0aW9uIGJ1aWxkRGVsYXllZFJlcmVuZGVyKHdhaXQpIHtcbiAgICB2YXIgZnVuYyA9IHRoaXMudHJ5UmVyZW5kZXIuYmluZCh0aGlzKTtcbiAgICBpZiAod2FpdCAhPSBudWxsKSB7XG4gICAgICAgIGZ1bmMgPSBkZWJvdW5jZShmdW5jLCB3YWl0KTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmM7XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50VWlCeVNvdXJjZShldmVudFNvdXJjZXMpIHtcbiAgICByZXR1cm4gbWFwSGFzaChldmVudFNvdXJjZXMsIGZ1bmN0aW9uIChldmVudFNvdXJjZSkge1xuICAgICAgICByZXR1cm4gZXZlbnRTb3VyY2UudWk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBidWlsZEV2ZW50VWlCYXNlcyhldmVudERlZnMsIGV2ZW50VWlTaW5nbGVCYXNlLCBldmVudFVpQnlTb3VyY2UpIHtcbiAgICB2YXIgZXZlbnRVaUJhc2VzID0geyAnJzogZXZlbnRVaVNpbmdsZUJhc2UgfTtcbiAgICBmb3IgKHZhciBkZWZJZCBpbiBldmVudERlZnMpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50RGVmc1tkZWZJZF07XG4gICAgICAgIGlmIChkZWYuc291cmNlSWQgJiYgZXZlbnRVaUJ5U291cmNlW2RlZi5zb3VyY2VJZF0pIHtcbiAgICAgICAgICAgIGV2ZW50VWlCYXNlc1tkZWZJZF0gPSBldmVudFVpQnlTb3VyY2VbZGVmLnNvdXJjZUlkXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXZlbnRVaUJhc2VzO1xufVxuXG52YXIgVmlldyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoVmlldywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBWaWV3KHZpZXdTcGVjLCBwYXJlbnRFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjcmVhdGVFbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogJ2ZjLXZpZXcgZmMtJyArIHZpZXdTcGVjLnR5cGUgKyAnLXZpZXcnIH0pKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yZW5kZXJEYXRlc01lbSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMucmVuZGVyRGF0ZXNXcmFwLCBfdGhpcy51bnJlbmRlckRhdGVzV3JhcCk7XG4gICAgICAgIF90aGlzLnJlbmRlckJ1c2luZXNzSG91cnNNZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckJ1c2luZXNzSG91cnMsIF90aGlzLnVucmVuZGVyQnVzaW5lc3NIb3VycywgW190aGlzLnJlbmRlckRhdGVzTWVtXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckRhdGVTZWxlY3Rpb25NZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckRhdGVTZWxlY3Rpb25XcmFwLCBfdGhpcy51bnJlbmRlckRhdGVTZWxlY3Rpb25XcmFwLCBbX3RoaXMucmVuZGVyRGF0ZXNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRzTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJFdmVudHMsIF90aGlzLnVucmVuZGVyRXZlbnRzLCBbX3RoaXMucmVuZGVyRGF0ZXNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnRTZWxlY3Rpb25NZW0gPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uV3JhcCwgX3RoaXMudW5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAsIFtfdGhpcy5yZW5kZXJFdmVudHNNZW1dKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnREcmFnTWVtID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5yZW5kZXJFdmVudERyYWdXcmFwLCBfdGhpcy51bnJlbmRlckV2ZW50RHJhZ1dyYXAsIFtfdGhpcy5yZW5kZXJEYXRlc01lbV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFJlc2l6ZU1lbSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMucmVuZGVyRXZlbnRSZXNpemVXcmFwLCBfdGhpcy51bnJlbmRlckV2ZW50UmVzaXplV3JhcCwgW190aGlzLnJlbmRlckRhdGVzTWVtXSk7XG4gICAgICAgIF90aGlzLnZpZXdTcGVjID0gdmlld1NwZWM7XG4gICAgICAgIF90aGlzLnR5cGUgPSB2aWV3U3BlYy50eXBlO1xuICAgICAgICBwYXJlbnRFbC5hcHBlbmRDaGlsZChfdGhpcy5lbCk7XG4gICAgICAgIF90aGlzLmluaXRpYWxpemUoKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBWaWV3LnByb3RvdHlwZS5pbml0aWFsaXplID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFZpZXcucHJvdG90eXBlLCBcImFjdGl2ZVN0YXJ0XCIsIHtcbiAgICAgICAgLy8gRGF0ZSBTZXR0aW5nL1Vuc2V0dGluZ1xuICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZGF0ZUVudi50b0RhdGUodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZS5zdGFydCk7XG4gICAgICAgIH0sXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShWaWV3LnByb3RvdHlwZSwgXCJhY3RpdmVFbmRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZGF0ZUVudi50b0RhdGUodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5hY3RpdmVSYW5nZS5lbmQpO1xuICAgICAgICB9LFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoVmlldy5wcm90b3R5cGUsIFwiY3VycmVudFN0YXJ0XCIsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmRhdGVFbnYudG9EYXRlKHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlLnN0YXJ0KTtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFZpZXcucHJvdG90eXBlLCBcImN1cnJlbnRFbmRcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZGF0ZUVudi50b0RhdGUodGhpcy5wcm9wcy5kYXRlUHJvZmlsZS5jdXJyZW50UmFuZ2UuZW5kKTtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgLy8gR2VuZXJhbCBSZW5kZXJpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgICAgICB0aGlzLnJlbmRlckRhdGVzTWVtKHByb3BzLmRhdGVQcm9maWxlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJCdXNpbmVzc0hvdXJzTWVtKHByb3BzLmJ1c2luZXNzSG91cnMpO1xuICAgICAgICB0aGlzLnJlbmRlckRhdGVTZWxlY3Rpb25NZW0ocHJvcHMuZGF0ZVNlbGVjdGlvbik7XG4gICAgICAgIHRoaXMucmVuZGVyRXZlbnRzTWVtKHByb3BzLmV2ZW50U3RvcmUpO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uTWVtKHByb3BzLmV2ZW50U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudERyYWdNZW0ocHJvcHMuZXZlbnREcmFnKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZU1lbShwcm9wcy5ldmVudFJlc2l6ZSk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5iZWZvcmVVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkU2Nyb2xsKHRoaXMucXVlcnlTY3JvbGwoKSk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJEYXRlc01lbS51bnJlbmRlcigpOyAvLyBzaG91bGQgdW5yZW5kZXIgZXZlcnl0aGluZyBlbHNlXG4gICAgfTtcbiAgICAvLyBTaXppbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnVwZGF0ZVNpemUgPSBmdW5jdGlvbiAoaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0bykge1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzLmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIGlmIChpc1Jlc2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5hZGRTY3JvbGwodGhpcy5xdWVyeVNjcm9sbCgpKTsgLy8gTk9URTogc2FtZSBjb2RlIGFzIGluIGJlZm9yZVVwZGF0ZVxuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Jlc2l6ZSB8fCAvLyBIQUNLUy4uLlxuICAgICAgICAgICAgY2FsZW5kYXIuaXNWaWV3VXBkYXRlZCB8fFxuICAgICAgICAgICAgY2FsZW5kYXIuaXNEYXRlc1VwZGF0ZWQgfHxcbiAgICAgICAgICAgIGNhbGVuZGFyLmlzRXZlbnRzVXBkYXRlZCkge1xuICAgICAgICAgICAgLy8gc29ydCBvZiB0aGUgY2F0Y2gtYWxsIHNpemluZ1xuICAgICAgICAgICAgLy8gYW55dGhpbmcgdGhhdCBtaWdodCBjYXVzZSBkaW1lbnNpb24gY2hhbmdlc1xuICAgICAgICAgICAgdGhpcy51cGRhdGVCYXNlU2l6ZShpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOT1RFOiBwb3BTY3JvbGwgaXMgY2FsbGVkIGJ5IENhbGVuZGFyQ29tcG9uZW50XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51cGRhdGVCYXNlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKSB7XG4gICAgfTtcbiAgICAvLyBEYXRlIFJlbmRlcmluZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRGF0ZXNXcmFwID0gZnVuY3Rpb24gKGRhdGVQcm9maWxlKSB7XG4gICAgICAgIHRoaXMucmVuZGVyRGF0ZXMoZGF0ZVByb2ZpbGUpO1xuICAgICAgICB0aGlzLmFkZFNjcm9sbCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogY3JlYXRlRHVyYXRpb24odGhpcy5jb250ZXh0Lm9wdGlvbnMuc2Nyb2xsVGltZSlcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckRhdGVzV3JhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdG9wTm93SW5kaWNhdG9yKCk7XG4gICAgICAgIHRoaXMudW5yZW5kZXJEYXRlcygpO1xuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRGF0ZXMgPSBmdW5jdGlvbiAoZGF0ZVByb2ZpbGUpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckRhdGVzID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgIC8vIEJ1c2luZXNzIEhvdXJzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJCdXNpbmVzc0hvdXJzID0gZnVuY3Rpb24gKGJ1c2luZXNzSG91cnMpIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckJ1c2luZXNzSG91cnMgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgLy8gRGF0ZSBTZWxlY3Rpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckRhdGVTZWxlY3Rpb25XcmFwID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xuICAgICAgICBpZiAoc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckRhdGVTZWxlY3Rpb24oc2VsZWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJEYXRlU2VsZWN0aW9uV3JhcCA9IGZ1bmN0aW9uIChzZWxlY3Rpb24pIHtcbiAgICAgICAgaWYgKHNlbGVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckRhdGVTZWxlY3Rpb24oc2VsZWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRGF0ZVNlbGVjdGlvbiA9IGZ1bmN0aW9uIChzZWxlY3Rpb24pIHsgfTtcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlckRhdGVTZWxlY3Rpb24gPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7IH07XG4gICAgLy8gRXZlbnQgUmVuZGVyaW5nXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudHMgPSBmdW5jdGlvbiAoZXZlbnRTdG9yZSkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRzID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgIC8vIHV0aWwgZm9yIHN1YmNsYXNzZXNcbiAgICBWaWV3LnByb3RvdHlwZS5zbGljZUV2ZW50cyA9IGZ1bmN0aW9uIChldmVudFN0b3JlLCBhbGxEYXkpIHtcbiAgICAgICAgdmFyIHByb3BzID0gdGhpcy5wcm9wcztcbiAgICAgICAgcmV0dXJuIHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBwcm9wcy5ldmVudFVpQmFzZXMsIHByb3BzLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBhbGxEYXkgPyB0aGlzLmNvbnRleHQubmV4dERheVRocmVzaG9sZCA6IG51bGwpLmZnO1xuICAgIH07XG4gICAgLy8gRXZlbnQgU2VsZWN0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbihpbnN0YW5jZUlkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudFNlbGVjdGlvbldyYXAgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckV2ZW50U2VsZWN0aW9uKGluc3RhbmNlSWQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IGZ1bmN0aW9uIChpbnN0YW5jZUlkKSB7IH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IGZ1bmN0aW9uIChpbnN0YW5jZUlkKSB7IH07XG4gICAgLy8gRXZlbnQgRHJhZ1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgVmlldy5wcm90b3R5cGUucmVuZGVyRXZlbnREcmFnV3JhcCA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyRXZlbnREcmFnKHN0YXRlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudERyYWdXcmFwID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy51bnJlbmRlckV2ZW50RHJhZyhzdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnJlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnREcmFnID0gZnVuY3Rpb24gKHN0YXRlKSB7IH07XG4gICAgLy8gRXZlbnQgUmVzaXplXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFJlc2l6ZVdyYXAgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckV2ZW50UmVzaXplKHN0YXRlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUudW5yZW5kZXJFdmVudFJlc2l6ZVdyYXAgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLnVucmVuZGVyRXZlbnRSZXNpemUoc3RhdGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJFdmVudFJlc2l6ZSA9IGZ1bmN0aW9uIChzdGF0ZSkgeyB9O1xuICAgIFZpZXcucHJvdG90eXBlLnVucmVuZGVyRXZlbnRSZXNpemUgPSBmdW5jdGlvbiAoc3RhdGUpIHsgfTtcbiAgICAvKiBOb3cgSW5kaWNhdG9yXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAvLyBJbW1lZGlhdGVseSByZW5kZXIgdGhlIGN1cnJlbnQgdGltZSBpbmRpY2F0b3IgYW5kIGJlZ2lucyByZS1yZW5kZXJpbmcgaXQgYXQgYW4gaW50ZXJ2YWwsXG4gICAgLy8gd2hpY2ggaXMgZGVmaW5lZCBieSB0aGlzLmdldE5vd0luZGljYXRvclVuaXQoKS5cbiAgICAvLyBUT0RPOiBzb21laG93IGRvIHRoaXMgZm9yIHRoZSBjdXJyZW50IHdob2xlIGRheSdzIGJhY2tncm91bmQgdG9vXG4gICAgLy8gVVNBR0U6IG11c3QgYmUgY2FsbGVkIG1hbnVhbGx5IGZyb20gc3ViY2xhc3NlcycgcmVuZGVyIG1ldGhvZHMhIGRvbid0IG5lZWQgdG8gY2FsbCBzdG9wTm93SW5kaWNhdG9yIHRob1xuICAgIFZpZXcucHJvdG90eXBlLnN0YXJ0Tm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKGRhdGVQcm9maWxlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIGRhdGVFbnYgPSBfYS5kYXRlRW52LCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIHVuaXQ7XG4gICAgICAgIHZhciB1cGRhdGU7XG4gICAgICAgIHZhciBkZWxheTsgLy8gbXMgd2FpdCB2YWx1ZVxuICAgICAgICBpZiAob3B0aW9ucy5ub3dJbmRpY2F0b3IgJiYgIXRoaXMuaW5pdGlhbE5vd0RhdGUpIHtcbiAgICAgICAgICAgIHVuaXQgPSB0aGlzLmdldE5vd0luZGljYXRvclVuaXQoZGF0ZVByb2ZpbGUsIGRhdGVQcm9maWxlR2VuZXJhdG9yKTtcbiAgICAgICAgICAgIGlmICh1bml0KSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlID0gdGhpcy51cGRhdGVOb3dJbmRpY2F0b3IuYmluZCh0aGlzKTtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRpYWxOb3dEYXRlID0gY2FsZW5kYXIuZ2V0Tm93KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsTm93UXVlcmllZE1zID0gbmV3IERhdGUoKS52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgLy8gd2FpdCB1bnRpbCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBuZXh0IGludGVydmFsXG4gICAgICAgICAgICAgICAgZGVsYXkgPSBkYXRlRW52LmFkZChkYXRlRW52LnN0YXJ0T2YodGhpcy5pbml0aWFsTm93RGF0ZSwgdW5pdCksIGNyZWF0ZUR1cmF0aW9uKDEsIHVuaXQpKS52YWx1ZU9mKCkgLSB0aGlzLmluaXRpYWxOb3dEYXRlLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBtYXliZSBhbHdheXMgdXNlIHNldFRpbWVvdXQsIHdhaXRpbmcgdW50aWwgc3RhcnQgb2YgbmV4dCB1bml0XG4gICAgICAgICAgICAgICAgdGhpcy5ub3dJbmRpY2F0b3JUaW1lb3V0SUQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubm93SW5kaWNhdG9yVGltZW91dElEID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1bml0ID09PSAnc2Vjb25kJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXkgPSAxMDAwOyAvLyBldmVyeSBzZWNvbmRcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5ID0gMTAwMCAqIDYwOyAvLyBvdGhlcndpc2UsIGV2ZXJ5IG1pbnV0ZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm5vd0luZGljYXRvckludGVydmFsSUQgPSBzZXRJbnRlcnZhbCh1cGRhdGUsIGRlbGF5KTsgLy8gdXBkYXRlIGV2ZXJ5IGludGVydmFsXG4gICAgICAgICAgICAgICAgfSwgZGVsYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmVuZGVyaW5nIHdpbGwgYmUgaW5pdGlhdGVkIGluIHVwZGF0ZVNpemVcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gcmVyZW5kZXJzIHRoZSBub3cgaW5kaWNhdG9yLCBjb21wdXRpbmcgdGhlIG5ldyBjdXJyZW50IHRpbWUgZnJvbSB0aGUgYW1vdW50IG9mIHRpbWUgdGhhdCBoYXMgcGFzc2VkXG4gICAgLy8gc2luY2UgdGhlIGluaXRpYWwgZ2V0Tm93IGNhbGwuXG4gICAgVmlldy5wcm90b3R5cGUudXBkYXRlTm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSAmJiAvLyBhIHdheSB0byBkZXRlcm1pbmUgaWYgZGF0ZXMgd2VyZSByZW5kZXJlZCB5ZXRcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbE5vd0RhdGUgLy8gYWN0aXZhdGVkIGJlZm9yZT9cbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnVucmVuZGVyTm93SW5kaWNhdG9yKCk7IC8vIHdvbid0IHVucmVuZGVyIGlmIHVubmVjZXNzYXJ5XG4gICAgICAgICAgICB0aGlzLnJlbmRlck5vd0luZGljYXRvcihhZGRNcyh0aGlzLmluaXRpYWxOb3dEYXRlLCBuZXcgRGF0ZSgpLnZhbHVlT2YoKSAtIHRoaXMuaW5pdGlhbE5vd1F1ZXJpZWRNcykpO1xuICAgICAgICAgICAgdGhpcy5pc05vd0luZGljYXRvclJlbmRlcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gSW1tZWRpYXRlbHkgdW5yZW5kZXJzIHRoZSB2aWV3J3MgY3VycmVudCB0aW1lIGluZGljYXRvciBhbmQgc3RvcHMgYW55IHJlLXJlbmRlcmluZyB0aW1lcnMuXG4gICAgLy8gV29uJ3QgY2F1c2Ugc2lkZSBlZmZlY3RzIGlmIGluZGljYXRvciBpc24ndCByZW5kZXJlZC5cbiAgICBWaWV3LnByb3RvdHlwZS5zdG9wTm93SW5kaWNhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ub3dJbmRpY2F0b3JUaW1lb3V0SUQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLm5vd0luZGljYXRvclRpbWVvdXRJRCk7XG4gICAgICAgICAgICB0aGlzLm5vd0luZGljYXRvclRpbWVvdXRJRCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubm93SW5kaWNhdG9ySW50ZXJ2YWxJRCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLm5vd0luZGljYXRvckludGVydmFsSUQpO1xuICAgICAgICAgICAgdGhpcy5ub3dJbmRpY2F0b3JJbnRlcnZhbElEID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc05vd0luZGljYXRvclJlbmRlcmVkKSB7XG4gICAgICAgICAgICB0aGlzLnVucmVuZGVyTm93SW5kaWNhdG9yKCk7XG4gICAgICAgICAgICB0aGlzLmlzTm93SW5kaWNhdG9yUmVuZGVyZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlldy5wcm90b3R5cGUuZ2V0Tm93SW5kaWNhdG9yVW5pdCA9IGZ1bmN0aW9uIChkYXRlUHJvZmlsZSwgZGF0ZVByb2ZpbGVHZW5lcmF0b3IpIHtcbiAgICAgICAgLy8gc3ViY2xhc3NlcyBzaG91bGQgaW1wbGVtZW50XG4gICAgfTtcbiAgICAvLyBSZW5kZXJzIGEgY3VycmVudCB0aW1lIGluZGljYXRvciBhdCB0aGUgZ2l2ZW4gZGF0ZXRpbWVcbiAgICBWaWV3LnByb3RvdHlwZS5yZW5kZXJOb3dJbmRpY2F0b3IgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICAvLyBTVUJDTEFTU0VTIE1VU1QgUEFTUyBUTyBDSElMRFJFTiFcbiAgICB9O1xuICAgIC8vIFVuZG9lcyB0aGUgcmVuZGVyaW5nIGFjdGlvbnMgZnJvbSByZW5kZXJOb3dJbmRpY2F0b3JcbiAgICBWaWV3LnByb3RvdHlwZS51bnJlbmRlck5vd0luZGljYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gU1VCQ0xBU1NFUyBNVVNUIFBBU1MgVE8gQ0hJTERSRU4hXG4gICAgfTtcbiAgICAvKiBTY3JvbGxlclxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgVmlldy5wcm90b3R5cGUuYWRkU2Nyb2xsID0gZnVuY3Rpb24gKHNjcm9sbCwgaXNGb3JjZWQpIHtcbiAgICAgICAgaWYgKGlzRm9yY2VkKSB7XG4gICAgICAgICAgICBzY3JvbGwuaXNGb3JjZWQgPSBpc0ZvcmNlZDtcbiAgICAgICAgfVxuICAgICAgICBfX2Fzc2lnbih0aGlzLnF1ZXVlZFNjcm9sbCB8fCAodGhpcy5xdWV1ZWRTY3JvbGwgPSB7fSksIHNjcm9sbCk7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5wb3BTY3JvbGwgPSBmdW5jdGlvbiAoaXNSZXNpemUpIHtcbiAgICAgICAgdGhpcy5hcHBseVF1ZXVlZFNjcm9sbChpc1Jlc2l6ZSk7XG4gICAgICAgIHRoaXMucXVldWVkU2Nyb2xsID0gbnVsbDtcbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLmFwcGx5UXVldWVkU2Nyb2xsID0gZnVuY3Rpb24gKGlzUmVzaXplKSB7XG4gICAgICAgIGlmICh0aGlzLnF1ZXVlZFNjcm9sbCkge1xuICAgICAgICAgICAgdGhpcy5hcHBseVNjcm9sbCh0aGlzLnF1ZXVlZFNjcm9sbCwgaXNSZXNpemUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5xdWVyeVNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNjcm9sbCA9IHt9O1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSkgeyAvLyBkYXRlcyByZW5kZXJlZCB5ZXQ/XG4gICAgICAgICAgICBfX2Fzc2lnbihzY3JvbGwsIHRoaXMucXVlcnlEYXRlU2Nyb2xsKCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzY3JvbGw7XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5hcHBseVNjcm9sbCA9IGZ1bmN0aW9uIChzY3JvbGwsIGlzUmVzaXplKSB7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IHNjcm9sbC5kdXJhdGlvbiwgaXNGb3JjZWQgPSBzY3JvbGwuaXNGb3JjZWQ7XG4gICAgICAgIGlmIChkdXJhdGlvbiAhPSBudWxsICYmICFpc0ZvcmNlZCkge1xuICAgICAgICAgICAgZGVsZXRlIHNjcm9sbC5kdXJhdGlvbjtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLmRhdGVQcm9maWxlKSB7IC8vIGRhdGVzIHJlbmRlcmVkIHlldD9cbiAgICAgICAgICAgICAgICBfX2Fzc2lnbihzY3JvbGwsIHRoaXMuY29tcHV0ZURhdGVTY3JvbGwoZHVyYXRpb24pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wcm9wcy5kYXRlUHJvZmlsZSkgeyAvLyBkYXRlcyByZW5kZXJlZCB5ZXQ/XG4gICAgICAgICAgICB0aGlzLmFwcGx5RGF0ZVNjcm9sbChzY3JvbGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5jb21wdXRlRGF0ZVNjcm9sbCA9IGZ1bmN0aW9uIChkdXJhdGlvbikge1xuICAgICAgICByZXR1cm4ge307IC8vIHN1YmNsYXNzZXMgbXVzdCBpbXBsZW1lbnRcbiAgICB9O1xuICAgIFZpZXcucHJvdG90eXBlLnF1ZXJ5RGF0ZVNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHt9OyAvLyBzdWJjbGFzc2VzIG11c3QgaW1wbGVtZW50XG4gICAgfTtcbiAgICBWaWV3LnByb3RvdHlwZS5hcHBseURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoc2Nyb2xsKSB7XG4gICAgICAgIC8vIHN1YmNsYXNzZXMgbXVzdCBpbXBsZW1lbnRcbiAgICB9O1xuICAgIC8vIGZvciBBUElcbiAgICBWaWV3LnByb3RvdHlwZS5zY3JvbGxUb0R1cmF0aW9uID0gZnVuY3Rpb24gKGR1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuYXBwbHlTY3JvbGwoeyBkdXJhdGlvbjogZHVyYXRpb24gfSwgZmFsc2UpO1xuICAgIH07XG4gICAgcmV0dXJuIFZpZXc7XG59KERhdGVDb21wb25lbnQpKTtcbkVtaXR0ZXJNaXhpbi5taXhJbnRvKFZpZXcpO1xuVmlldy5wcm90b3R5cGUudXNlc01pbk1heFRpbWUgPSBmYWxzZTtcblZpZXcucHJvdG90eXBlLmRhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3MgPSBEYXRlUHJvZmlsZUdlbmVyYXRvcjtcblxudmFyIEZnRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGZ0V2ZW50UmVuZGVyZXIoKSB7XG4gICAgICAgIHRoaXMuc2VncyA9IFtdO1xuICAgICAgICB0aGlzLmlzU2l6ZURpcnR5ID0gZmFsc2U7XG4gICAgfVxuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VncyA9IGZ1bmN0aW9uIChjb250ZXh0LCBzZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRoaXMucmFuZ2VVcGRhdGVkKCk7IC8vIGNhbGxlZCB0b28gZnJlcXVlbnRseSA6KFxuICAgICAgICAvLyByZW5kZXIgYW4gYC5lbGAgb24gZWFjaCBzZWdcbiAgICAgICAgLy8gcmV0dXJucyBhIHN1YnNldCBvZiB0aGUgc2Vncy4gc2VncyB0aGF0IHdlcmUgYWN0dWFsbHkgcmVuZGVyZWRcbiAgICAgICAgc2VncyA9IHRoaXMucmVuZGVyU2VnRWxzKHNlZ3MsIG1pcnJvckluZm8pO1xuICAgICAgICB0aGlzLnNlZ3MgPSBzZWdzO1xuICAgICAgICB0aGlzLmF0dGFjaFNlZ3Moc2VncywgbWlycm9ySW5mbyk7XG4gICAgICAgIHRoaXMuaXNTaXplRGlydHkgPSB0cnVlO1xuICAgICAgICB0cmlnZ2VyUmVuZGVyZWRTZWdzKHRoaXMuY29udGV4dCwgdGhpcy5zZWdzLCBCb29sZWFuKG1pcnJvckluZm8pKTtcbiAgICB9O1xuICAgIEZnRXZlbnRSZW5kZXJlci5wcm90b3R5cGUudW5yZW5kZXIgPSBmdW5jdGlvbiAoY29udGV4dCwgX3NlZ3MsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdHJpZ2dlcldpbGxSZW1vdmVTZWdzKHRoaXMuY29udGV4dCwgdGhpcy5zZWdzLCBCb29sZWFuKG1pcnJvckluZm8pKTtcbiAgICAgICAgdGhpcy5kZXRhY2hTZWdzKHRoaXMuc2Vncyk7XG4gICAgICAgIHRoaXMuc2VncyA9IFtdO1xuICAgIH07XG4gICAgLy8gVXBkYXRlcyB2YWx1ZXMgdGhhdCByZWx5IG9uIG9wdGlvbnMgYW5kIGFsc28gcmVsYXRlIHRvIHJhbmdlXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yYW5nZVVwZGF0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvcHRpb25zID0gdGhpcy5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIHZhciBkaXNwbGF5RXZlbnRUaW1lO1xuICAgICAgICB2YXIgZGlzcGxheUV2ZW50RW5kO1xuICAgICAgICB0aGlzLmV2ZW50VGltZUZvcm1hdCA9IGNyZWF0ZUZvcm1hdHRlcihvcHRpb25zLmV2ZW50VGltZUZvcm1hdCB8fCB0aGlzLmNvbXB1dGVFdmVudFRpbWVGb3JtYXQoKSwgb3B0aW9ucy5kZWZhdWx0UmFuZ2VTZXBhcmF0b3IpO1xuICAgICAgICBkaXNwbGF5RXZlbnRUaW1lID0gb3B0aW9ucy5kaXNwbGF5RXZlbnRUaW1lO1xuICAgICAgICBpZiAoZGlzcGxheUV2ZW50VGltZSA9PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwbGF5RXZlbnRUaW1lID0gdGhpcy5jb21wdXRlRGlzcGxheUV2ZW50VGltZSgpOyAvLyBtaWdodCBiZSBiYXNlZCBvZmYgb2YgcmFuZ2VcbiAgICAgICAgfVxuICAgICAgICBkaXNwbGF5RXZlbnRFbmQgPSBvcHRpb25zLmRpc3BsYXlFdmVudEVuZDtcbiAgICAgICAgaWYgKGRpc3BsYXlFdmVudEVuZCA9PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwbGF5RXZlbnRFbmQgPSB0aGlzLmNvbXB1dGVEaXNwbGF5RXZlbnRFbmQoKTsgLy8gbWlnaHQgYmUgYmFzZWQgb2ZmIG9mIHJhbmdlXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwbGF5RXZlbnRUaW1lID0gZGlzcGxheUV2ZW50VGltZTtcbiAgICAgICAgdGhpcy5kaXNwbGF5RXZlbnRFbmQgPSBkaXNwbGF5RXZlbnRFbmQ7XG4gICAgfTtcbiAgICAvLyBSZW5kZXJzIGFuZCBhc3NpZ25zIGFuIGBlbGAgcHJvcGVydHkgZm9yIGVhY2ggZm9yZWdyb3VuZCBldmVudCBzZWdtZW50LlxuICAgIC8vIE9ubHkgcmV0dXJucyBzZWdtZW50cyB0aGF0IHN1Y2Nlc3NmdWxseSByZW5kZXJlZC5cbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLnJlbmRlclNlZ0VscyA9IGZ1bmN0aW9uIChzZWdzLCBtaXJyb3JJbmZvKSB7XG4gICAgICAgIHZhciBodG1sID0gJyc7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBpZiAoc2Vncy5sZW5ndGgpIHsgLy8gZG9uJ3QgYnVpbGQgYW4gZW1wdHkgaHRtbCBzdHJpbmdcbiAgICAgICAgICAgIC8vIGJ1aWxkIGEgbGFyZ2UgY29uY2F0ZW5hdGlvbiBvZiBldmVudCBzZWdtZW50IEhUTUxcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSB0aGlzLnJlbmRlclNlZ0h0bWwoc2Vnc1tpXSwgbWlycm9ySW5mbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBHcmFiIGluZGl2aWR1YWwgZWxlbWVudHMgZnJvbSB0aGUgY29tYmluZWQgSFRNTCBzdHJpbmcuIFVzZSBlYWNoIGFzIHRoZSBkZWZhdWx0IHJlbmRlcmluZy5cbiAgICAgICAgICAgIC8vIFRoZW4sIGNvbXB1dGUgdGhlICdlbCcgZm9yIGVhY2ggc2VnbWVudC4gQW4gZWwgbWlnaHQgYmUgbnVsbCBpZiB0aGUgZXZlbnRSZW5kZXIgY2FsbGJhY2sgcmV0dXJuZWQgZmFsc2UuXG4gICAgICAgICAgICBodG1sVG9FbGVtZW50cyhodG1sKS5mb3JFYWNoKGZ1bmN0aW9uIChlbCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciBzZWcgPSBzZWdzW2ldO1xuICAgICAgICAgICAgICAgIGlmIChlbCkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwgPSBlbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlZ3MgPSBmaWx0ZXJTZWdzVmlhRWxzKHRoaXMuY29udGV4dCwgc2VncywgQm9vbGVhbihtaXJyb3JJbmZvKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICAvLyBHZW5lcmljIHV0aWxpdHkgZm9yIGdlbmVyYXRpbmcgdGhlIEhUTUwgY2xhc3NOYW1lcyBmb3IgYW4gZXZlbnQgc2VnbWVudCdzIGVsZW1lbnRcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmdldFNlZ0NsYXNzZXMgPSBmdW5jdGlvbiAoc2VnLCBpc0RyYWdnYWJsZSwgaXNSZXNpemFibGUsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIGNsYXNzZXMgPSBbXG4gICAgICAgICAgICAnZmMtZXZlbnQnLFxuICAgICAgICAgICAgc2VnLmlzU3RhcnQgPyAnZmMtc3RhcnQnIDogJ2ZjLW5vdC1zdGFydCcsXG4gICAgICAgICAgICBzZWcuaXNFbmQgPyAnZmMtZW5kJyA6ICdmYy1ub3QtZW5kJ1xuICAgICAgICBdLmNvbmNhdChzZWcuZXZlbnRSYW5nZS51aS5jbGFzc05hbWVzKTtcbiAgICAgICAgaWYgKGlzRHJhZ2dhYmxlKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLWRyYWdnYWJsZScpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Jlc2l6YWJsZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1yZXNpemFibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWlycm9ySW5mbykge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1taXJyb3InKTtcbiAgICAgICAgICAgIGlmIChtaXJyb3JJbmZvLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2ZjLWRyYWdnaW5nJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWlycm9ySW5mby5pc1Jlc2l6aW5nKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdmYy1yZXNpemluZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbGFzc2VzO1xuICAgIH07XG4gICAgLy8gQ29tcHV0ZSB0aGUgdGV4dCB0aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQgb24gYW4gZXZlbnQncyBlbGVtZW50LlxuICAgIC8vIGByYW5nZWAgY2FuIGJlIHRoZSBFdmVudCBvYmplY3QgaXRzZWxmLCBvciBzb21ldGhpbmcgcmFuZ2UtbGlrZSwgd2l0aCBhdCBsZWFzdCBhIGBzdGFydGAuXG4gICAgLy8gSWYgZXZlbnQgdGltZXMgYXJlIGRpc2FibGVkLCBvciB0aGUgZXZlbnQgaGFzIG5vIHRpbWUsIHdpbGwgcmV0dXJuIGEgYmxhbmsgc3RyaW5nLlxuICAgIC8vIElmIG5vdCBzcGVjaWZpZWQsIGZvcm1hdHRlciB3aWxsIGRlZmF1bHQgdG8gdGhlIGV2ZW50VGltZUZvcm1hdCBzZXR0aW5nLFxuICAgIC8vIGFuZCBkaXNwbGF5RW5kIHdpbGwgZGVmYXVsdCB0byB0aGUgZGlzcGxheUV2ZW50RW5kIHNldHRpbmcuXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5nZXRUaW1lVGV4dCA9IGZ1bmN0aW9uIChldmVudFJhbmdlLCBmb3JtYXR0ZXIsIGRpc3BsYXlFbmQpIHtcbiAgICAgICAgdmFyIGRlZiA9IGV2ZW50UmFuZ2UuZGVmLCBpbnN0YW5jZSA9IGV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRUaW1lVGV4dChpbnN0YW5jZS5yYW5nZS5zdGFydCwgZGVmLmhhc0VuZCA/IGluc3RhbmNlLnJhbmdlLmVuZCA6IG51bGwsIGRlZi5hbGxEYXksIGZvcm1hdHRlciwgZGlzcGxheUVuZCwgaW5zdGFuY2UuZm9yY2VkU3RhcnRUem8sIGluc3RhbmNlLmZvcmNlZEVuZFR6byk7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLl9nZXRUaW1lVGV4dCA9IGZ1bmN0aW9uIChzdGFydCwgZW5kLCBhbGxEYXksIGZvcm1hdHRlciwgZGlzcGxheUVuZCwgZm9yY2VkU3RhcnRUem8sIGZvcmNlZEVuZFR6bykge1xuICAgICAgICB2YXIgZGF0ZUVudiA9IHRoaXMuY29udGV4dC5kYXRlRW52O1xuICAgICAgICBpZiAoZm9ybWF0dGVyID09IG51bGwpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IHRoaXMuZXZlbnRUaW1lRm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaXNwbGF5RW5kID09IG51bGwpIHtcbiAgICAgICAgICAgIGRpc3BsYXlFbmQgPSB0aGlzLmRpc3BsYXlFdmVudEVuZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5kaXNwbGF5RXZlbnRUaW1lICYmICFhbGxEYXkpIHtcbiAgICAgICAgICAgIGlmIChkaXNwbGF5RW5kICYmIGVuZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkYXRlRW52LmZvcm1hdFJhbmdlKHN0YXJ0LCBlbmQsIGZvcm1hdHRlciwge1xuICAgICAgICAgICAgICAgICAgICBmb3JjZWRTdGFydFR6bzogZm9yY2VkU3RhcnRUem8sXG4gICAgICAgICAgICAgICAgICAgIGZvcmNlZEVuZFR6bzogZm9yY2VkRW5kVHpvXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoc3RhcnQsIGZvcm1hdHRlciwge1xuICAgICAgICAgICAgICAgICAgICBmb3JjZWRUem86IGZvcmNlZFN0YXJ0VHpvXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRXZlbnRUaW1lRm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG91cjogJ251bWVyaWMnLFxuICAgICAgICAgICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgICAgICAgICBvbWl0WmVyb01pbnV0ZTogdHJ1ZVxuICAgICAgICB9O1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRGlzcGxheUV2ZW50VGltZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVEaXNwbGF5RXZlbnRFbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgLy8gVXRpbGl0eSBmb3IgZ2VuZXJhdGluZyBldmVudCBza2luLXJlbGF0ZWQgQ1NTIHByb3BlcnRpZXNcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmdldFNraW5Dc3MgPSBmdW5jdGlvbiAodWkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogdWkuYmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgJ2JvcmRlci1jb2xvcic6IHVpLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgY29sb3I6IHVpLnRleHRDb2xvclxuICAgICAgICB9O1xuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5zb3J0RXZlbnRTZWdzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIHNwZWNzID0gdGhpcy5jb250ZXh0LmV2ZW50T3JkZXJTcGVjcztcbiAgICAgICAgdmFyIG9ianMgPSBzZWdzLm1hcChidWlsZFNlZ0NvbXBhcmVPYmopO1xuICAgICAgICBvYmpzLnNvcnQoZnVuY3Rpb24gKG9iajAsIG9iajEpIHtcbiAgICAgICAgICAgIHJldHVybiBjb21wYXJlQnlGaWVsZFNwZWNzKG9iajAsIG9iajEsIHNwZWNzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBvYmpzLm1hcChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgcmV0dXJuIGMuX3NlZztcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVTaXplcyA9IGZ1bmN0aW9uIChmb3JjZSkge1xuICAgICAgICBpZiAoZm9yY2UgfHwgdGhpcy5pc1NpemVEaXJ0eSkge1xuICAgICAgICAgICAgdGhpcy5jb21wdXRlU2VnU2l6ZXModGhpcy5zZWdzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TaXplcyA9IGZ1bmN0aW9uIChmb3JjZSkge1xuICAgICAgICBpZiAoZm9yY2UgfHwgdGhpcy5pc1NpemVEaXJ0eSkge1xuICAgICAgICAgICAgdGhpcy5hc3NpZ25TZWdTaXplcyh0aGlzLnNlZ3MpO1xuICAgICAgICAgICAgdGhpcy5pc1NpemVEaXJ0eSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVTZWdTaXplcyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgfTtcbiAgICBGZ0V2ZW50UmVuZGVyZXIucHJvdG90eXBlLmFzc2lnblNlZ1NpemVzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICB9O1xuICAgIC8vIE1hbmlwdWxhdGlvbiBvbiByZW5kZXJlZCBzZWdzXG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5oaWRlQnlIYXNoID0gZnVuY3Rpb24gKGhhc2gpIHtcbiAgICAgICAgaWYgKGhhc2gpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNlZ3M7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlZyA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzaFtzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5zaG93QnlIYXNoID0gZnVuY3Rpb24gKGhhc2gpIHtcbiAgICAgICAgaWYgKGhhc2gpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNlZ3M7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlZyA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzaFtzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkXSkge1xuICAgICAgICAgICAgICAgICAgICBzZWcuZWwuc3R5bGUudmlzaWJpbGl0eSA9ICcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5zZWxlY3RCeUluc3RhbmNlSWQgPSBmdW5jdGlvbiAoaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoaW5zdGFuY2VJZCkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2VnczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VnID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlID0gc2VnLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50SW5zdGFuY2UgJiYgZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkID09PSBpbnN0YW5jZUlkICYmXG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbCAvLyBuZWNlc3Nhcnk/XG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbC5jbGFzc0xpc3QuYWRkKCdmYy1zZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmdFdmVudFJlbmRlcmVyLnByb3RvdHlwZS51bnNlbGVjdEJ5SW5zdGFuY2VJZCA9IGZ1bmN0aW9uIChpbnN0YW5jZUlkKSB7XG4gICAgICAgIGlmIChpbnN0YW5jZUlkKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zZWdzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBzZWcgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKHNlZy5lbCkgeyAvLyBuZWNlc3Nhcnk/XG4gICAgICAgICAgICAgICAgICAgIHNlZy5lbC5jbGFzc0xpc3QucmVtb3ZlKCdmYy1zZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEZnRXZlbnRSZW5kZXJlcjtcbn0oKSk7XG4vLyByZXR1cm5zIGEgb2JqZWN0IHdpdGggYWxsIHByaW1pdGl2ZSBwcm9wcyB0aGF0IGNhbiBiZSBjb21wYXJlZFxuZnVuY3Rpb24gYnVpbGRTZWdDb21wYXJlT2JqKHNlZykge1xuICAgIHZhciBldmVudERlZiA9IHNlZy5ldmVudFJhbmdlLmRlZjtcbiAgICB2YXIgcmFuZ2UgPSBzZWcuZXZlbnRSYW5nZS5pbnN0YW5jZS5yYW5nZTtcbiAgICB2YXIgc3RhcnQgPSByYW5nZS5zdGFydCA/IHJhbmdlLnN0YXJ0LnZhbHVlT2YoKSA6IDA7IC8vIFRPRE86IGJldHRlciBzdXBwb3J0IGZvciBvcGVuLXJhbmdlIGV2ZW50c1xuICAgIHZhciBlbmQgPSByYW5nZS5lbmQgPyByYW5nZS5lbmQudmFsdWVPZigpIDogMDsgLy8gXCJcbiAgICByZXR1cm4gX19hc3NpZ24oe30sIGV2ZW50RGVmLmV4dGVuZGVkUHJvcHMsIGV2ZW50RGVmLCB7IGlkOiBldmVudERlZi5wdWJsaWNJZCwgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICBlbmQ6IGVuZCwgZHVyYXRpb246IGVuZCAtIHN0YXJ0LCBhbGxEYXk6IE51bWJlcihldmVudERlZi5hbGxEYXkpLCBfc2VnOiBzZWcgLy8gZm9yIGxhdGVyIHJldHJpZXZhbFxuICAgICB9KTtcbn1cblxuLypcblRPRE86IHdoZW4gcmVmYWN0b3JpbmcgdGhpcyBjbGFzcywgbWFrZSBhIG5ldyBGaWxsUmVuZGVyZXIgaW5zdGFuY2UgZm9yIGVhY2ggYHR5cGVgXG4qL1xudmFyIEZpbGxSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGaWxsUmVuZGVyZXIoKSB7XG4gICAgICAgIHRoaXMuZmlsbFNlZ1RhZyA9ICdkaXYnO1xuICAgICAgICB0aGlzLmRpcnR5U2l6ZUZsYWdzID0ge307XG4gICAgICAgIHRoaXMuY29udGFpbmVyRWxzQnlUeXBlID0ge307XG4gICAgICAgIHRoaXMuc2Vnc0J5VHlwZSA9IHt9O1xuICAgIH1cbiAgICBGaWxsUmVuZGVyZXIucHJvdG90eXBlLmdldFNlZ3NCeVR5cGUgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWdzQnlUeXBlW3R5cGVdIHx8IFtdO1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdzID0gZnVuY3Rpb24gKHR5cGUsIGNvbnRleHQsIHNlZ3MpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB2YXIgcmVuZGVyZWRTZWdzID0gdGhpcy5yZW5kZXJTZWdFbHModHlwZSwgc2Vncyk7IC8vIGFzc2lnbmVzIGAuZWxgIHRvIGVhY2ggc2VnLiByZXR1cm5zIHN1Y2Nlc3NmdWxseSByZW5kZXJlZCBzZWdzXG4gICAgICAgIHZhciBjb250YWluZXJFbHMgPSB0aGlzLmF0dGFjaFNlZ3ModHlwZSwgcmVuZGVyZWRTZWdzKTtcbiAgICAgICAgaWYgKGNvbnRhaW5lckVscykge1xuICAgICAgICAgICAgKF9hID0gKHRoaXMuY29udGFpbmVyRWxzQnlUeXBlW3R5cGVdIHx8ICh0aGlzLmNvbnRhaW5lckVsc0J5VHlwZVt0eXBlXSA9IFtdKSkpLnB1c2guYXBwbHkoX2EsIGNvbnRhaW5lckVscyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWdzQnlUeXBlW3R5cGVdID0gcmVuZGVyZWRTZWdzO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2JnRXZlbnQnKSB7XG4gICAgICAgICAgICB0cmlnZ2VyUmVuZGVyZWRTZWdzKGNvbnRleHQsIHJlbmRlcmVkU2VncywgZmFsc2UpOyAvLyBpc01pcnJvcj1mYWxzZVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlydHlTaXplRmxhZ3NbdHlwZV0gPSB0cnVlO1xuICAgIH07XG4gICAgLy8gVW5yZW5kZXJzIGEgc3BlY2lmaWMgdHlwZSBvZiBmaWxsIHRoYXQgaXMgY3VycmVudGx5IHJlbmRlcmVkIG9uIHRoZSBncmlkXG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS51bnJlbmRlciA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBzZWdzID0gdGhpcy5zZWdzQnlUeXBlW3R5cGVdO1xuICAgICAgICBpZiAoc2Vncykge1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdiZ0V2ZW50Jykge1xuICAgICAgICAgICAgICAgIHRyaWdnZXJXaWxsUmVtb3ZlU2Vncyhjb250ZXh0LCBzZWdzLCBmYWxzZSk7IC8vIGlzTWlycm9yPWZhbHNlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRldGFjaFNlZ3ModHlwZSwgc2Vncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJlbmRlcnMgYW5kIGFzc2lnbnMgYW4gYGVsYCBwcm9wZXJ0eSBmb3IgZWFjaCBmaWxsIHNlZ21lbnQuIEdlbmVyaWMgZW5vdWdoIHRvIHdvcmsgd2l0aCBkaWZmZXJlbnQgdHlwZXMuXG4gICAgLy8gT25seSByZXR1cm5zIHNlZ21lbnRzIHRoYXQgc3VjY2Vzc2Z1bGx5IHJlbmRlcmVkLlxuICAgIEZpbGxSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnRWxzID0gZnVuY3Rpb24gKHR5cGUsIHNlZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGh0bWwgPSAnJztcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGlmIChzZWdzLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gYnVpbGQgYSBsYXJnZSBjb25jYXRlbmF0aW9uIG9mIHNlZ21lbnQgSFRNTFxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBodG1sICs9IHRoaXMucmVuZGVyU2VnSHRtbCh0eXBlLCBzZWdzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEdyYWIgaW5kaXZpZHVhbCBlbGVtZW50cyBmcm9tIHRoZSBjb21iaW5lZCBIVE1MIHN0cmluZy4gVXNlIGVhY2ggYXMgdGhlIGRlZmF1bHQgcmVuZGVyaW5nLlxuICAgICAgICAgICAgLy8gVGhlbiwgY29tcHV0ZSB0aGUgJ2VsJyBmb3IgZWFjaCBzZWdtZW50LlxuICAgICAgICAgICAgaHRtbFRvRWxlbWVudHMoaHRtbCkuZm9yRWFjaChmdW5jdGlvbiAoZWwsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnLmVsID0gZWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ2JnRXZlbnQnKSB7XG4gICAgICAgICAgICAgICAgc2VncyA9IGZpbHRlclNlZ3NWaWFFbHModGhpcy5jb250ZXh0LCBzZWdzLCBmYWxzZSAvLyBpc01pcnJvci4gYmFja2dyb3VuZCBldmVudHMgY2FuIG5ldmVyIGJlIG1pcnJvciBlbGVtZW50c1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBjb3JyZWN0IGVsZW1lbnQgdHlwZT8gKHdvdWxkIGJlIGJhZCBpZiBhIG5vbi1URCB3ZXJlIGluc2VydGVkIGludG8gYSB0YWJsZSBmb3IgZXhhbXBsZSlcbiAgICAgICAgICAgIHNlZ3MgPSBzZWdzLmZpbHRlcihmdW5jdGlvbiAoc2VnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnRNYXRjaGVzKHNlZy5lbCwgX3RoaXMuZmlsbFNlZ1RhZyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VncztcbiAgICB9O1xuICAgIC8vIEJ1aWxkcyB0aGUgSFRNTCBuZWVkZWQgZm9yIG9uZSBmaWxsIHNlZ21lbnQuIEdlbmVyaWMgZW5vdWdoIHRvIHdvcmsgd2l0aCBkaWZmZXJlbnQgdHlwZXMuXG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdIdG1sID0gZnVuY3Rpb24gKHR5cGUsIHNlZykge1xuICAgICAgICB2YXIgY3NzID0gbnVsbDtcbiAgICAgICAgdmFyIGNsYXNzTmFtZXMgPSBbXTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdoaWdobGlnaHQnICYmIHR5cGUgIT09ICdidXNpbmVzc0hvdXJzJykge1xuICAgICAgICAgICAgY3NzID0ge1xuICAgICAgICAgICAgICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogc2VnLmV2ZW50UmFuZ2UudWkuYmFja2dyb3VuZENvbG9yXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlICE9PSAnaGlnaGxpZ2h0Jykge1xuICAgICAgICAgICAgY2xhc3NOYW1lcyA9IGNsYXNzTmFtZXMuY29uY2F0KHNlZy5ldmVudFJhbmdlLnVpLmNsYXNzTmFtZXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZXMucHVzaCgnZmMtYmdldmVudCcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKCdmYy0nICsgdHlwZS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJzwnICsgdGhpcy5maWxsU2VnVGFnICtcbiAgICAgICAgICAgIChjbGFzc05hbWVzLmxlbmd0aCA/ICcgY2xhc3M9XCInICsgY2xhc3NOYW1lcy5qb2luKCcgJykgKyAnXCInIDogJycpICtcbiAgICAgICAgICAgIChjc3MgPyAnIHN0eWxlPVwiJyArIGNzc1RvU3RyKGNzcykgKyAnXCInIDogJycpICtcbiAgICAgICAgICAgICc+PC8nICsgdGhpcy5maWxsU2VnVGFnICsgJz4nO1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5kZXRhY2hTZWdzID0gZnVuY3Rpb24gKHR5cGUsIHNlZ3MpIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lckVscyA9IHRoaXMuY29udGFpbmVyRWxzQnlUeXBlW3R5cGVdO1xuICAgICAgICBpZiAoY29udGFpbmVyRWxzKSB7XG4gICAgICAgICAgICBjb250YWluZXJFbHMuZm9yRWFjaChyZW1vdmVFbGVtZW50KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNvbnRhaW5lckVsc0J5VHlwZVt0eXBlXTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlU2l6ZXMgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICAgICAgZm9yICh2YXIgdHlwZSBpbiB0aGlzLnNlZ3NCeVR5cGUpIHtcbiAgICAgICAgICAgIGlmIChmb3JjZSB8fCB0aGlzLmRpcnR5U2l6ZUZsYWdzW3R5cGVdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wdXRlU2VnU2l6ZXModGhpcy5zZWdzQnlUeXBlW3R5cGVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TaXplcyA9IGZ1bmN0aW9uIChmb3JjZSkge1xuICAgICAgICBmb3IgKHZhciB0eXBlIGluIHRoaXMuc2Vnc0J5VHlwZSkge1xuICAgICAgICAgICAgaWYgKGZvcmNlIHx8IHRoaXMuZGlydHlTaXplRmxhZ3NbdHlwZV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFzc2lnblNlZ1NpemVzKHRoaXMuc2Vnc0J5VHlwZVt0eXBlXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXJ0eVNpemVGbGFncyA9IHt9O1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlU2VnU2l6ZXMgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgIH07XG4gICAgRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5hc3NpZ25TZWdTaXplcyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgfTtcbiAgICByZXR1cm4gRmlsbFJlbmRlcmVyO1xufSgpKTtcblxudmFyIE5hbWVkVGltZVpvbmVJbXBsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE5hbWVkVGltZVpvbmVJbXBsKHRpbWVab25lTmFtZSkge1xuICAgICAgICB0aGlzLnRpbWVab25lTmFtZSA9IHRpbWVab25lTmFtZTtcbiAgICB9XG4gICAgcmV0dXJuIE5hbWVkVGltZVpvbmVJbXBsO1xufSgpKTtcblxuLypcbkFuIGFic3RyYWN0aW9uIGZvciBhIGRyYWdnaW5nIGludGVyYWN0aW9uIG9yaWdpbmF0aW5nIG9uIGFuIGV2ZW50LlxuRG9lcyBoaWdoZXItbGV2ZWwgdGhpbmdzIHRoYW4gUG9pbnRlckRyYWdnZXIsIHN1Y2ggYXMgcG9zc2libHk6XG4tIGEgXCJtaXJyb3JcIiB0aGF0IG1vdmVzIHdpdGggdGhlIHBvaW50ZXJcbi0gYSBtaW5pbXVtIG51bWJlciBvZiBwaXhlbHMgb3Igb3RoZXIgY3JpdGVyaWEgZm9yIGEgdHJ1ZSBkcmFnIHRvIGJlZ2luXG5cbnN1YmNsYXNzZXMgbXVzdCBlbWl0OlxuLSBwb2ludGVyZG93blxuLSBkcmFnc3RhcnRcbi0gZHJhZ21vdmVcbi0gcG9pbnRlcnVwXG4tIGRyYWdlbmRcbiovXG52YXIgRWxlbWVudERyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEVsZW1lbnREcmFnZ2luZyhlbCkge1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlck1peGluKCk7XG4gICAgfVxuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9ySXNWaXNpYmxlID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgLy8gb3B0aW9uYWwgaWYgc3ViY2xhc3MgZG9lc24ndCB3YW50IHRvIHN1cHBvcnQgYSBtaXJyb3JcbiAgICB9O1xuICAgIEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9yTmVlZHNSZXZlcnQgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICAvLyBvcHRpb25hbCBpZiBzdWJjbGFzcyBkb2Vzbid0IHdhbnQgdG8gc3VwcG9ydCBhIG1pcnJvclxuICAgIH07XG4gICAgRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRBdXRvU2Nyb2xsRW5hYmxlZCA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIC8vIG9wdGlvbmFsXG4gICAgfTtcbiAgICByZXR1cm4gRWxlbWVudERyYWdnaW5nO1xufSgpKTtcblxuZnVuY3Rpb24gZm9ybWF0RGF0ZShkYXRlSW5wdXQsIHNldHRpbmdzKSB7XG4gICAgaWYgKHNldHRpbmdzID09PSB2b2lkIDApIHsgc2V0dGluZ3MgPSB7fTsgfVxuICAgIHZhciBkYXRlRW52ID0gYnVpbGREYXRlRW52JDEoc2V0dGluZ3MpO1xuICAgIHZhciBmb3JtYXR0ZXIgPSBjcmVhdGVGb3JtYXR0ZXIoc2V0dGluZ3MpO1xuICAgIHZhciBkYXRlTWV0YSA9IGRhdGVFbnYuY3JlYXRlTWFya2VyTWV0YShkYXRlSW5wdXQpO1xuICAgIGlmICghZGF0ZU1ldGEpIHsgLy8gVE9ETzogd2FybmluZz9cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUVudi5mb3JtYXQoZGF0ZU1ldGEubWFya2VyLCBmb3JtYXR0ZXIsIHtcbiAgICAgICAgZm9yY2VkVHpvOiBkYXRlTWV0YS5mb3JjZWRUem9cbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGZvcm1hdFJhbmdlKHN0YXJ0SW5wdXQsIGVuZElucHV0LCBzZXR0aW5ncyAvLyBtaXh0dXJlIG9mIGVudiBhbmQgZm9ybWF0dGVyIHNldHRpbmdzXG4pIHtcbiAgICB2YXIgZGF0ZUVudiA9IGJ1aWxkRGF0ZUVudiQxKHR5cGVvZiBzZXR0aW5ncyA9PT0gJ29iamVjdCcgJiYgc2V0dGluZ3MgPyBzZXR0aW5ncyA6IHt9KTsgLy8gcGFzcyBpbiBpZiBub24tbnVsbCBvYmplY3RcbiAgICB2YXIgZm9ybWF0dGVyID0gY3JlYXRlRm9ybWF0dGVyKHNldHRpbmdzLCBnbG9iYWxEZWZhdWx0cy5kZWZhdWx0UmFuZ2VTZXBhcmF0b3IpO1xuICAgIHZhciBzdGFydE1ldGEgPSBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoc3RhcnRJbnB1dCk7XG4gICAgdmFyIGVuZE1ldGEgPSBkYXRlRW52LmNyZWF0ZU1hcmtlck1ldGEoZW5kSW5wdXQpO1xuICAgIGlmICghc3RhcnRNZXRhIHx8ICFlbmRNZXRhKSB7IC8vIFRPRE86IHdhcm5pbmc/XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIGRhdGVFbnYuZm9ybWF0UmFuZ2Uoc3RhcnRNZXRhLm1hcmtlciwgZW5kTWV0YS5tYXJrZXIsIGZvcm1hdHRlciwge1xuICAgICAgICBmb3JjZWRTdGFydFR6bzogc3RhcnRNZXRhLmZvcmNlZFR6byxcbiAgICAgICAgZm9yY2VkRW5kVHpvOiBlbmRNZXRhLmZvcmNlZFR6byxcbiAgICAgICAgaXNFbmRFeGNsdXNpdmU6IHNldHRpbmdzLmlzRW5kRXhjbHVzaXZlXG4gICAgfSk7XG59XG4vLyBUT0RPOiBtb3JlIERSWSBhbmQgb3B0aW1pemVkXG5mdW5jdGlvbiBidWlsZERhdGVFbnYkMShzZXR0aW5ncykge1xuICAgIHZhciBsb2NhbGUgPSBidWlsZExvY2FsZShzZXR0aW5ncy5sb2NhbGUgfHwgJ2VuJywgcGFyc2VSYXdMb2NhbGVzKFtdKS5tYXApOyAvLyBUT0RPOiBkb24ndCBoYXJkY29kZSAnZW4nIGV2ZXJ5d2hlcmVcbiAgICAvLyBlbnN1cmUgcmVxdWlyZWQgc2V0dGluZ3NcbiAgICBzZXR0aW5ncyA9IF9fYXNzaWduKHsgdGltZVpvbmU6IGdsb2JhbERlZmF1bHRzLnRpbWVab25lLCBjYWxlbmRhclN5c3RlbTogJ2dyZWdvcnknIH0sIHNldHRpbmdzLCB7IGxvY2FsZTogbG9jYWxlIH0pO1xuICAgIHJldHVybiBuZXcgRGF0ZUVudihzZXR0aW5ncyk7XG59XG5cbnZhciBEUkFHX01FVEFfUFJPUFMgPSB7XG4gICAgc3RhcnRUaW1lOiBjcmVhdGVEdXJhdGlvbixcbiAgICBkdXJhdGlvbjogY3JlYXRlRHVyYXRpb24sXG4gICAgY3JlYXRlOiBCb29sZWFuLFxuICAgIHNvdXJjZUlkOiBTdHJpbmdcbn07XG52YXIgRFJBR19NRVRBX0RFRkFVTFRTID0ge1xuICAgIGNyZWF0ZTogdHJ1ZVxufTtcbmZ1bmN0aW9uIHBhcnNlRHJhZ01ldGEocmF3KSB7XG4gICAgdmFyIGxlZnRvdmVyUHJvcHMgPSB7fTtcbiAgICB2YXIgcmVmaW5lZCA9IHJlZmluZVByb3BzKHJhdywgRFJBR19NRVRBX1BST1BTLCBEUkFHX01FVEFfREVGQVVMVFMsIGxlZnRvdmVyUHJvcHMpO1xuICAgIHJlZmluZWQubGVmdG92ZXJQcm9wcyA9IGxlZnRvdmVyUHJvcHM7XG4gICAgcmV0dXJuIHJlZmluZWQ7XG59XG5cbi8vIENvbXB1dGVzIGEgZGVmYXVsdCBjb2x1bW4gaGVhZGVyIGZvcm1hdHRpbmcgc3RyaW5nIGlmIGBjb2xGb3JtYXRgIGlzIG5vdCBleHBsaWNpdGx5IGRlZmluZWRcbmZ1bmN0aW9uIGNvbXB1dGVGYWxsYmFja0hlYWRlckZvcm1hdChkYXRlc1JlcERpc3RpbmN0RGF5cywgZGF5Q250KSB7XG4gICAgLy8gaWYgbW9yZSB0aGFuIG9uZSB3ZWVrIHJvdywgb3IgaWYgdGhlcmUgYXJlIGEgbG90IG9mIGNvbHVtbnMgd2l0aCBub3QgbXVjaCBzcGFjZSxcbiAgICAvLyBwdXQganVzdCB0aGUgZGF5IG51bWJlcnMgd2lsbCBiZSBpbiBlYWNoIGNlbGxcbiAgICBpZiAoIWRhdGVzUmVwRGlzdGluY3REYXlzIHx8IGRheUNudCA+IDEwKSB7XG4gICAgICAgIHJldHVybiB7IHdlZWtkYXk6ICdzaG9ydCcgfTsgLy8gXCJTYXRcIlxuICAgIH1cbiAgICBlbHNlIGlmIChkYXlDbnQgPiAxKSB7XG4gICAgICAgIHJldHVybiB7IHdlZWtkYXk6ICdzaG9ydCcsIG1vbnRoOiAnbnVtZXJpYycsIGRheTogJ251bWVyaWMnLCBvbWl0Q29tbWFzOiB0cnVlIH07IC8vIFwiU2F0IDExLzEyXCJcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB7IHdlZWtkYXk6ICdsb25nJyB9OyAvLyBcIlNhdHVyZGF5XCJcbiAgICB9XG59XG5mdW5jdGlvbiByZW5kZXJEYXRlQ2VsbChkYXRlTWFya2VyLCBkYXRlUHJvZmlsZSwgZGF0ZXNSZXBEaXN0aW5jdERheXMsIGNvbENudCwgY29sSGVhZEZvcm1hdCwgY29udGV4dCwgY29sc3Bhbiwgb3RoZXJBdHRycykge1xuICAgIHZhciBkYXRlRW52ID0gY29udGV4dC5kYXRlRW52LCB0aGVtZSA9IGNvbnRleHQudGhlbWUsIG9wdGlvbnMgPSBjb250ZXh0Lm9wdGlvbnM7XG4gICAgdmFyIGlzRGF0ZVZhbGlkID0gcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgZGF0ZU1hcmtlcik7IC8vIFRPRE86IGNhbGxlZCB0b28gZnJlcXVlbnRseS4gY2FjaGUgc29tZWhvdy5cbiAgICB2YXIgY2xhc3NOYW1lcyA9IFtcbiAgICAgICAgJ2ZjLWRheS1oZWFkZXInLFxuICAgICAgICB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0SGVhZGVyJylcbiAgICBdO1xuICAgIHZhciBpbm5lckh0bWw7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmNvbHVtbkhlYWRlckh0bWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgaW5uZXJIdG1sID0gb3B0aW9ucy5jb2x1bW5IZWFkZXJIdG1sKGRhdGVFbnYudG9EYXRlKGRhdGVNYXJrZXIpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMuY29sdW1uSGVhZGVyVGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBpbm5lckh0bWwgPSBodG1sRXNjYXBlKG9wdGlvbnMuY29sdW1uSGVhZGVyVGV4dChkYXRlRW52LnRvRGF0ZShkYXRlTWFya2VyKSkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaW5uZXJIdG1sID0gaHRtbEVzY2FwZShkYXRlRW52LmZvcm1hdChkYXRlTWFya2VyLCBjb2xIZWFkRm9ybWF0KSk7XG4gICAgfVxuICAgIC8vIGlmIG9ubHkgb25lIHJvdyBvZiBkYXlzLCB0aGUgY2xhc3NOYW1lcyBvbiB0aGUgaGVhZGVyIGNhbiByZXByZXNlbnQgdGhlIHNwZWNpZmljIGRheXMgYmVuZWF0aFxuICAgIGlmIChkYXRlc1JlcERpc3RpbmN0RGF5cykge1xuICAgICAgICBjbGFzc05hbWVzID0gY2xhc3NOYW1lcy5jb25jYXQoXG4gICAgICAgIC8vIGluY2x1ZGVzIHRoZSBkYXktb2Ytd2VlayBjbGFzc1xuICAgICAgICAvLyBub1RoZW1lSGlnaGxpZ2h0PXRydWUgKGRvbid0IGhpZ2hsaWdodCB0aGUgaGVhZGVyKVxuICAgICAgICBnZXREYXlDbGFzc2VzKGRhdGVNYXJrZXIsIGRhdGVQcm9maWxlLCBjb250ZXh0LCB0cnVlKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjbGFzc05hbWVzLnB1c2goJ2ZjLScgKyBEQVlfSURTW2RhdGVNYXJrZXIuZ2V0VVRDRGF5KCldKTsgLy8gb25seSBhZGQgdGhlIGRheS1vZi13ZWVrIGNsYXNzXG4gICAgfVxuICAgIHJldHVybiAnJyArXG4gICAgICAgICc8dGggY2xhc3M9XCInICsgY2xhc3NOYW1lcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgKChpc0RhdGVWYWxpZCAmJiBkYXRlc1JlcERpc3RpbmN0RGF5cykgP1xuICAgICAgICAgICAgJyBkYXRhLWRhdGU9XCInICsgZGF0ZUVudi5mb3JtYXRJc28oZGF0ZU1hcmtlciwgeyBvbWl0VGltZTogdHJ1ZSB9KSArICdcIicgOlxuICAgICAgICAgICAgJycpICtcbiAgICAgICAgKGNvbHNwYW4gPiAxID9cbiAgICAgICAgICAgICcgY29sc3Bhbj1cIicgKyBjb2xzcGFuICsgJ1wiJyA6XG4gICAgICAgICAgICAnJykgK1xuICAgICAgICAob3RoZXJBdHRycyA/XG4gICAgICAgICAgICAnICcgKyBvdGhlckF0dHJzIDpcbiAgICAgICAgICAgICcnKSArXG4gICAgICAgICc+JyArXG4gICAgICAgIChpc0RhdGVWYWxpZCA/XG4gICAgICAgICAgICAvLyBkb24ndCBtYWtlIGEgbGluayBpZiB0aGUgaGVhZGluZyBjb3VsZCByZXByZXNlbnQgbXVsdGlwbGUgZGF5cywgb3IgaWYgdGhlcmUncyBvbmx5IG9uZSBkYXkgKGZvcmNlT2ZmKVxuICAgICAgICAgICAgYnVpbGRHb3RvQW5jaG9ySHRtbChvcHRpb25zLCBkYXRlRW52LCB7IGRhdGU6IGRhdGVNYXJrZXIsIGZvcmNlT2ZmOiAhZGF0ZXNSZXBEaXN0aW5jdERheXMgfHwgY29sQ250ID09PSAxIH0sIGlubmVySHRtbCkgOlxuICAgICAgICAgICAgLy8gaWYgbm90IHZhbGlkLCBkaXNwbGF5IHRleHQsIGJ1dCBubyBsaW5rXG4gICAgICAgICAgICBpbm5lckh0bWwpICtcbiAgICAgICAgJzwvdGg+Jztcbn1cblxudmFyIERheUhlYWRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5SGVhZGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUhlYWRlcihwYXJlbnRFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yZW5kZXJTa2VsZXRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclNrZWxldG9uLCBfdGhpcy5fdW5yZW5kZXJTa2VsZXRvbik7XG4gICAgICAgIF90aGlzLnBhcmVudEVsID0gcGFyZW50RWw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5SGVhZGVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGRhdGVzID0gcHJvcHMuZGF0ZXMsIGRhdGVzUmVwRGlzdGluY3REYXlzID0gcHJvcHMuZGF0ZXNSZXBEaXN0aW5jdERheXM7XG4gICAgICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uKGNvbnRleHQpO1xuICAgICAgICBpZiAocHJvcHMucmVuZGVySW50cm9IdG1sKSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHByb3BzLnJlbmRlckludHJvSHRtbCgpKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sSGVhZEZvcm1hdCA9IGNyZWF0ZUZvcm1hdHRlcihjb250ZXh0Lm9wdGlvbnMuY29sdW1uSGVhZGVyRm9ybWF0IHx8XG4gICAgICAgICAgICBjb21wdXRlRmFsbGJhY2tIZWFkZXJGb3JtYXQoZGF0ZXNSZXBEaXN0aW5jdERheXMsIGRhdGVzLmxlbmd0aCkpO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIGRhdGVzXzEgPSBkYXRlczsgX2kgPCBkYXRlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGRhdGUgPSBkYXRlc18xW19pXTtcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocmVuZGVyRGF0ZUNlbGwoZGF0ZSwgcHJvcHMuZGF0ZVByb2ZpbGUsIGRhdGVzUmVwRGlzdGluY3REYXlzLCBkYXRlcy5sZW5ndGgsIGNvbEhlYWRGb3JtYXQsIGNvbnRleHQpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29udGV4dC5pc1J0bCkge1xuICAgICAgICAgICAgcGFydHMucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudGhlYWQuaW5uZXJIVE1MID0gJzx0cj4nICsgcGFydHMuam9pbignJykgKyAnPC90cj4nO1xuICAgIH07XG4gICAgRGF5SGVhZGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJTa2VsZXRvbi51bnJlbmRlcigpO1xuICAgIH07XG4gICAgRGF5SGVhZGVyLnByb3RvdHlwZS5fcmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICB2YXIgdGhlbWUgPSBjb250ZXh0LnRoZW1lO1xuICAgICAgICB2YXIgcGFyZW50RWwgPSB0aGlzLnBhcmVudEVsO1xuICAgICAgICBwYXJlbnRFbC5pbm5lckhUTUwgPSAnJzsgLy8gYmVjYXVzZSBtaWdodCBiZSBuYnNwXG4gICAgICAgIHBhcmVudEVsLmFwcGVuZENoaWxkKHRoaXMuZWwgPSBodG1sVG9FbGVtZW50KCc8ZGl2IGNsYXNzPVwiZmMtcm93ICcgKyB0aGVtZS5nZXRDbGFzcygnaGVhZGVyUm93JykgKyAnXCI+JyArXG4gICAgICAgICAgICAnPHRhYmxlIGNsYXNzPVwiJyArIHRoZW1lLmdldENsYXNzKCd0YWJsZUdyaWQnKSArICdcIj4nICtcbiAgICAgICAgICAgICc8dGhlYWQ+PC90aGVhZD4nICtcbiAgICAgICAgICAgICc8L3RhYmxlPicgK1xuICAgICAgICAgICAgJzwvZGl2PicpKTtcbiAgICAgICAgdGhpcy50aGVhZCA9IHRoaXMuZWwucXVlcnlTZWxlY3RvcigndGhlYWQnKTtcbiAgICB9O1xuICAgIERheUhlYWRlci5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5lbCk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5SGVhZGVyO1xufShDb21wb25lbnQpKTtcblxudmFyIERheVNlcmllcyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEYXlTZXJpZXMocmFuZ2UsIGRhdGVQcm9maWxlR2VuZXJhdG9yKSB7XG4gICAgICAgIHZhciBkYXRlID0gcmFuZ2Uuc3RhcnQ7XG4gICAgICAgIHZhciBlbmQgPSByYW5nZS5lbmQ7XG4gICAgICAgIHZhciBpbmRpY2VzID0gW107XG4gICAgICAgIHZhciBkYXRlcyA9IFtdO1xuICAgICAgICB2YXIgZGF5SW5kZXggPSAtMTtcbiAgICAgICAgd2hpbGUgKGRhdGUgPCBlbmQpIHsgLy8gbG9vcCBlYWNoIGRheSBmcm9tIHN0YXJ0IHRvIGVuZFxuICAgICAgICAgICAgaWYgKGRhdGVQcm9maWxlR2VuZXJhdG9yLmlzSGlkZGVuRGF5KGRhdGUpKSB7XG4gICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKGRheUluZGV4ICsgMC41KTsgLy8gbWFyayB0aGF0IGl0J3MgYmV0d2VlbiBpbmRpY2VzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkYXlJbmRleCsrO1xuICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChkYXlJbmRleCk7XG4gICAgICAgICAgICAgICAgZGF0ZXMucHVzaChkYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRhdGUgPSBhZGREYXlzKGRhdGUsIDEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGF0ZXMgPSBkYXRlcztcbiAgICAgICAgdGhpcy5pbmRpY2VzID0gaW5kaWNlcztcbiAgICAgICAgdGhpcy5jbnQgPSBkYXRlcy5sZW5ndGg7XG4gICAgfVxuICAgIERheVNlcmllcy5wcm90b3R5cGUuc2xpY2VSYW5nZSA9IGZ1bmN0aW9uIChyYW5nZSkge1xuICAgICAgICB2YXIgZmlyc3RJbmRleCA9IHRoaXMuZ2V0RGF0ZURheUluZGV4KHJhbmdlLnN0YXJ0KTsgLy8gaW5jbHVzaXZlIGZpcnN0IGluZGV4XG4gICAgICAgIHZhciBsYXN0SW5kZXggPSB0aGlzLmdldERhdGVEYXlJbmRleChhZGREYXlzKHJhbmdlLmVuZCwgLTEpKTsgLy8gaW5jbHVzaXZlIGxhc3QgaW5kZXhcbiAgICAgICAgdmFyIGNsaXBwZWRGaXJzdEluZGV4ID0gTWF0aC5tYXgoMCwgZmlyc3RJbmRleCk7XG4gICAgICAgIHZhciBjbGlwcGVkTGFzdEluZGV4ID0gTWF0aC5taW4odGhpcy5jbnQgLSAxLCBsYXN0SW5kZXgpO1xuICAgICAgICAvLyBkZWFsIHdpdGggaW4tYmV0d2VlbiBpbmRpY2VzXG4gICAgICAgIGNsaXBwZWRGaXJzdEluZGV4ID0gTWF0aC5jZWlsKGNsaXBwZWRGaXJzdEluZGV4KTsgLy8gaW4tYmV0d2VlbiBzdGFydHMgcm91bmQgdG8gbmV4dCBjZWxsXG4gICAgICAgIGNsaXBwZWRMYXN0SW5kZXggPSBNYXRoLmZsb29yKGNsaXBwZWRMYXN0SW5kZXgpOyAvLyBpbi1iZXR3ZWVuIGVuZHMgcm91bmQgdG8gcHJldiBjZWxsXG4gICAgICAgIGlmIChjbGlwcGVkRmlyc3RJbmRleCA8PSBjbGlwcGVkTGFzdEluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGZpcnN0SW5kZXg6IGNsaXBwZWRGaXJzdEluZGV4LFxuICAgICAgICAgICAgICAgIGxhc3RJbmRleDogY2xpcHBlZExhc3RJbmRleCxcbiAgICAgICAgICAgICAgICBpc1N0YXJ0OiBmaXJzdEluZGV4ID09PSBjbGlwcGVkRmlyc3RJbmRleCxcbiAgICAgICAgICAgICAgICBpc0VuZDogbGFzdEluZGV4ID09PSBjbGlwcGVkTGFzdEluZGV4XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEdpdmVuIGEgZGF0ZSwgcmV0dXJucyBpdHMgY2hyb25vbG9jaWFsIGNlbGwtaW5kZXggZnJvbSB0aGUgZmlyc3QgY2VsbCBvZiB0aGUgZ3JpZC5cbiAgICAvLyBJZiB0aGUgZGF0ZSBsaWVzIGJldHdlZW4gY2VsbHMgKGJlY2F1c2Ugb2YgaGlkZGVuRGF5cyksIHJldHVybnMgYSBmbG9hdGluZy1wb2ludCB2YWx1ZSBiZXR3ZWVuIG9mZnNldHMuXG4gICAgLy8gSWYgYmVmb3JlIHRoZSBmaXJzdCBvZmZzZXQsIHJldHVybnMgYSBuZWdhdGl2ZSBudW1iZXIuXG4gICAgLy8gSWYgYWZ0ZXIgdGhlIGxhc3Qgb2Zmc2V0LCByZXR1cm5zIGFuIG9mZnNldCBwYXN0IHRoZSBsYXN0IGNlbGwgb2Zmc2V0LlxuICAgIC8vIE9ubHkgd29ya3MgZm9yICpzdGFydCogZGF0ZXMgb2YgY2VsbHMuIFdpbGwgbm90IHdvcmsgZm9yIGV4Y2x1c2l2ZSBlbmQgZGF0ZXMgZm9yIGNlbGxzLlxuICAgIERheVNlcmllcy5wcm90b3R5cGUuZ2V0RGF0ZURheUluZGV4ID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgdmFyIGluZGljZXMgPSB0aGlzLmluZGljZXM7XG4gICAgICAgIHZhciBkYXlPZmZzZXQgPSBNYXRoLmZsb29yKGRpZmZEYXlzKHRoaXMuZGF0ZXNbMF0sIGRhdGUpKTtcbiAgICAgICAgaWYgKGRheU9mZnNldCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBpbmRpY2VzWzBdIC0gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkYXlPZmZzZXQgPj0gaW5kaWNlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV0gKyAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGluZGljZXNbZGF5T2Zmc2V0XTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERheVNlcmllcztcbn0oKSk7XG5cbnZhciBEYXlUYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEYXlUYWJsZShkYXlTZXJpZXMsIGJyZWFrT25XZWVrcykge1xuICAgICAgICB2YXIgZGF0ZXMgPSBkYXlTZXJpZXMuZGF0ZXM7XG4gICAgICAgIHZhciBkYXlzUGVyUm93O1xuICAgICAgICB2YXIgZmlyc3REYXk7XG4gICAgICAgIHZhciByb3dDbnQ7XG4gICAgICAgIGlmIChicmVha09uV2Vla3MpIHtcbiAgICAgICAgICAgIC8vIGNvdW50IGNvbHVtbnMgdW50aWwgdGhlIGRheS1vZi13ZWVrIHJlcGVhdHNcbiAgICAgICAgICAgIGZpcnN0RGF5ID0gZGF0ZXNbMF0uZ2V0VVRDRGF5KCk7XG4gICAgICAgICAgICBmb3IgKGRheXNQZXJSb3cgPSAxOyBkYXlzUGVyUm93IDwgZGF0ZXMubGVuZ3RoOyBkYXlzUGVyUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZXNbZGF5c1BlclJvd10uZ2V0VVRDRGF5KCkgPT09IGZpcnN0RGF5KSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJvd0NudCA9IE1hdGguY2VpbChkYXRlcy5sZW5ndGggLyBkYXlzUGVyUm93KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJvd0NudCA9IDE7XG4gICAgICAgICAgICBkYXlzUGVyUm93ID0gZGF0ZXMubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucm93Q250ID0gcm93Q250O1xuICAgICAgICB0aGlzLmNvbENudCA9IGRheXNQZXJSb3c7XG4gICAgICAgIHRoaXMuZGF5U2VyaWVzID0gZGF5U2VyaWVzO1xuICAgICAgICB0aGlzLmNlbGxzID0gdGhpcy5idWlsZENlbGxzKCk7XG4gICAgICAgIHRoaXMuaGVhZGVyRGF0ZXMgPSB0aGlzLmJ1aWxkSGVhZGVyRGF0ZXMoKTtcbiAgICB9XG4gICAgRGF5VGFibGUucHJvdG90eXBlLmJ1aWxkQ2VsbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dzID0gW107XG4gICAgICAgIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IHRoaXMucm93Q250OyByb3crKykge1xuICAgICAgICAgICAgdmFyIGNlbGxzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBjb2wgPSAwOyBjb2wgPCB0aGlzLmNvbENudDsgY29sKyspIHtcbiAgICAgICAgICAgICAgICBjZWxscy5wdXNoKHRoaXMuYnVpbGRDZWxsKHJvdywgY29sKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByb3dzLnB1c2goY2VsbHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dzO1xuICAgIH07XG4gICAgRGF5VGFibGUucHJvdG90eXBlLmJ1aWxkQ2VsbCA9IGZ1bmN0aW9uIChyb3csIGNvbCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0ZTogdGhpcy5kYXlTZXJpZXMuZGF0ZXNbcm93ICogdGhpcy5jb2xDbnQgKyBjb2xdXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBEYXlUYWJsZS5wcm90b3R5cGUuYnVpbGRIZWFkZXJEYXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGVzID0gW107XG4gICAgICAgIGZvciAodmFyIGNvbCA9IDA7IGNvbCA8IHRoaXMuY29sQ250OyBjb2wrKykge1xuICAgICAgICAgICAgZGF0ZXMucHVzaCh0aGlzLmNlbGxzWzBdW2NvbF0uZGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGVzO1xuICAgIH07XG4gICAgRGF5VGFibGUucHJvdG90eXBlLnNsaWNlUmFuZ2UgPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgICAgICAgdmFyIGNvbENudCA9IHRoaXMuY29sQ250O1xuICAgICAgICB2YXIgc2VyaWVzU2VnID0gdGhpcy5kYXlTZXJpZXMuc2xpY2VSYW5nZShyYW5nZSk7XG4gICAgICAgIHZhciBzZWdzID0gW107XG4gICAgICAgIGlmIChzZXJpZXNTZWcpIHtcbiAgICAgICAgICAgIHZhciBmaXJzdEluZGV4ID0gc2VyaWVzU2VnLmZpcnN0SW5kZXgsIGxhc3RJbmRleCA9IHNlcmllc1NlZy5sYXN0SW5kZXg7XG4gICAgICAgICAgICB2YXIgaW5kZXggPSBmaXJzdEluZGV4O1xuICAgICAgICAgICAgd2hpbGUgKGluZGV4IDw9IGxhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciByb3cgPSBNYXRoLmZsb29yKGluZGV4IC8gY29sQ250KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gTWF0aC5taW4oKHJvdyArIDEpICogY29sQ250LCBsYXN0SW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgICBzZWdzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICByb3c6IHJvdyxcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RDb2w6IGluZGV4ICUgY29sQ250LFxuICAgICAgICAgICAgICAgICAgICBsYXN0Q29sOiAobmV4dEluZGV4IC0gMSkgJSBjb2xDbnQsXG4gICAgICAgICAgICAgICAgICAgIGlzU3RhcnQ6IHNlcmllc1NlZy5pc1N0YXJ0ICYmIGluZGV4ID09PSBmaXJzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICBpc0VuZDogc2VyaWVzU2VnLmlzRW5kICYmIChuZXh0SW5kZXggLSAxKSA9PT0gbGFzdEluZGV4XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5VGFibGU7XG59KCkpO1xuXG52YXIgU2xpY2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNsaWNlcigpIHtcbiAgICAgICAgdGhpcy5zbGljZUJ1c2luZXNzSG91cnMgPSBtZW1vaXplKHRoaXMuX3NsaWNlQnVzaW5lc3NIb3Vycyk7XG4gICAgICAgIHRoaXMuc2xpY2VEYXRlU2VsZWN0aW9uID0gbWVtb2l6ZSh0aGlzLl9zbGljZURhdGVTcGFuKTtcbiAgICAgICAgdGhpcy5zbGljZUV2ZW50U3RvcmUgPSBtZW1vaXplKHRoaXMuX3NsaWNlRXZlbnRTdG9yZSk7XG4gICAgICAgIHRoaXMuc2xpY2VFdmVudERyYWcgPSBtZW1vaXplKHRoaXMuX3NsaWNlSW50ZXJhY3Rpb24pO1xuICAgICAgICB0aGlzLnNsaWNlRXZlbnRSZXNpemUgPSBtZW1vaXplKHRoaXMuX3NsaWNlSW50ZXJhY3Rpb24pO1xuICAgIH1cbiAgICBTbGljZXIucHJvdG90eXBlLnNsaWNlUHJvcHMgPSBmdW5jdGlvbiAocHJvcHMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjYWxlbmRhciwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSA1OyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDVdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXZlbnRVaUJhc2VzID0gcHJvcHMuZXZlbnRVaUJhc2VzO1xuICAgICAgICB2YXIgZXZlbnRTZWdzID0gdGhpcy5zbGljZUV2ZW50U3RvcmUuYXBwbHkodGhpcywgW3Byb3BzLmV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvblNlZ3M6IHRoaXMuc2xpY2VEYXRlU2VsZWN0aW9uLmFwcGx5KHRoaXMsIFtwcm9wcy5kYXRlU2VsZWN0aW9uLCBldmVudFVpQmFzZXMsIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpLFxuICAgICAgICAgICAgYnVzaW5lc3NIb3VyU2VnczogdGhpcy5zbGljZUJ1c2luZXNzSG91cnMuYXBwbHkodGhpcywgW3Byb3BzLmJ1c2luZXNzSG91cnMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjYWxlbmRhciwgY29tcG9uZW50XS5jb25jYXQoZXh0cmFBcmdzKSksXG4gICAgICAgICAgICBmZ0V2ZW50U2VnczogZXZlbnRTZWdzLmZnLFxuICAgICAgICAgICAgYmdFdmVudFNlZ3M6IGV2ZW50U2Vncy5iZyxcbiAgICAgICAgICAgIGV2ZW50RHJhZzogdGhpcy5zbGljZUV2ZW50RHJhZy5hcHBseSh0aGlzLCBbcHJvcHMuZXZlbnREcmFnLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKSxcbiAgICAgICAgICAgIGV2ZW50UmVzaXplOiB0aGlzLnNsaWNlRXZlbnRSZXNpemUuYXBwbHkodGhpcywgW3Byb3BzLmV2ZW50UmVzaXplLCBldmVudFVpQmFzZXMsIGRhdGVQcm9maWxlLCBuZXh0RGF5VGhyZXNob2xkLCBjb21wb25lbnRdLmNvbmNhdChleHRyYUFyZ3MpKSxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvblxuICAgICAgICB9OyAvLyBUT0RPOiBnaXZlIGludGVyYWN0aW9uU2Vncz9cbiAgICB9O1xuICAgIFNsaWNlci5wcm90b3R5cGUuc2xpY2VOb3dEYXRlID0gZnVuY3Rpb24gKC8vIGRvZXMgbm90IG1lbW9pemVcbiAgICBkYXRlLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIGV4dHJhQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDI7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgZXh0cmFBcmdzW19pIC0gMl0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zbGljZURhdGVTcGFuLmFwcGx5KHRoaXMsIFt7IHJhbmdlOiB7IHN0YXJ0OiBkYXRlLCBlbmQ6IGFkZE1zKGRhdGUsIDEpIH0sIGFsbERheTogZmFsc2UgfSxcbiAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgY29tcG9uZW50XS5jb25jYXQoZXh0cmFBcmdzKSk7XG4gICAgfTtcbiAgICBTbGljZXIucHJvdG90eXBlLl9zbGljZUJ1c2luZXNzSG91cnMgPSBmdW5jdGlvbiAoYnVzaW5lc3NIb3VycywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNhbGVuZGFyLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIGV4dHJhQXJncyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDU7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgZXh0cmFBcmdzW19pIC0gNV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmICghYnVzaW5lc3NIb3Vycykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zbGljZUV2ZW50U3RvcmUuYXBwbHkodGhpcywgW2V4cGFuZFJlY3VycmluZyhidXNpbmVzc0hvdXJzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBjYWxlbmRhciksXG4gICAgICAgICAgICB7fSxcbiAgICAgICAgICAgIGRhdGVQcm9maWxlLFxuICAgICAgICAgICAgbmV4dERheVRocmVzaG9sZCxcbiAgICAgICAgICAgIGNvbXBvbmVudF0uY29uY2F0KGV4dHJhQXJncykpLmJnO1xuICAgIH07XG4gICAgU2xpY2VyLnByb3RvdHlwZS5fc2xpY2VFdmVudFN0b3JlID0gZnVuY3Rpb24gKGV2ZW50U3RvcmUsIGV2ZW50VWlCYXNlcywgZGF0ZVByb2ZpbGUsIG5leHREYXlUaHJlc2hvbGQsIGNvbXBvbmVudCkge1xuICAgICAgICB2YXIgZXh0cmFBcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gNTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBleHRyYUFyZ3NbX2kgLSA1XSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50U3RvcmUpIHtcbiAgICAgICAgICAgIHZhciByYW5nZVJlcyA9IHNsaWNlRXZlbnRTdG9yZShldmVudFN0b3JlLCBldmVudFVpQmFzZXMsIGNvbXB1dGVBY3RpdmVSYW5nZShkYXRlUHJvZmlsZSwgQm9vbGVhbihuZXh0RGF5VGhyZXNob2xkKSksIG5leHREYXlUaHJlc2hvbGQpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBiZzogdGhpcy5zbGljZUV2ZW50UmFuZ2VzKHJhbmdlUmVzLmJnLCBjb21wb25lbnQsIGV4dHJhQXJncyksXG4gICAgICAgICAgICAgICAgZmc6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5mZywgY29tcG9uZW50LCBleHRyYUFyZ3MpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHsgYmc6IFtdLCBmZzogW10gfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2xpY2VyLnByb3RvdHlwZS5fc2xpY2VJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbiwgZXZlbnRVaUJhc2VzLCBkYXRlUHJvZmlsZSwgbmV4dERheVRocmVzaG9sZCwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSA1OyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDVdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWludGVyYWN0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmFuZ2VSZXMgPSBzbGljZUV2ZW50U3RvcmUoaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cywgZXZlbnRVaUJhc2VzLCBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIEJvb2xlYW4obmV4dERheVRocmVzaG9sZCkpLCBuZXh0RGF5VGhyZXNob2xkKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNlZ3M6IHRoaXMuc2xpY2VFdmVudFJhbmdlcyhyYW5nZVJlcy5mZywgY29tcG9uZW50LCBleHRyYUFyZ3MpLFxuICAgICAgICAgICAgYWZmZWN0ZWRJbnN0YW5jZXM6IGludGVyYWN0aW9uLmFmZmVjdGVkRXZlbnRzLmluc3RhbmNlcyxcbiAgICAgICAgICAgIGlzRXZlbnQ6IGludGVyYWN0aW9uLmlzRXZlbnQsXG4gICAgICAgICAgICBzb3VyY2VTZWc6IGludGVyYWN0aW9uLm9yaWdTZWdcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFNsaWNlci5wcm90b3R5cGUuX3NsaWNlRGF0ZVNwYW4gPSBmdW5jdGlvbiAoZGF0ZVNwYW4sIGV2ZW50VWlCYXNlcywgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBleHRyYUFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAzOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGV4dHJhQXJnc1tfaSAtIDNdID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWRhdGVTcGFuKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBmYWJyaWNhdGVFdmVudFJhbmdlKGRhdGVTcGFuLCBldmVudFVpQmFzZXMsIGNvbXBvbmVudC5jb250ZXh0LmNhbGVuZGFyKTtcbiAgICAgICAgdmFyIHNlZ3MgPSB0aGlzLnNsaWNlUmFuZ2UuYXBwbHkodGhpcywgW2RhdGVTcGFuLnJhbmdlXS5jb25jYXQoZXh0cmFBcmdzKSk7XG4gICAgICAgIGZvciAodmFyIF9hID0gMCwgc2Vnc18xID0gc2VnczsgX2EgPCBzZWdzXzEubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18xW19hXTtcbiAgICAgICAgICAgIHNlZy5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgICBzZWcuZXZlbnRSYW5nZSA9IGV2ZW50UmFuZ2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICAvKlxuICAgIFwiY29tcGxldGVcIiBzZWcgbWVhbnMgaXQgaGFzIGNvbXBvbmVudCBhbmQgZXZlbnRSYW5nZVxuICAgICovXG4gICAgU2xpY2VyLnByb3RvdHlwZS5zbGljZUV2ZW50UmFuZ2VzID0gZnVuY3Rpb24gKGV2ZW50UmFuZ2VzLCBjb21wb25lbnQsIC8vIFRPRE86IGtpbGxcbiAgICBleHRyYUFyZ3MpIHtcbiAgICAgICAgdmFyIHNlZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBldmVudFJhbmdlc18xID0gZXZlbnRSYW5nZXM7IF9pIDwgZXZlbnRSYW5nZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gZXZlbnRSYW5nZXNfMVtfaV07XG4gICAgICAgICAgICBzZWdzLnB1c2guYXBwbHkoc2VncywgdGhpcy5zbGljZUV2ZW50UmFuZ2UoZXZlbnRSYW5nZSwgY29tcG9uZW50LCBleHRyYUFyZ3MpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VncztcbiAgICB9O1xuICAgIC8qXG4gICAgXCJjb21wbGV0ZVwiIHNlZyBtZWFucyBpdCBoYXMgY29tcG9uZW50IGFuZCBldmVudFJhbmdlXG4gICAgKi9cbiAgICBTbGljZXIucHJvdG90eXBlLnNsaWNlRXZlbnRSYW5nZSA9IGZ1bmN0aW9uIChldmVudFJhbmdlLCBjb21wb25lbnQsIC8vIFRPRE86IGtpbGxcbiAgICBleHRyYUFyZ3MpIHtcbiAgICAgICAgdmFyIHNlZ3MgPSB0aGlzLnNsaWNlUmFuZ2UuYXBwbHkodGhpcywgW2V2ZW50UmFuZ2UucmFuZ2VdLmNvbmNhdChleHRyYUFyZ3MpKTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBzZWdzXzIgPSBzZWdzOyBfaSA8IHNlZ3NfMi5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzZWcgPSBzZWdzXzJbX2ldO1xuICAgICAgICAgICAgc2VnLmNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICAgICAgICAgIHNlZy5ldmVudFJhbmdlID0gZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIHNlZy5pc1N0YXJ0ID0gZXZlbnRSYW5nZS5pc1N0YXJ0ICYmIHNlZy5pc1N0YXJ0O1xuICAgICAgICAgICAgc2VnLmlzRW5kID0gZXZlbnRSYW5nZS5pc0VuZCAmJiBzZWcuaXNFbmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICByZXR1cm4gU2xpY2VyO1xufSgpKTtcbi8qXG5mb3IgaW5jb3Jwb3JhdGluZyBtaW5UaW1lL21heFRpbWUgaWYgYXBwcm9wcmlhdGVcblRPRE86IHNob3VsZCBiZSBwYXJ0IG9mIERhdGVQcm9maWxlIVxuVGltZWxpbmVEYXRlUHJvZmlsZSBhbHJlYWR5IGRvZXMgdGhpcyBidHdcbiovXG5mdW5jdGlvbiBjb21wdXRlQWN0aXZlUmFuZ2UoZGF0ZVByb2ZpbGUsIGlzQ29tcG9uZW50QWxsRGF5KSB7XG4gICAgdmFyIHJhbmdlID0gZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2U7XG4gICAgaWYgKGlzQ29tcG9uZW50QWxsRGF5KSB7XG4gICAgICAgIHJldHVybiByYW5nZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IGFkZE1zKHJhbmdlLnN0YXJ0LCBkYXRlUHJvZmlsZS5taW5UaW1lLm1pbGxpc2Vjb25kcyksXG4gICAgICAgIGVuZDogYWRkTXMocmFuZ2UuZW5kLCBkYXRlUHJvZmlsZS5tYXhUaW1lLm1pbGxpc2Vjb25kcyAtIDg2NGU1KSAvLyA4NjRlNSA9IG1zIGluIGEgZGF5XG4gICAgfTtcbn1cblxuLy8gZXhwb3J0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbnZhciB2ZXJzaW9uID0gJzQuNC4yJztcblxuZXhwb3J0IHsgQ2FsZW5kYXIsIENvbXBvbmVudCwgQ29tcG9uZW50Q29udGV4dCwgRGF0ZUNvbXBvbmVudCwgRGF0ZUVudiwgRGF0ZVByb2ZpbGVHZW5lcmF0b3IsIERheUhlYWRlciwgRGF5U2VyaWVzLCBEYXlUYWJsZSwgRWxlbWVudERyYWdnaW5nLCBFbGVtZW50U2Nyb2xsQ29udHJvbGxlciwgRW1pdHRlck1peGluLCBFdmVudEFwaSwgRmdFdmVudFJlbmRlcmVyLCBGaWxsUmVuZGVyZXIsIEludGVyYWN0aW9uLCBNaXhpbiwgTmFtZWRUaW1lWm9uZUltcGwsIFBvc2l0aW9uQ2FjaGUsIFNjcm9sbENvbXBvbmVudCwgU2Nyb2xsQ29udHJvbGxlciwgU2xpY2VyLCBTcGxpdHRlciwgVGhlbWUsIFZpZXcsIFdpbmRvd1Njcm9sbENvbnRyb2xsZXIsIGFkZERheXMsIGFkZER1cmF0aW9ucywgYWRkTXMsIGFkZFdlZWtzLCBhbGxvd0NvbnRleHRNZW51LCBhbGxvd1NlbGVjdGlvbiwgYXBwZW5kVG9FbGVtZW50LCBhcHBseUFsbCwgYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZSwgYXBwbHlTdHlsZSwgYXBwbHlTdHlsZVByb3AsIGFzUm91Z2hNaW51dGVzLCBhc1JvdWdoTXMsIGFzUm91Z2hTZWNvbmRzLCBidWlsZEdvdG9BbmNob3JIdG1sLCBidWlsZFNlZ0NvbXBhcmVPYmosIGNhcGl0YWxpc2VGaXJzdExldHRlciwgY29tYmluZUV2ZW50VWlzLCBjb21wYXJlQnlGaWVsZFNwZWMsIGNvbXBhcmVCeUZpZWxkU3BlY3MsIGNvbXBhcmVOdW1iZXJzLCBjb21wZW5zYXRlU2Nyb2xsLCBjb21wdXRlQ2xpcHBpbmdSZWN0LCBjb21wdXRlRWRnZXMsIGNvbXB1dGVFdmVudERyYWdnYWJsZSwgY29tcHV0ZUV2ZW50RW5kUmVzaXphYmxlLCBjb21wdXRlRXZlbnRTdGFydFJlc2l6YWJsZSwgY29tcHV0ZUZhbGxiYWNrSGVhZGVyRm9ybWF0LCBjb21wdXRlSGVpZ2h0QW5kTWFyZ2lucywgY29tcHV0ZUlubmVyUmVjdCwgY29tcHV0ZVJlY3QsIGNvbXB1dGVWaXNpYmxlRGF5UmFuZ2UsIGNvbmZpZywgY29uc3RyYWluUG9pbnQsIGNyZWF0ZUR1cmF0aW9uLCBjcmVhdGVFbGVtZW50LCBjcmVhdGVFbXB0eUV2ZW50U3RvcmUsIGNyZWF0ZUV2ZW50SW5zdGFuY2UsIGNyZWF0ZUZvcm1hdHRlciwgY3JlYXRlUGx1Z2luLCBjc3NUb1N0ciwgZGVib3VuY2UsIGRpZmZEYXRlcywgZGlmZkRheUFuZFRpbWUsIGRpZmZEYXlzLCBkaWZmUG9pbnRzLCBkaWZmV2Vla3MsIGRpZmZXaG9sZURheXMsIGRpZmZXaG9sZVdlZWtzLCBkaXNhYmxlQ3Vyc29yLCBkaXN0cmlidXRlSGVpZ2h0LCBlbGVtZW50Q2xvc2VzdCwgZWxlbWVudE1hdGNoZXMsIGVuYWJsZUN1cnNvciwgZXZlbnRUdXBsZVRvU3RvcmUsIGZpbHRlckV2ZW50U3RvcmVEZWZzLCBmaWx0ZXJIYXNoLCBmaW5kQ2hpbGRyZW4sIGZpbmRFbGVtZW50cywgZmxleGlibGVDb21wYXJlLCBmb3JjZUNsYXNzTmFtZSwgZm9ybWF0RGF0ZSwgZm9ybWF0SXNvVGltZVN0cmluZywgZm9ybWF0UmFuZ2UsIGdldEFsbERheUh0bWwsIGdldENsaXBwaW5nUGFyZW50cywgZ2V0RGF5Q2xhc3NlcywgZ2V0RWxTZWcsIGdldFJlY3RDZW50ZXIsIGdldFJlbGV2YW50RXZlbnRzLCBnbG9iYWxEZWZhdWx0cywgZ3JlYXRlc3REdXJhdGlvbkRlbm9taW5hdG9yLCBoYXNCZ1JlbmRlcmluZywgaHRtbEVzY2FwZSwgaHRtbFRvRWxlbWVudCwgaW5zZXJ0QWZ0ZXJFbGVtZW50LCBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUsIGludGVyYWN0aW9uU2V0dGluZ3NUb1N0b3JlLCBpbnRlcnNlY3RSYW5nZXMsIGludGVyc2VjdFJlY3RzLCBpc0FycmF5c0VxdWFsLCBpc0RhdGVTcGFuc0VxdWFsLCBpc0ludCwgaXNJbnRlcmFjdGlvblZhbGlkLCBpc011bHRpRGF5UmFuZ2UsIGlzUHJvcHNFcXVhbCwgaXNQcm9wc1ZhbGlkLCBpc1NpbmdsZURheSwgaXNWYWxpZERhdGUsIGxpc3RlbkJ5U2VsZWN0b3IsIG1hcEhhc2gsIG1hdGNoQ2VsbFdpZHRocywgbWVtb2l6ZSwgbWVtb2l6ZU91dHB1dCwgbWVtb2l6ZVJlbmRlcmluZywgbWVyZ2VFdmVudFN0b3JlcywgbXVsdGlwbHlEdXJhdGlvbiwgcGFkU3RhcnQsIHBhcnNlQnVzaW5lc3NIb3VycywgcGFyc2VEcmFnTWV0YSwgcGFyc2VFdmVudERlZiwgcGFyc2VGaWVsZFNwZWNzLCBwYXJzZSBhcyBwYXJzZU1hcmtlciwgcG9pbnRJbnNpZGVSZWN0LCBwcmVwZW5kVG9FbGVtZW50LCBwcmV2ZW50Q29udGV4dE1lbnUsIHByZXZlbnREZWZhdWx0LCBwcmV2ZW50U2VsZWN0aW9uLCBwcm9jZXNzU2NvcGVkVWlQcm9wcywgcmFuZ2VDb250YWluc01hcmtlciwgcmFuZ2VDb250YWluc1JhbmdlLCByYW5nZXNFcXVhbCwgcmFuZ2VzSW50ZXJzZWN0LCByZWZpbmVQcm9wcywgcmVtb3ZlRWxlbWVudCwgcmVtb3ZlRXhhY3QsIHJlbmRlckRhdGVDZWxsLCByZXF1ZXN0SnNvbiwgc2xpY2VFdmVudFN0b3JlLCBzdGFydE9mRGF5LCBzdWJ0cmFjdElubmVyRWxIZWlnaHQsIHRyYW5zbGF0ZVJlY3QsIHVuY29tcGVuc2F0ZVNjcm9sbCwgdW5kaXN0cmlidXRlSGVpZ2h0LCB1bnByb21pc2lmeSwgdmVyc2lvbiwgd2hlblRyYW5zaXRpb25Eb25lLCB3aG9sZURpdmlkZUR1cmF0aW9ucyB9O1xuIiwiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luIiwiLyohXG5GdWxsQ2FsZW5kYXIgRGF5IEdyaWQgUGx1Z2luIHY0LjQuMlxuRG9jcyAmIExpY2Vuc2U6IGh0dHBzOi8vZnVsbGNhbGVuZGFyLmlvL1xuKGMpIDIwMTkgQWRhbSBTaGF3XG4qL1xuXG5pbXBvcnQgeyBhZGRXZWVrcywgZGlmZldlZWtzLCBEYXRlUHJvZmlsZUdlbmVyYXRvciwgY3JlYXRlRWxlbWVudCwgbGlzdGVuQnlTZWxlY3RvciwgcmVtb3ZlRWxlbWVudCwgY29tcHV0ZVJlY3QsIGNvbXB1dGVDbGlwcGluZ1JlY3QsIGFwcGx5U3R5bGUsIGNvbXB1dGVFdmVudERyYWdnYWJsZSwgY29tcHV0ZUV2ZW50U3RhcnRSZXNpemFibGUsIGNvbXB1dGVFdmVudEVuZFJlc2l6YWJsZSwgY3NzVG9TdHIsIGh0bWxFc2NhcGUsIEZnRXZlbnRSZW5kZXJlciwgYXBwZW5kVG9FbGVtZW50LCBwcmVwZW5kVG9FbGVtZW50LCBodG1sVG9FbGVtZW50LCBGaWxsUmVuZGVyZXIsIG1lbW9pemVSZW5kZXJpbmcsIGNyZWF0ZUZvcm1hdHRlciwgYWRkRGF5cywgRGF0ZUNvbXBvbmVudCwgcmFuZ2VDb250YWluc01hcmtlciwgZ2V0RGF5Q2xhc3NlcywgZmluZEVsZW1lbnRzLCBQb3NpdGlvbkNhY2hlLCBidWlsZEdvdG9BbmNob3JIdG1sLCBmaW5kQ2hpbGRyZW4sIGluc2VydEFmdGVyRWxlbWVudCwgaW50ZXJzZWN0UmFuZ2VzLCBtZW1vaXplLCBTY3JvbGxDb21wb25lbnQsIG1hdGNoQ2VsbFdpZHRocywgdW5jb21wZW5zYXRlU2Nyb2xsLCBjb21wZW5zYXRlU2Nyb2xsLCBzdWJ0cmFjdElubmVyRWxIZWlnaHQsIGRpc3RyaWJ1dGVIZWlnaHQsIHVuZGlzdHJpYnV0ZUhlaWdodCwgVmlldywgU2xpY2VyLCBEYXlIZWFkZXIsIERheVNlcmllcywgRGF5VGFibGUsIGNyZWF0ZVBsdWdpbiB9IGZyb20gJ0BmdWxsY2FsZW5kYXIvY29yZSc7XG5cbi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbnZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn07XG5cbnZhciBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUdyaWREYXRlUHJvZmlsZUdlbmVyYXRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3IoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gQ29tcHV0ZXMgdGhlIGRhdGUgcmFuZ2UgdGhhdCB3aWxsIGJlIHJlbmRlcmVkLlxuICAgIERheUdyaWREYXRlUHJvZmlsZUdlbmVyYXRvci5wcm90b3R5cGUuYnVpbGRSZW5kZXJSYW5nZSA9IGZ1bmN0aW9uIChjdXJyZW50UmFuZ2UsIGN1cnJlbnRSYW5nZVVuaXQsIGlzUmFuZ2VBbGxEYXkpIHtcbiAgICAgICAgdmFyIGRhdGVFbnYgPSB0aGlzLmRhdGVFbnY7XG4gICAgICAgIHZhciByZW5kZXJSYW5nZSA9IF9zdXBlci5wcm90b3R5cGUuYnVpbGRSZW5kZXJSYW5nZS5jYWxsKHRoaXMsIGN1cnJlbnRSYW5nZSwgY3VycmVudFJhbmdlVW5pdCwgaXNSYW5nZUFsbERheSk7XG4gICAgICAgIHZhciBzdGFydCA9IHJlbmRlclJhbmdlLnN0YXJ0O1xuICAgICAgICB2YXIgZW5kID0gcmVuZGVyUmFuZ2UuZW5kO1xuICAgICAgICB2YXIgZW5kT2ZXZWVrO1xuICAgICAgICAvLyB5ZWFyIGFuZCBtb250aCB2aWV3cyBzaG91bGQgYmUgYWxpZ25lZCB3aXRoIHdlZWtzLiB0aGlzIGlzIGFscmVhZHkgZG9uZSBmb3Igd2Vla1xuICAgICAgICBpZiAoL14oeWVhcnxtb250aCkkLy50ZXN0KGN1cnJlbnRSYW5nZVVuaXQpKSB7XG4gICAgICAgICAgICBzdGFydCA9IGRhdGVFbnYuc3RhcnRPZldlZWsoc3RhcnQpO1xuICAgICAgICAgICAgLy8gbWFrZSBlbmQtb2Ytd2VlayBpZiBub3QgYWxyZWFkeVxuICAgICAgICAgICAgZW5kT2ZXZWVrID0gZGF0ZUVudi5zdGFydE9mV2VlayhlbmQpO1xuICAgICAgICAgICAgaWYgKGVuZE9mV2Vlay52YWx1ZU9mKCkgIT09IGVuZC52YWx1ZU9mKCkpIHtcbiAgICAgICAgICAgICAgICBlbmQgPSBhZGRXZWVrcyhlbmRPZldlZWssIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGVuc3VyZSA2IHdlZWtzXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMubW9udGhNb2RlICYmXG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuZml4ZWRXZWVrQ291bnQpIHtcbiAgICAgICAgICAgIHZhciByb3dDbnQgPSBNYXRoLmNlaWwoLy8gY291bGQgYmUgcGFydGlhbCB3ZWVrcyBkdWUgdG8gaGlkZGVuRGF5c1xuICAgICAgICAgICAgZGlmZldlZWtzKHN0YXJ0LCBlbmQpKTtcbiAgICAgICAgICAgIGVuZCA9IGFkZFdlZWtzKGVuZCwgNiAtIHJvd0NudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9O1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWREYXRlUHJvZmlsZUdlbmVyYXRvcjtcbn0oRGF0ZVByb2ZpbGVHZW5lcmF0b3IpKTtcblxuLyogQSByZWN0YW5ndWxhciBwYW5lbCB0aGF0IGlzIGFic29sdXRlbHkgcG9zaXRpb25lZCBvdmVyIG90aGVyIGNvbnRlbnRcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuT3B0aW9uczpcbiAgLSBjbGFzc05hbWUgKHN0cmluZylcbiAgLSBjb250ZW50IChIVE1MIHN0cmluZywgZWxlbWVudCwgb3IgZWxlbWVudCBhcnJheSlcbiAgLSBwYXJlbnRFbFxuICAtIHRvcFxuICAtIGxlZnRcbiAgLSByaWdodCAodGhlIHggY29vcmQgb2Ygd2hlcmUgdGhlIHJpZ2h0IGVkZ2Ugc2hvdWxkIGJlLiBub3QgYSBcIkNTU1wiIHJpZ2h0KVxuICAtIGF1dG9IaWRlIChib29sZWFuKVxuICAtIHNob3cgKGNhbGxiYWNrKVxuICAtIGhpZGUgKGNhbGxiYWNrKVxuKi9cbnZhciBQb3BvdmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBvcG92ZXIob3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmlzSGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tYXJnaW4gPSAxMDsgLy8gdGhlIHNwYWNlIHJlcXVpcmVkIGJldHdlZW4gdGhlIHBvcG92ZXIgYW5kIHRoZSBlZGdlcyBvZiB0aGUgc2Nyb2xsIGNvbnRhaW5lclxuICAgICAgICAvLyBUcmlnZ2VyZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgKmFueXdoZXJlKiBpbiB0aGUgZG9jdW1lbnQsIGZvciB0aGUgYXV0b0hpZGUgZmVhdHVyZVxuICAgICAgICB0aGlzLmRvY3VtZW50TW91c2Vkb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICAvLyBvbmx5IGhpZGUgdGhlIHBvcG92ZXIgaWYgdGhlIGNsaWNrIGhhcHBlbmVkIG91dHNpZGUgdGhlIHBvcG92ZXJcbiAgICAgICAgICAgIGlmIChfdGhpcy5lbCAmJiAhX3RoaXMuZWwuY29udGFpbnMoZXYudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB9XG4gICAgLy8gU2hvd3MgdGhlIHBvcG92ZXIgb24gdGhlIHNwZWNpZmllZCBwb3NpdGlvbi4gUmVuZGVycyBpdCBpZiBub3QgYWxyZWFkeVxuICAgIFBvcG92ZXIucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSGlkZGVuKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbC5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICAgICAgICB0aGlzLnBvc2l0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLmlzSGlkZGVuID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIoJ3Nob3cnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gSGlkZXMgdGhlIHBvcG92ZXIsIHRocm91Z2ggQ1NTLCBidXQgZG9lcyBub3QgcmVtb3ZlIGl0IGZyb20gdGhlIERPTVxuICAgIFBvcG92ZXIucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pc0hpZGRlbikge1xuICAgICAgICAgICAgdGhpcy5lbC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgdGhpcy5pc0hpZGRlbiA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIoJ2hpZGUnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gQ3JlYXRlcyBgdGhpcy5lbGAgYW5kIHJlbmRlcnMgY29udGVudCBpbnNpZGUgb2YgaXRcbiAgICBQb3BvdmVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICB2YXIgZWwgPSB0aGlzLmVsID0gY3JlYXRlRWxlbWVudCgnZGl2Jywge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnZmMtcG9wb3ZlciAnICsgKG9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKSxcbiAgICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgdG9wOiAnMCcsXG4gICAgICAgICAgICAgICAgbGVmdDogJzAnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuY29udGVudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgb3B0aW9ucy5jb250ZW50KGVsKTtcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zLnBhcmVudEVsLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgLy8gd2hlbiBhIGNsaWNrIGhhcHBlbnMgb24gYW55dGhpbmcgaW5zaWRlIHdpdGggYSAnZmMtY2xvc2UnIGNsYXNzTmFtZSwgaGlkZSB0aGUgcG9wb3ZlclxuICAgICAgICBsaXN0ZW5CeVNlbGVjdG9yKGVsLCAnY2xpY2snLCAnLmZjLWNsb3NlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5oaWRlKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob3B0aW9ucy5hdXRvSGlkZSkge1xuICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5kb2N1bWVudE1vdXNlZG93bik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIEhpZGVzIGFuZCB1bnJlZ2lzdGVycyBhbnkgaGFuZGxlcnNcbiAgICBQb3BvdmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgaWYgKHRoaXMuZWwpIHtcbiAgICAgICAgICAgIHJlbW92ZUVsZW1lbnQodGhpcy5lbCk7XG4gICAgICAgICAgICB0aGlzLmVsID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmRvY3VtZW50TW91c2Vkb3duKTtcbiAgICB9O1xuICAgIC8vIFBvc2l0aW9ucyB0aGUgcG9wb3ZlciBvcHRpbWFsbHksIHVzaW5nIHRoZSB0b3AvbGVmdC9yaWdodCBvcHRpb25zXG4gICAgUG9wb3Zlci5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICB2YXIgZWwgPSB0aGlzLmVsO1xuICAgICAgICB2YXIgZWxEaW1zID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IC8vIG9ubHkgdXNlZCBmb3Igd2lkdGgsaGVpZ2h0XG4gICAgICAgIHZhciBvcmlnaW4gPSBjb21wdXRlUmVjdChlbC5vZmZzZXRQYXJlbnQpO1xuICAgICAgICB2YXIgY2xpcHBpbmdSZWN0ID0gY29tcHV0ZUNsaXBwaW5nUmVjdChvcHRpb25zLnBhcmVudEVsKTtcbiAgICAgICAgdmFyIHRvcDsgLy8gdGhlIFwicG9zaXRpb25cIiAobm90IFwib2Zmc2V0XCIpIHZhbHVlcyBmb3IgdGhlIHBvcG92ZXJcbiAgICAgICAgdmFyIGxlZnQ7IC8vXG4gICAgICAgIC8vIGNvbXB1dGUgdG9wIGFuZCBsZWZ0XG4gICAgICAgIHRvcCA9IG9wdGlvbnMudG9wIHx8IDA7XG4gICAgICAgIGlmIChvcHRpb25zLmxlZnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbGVmdCA9IG9wdGlvbnMubGVmdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLnJpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGxlZnQgPSBvcHRpb25zLnJpZ2h0IC0gZWxEaW1zLndpZHRoOyAvLyBkZXJpdmUgdGhlIGxlZnQgdmFsdWUgZnJvbSB0aGUgcmlnaHQgdmFsdWVcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxlZnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnN0cmFpbiB0byB0aGUgdmlldyBwb3J0LiBpZiBjb25zdHJhaW5lZCBieSB0d28gZWRnZXMsIGdpdmUgcHJlY2VkZW5jZSB0byB0b3AvbGVmdFxuICAgICAgICB0b3AgPSBNYXRoLm1pbih0b3AsIGNsaXBwaW5nUmVjdC5ib3R0b20gLSBlbERpbXMuaGVpZ2h0IC0gdGhpcy5tYXJnaW4pO1xuICAgICAgICB0b3AgPSBNYXRoLm1heCh0b3AsIGNsaXBwaW5nUmVjdC50b3AgKyB0aGlzLm1hcmdpbik7XG4gICAgICAgIGxlZnQgPSBNYXRoLm1pbihsZWZ0LCBjbGlwcGluZ1JlY3QucmlnaHQgLSBlbERpbXMud2lkdGggLSB0aGlzLm1hcmdpbik7XG4gICAgICAgIGxlZnQgPSBNYXRoLm1heChsZWZ0LCBjbGlwcGluZ1JlY3QubGVmdCArIHRoaXMubWFyZ2luKTtcbiAgICAgICAgYXBwbHlTdHlsZShlbCwge1xuICAgICAgICAgICAgdG9wOiB0b3AgLSBvcmlnaW4udG9wLFxuICAgICAgICAgICAgbGVmdDogbGVmdCAtIG9yaWdpbi5sZWZ0XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gVHJpZ2dlcnMgYSBjYWxsYmFjay4gQ2FsbHMgYSBmdW5jdGlvbiBpbiB0aGUgb3B0aW9uIGhhc2ggb2YgdGhlIHNhbWUgbmFtZS5cbiAgICAvLyBBcmd1bWVudHMgYmV5b25kIHRoZSBmaXJzdCBgbmFtZWAgYXJlIGZvcndhcmRlZCBvbi5cbiAgICAvLyBUT0RPOiBiZXR0ZXIgY29kZSByZXVzZSBmb3IgdGhpcy4gUmVwZWF0IGNvZGVcbiAgICAvLyBjYW4ga2lsbCB0aGlzPz8/XG4gICAgUG9wb3Zlci5wcm90b3R5cGUudHJpZ2dlciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnNbbmFtZV0pIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9uc1tuYW1lXS5hcHBseSh0aGlzLCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFBvcG92ZXI7XG59KCkpO1xuXG4vKiBFdmVudC1yZW5kZXJpbmcgbWV0aG9kcyBmb3IgdGhlIERheUdyaWQgY2xhc3Ncbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLy8gXCJTaW1wbGVcIiBpcyBiYWQgYSBuYW1lLiBoYXMgbm90aGluZyB0byBkbyB3aXRoIFNpbXBsZURheUdyaWRcbnZhciBTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gQnVpbGRzIHRoZSBIVE1MIHRvIGJlIHVzZWQgZm9yIHRoZSBkZWZhdWx0IGVsZW1lbnQgZm9yIGFuIGluZGl2aWR1YWwgc2VnbWVudFxuICAgIFNpbXBsZURheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdIdG1sID0gZnVuY3Rpb24gKHNlZywgbWlycm9ySW5mbykge1xuICAgICAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBzZWcuZXZlbnRSYW5nZTtcbiAgICAgICAgdmFyIGV2ZW50RGVmID0gZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgIHZhciBldmVudFVpID0gZXZlbnRSYW5nZS51aTtcbiAgICAgICAgdmFyIGFsbERheSA9IGV2ZW50RGVmLmFsbERheTtcbiAgICAgICAgdmFyIGlzRHJhZ2dhYmxlID0gY29tcHV0ZUV2ZW50RHJhZ2dhYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKTtcbiAgICAgICAgdmFyIGlzUmVzaXphYmxlRnJvbVN0YXJ0ID0gYWxsRGF5ICYmIHNlZy5pc1N0YXJ0ICYmIGNvbXB1dGVFdmVudFN0YXJ0UmVzaXphYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKTtcbiAgICAgICAgdmFyIGlzUmVzaXphYmxlRnJvbUVuZCA9IGFsbERheSAmJiBzZWcuaXNFbmQgJiYgY29tcHV0ZUV2ZW50RW5kUmVzaXphYmxlKGNvbnRleHQsIGV2ZW50RGVmLCBldmVudFVpKTtcbiAgICAgICAgdmFyIGNsYXNzZXMgPSB0aGlzLmdldFNlZ0NsYXNzZXMoc2VnLCBpc0RyYWdnYWJsZSwgaXNSZXNpemFibGVGcm9tU3RhcnQgfHwgaXNSZXNpemFibGVGcm9tRW5kLCBtaXJyb3JJbmZvKTtcbiAgICAgICAgdmFyIHNraW5Dc3MgPSBjc3NUb1N0cih0aGlzLmdldFNraW5Dc3MoZXZlbnRVaSkpO1xuICAgICAgICB2YXIgdGltZUh0bWwgPSAnJztcbiAgICAgICAgdmFyIHRpbWVUZXh0O1xuICAgICAgICB2YXIgdGl0bGVIdG1sO1xuICAgICAgICBjbGFzc2VzLnVuc2hpZnQoJ2ZjLWRheS1ncmlkLWV2ZW50JywgJ2ZjLWgtZXZlbnQnKTtcbiAgICAgICAgLy8gT25seSBkaXNwbGF5IGEgdGltZWQgZXZlbnRzIHRpbWUgaWYgaXQgaXMgdGhlIHN0YXJ0aW5nIHNlZ21lbnRcbiAgICAgICAgaWYgKHNlZy5pc1N0YXJ0KSB7XG4gICAgICAgICAgICB0aW1lVGV4dCA9IHRoaXMuZ2V0VGltZVRleHQoZXZlbnRSYW5nZSk7XG4gICAgICAgICAgICBpZiAodGltZVRleHQpIHtcbiAgICAgICAgICAgICAgICB0aW1lSHRtbCA9ICc8c3BhbiBjbGFzcz1cImZjLXRpbWVcIj4nICsgaHRtbEVzY2FwZSh0aW1lVGV4dCkgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGl0bGVIdG1sID1cbiAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cImZjLXRpdGxlXCI+JyArXG4gICAgICAgICAgICAgICAgKGh0bWxFc2NhcGUoZXZlbnREZWYudGl0bGUgfHwgJycpIHx8ICcmbmJzcDsnKSArIC8vIHdlIGFsd2F5cyB3YW50IG9uZSBsaW5lIG9mIGhlaWdodFxuICAgICAgICAgICAgICAgICc8L3NwYW4+JztcbiAgICAgICAgcmV0dXJuICc8YSBjbGFzcz1cIicgKyBjbGFzc2VzLmpvaW4oJyAnKSArICdcIicgK1xuICAgICAgICAgICAgKGV2ZW50RGVmLnVybCA/XG4gICAgICAgICAgICAgICAgJyBocmVmPVwiJyArIGh0bWxFc2NhcGUoZXZlbnREZWYudXJsKSArICdcIicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAoc2tpbkNzcyA/XG4gICAgICAgICAgICAgICAgJyBzdHlsZT1cIicgKyBza2luQ3NzICsgJ1wiJyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgICc+JyArXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLWNvbnRlbnRcIj4nICtcbiAgICAgICAgICAgIChjb250ZXh0Lm9wdGlvbnMuZGlyID09PSAncnRsJyA/XG4gICAgICAgICAgICAgICAgdGl0bGVIdG1sICsgJyAnICsgdGltZUh0bWwgOiAvLyBwdXQgYSBuYXR1cmFsIHNwYWNlIGluIGJldHdlZW5cbiAgICAgICAgICAgICAgICB0aW1lSHRtbCArICcgJyArIHRpdGxlSHRtbCAvL1xuICAgICAgICAgICAgKSArXG4gICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAoaXNSZXNpemFibGVGcm9tU3RhcnQgP1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtcmVzaXplciBmYy1zdGFydC1yZXNpemVyXCI+PC9kaXY+JyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgIChpc1Jlc2l6YWJsZUZyb21FbmQgP1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmMtcmVzaXplciBmYy1lbmQtcmVzaXplclwiPjwvZGl2PicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAnPC9hPic7XG4gICAgfTtcbiAgICAvLyBDb21wdXRlcyBhIGRlZmF1bHQgZXZlbnQgdGltZSBmb3JtYXR0aW5nIHN0cmluZyBpZiBgZXZlbnRUaW1lRm9ybWF0YCBpcyBub3QgZXhwbGljaXRseSBkZWZpbmVkXG4gICAgU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIucHJvdG90eXBlLmNvbXB1dGVFdmVudFRpbWVGb3JtYXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBob3VyOiAnbnVtZXJpYycsXG4gICAgICAgICAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICAgICAgICAgIG9taXRaZXJvTWludXRlOiB0cnVlLFxuICAgICAgICAgICAgbWVyaWRpZW06ICduYXJyb3cnXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuY29tcHV0ZURpc3BsYXlFdmVudEVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBUT0RPOiBzb21laG93IGNvbnNpZGVyIHRoZSBvcmlnaW5hdGluZyBEYXlHcmlkJ3MgY29sdW1uIGNvdW50XG4gICAgfTtcbiAgICByZXR1cm4gU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXI7XG59KEZnRXZlbnRSZW5kZXJlcikpO1xuXG4vKiBFdmVudC1yZW5kZXJpbmcgbWV0aG9kcyBmb3IgdGhlIERheUdyaWQgY2xhc3Ncbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xudmFyIERheUdyaWRFdmVudFJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkRXZlbnRSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkRXZlbnRSZW5kZXJlcihkYXlHcmlkKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmRheUdyaWQgPSBkYXlHcmlkO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIC8vIFJlbmRlcnMgdGhlIGdpdmVuIGZvcmVncm91bmQgZXZlbnQgc2VnbWVudHMgb250byB0aGUgZ3JpZFxuICAgIERheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5hdHRhY2hTZWdzID0gZnVuY3Rpb24gKHNlZ3MsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSB0aGlzLnJvd1N0cnVjdHMgPSB0aGlzLnJlbmRlclNlZ1Jvd3Moc2Vncyk7XG4gICAgICAgIC8vIGFwcGVuZCB0byBlYWNoIHJvdydzIGNvbnRlbnQgc2tlbGV0b25cbiAgICAgICAgdGhpcy5kYXlHcmlkLnJvd0Vscy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlLCBpKSB7XG4gICAgICAgICAgICByb3dOb2RlLnF1ZXJ5U2VsZWN0b3IoJy5mYy1jb250ZW50LXNrZWxldG9uID4gdGFibGUnKS5hcHBlbmRDaGlsZChyb3dTdHJ1Y3RzW2ldLnRib2R5RWwpO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gcmVtb3ZlcyB0aGUgXCJtb3JlLi5cIiBldmVudHMgcG9wb3ZlclxuICAgICAgICBpZiAoIW1pcnJvckluZm8pIHtcbiAgICAgICAgICAgIHRoaXMuZGF5R3JpZC5yZW1vdmVTZWdQb3BvdmVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFVucmVuZGVycyBhbGwgY3VycmVudGx5IHJlbmRlcmVkIGZvcmVncm91bmQgZXZlbnQgc2VnbWVudHNcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZGV0YWNoU2VncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSB0aGlzLnJvd1N0cnVjdHMgfHwgW107XG4gICAgICAgIHZhciByb3dTdHJ1Y3Q7XG4gICAgICAgIHdoaWxlICgocm93U3RydWN0ID0gcm93U3RydWN0cy5wb3AoKSkpIHtcbiAgICAgICAgICAgIHJlbW92ZUVsZW1lbnQocm93U3RydWN0LnRib2R5RWwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucm93U3RydWN0cyA9IG51bGw7XG4gICAgfTtcbiAgICAvLyBVc2VzIHRoZSBnaXZlbiBldmVudHMgYXJyYXkgdG8gZ2VuZXJhdGUgPHRib2R5PiBlbGVtZW50cyB0aGF0IHNob3VsZCBiZSBhcHBlbmRlZCB0byBlYWNoIHJvdydzIGNvbnRlbnQgc2tlbGV0b24uXG4gICAgLy8gUmV0dXJucyBhbiBhcnJheSBvZiByb3dTdHJ1Y3Qgb2JqZWN0cyAoc2VlIHRoZSBib3R0b20gb2YgYHJlbmRlclNlZ1Jvd2ApLlxuICAgIC8vIFBSRUNPTkRJVElPTjogZWFjaCBzZWdtZW50IHNob3VkIGFscmVhZHkgaGF2ZSBhIHJlbmRlcmVkIGFuZCBhc3NpZ25lZCBgLmVsYFxuICAgIERheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJTZWdSb3dzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdHMgPSBbXTtcbiAgICAgICAgdmFyIHNlZ1Jvd3M7XG4gICAgICAgIHZhciByb3c7XG4gICAgICAgIHNlZ1Jvd3MgPSB0aGlzLmdyb3VwU2VnUm93cyhzZWdzKTsgLy8gZ3JvdXAgaW50byBuZXN0ZWQgYXJyYXlzXG4gICAgICAgIC8vIGl0ZXJhdGUgZWFjaCByb3cgb2Ygc2VnbWVudCBncm91cGluZ3NcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCBzZWdSb3dzLmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgIHJvd1N0cnVjdHMucHVzaCh0aGlzLnJlbmRlclNlZ1Jvdyhyb3csIHNlZ1Jvd3Nbcm93XSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dTdHJ1Y3RzO1xuICAgIH07XG4gICAgLy8gR2l2ZW4gYSByb3cgIyBhbmQgYW4gYXJyYXkgb2Ygc2VnbWVudHMgYWxsIGluIHRoZSBzYW1lIHJvdywgcmVuZGVyIGEgPHRib2R5PiBlbGVtZW50LCBhIHNrZWxldG9uIHRoYXQgY29udGFpbnNcbiAgICAvLyB0aGUgc2VnbWVudHMuIFJldHVybnMgb2JqZWN0IHdpdGggYSBidW5jaCBvZiBpbnRlcm5hbCBkYXRhIGFib3V0IGhvdyB0aGUgcmVuZGVyIHdhcyBjYWxjdWxhdGVkLlxuICAgIC8vIE5PVEU6IG1vZGlmaWVzIHJvd1NlZ3NcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VnUm93ID0gZnVuY3Rpb24gKHJvdywgcm93U2Vncykge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgY29sQ250ID0gZGF5R3JpZC5jb2xDbnQ7XG4gICAgICAgIHZhciBzZWdMZXZlbHMgPSB0aGlzLmJ1aWxkU2VnTGV2ZWxzKHJvd1NlZ3MpOyAvLyBncm91cCBpbnRvIHN1Yi1hcnJheXMgb2YgbGV2ZWxzXG4gICAgICAgIHZhciBsZXZlbENudCA9IE1hdGgubWF4KDEsIHNlZ0xldmVscy5sZW5ndGgpOyAvLyBlbnN1cmUgYXQgbGVhc3Qgb25lIGxldmVsXG4gICAgICAgIHZhciB0Ym9keSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3Rib2R5Jyk7XG4gICAgICAgIHZhciBzZWdNYXRyaXggPSBbXTsgLy8gbG9va3VwIGZvciB3aGljaCBzZWdtZW50cyBhcmUgcmVuZGVyZWQgaW50byB3aGljaCBsZXZlbCtjb2wgY2VsbHNcbiAgICAgICAgdmFyIGNlbGxNYXRyaXggPSBbXTsgLy8gbG9va3VwIGZvciBhbGwgPHRkPiBlbGVtZW50cyBvZiB0aGUgbGV2ZWwrY29sIG1hdHJpeFxuICAgICAgICB2YXIgbG9uZUNlbGxNYXRyaXggPSBbXTsgLy8gbG9va3VwIGZvciA8dGQ+IGVsZW1lbnRzIHRoYXQgb25seSB0YWtlIHVwIGEgc2luZ2xlIGNvbHVtblxuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGxldmVsU2VncztcbiAgICAgICAgdmFyIGNvbDtcbiAgICAgICAgdmFyIHRyO1xuICAgICAgICB2YXIgajtcbiAgICAgICAgdmFyIHNlZztcbiAgICAgICAgdmFyIHRkO1xuICAgICAgICAvLyBwb3B1bGF0ZXMgZW1wdHkgY2VsbHMgZnJvbSB0aGUgY3VycmVudCBjb2x1bW4gKGBjb2xgKSB0byBgZW5kQ29sYFxuICAgICAgICBmdW5jdGlvbiBlbXB0eUNlbGxzVW50aWwoZW5kQ29sKSB7XG4gICAgICAgICAgICB3aGlsZSAoY29sIDwgZW5kQ29sKSB7XG4gICAgICAgICAgICAgICAgLy8gdHJ5IHRvIGdyYWIgYSBjZWxsIGZyb20gdGhlIGxldmVsIGFib3ZlIGFuZCBleHRlbmQgaXRzIHJvd3NwYW4uIG90aGVyd2lzZSwgY3JlYXRlIGEgZnJlc2ggY2VsbFxuICAgICAgICAgICAgICAgIHRkID0gKGxvbmVDZWxsTWF0cml4W2kgLSAxXSB8fCBbXSlbY29sXTtcbiAgICAgICAgICAgICAgICBpZiAodGQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGQucm93U3BhbiA9ICh0ZC5yb3dTcGFuIHx8IDEpICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGQnKTtcbiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjZWxsTWF0cml4W2ldW2NvbF0gPSB0ZDtcbiAgICAgICAgICAgICAgICBsb25lQ2VsbE1hdHJpeFtpXVtjb2xdID0gdGQ7XG4gICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxldmVsQ250OyBpKyspIHsgLy8gaXRlcmF0ZSB0aHJvdWdoIGFsbCBsZXZlbHNcbiAgICAgICAgICAgIGxldmVsU2VncyA9IHNlZ0xldmVsc1tpXTtcbiAgICAgICAgICAgIGNvbCA9IDA7XG4gICAgICAgICAgICB0ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RyJyk7XG4gICAgICAgICAgICBzZWdNYXRyaXgucHVzaChbXSk7XG4gICAgICAgICAgICBjZWxsTWF0cml4LnB1c2goW10pO1xuICAgICAgICAgICAgbG9uZUNlbGxNYXRyaXgucHVzaChbXSk7XG4gICAgICAgICAgICAvLyBsZXZlbENudCBtaWdodCBiZSAxIGV2ZW4gdGhvdWdoIHRoZXJlIGFyZSBubyBhY3R1YWwgbGV2ZWxzLiBwcm90ZWN0IGFnYWluc3QgdGhpcy5cbiAgICAgICAgICAgIC8vIHRoaXMgc2luZ2xlIGVtcHR5IHJvdyBpcyB1c2VmdWwgZm9yIHN0eWxpbmcuXG4gICAgICAgICAgICBpZiAobGV2ZWxTZWdzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGxldmVsU2Vncy5sZW5ndGg7IGorKykgeyAvLyBpdGVyYXRlIHRocm91Z2ggc2VnbWVudHMgaW4gbGV2ZWxcbiAgICAgICAgICAgICAgICAgICAgc2VnID0gbGV2ZWxTZWdzW2pdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcubGFzdENvbCkgOiBzZWcuZmlyc3RDb2w7XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcuZmlyc3RDb2wpIDogc2VnLmxhc3RDb2w7XG4gICAgICAgICAgICAgICAgICAgIGVtcHR5Q2VsbHNVbnRpbChsZWZ0Q29sKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIGEgY29udGFpbmVyIHRoYXQgb2NjdXBpZXMgb3IgbW9yZSBjb2x1bW5zLiBhcHBlbmQgdGhlIGV2ZW50IGVsZW1lbnQuXG4gICAgICAgICAgICAgICAgICAgIHRkID0gY3JlYXRlRWxlbWVudCgndGQnLCB7IGNsYXNzTmFtZTogJ2ZjLWV2ZW50LWNvbnRhaW5lcicgfSwgc2VnLmVsKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRDb2wgIT09IHJpZ2h0Q29sKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZC5jb2xTcGFuID0gcmlnaHRDb2wgLSBsZWZ0Q29sICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHsgLy8gYSBzaW5nbGUtY29sdW1uIHNlZ21lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvbmVDZWxsTWF0cml4W2ldW2NvbF0gPSB0ZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY29sIDw9IHJpZ2h0Q29sKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjZWxsTWF0cml4W2ldW2NvbF0gPSB0ZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlZ01hdHJpeFtpXVtjb2xdID0gc2VnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVtcHR5Q2VsbHNVbnRpbChjb2xDbnQpOyAvLyBmaW5pc2ggb2ZmIHRoZSByb3dcbiAgICAgICAgICAgIHZhciBpbnRyb0h0bWwgPSBkYXlHcmlkLnJlbmRlclByb3BzLnJlbmRlckludHJvSHRtbCgpO1xuICAgICAgICAgICAgaWYgKGludHJvSHRtbCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1J0bCkge1xuICAgICAgICAgICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQodHIsIGludHJvSHRtbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwcmVwZW5kVG9FbGVtZW50KHRyLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRib2R5LmFwcGVuZENoaWxkKHRyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICB0Ym9keUVsOiB0Ym9keSxcbiAgICAgICAgICAgIGNlbGxNYXRyaXg6IGNlbGxNYXRyaXgsXG4gICAgICAgICAgICBzZWdNYXRyaXg6IHNlZ01hdHJpeCxcbiAgICAgICAgICAgIHNlZ0xldmVsczogc2VnTGV2ZWxzLFxuICAgICAgICAgICAgc2Vnczogcm93U2Vnc1xuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gU3RhY2tzIGEgZmxhdCBhcnJheSBvZiBzZWdtZW50cywgd2hpY2ggYXJlIGFsbCBhc3N1bWVkIHRvIGJlIGluIHRoZSBzYW1lIHJvdywgaW50byBzdWJhcnJheXMgb2YgdmVydGljYWwgbGV2ZWxzLlxuICAgIC8vIE5PVEU6IG1vZGlmaWVzIHNlZ3NcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuYnVpbGRTZWdMZXZlbHMgPSBmdW5jdGlvbiAoc2Vncykge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciBjb2xDbnQgPSB0aGlzLmRheUdyaWQuY29sQ250O1xuICAgICAgICB2YXIgbGV2ZWxzID0gW107XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgc2VnO1xuICAgICAgICB2YXIgajtcbiAgICAgICAgLy8gR2l2ZSBwcmVmZXJlbmNlIHRvIGVsZW1lbnRzIHdpdGggY2VydGFpbiBjcml0ZXJpYSwgc28gdGhleSBoYXZlXG4gICAgICAgIC8vIGEgY2hhbmNlIHRvIGJlIGNsb3NlciB0byB0aGUgdG9wLlxuICAgICAgICBzZWdzID0gdGhpcy5zb3J0RXZlbnRTZWdzKHNlZ3MpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc2VnID0gc2Vnc1tpXTtcbiAgICAgICAgICAgIC8vIGxvb3AgdGhyb3VnaCBsZXZlbHMsIHN0YXJ0aW5nIHdpdGggdGhlIHRvcG1vc3QsIHVudGlsIHRoZSBzZWdtZW50IGRvZXNuJ3QgY29sbGlkZSB3aXRoIG90aGVyIHNlZ21lbnRzXG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbGV2ZWxzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0RheVNlZ0NvbGxpc2lvbihzZWcsIGxldmVsc1tqXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYGpgIG5vdyBob2xkcyB0aGUgZGVzaXJlZCBzdWJyb3cgaW5kZXhcbiAgICAgICAgICAgIHNlZy5sZXZlbCA9IGo7XG4gICAgICAgICAgICBzZWcubGVmdENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcubGFzdENvbCkgOiBzZWcuZmlyc3RDb2w7IC8vIGZvciBzb3J0aW5nIG9ubHlcbiAgICAgICAgICAgIHNlZy5yaWdodENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcuZmlyc3RDb2wpIDogc2VnLmxhc3RDb2wgLy8gZm9yIHNvcnRpbmcgb25seVxuICAgICAgICAgICAgO1xuICAgICAgICAgICAgKGxldmVsc1tqXSB8fCAobGV2ZWxzW2pdID0gW10pKS5wdXNoKHNlZyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb3JkZXIgc2VnbWVudHMgbGVmdC10by1yaWdodC4gdmVyeSBpbXBvcnRhbnQgaWYgY2FsZW5kYXIgaXMgUlRMXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZXZlbHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGxldmVsc1tqXS5zb3J0KGNvbXBhcmVEYXlTZWdDb2xzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGV2ZWxzO1xuICAgIH07XG4gICAgLy8gR2l2ZW4gYSBmbGF0IGFycmF5IG9mIHNlZ21lbnRzLCByZXR1cm4gYW4gYXJyYXkgb2Ygc3ViLWFycmF5cywgZ3JvdXBlZCBieSBlYWNoIHNlZ21lbnQncyByb3dcbiAgICBEYXlHcmlkRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZ3JvdXBTZWdSb3dzID0gZnVuY3Rpb24gKHNlZ3MpIHtcbiAgICAgICAgdmFyIHNlZ1Jvd3MgPSBbXTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmRheUdyaWQucm93Q250OyBpKyspIHtcbiAgICAgICAgICAgIHNlZ1Jvd3MucHVzaChbXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNlZ1Jvd3Nbc2Vnc1tpXS5yb3ddLnB1c2goc2Vnc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ1Jvd3M7XG4gICAgfTtcbiAgICAvLyBDb21wdXRlcyBhIGRlZmF1bHQgYGRpc3BsYXlFdmVudEVuZGAgdmFsdWUgaWYgb25lIGlzIG5vdCBleHBsaWNsdHkgZGVmaW5lZFxuICAgIERheUdyaWRFdmVudFJlbmRlcmVyLnByb3RvdHlwZS5jb21wdXRlRGlzcGxheUV2ZW50RW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlHcmlkLmNvbENudCA9PT0gMTsgLy8gd2UnbGwgbGlrZWx5IGhhdmUgc3BhY2UgaWYgdGhlcmUncyBvbmx5IG9uZSBkYXlcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkRXZlbnRSZW5kZXJlcjtcbn0oU2ltcGxlRGF5R3JpZEV2ZW50UmVuZGVyZXIpKTtcbi8vIENvbXB1dGVzIHdoZXRoZXIgdHdvIHNlZ21lbnRzJyBjb2x1bW5zIGNvbGxpZGUuIFRoZXkgYXJlIGFzc3VtZWQgdG8gYmUgaW4gdGhlIHNhbWUgcm93LlxuZnVuY3Rpb24gaXNEYXlTZWdDb2xsaXNpb24oc2VnLCBvdGhlclNlZ3MpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgb3RoZXJTZWc7XG4gICAgZm9yIChpID0gMDsgaSA8IG90aGVyU2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvdGhlclNlZyA9IG90aGVyU2Vnc1tpXTtcbiAgICAgICAgaWYgKG90aGVyU2VnLmZpcnN0Q29sIDw9IHNlZy5sYXN0Q29sICYmXG4gICAgICAgICAgICBvdGhlclNlZy5sYXN0Q29sID49IHNlZy5maXJzdENvbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuLy8gQSBjbXAgZnVuY3Rpb24gZm9yIGRldGVybWluaW5nIHRoZSBsZWZ0bW9zdCBldmVudFxuZnVuY3Rpb24gY29tcGFyZURheVNlZ0NvbHMoYSwgYikge1xuICAgIHJldHVybiBhLmxlZnRDb2wgLSBiLmxlZnRDb2w7XG59XG5cbnZhciBEYXlHcmlkTWlycm9yUmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUdyaWRNaXJyb3JSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkTWlycm9yUmVuZGVyZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgRGF5R3JpZE1pcnJvclJlbmRlcmVyLnByb3RvdHlwZS5hdHRhY2hTZWdzID0gZnVuY3Rpb24gKHNlZ3MsIG1pcnJvckluZm8pIHtcbiAgICAgICAgdmFyIHNvdXJjZVNlZyA9IG1pcnJvckluZm8uc291cmNlU2VnO1xuICAgICAgICB2YXIgcm93U3RydWN0cyA9IHRoaXMucm93U3RydWN0cyA9IHRoaXMucmVuZGVyU2VnUm93cyhzZWdzKTtcbiAgICAgICAgLy8gaW5qZWN0IGVhY2ggbmV3IGV2ZW50IHNrZWxldG9uIGludG8gZWFjaCBhc3NvY2lhdGVkIHJvd1xuICAgICAgICB0aGlzLmRheUdyaWQucm93RWxzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUsIHJvdykge1xuICAgICAgICAgICAgdmFyIHNrZWxldG9uRWwgPSBodG1sVG9FbGVtZW50KCc8ZGl2IGNsYXNzPVwiZmMtbWlycm9yLXNrZWxldG9uXCI+PHRhYmxlPjwvdGFibGU+PC9kaXY+Jyk7IC8vIHdpbGwgYmUgYWJzb2x1dGVseSBwb3NpdGlvbmVkXG4gICAgICAgICAgICB2YXIgc2tlbGV0b25Ub3BFbDtcbiAgICAgICAgICAgIHZhciBza2VsZXRvblRvcDtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIGFuIG9yaWdpbmFsIHNlZ21lbnQsIG1hdGNoIHRoZSB0b3AgcG9zaXRpb24uIE90aGVyd2lzZSwgcHV0IGl0IGF0IHRoZSByb3cncyB0b3AgbGV2ZWxcbiAgICAgICAgICAgIGlmIChzb3VyY2VTZWcgJiYgc291cmNlU2VnLnJvdyA9PT0gcm93KSB7XG4gICAgICAgICAgICAgICAgc2tlbGV0b25Ub3BFbCA9IHNvdXJjZVNlZy5lbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHNrZWxldG9uVG9wRWwgPSByb3dOb2RlLnF1ZXJ5U2VsZWN0b3IoJy5mYy1jb250ZW50LXNrZWxldG9uIHRib2R5Jyk7XG4gICAgICAgICAgICAgICAgaWYgKCFza2VsZXRvblRvcEVsKSB7IC8vIHdoZW4gbm8gZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgIHNrZWxldG9uVG9wRWwgPSByb3dOb2RlLnF1ZXJ5U2VsZWN0b3IoJy5mYy1jb250ZW50LXNrZWxldG9uIHRhYmxlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2tlbGV0b25Ub3AgPSBza2VsZXRvblRvcEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtXG4gICAgICAgICAgICAgICAgcm93Tm9kZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3A7IC8vIHRoZSBvZmZzZXRQYXJlbnQgb3JpZ2luXG4gICAgICAgICAgICBza2VsZXRvbkVsLnN0eWxlLnRvcCA9IHNrZWxldG9uVG9wICsgJ3B4JztcbiAgICAgICAgICAgIHNrZWxldG9uRWwucXVlcnlTZWxlY3RvcigndGFibGUnKS5hcHBlbmRDaGlsZChyb3dTdHJ1Y3RzW3Jvd10udGJvZHlFbCk7XG4gICAgICAgICAgICByb3dOb2RlLmFwcGVuZENoaWxkKHNrZWxldG9uRWwpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkTWlycm9yUmVuZGVyZXI7XG59KERheUdyaWRFdmVudFJlbmRlcmVyKSk7XG5cbnZhciBFTVBUWV9DRUxMX0hUTUwgPSAnPHRkIHN0eWxlPVwicG9pbnRlci1ldmVudHM6bm9uZVwiPjwvdGQ+JztcbnZhciBEYXlHcmlkRmlsbFJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkRmlsbFJlbmRlcmVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUdyaWRGaWxsUmVuZGVyZXIoZGF5R3JpZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5maWxsU2VnVGFnID0gJ3RkJzsgLy8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgdGFnIG5hbWVcbiAgICAgICAgX3RoaXMuZGF5R3JpZCA9IGRheUdyaWQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF5R3JpZEZpbGxSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyU2VncyA9IGZ1bmN0aW9uICh0eXBlLCBjb250ZXh0LCBzZWdzKSB7XG4gICAgICAgIC8vIGRvbid0IHJlbmRlciB0aW1lZCBiYWNrZ3JvdW5kIGV2ZW50c1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2JnRXZlbnQnKSB7XG4gICAgICAgICAgICBzZWdzID0gc2Vncy5maWx0ZXIoZnVuY3Rpb24gKHNlZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWcuZXZlbnRSYW5nZS5kZWYuYWxsRGF5O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZW5kZXJTZWdzLmNhbGwodGhpcywgdHlwZSwgY29udGV4dCwgc2Vncyk7XG4gICAgfTtcbiAgICBEYXlHcmlkRmlsbFJlbmRlcmVyLnByb3RvdHlwZS5hdHRhY2hTZWdzID0gZnVuY3Rpb24gKHR5cGUsIHNlZ3MpIHtcbiAgICAgICAgdmFyIGVscyA9IFtdO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHNlZztcbiAgICAgICAgdmFyIHNrZWxldG9uRWw7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzZWcgPSBzZWdzW2ldO1xuICAgICAgICAgICAgc2tlbGV0b25FbCA9IHRoaXMucmVuZGVyRmlsbFJvdyh0eXBlLCBzZWcpO1xuICAgICAgICAgICAgdGhpcy5kYXlHcmlkLnJvd0Vsc1tzZWcucm93XS5hcHBlbmRDaGlsZChza2VsZXRvbkVsKTtcbiAgICAgICAgICAgIGVscy5wdXNoKHNrZWxldG9uRWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbHM7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgbmVlZGVkIGZvciBvbmUgcm93IG9mIGEgZmlsbC4gUmVxdWlyZXMgdGhlIHNlZydzIGVsIHRvIGJlIHJlbmRlcmVkLlxuICAgIERheUdyaWRGaWxsUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlckZpbGxSb3cgPSBmdW5jdGlvbiAodHlwZSwgc2VnKSB7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciBjb2xDbnQgPSBkYXlHcmlkLmNvbENudDtcbiAgICAgICAgdmFyIGxlZnRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmxhc3RDb2wpIDogc2VnLmZpcnN0Q29sO1xuICAgICAgICB2YXIgcmlnaHRDb2wgPSBpc1J0bCA/IChjb2xDbnQgLSAxIC0gc2VnLmZpcnN0Q29sKSA6IHNlZy5sYXN0Q29sO1xuICAgICAgICB2YXIgc3RhcnRDb2wgPSBsZWZ0Q29sO1xuICAgICAgICB2YXIgZW5kQ29sID0gcmlnaHRDb2wgKyAxO1xuICAgICAgICB2YXIgY2xhc3NOYW1lO1xuICAgICAgICB2YXIgc2tlbGV0b25FbDtcbiAgICAgICAgdmFyIHRyRWw7XG4gICAgICAgIGlmICh0eXBlID09PSAnYnVzaW5lc3NIb3VycycpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSA9ICdiZ2V2ZW50JztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSA9IHR5cGUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBza2VsZXRvbkVsID0gaHRtbFRvRWxlbWVudCgnPGRpdiBjbGFzcz1cImZjLScgKyBjbGFzc05hbWUgKyAnLXNrZWxldG9uXCI+JyArXG4gICAgICAgICAgICAnPHRhYmxlPjx0cj48L3RyPjwvdGFibGU+JyArXG4gICAgICAgICAgICAnPC9kaXY+Jyk7XG4gICAgICAgIHRyRWwgPSBza2VsZXRvbkVsLmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0cicpWzBdO1xuICAgICAgICBpZiAoc3RhcnRDb2wgPiAwKSB7XG4gICAgICAgICAgICBhcHBlbmRUb0VsZW1lbnQodHJFbCwgXG4gICAgICAgICAgICAvLyB3aWxsIGNyZWF0ZSAoc3RhcnRDb2wgKyAxKSB0ZCdzXG4gICAgICAgICAgICBuZXcgQXJyYXkoc3RhcnRDb2wgKyAxKS5qb2luKEVNUFRZX0NFTExfSFRNTCkpO1xuICAgICAgICB9XG4gICAgICAgIHNlZy5lbC5jb2xTcGFuID0gZW5kQ29sIC0gc3RhcnRDb2w7XG4gICAgICAgIHRyRWwuYXBwZW5kQ2hpbGQoc2VnLmVsKTtcbiAgICAgICAgaWYgKGVuZENvbCA8IGNvbENudCkge1xuICAgICAgICAgICAgYXBwZW5kVG9FbGVtZW50KHRyRWwsIFxuICAgICAgICAgICAgLy8gd2lsbCBjcmVhdGUgKGNvbENudCAtIGVuZENvbCkgdGQnc1xuICAgICAgICAgICAgbmV3IEFycmF5KGNvbENudCAtIGVuZENvbCArIDEpLmpvaW4oRU1QVFlfQ0VMTF9IVE1MKSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGludHJvSHRtbCA9IGRheUdyaWQucmVuZGVyUHJvcHMucmVuZGVySW50cm9IdG1sKCk7XG4gICAgICAgIGlmIChpbnRyb0h0bWwpIHtcbiAgICAgICAgICAgIGlmIChpc1J0bCkge1xuICAgICAgICAgICAgICAgIGFwcGVuZFRvRWxlbWVudCh0ckVsLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcHJlcGVuZFRvRWxlbWVudCh0ckVsLCBpbnRyb0h0bWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBza2VsZXRvbkVsO1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWRGaWxsUmVuZGVyZXI7XG59KEZpbGxSZW5kZXJlcikpO1xuXG52YXIgRGF5VGlsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5VGlsZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlUaWxlKGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGVsKSB8fCB0aGlzO1xuICAgICAgICB2YXIgZXZlbnRSZW5kZXJlciA9IF90aGlzLmV2ZW50UmVuZGVyZXIgPSBuZXcgRGF5VGlsZUV2ZW50UmVuZGVyZXIoX3RoaXMpO1xuICAgICAgICB2YXIgcmVuZGVyRnJhbWUgPSBfdGhpcy5yZW5kZXJGcmFtZSA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlckZyYW1lKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRmdFdmVudHMgPSBtZW1vaXplUmVuZGVyaW5nKGV2ZW50UmVuZGVyZXIucmVuZGVyU2Vncy5iaW5kKGV2ZW50UmVuZGVyZXIpLCBldmVudFJlbmRlcmVyLnVucmVuZGVyLmJpbmQoZXZlbnRSZW5kZXJlciksIFtyZW5kZXJGcmFtZV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFNlbGVjdGlvbiA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5zZWxlY3RCeUluc3RhbmNlSWQuYmluZChldmVudFJlbmRlcmVyKSwgZXZlbnRSZW5kZXJlci51bnNlbGVjdEJ5SW5zdGFuY2VJZC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbX3RoaXMucmVuZGVyRmdFdmVudHNdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyRXZlbnREcmFnID0gbWVtb2l6ZVJlbmRlcmluZyhldmVudFJlbmRlcmVyLmhpZGVCeUhhc2guYmluZChldmVudFJlbmRlcmVyKSwgZXZlbnRSZW5kZXJlci5zaG93QnlIYXNoLmJpbmQoZXZlbnRSZW5kZXJlciksIFtyZW5kZXJGcmFtZV0pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudFJlc2l6ZSA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5oaWRlQnlIYXNoLmJpbmQoZXZlbnRSZW5kZXJlciksIGV2ZW50UmVuZGVyZXIuc2hvd0J5SGFzaC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBbcmVuZGVyRnJhbWVdKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlUaWxlLnByb3RvdHlwZS5maXJzdENvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICBjb250ZXh0LmNhbGVuZGFyLnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcywge1xuICAgICAgICAgICAgZWw6IHRoaXMuZWwsXG4gICAgICAgICAgICB1c2VFdmVudENlbnRlcjogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJGcmFtZShwcm9wcy5kYXRlKTtcbiAgICAgICAgdGhpcy5yZW5kZXJGZ0V2ZW50cyhjb250ZXh0LCBwcm9wcy5mZ1NlZ3MpO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uKHByb3BzLmV2ZW50U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudERyYWcocHJvcHMuZXZlbnREcmFnSW5zdGFuY2VzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZShwcm9wcy5ldmVudFJlc2l6ZUluc3RhbmNlcyk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJGcmFtZS51bnJlbmRlcigpOyAvLyBzaG91bGQgdW5yZW5kZXIgZXZlcnl0aGluZyBlbHNlXG4gICAgICAgIHRoaXMuY29udGV4dC5jYWxlbmRhci51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcyk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5fcmVuZGVyRnJhbWUgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIHRoZW1lID0gX2EudGhlbWUsIGRhdGVFbnYgPSBfYS5kYXRlRW52LCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIHRpdGxlID0gZGF0ZUVudi5mb3JtYXQoZGF0ZSwgY3JlYXRlRm9ybWF0dGVyKG9wdGlvbnMuZGF5UG9wb3ZlckZvcm1hdCkgLy8gVE9ETzogY2FjaGVcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5lbC5pbm5lckhUTUwgPVxuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1oZWFkZXIgJyArIHRoZW1lLmdldENsYXNzKCdwb3BvdmVySGVhZGVyJykgKyAnXCI+JyArXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiZmMtdGl0bGVcIj4nICtcbiAgICAgICAgICAgICAgICBodG1sRXNjYXBlKHRpdGxlKSArXG4gICAgICAgICAgICAgICAgJzwvc3Bhbj4nICtcbiAgICAgICAgICAgICAgICAnPHNwYW4gY2xhc3M9XCJmYy1jbG9zZSAnICsgdGhlbWUuZ2V0SWNvbkNsYXNzKCdjbG9zZScpICsgJ1wiPjwvc3Bhbj4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1ib2R5ICcgKyB0aGVtZS5nZXRDbGFzcygncG9wb3ZlckNvbnRlbnQnKSArICdcIj4nICtcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLWV2ZW50LWNvbnRhaW5lclwiPjwvZGl2PicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICB0aGlzLnNlZ0NvbnRhaW5lckVsID0gdGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZmMtZXZlbnQtY29udGFpbmVyJyk7XG4gICAgfTtcbiAgICBEYXlUaWxlLnByb3RvdHlwZS5xdWVyeUhpdCA9IGZ1bmN0aW9uIChwb3NpdGlvbkxlZnQsIHBvc2l0aW9uVG9wLCBlbFdpZHRoLCBlbEhlaWdodCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMucHJvcHMuZGF0ZTsgLy8gSEFDS1xuICAgICAgICBpZiAocG9zaXRpb25MZWZ0IDwgZWxXaWR0aCAmJiBwb3NpdGlvblRvcCA8IGVsSGVpZ2h0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudDogdGhpcyxcbiAgICAgICAgICAgICAgICBkYXRlU3Bhbjoge1xuICAgICAgICAgICAgICAgICAgICBhbGxEYXk6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHJhbmdlOiB7IHN0YXJ0OiBkYXRlLCBlbmQ6IGFkZERheXMoZGF0ZSwgMSkgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGF5RWw6IHRoaXMuZWwsXG4gICAgICAgICAgICAgICAgcmVjdDoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBlbFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IGVsSGVpZ2h0XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsYXllcjogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERheVRpbGU7XG59KERhdGVDb21wb25lbnQpKTtcbnZhciBEYXlUaWxlRXZlbnRSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF5VGlsZUV2ZW50UmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5VGlsZUV2ZW50UmVuZGVyZXIoZGF5VGlsZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5kYXlUaWxlID0gZGF5VGlsZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlUaWxlRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuYXR0YWNoU2VncyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18xID0gc2VnczsgX2kgPCBzZWdzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18xW19pXTtcbiAgICAgICAgICAgIHRoaXMuZGF5VGlsZS5zZWdDb250YWluZXJFbC5hcHBlbmRDaGlsZChzZWcuZWwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXlUaWxlRXZlbnRSZW5kZXJlci5wcm90b3R5cGUuZGV0YWNoU2VncyA9IGZ1bmN0aW9uIChzZWdzKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18yID0gc2VnczsgX2kgPCBzZWdzXzIubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18yW19pXTtcbiAgICAgICAgICAgIHJlbW92ZUVsZW1lbnQoc2VnLmVsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIERheVRpbGVFdmVudFJlbmRlcmVyO1xufShTaW1wbGVEYXlHcmlkRXZlbnRSZW5kZXJlcikpO1xuXG52YXIgRGF5QmdSb3cgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRGF5QmdSb3coY29udGV4dCkge1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgIH1cbiAgICBEYXlCZ1Jvdy5wcm90b3R5cGUucmVuZGVySHRtbCA9IGZ1bmN0aW9uIChwcm9wcykge1xuICAgICAgICB2YXIgcGFydHMgPSBbXTtcbiAgICAgICAgaWYgKHByb3BzLnJlbmRlckludHJvSHRtbCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChwcm9wcy5yZW5kZXJJbnRyb0h0bWwoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHByb3BzLmNlbGxzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGNlbGwgPSBfYVtfaV07XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHJlbmRlckNlbGxIdG1sKGNlbGwuZGF0ZSwgcHJvcHMuZGF0ZVByb2ZpbGUsIHRoaXMuY29udGV4dCwgY2VsbC5odG1sQXR0cnMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXByb3BzLmNlbGxzLmxlbmd0aCkge1xuICAgICAgICAgICAgcGFydHMucHVzaCgnPHRkIGNsYXNzPVwiZmMtZGF5ICcgKyB0aGlzLmNvbnRleHQudGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSArICdcIj48L3RkPicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbnRleHQub3B0aW9ucy5kaXIgPT09ICdydGwnKSB7XG4gICAgICAgICAgICBwYXJ0cy5yZXZlcnNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICc8dHI+JyArIHBhcnRzLmpvaW4oJycpICsgJzwvdHI+JztcbiAgICB9O1xuICAgIHJldHVybiBEYXlCZ1Jvdztcbn0oKSk7XG5mdW5jdGlvbiByZW5kZXJDZWxsSHRtbChkYXRlLCBkYXRlUHJvZmlsZSwgY29udGV4dCwgb3RoZXJBdHRycykge1xuICAgIHZhciBkYXRlRW52ID0gY29udGV4dC5kYXRlRW52LCB0aGVtZSA9IGNvbnRleHQudGhlbWU7XG4gICAgdmFyIGlzRGF0ZVZhbGlkID0gcmFuZ2VDb250YWluc01hcmtlcihkYXRlUHJvZmlsZS5hY3RpdmVSYW5nZSwgZGF0ZSk7IC8vIFRPRE86IGNhbGxlZCB0b28gZnJlcXVlbnRseS4gY2FjaGUgc29tZWhvdy5cbiAgICB2YXIgY2xhc3NlcyA9IGdldERheUNsYXNzZXMoZGF0ZSwgZGF0ZVByb2ZpbGUsIGNvbnRleHQpO1xuICAgIGNsYXNzZXMudW5zaGlmdCgnZmMtZGF5JywgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSk7XG4gICAgcmV0dXJuICc8dGQgY2xhc3M9XCInICsgY2xhc3Nlcy5qb2luKCcgJykgKyAnXCInICtcbiAgICAgICAgKGlzRGF0ZVZhbGlkID9cbiAgICAgICAgICAgICcgZGF0YS1kYXRlPVwiJyArIGRhdGVFbnYuZm9ybWF0SXNvKGRhdGUsIHsgb21pdFRpbWU6IHRydWUgfSkgKyAnXCInIDpcbiAgICAgICAgICAgICcnKSArXG4gICAgICAgIChvdGhlckF0dHJzID9cbiAgICAgICAgICAgICcgJyArIG90aGVyQXR0cnMgOlxuICAgICAgICAgICAgJycpICtcbiAgICAgICAgJz48L3RkPic7XG59XG5cbnZhciBEQVlfTlVNX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7IGRheTogJ251bWVyaWMnIH0pO1xudmFyIFdFRUtfTlVNX0ZPUk1BVCA9IGNyZWF0ZUZvcm1hdHRlcih7IHdlZWs6ICdudW1lcmljJyB9KTtcbnZhciBEYXlHcmlkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERheUdyaWQoZWwsIHJlbmRlclByb3BzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGVsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5ib3R0b21Db29yZFBhZGRpbmcgPSAwOyAvLyBoYWNrIGZvciBleHRlbmRpbmcgdGhlIGhpdCBhcmVhIGZvciB0aGUgbGFzdCByb3cgb2YgdGhlIGNvb3JkaW5hdGUgZ3JpZFxuICAgICAgICBfdGhpcy5pc0NlbGxTaXplc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnJlbmRlclByb3BzID0gcmVuZGVyUHJvcHM7XG4gICAgICAgIHZhciBldmVudFJlbmRlcmVyID0gX3RoaXMuZXZlbnRSZW5kZXJlciA9IG5ldyBEYXlHcmlkRXZlbnRSZW5kZXJlcihfdGhpcyk7XG4gICAgICAgIHZhciBmaWxsUmVuZGVyZXIgPSBfdGhpcy5maWxsUmVuZGVyZXIgPSBuZXcgRGF5R3JpZEZpbGxSZW5kZXJlcihfdGhpcyk7XG4gICAgICAgIF90aGlzLm1pcnJvclJlbmRlcmVyID0gbmV3IERheUdyaWRNaXJyb3JSZW5kZXJlcihfdGhpcyk7XG4gICAgICAgIHZhciByZW5kZXJDZWxscyA9IF90aGlzLnJlbmRlckNlbGxzID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyQ2VsbHMsIF90aGlzLl91bnJlbmRlckNlbGxzKTtcbiAgICAgICAgX3RoaXMucmVuZGVyQnVzaW5lc3NIb3VycyA9IG1lbW9pemVSZW5kZXJpbmcoZmlsbFJlbmRlcmVyLnJlbmRlclNlZ3MuYmluZChmaWxsUmVuZGVyZXIsICdidXNpbmVzc0hvdXJzJyksIGZpbGxSZW5kZXJlci51bnJlbmRlci5iaW5kKGZpbGxSZW5kZXJlciwgJ2J1c2luZXNzSG91cnMnKSwgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckRhdGVTZWxlY3Rpb24gPSBtZW1vaXplUmVuZGVyaW5nKGZpbGxSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZmlsbFJlbmRlcmVyLCAnaGlnaGxpZ2h0JyksIGZpbGxSZW5kZXJlci51bnJlbmRlci5iaW5kKGZpbGxSZW5kZXJlciwgJ2hpZ2hsaWdodCcpLCBbcmVuZGVyQ2VsbHNdKTtcbiAgICAgICAgX3RoaXMucmVuZGVyQmdFdmVudHMgPSBtZW1vaXplUmVuZGVyaW5nKGZpbGxSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZmlsbFJlbmRlcmVyLCAnYmdFdmVudCcpLCBmaWxsUmVuZGVyZXIudW5yZW5kZXIuYmluZChmaWxsUmVuZGVyZXIsICdiZ0V2ZW50JyksIFtyZW5kZXJDZWxsc10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJGZ0V2ZW50cyA9IG1lbW9pemVSZW5kZXJpbmcoZXZlbnRSZW5kZXJlci5yZW5kZXJTZWdzLmJpbmQoZXZlbnRSZW5kZXJlciksIGV2ZW50UmVuZGVyZXIudW5yZW5kZXIuYmluZChldmVudFJlbmRlcmVyKSwgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uID0gbWVtb2l6ZVJlbmRlcmluZyhldmVudFJlbmRlcmVyLnNlbGVjdEJ5SW5zdGFuY2VJZC5iaW5kKGV2ZW50UmVuZGVyZXIpLCBldmVudFJlbmRlcmVyLnVuc2VsZWN0QnlJbnN0YW5jZUlkLmJpbmQoZXZlbnRSZW5kZXJlciksIFtfdGhpcy5yZW5kZXJGZ0V2ZW50c10pO1xuICAgICAgICBfdGhpcy5yZW5kZXJFdmVudERyYWcgPSBtZW1vaXplUmVuZGVyaW5nKF90aGlzLl9yZW5kZXJFdmVudERyYWcsIF90aGlzLl91bnJlbmRlckV2ZW50RHJhZywgW3JlbmRlckNlbGxzXSk7XG4gICAgICAgIF90aGlzLnJlbmRlckV2ZW50UmVzaXplID0gbWVtb2l6ZVJlbmRlcmluZyhfdGhpcy5fcmVuZGVyRXZlbnRSZXNpemUsIF90aGlzLl91bnJlbmRlckV2ZW50UmVzaXplLCBbcmVuZGVyQ2VsbHNdKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGNlbGxzID0gcHJvcHMuY2VsbHM7XG4gICAgICAgIHRoaXMucm93Q250ID0gY2VsbHMubGVuZ3RoO1xuICAgICAgICB0aGlzLmNvbENudCA9IGNlbGxzWzBdLmxlbmd0aDtcbiAgICAgICAgdGhpcy5yZW5kZXJDZWxscyhjZWxscywgcHJvcHMuaXNSaWdpZCk7XG4gICAgICAgIHRoaXMucmVuZGVyQnVzaW5lc3NIb3Vycyhjb250ZXh0LCBwcm9wcy5idXNpbmVzc0hvdXJTZWdzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJEYXRlU2VsZWN0aW9uKGNvbnRleHQsIHByb3BzLmRhdGVTZWxlY3Rpb25TZWdzKTtcbiAgICAgICAgdGhpcy5yZW5kZXJCZ0V2ZW50cyhjb250ZXh0LCBwcm9wcy5iZ0V2ZW50U2Vncyk7XG4gICAgICAgIHRoaXMucmVuZGVyRmdFdmVudHMoY29udGV4dCwgcHJvcHMuZmdFdmVudFNlZ3MpO1xuICAgICAgICB0aGlzLnJlbmRlckV2ZW50U2VsZWN0aW9uKHByb3BzLmV2ZW50U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudERyYWcocHJvcHMuZXZlbnREcmFnKTtcbiAgICAgICAgdGhpcy5yZW5kZXJFdmVudFJlc2l6ZShwcm9wcy5ldmVudFJlc2l6ZSk7XG4gICAgICAgIGlmICh0aGlzLnNlZ1BvcG92ZXJUaWxlKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNlZ1BvcG92ZXJUaWxlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLnJlbmRlckNlbGxzLnVucmVuZGVyKCk7IC8vIHdpbGwgdW5yZW5kZXIgZXZlcnl0aGluZyBlbHNlXG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRDZWxsUmFuZ2UgPSBmdW5jdGlvbiAocm93LCBjb2wpIHtcbiAgICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5wcm9wcy5jZWxsc1tyb3ddW2NvbF0uZGF0ZTtcbiAgICAgICAgdmFyIGVuZCA9IGFkZERheXMoc3RhcnQsIDEpO1xuICAgICAgICByZXR1cm4geyBzdGFydDogc3RhcnQsIGVuZDogZW5kIH07XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS51cGRhdGVTZWdQb3BvdmVyVGlsZSA9IGZ1bmN0aW9uIChkYXRlLCBzZWdzKSB7XG4gICAgICAgIHZhciBvd25Qcm9wcyA9IHRoaXMucHJvcHM7XG4gICAgICAgIHRoaXMuc2VnUG9wb3ZlclRpbGUucmVjZWl2ZVByb3BzKHtcbiAgICAgICAgICAgIGRhdGU6IGRhdGUgfHwgdGhpcy5zZWdQb3BvdmVyVGlsZS5wcm9wcy5kYXRlLFxuICAgICAgICAgICAgZmdTZWdzOiBzZWdzIHx8IHRoaXMuc2VnUG9wb3ZlclRpbGUucHJvcHMuZmdTZWdzLFxuICAgICAgICAgICAgZXZlbnRTZWxlY3Rpb246IG93blByb3BzLmV2ZW50U2VsZWN0aW9uLFxuICAgICAgICAgICAgZXZlbnREcmFnSW5zdGFuY2VzOiBvd25Qcm9wcy5ldmVudERyYWcgPyBvd25Qcm9wcy5ldmVudERyYWcuYWZmZWN0ZWRJbnN0YW5jZXMgOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRSZXNpemVJbnN0YW5jZXM6IG93blByb3BzLmV2ZW50UmVzaXplID8gb3duUHJvcHMuZXZlbnRSZXNpemUuYWZmZWN0ZWRJbnN0YW5jZXMgOiBudWxsXG4gICAgICAgIH0sIHRoaXMuY29udGV4dCk7XG4gICAgfTtcbiAgICAvKiBEYXRlIFJlbmRlcmluZ1xuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3JlbmRlckNlbGxzID0gZnVuY3Rpb24gKGNlbGxzLCBpc1JpZ2lkKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29udGV4dCwgY2FsZW5kYXIgPSBfYS5jYWxlbmRhciwgdmlldyA9IF9hLnZpZXcsIGlzUnRsID0gX2EuaXNSdGwsIGRhdGVFbnYgPSBfYS5kYXRlRW52O1xuICAgICAgICB2YXIgX2IgPSB0aGlzLCByb3dDbnQgPSBfYi5yb3dDbnQsIGNvbENudCA9IF9iLmNvbENudDtcbiAgICAgICAgdmFyIGh0bWwgPSAnJztcbiAgICAgICAgdmFyIHJvdztcbiAgICAgICAgdmFyIGNvbDtcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCByb3dDbnQ7IHJvdysrKSB7XG4gICAgICAgICAgICBodG1sICs9IHRoaXMucmVuZGVyRGF5Um93SHRtbChyb3csIGlzUmlnaWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gaHRtbDtcbiAgICAgICAgdGhpcy5yb3dFbHMgPSBmaW5kRWxlbWVudHModGhpcy5lbCwgJy5mYy1yb3cnKTtcbiAgICAgICAgdGhpcy5jZWxsRWxzID0gZmluZEVsZW1lbnRzKHRoaXMuZWwsICcuZmMtZGF5LCAuZmMtZGlzYWJsZWQtZGF5Jyk7XG4gICAgICAgIGlmIChpc1J0bCkge1xuICAgICAgICAgICAgdGhpcy5jZWxsRWxzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd1Bvc2l0aW9ucyA9IG5ldyBQb3NpdGlvbkNhY2hlKHRoaXMuZWwsIHRoaXMucm93RWxzLCBmYWxzZSwgdHJ1ZSAvLyB2ZXJ0aWNhbFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmNvbFBvc2l0aW9ucyA9IG5ldyBQb3NpdGlvbkNhY2hlKHRoaXMuZWwsIHRoaXMuY2VsbEVscy5zbGljZSgwLCBjb2xDbnQpLCAvLyBvbmx5IHRoZSBmaXJzdCByb3dcbiAgICAgICAgdHJ1ZSwgZmFsc2UgLy8gaG9yaXpvbnRhbFxuICAgICAgICApO1xuICAgICAgICAvLyB0cmlnZ2VyIGRheVJlbmRlciB3aXRoIGVhY2ggY2VsbCdzIGVsZW1lbnRcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCByb3dDbnQ7IHJvdysrKSB7XG4gICAgICAgICAgICBmb3IgKGNvbCA9IDA7IGNvbCA8IGNvbENudDsgY29sKyspIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2RheVJlbmRlcicsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZTogZGF0ZUVudi50b0RhdGUoY2VsbHNbcm93XVtjb2xdLmRhdGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IHRoaXMuZ2V0Q2VsbEVsKHJvdywgY29sKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXNDZWxsU2l6ZXNEaXJ0eSA9IHRydWU7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5fdW5yZW5kZXJDZWxscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVTZWdQb3BvdmVyKCk7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgZm9yIGEgc2luZ2xlIHJvdywgd2hpY2ggaXMgYSBkaXYgdGhhdCB3cmFwcyBhIHRhYmxlLlxuICAgIC8vIGByb3dgIGlzIHRoZSByb3cgbnVtYmVyLlxuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlckRheVJvd0h0bWwgPSBmdW5jdGlvbiAocm93LCBpc1JpZ2lkKSB7XG4gICAgICAgIHZhciB0aGVtZSA9IHRoaXMuY29udGV4dC50aGVtZTtcbiAgICAgICAgdmFyIGNsYXNzZXMgPSBbJ2ZjLXJvdycsICdmYy13ZWVrJywgdGhlbWUuZ2V0Q2xhc3MoJ2RheVJvdycpXTtcbiAgICAgICAgaWYgKGlzUmlnaWQpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnZmMtcmlnaWQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYmdSb3cgPSBuZXcgRGF5QmdSb3codGhpcy5jb250ZXh0KTtcbiAgICAgICAgcmV0dXJuICcnICtcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiJyArIGNsYXNzZXMuam9pbignICcpICsgJ1wiPicgK1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmYy1iZ1wiPicgK1xuICAgICAgICAgICAgJzx0YWJsZSBjbGFzcz1cIicgKyB0aGVtZS5nZXRDbGFzcygndGFibGVHcmlkJykgKyAnXCI+JyArXG4gICAgICAgICAgICBiZ1Jvdy5yZW5kZXJIdG1sKHtcbiAgICAgICAgICAgICAgICBjZWxsczogdGhpcy5wcm9wcy5jZWxsc1tyb3ddLFxuICAgICAgICAgICAgICAgIGRhdGVQcm9maWxlOiB0aGlzLnByb3BzLmRhdGVQcm9maWxlLFxuICAgICAgICAgICAgICAgIHJlbmRlckludHJvSHRtbDogdGhpcy5yZW5kZXJQcm9wcy5yZW5kZXJCZ0ludHJvSHRtbFxuICAgICAgICAgICAgfSkgK1xuICAgICAgICAgICAgJzwvdGFibGU+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cImZjLWNvbnRlbnQtc2tlbGV0b25cIj4nICtcbiAgICAgICAgICAgICc8dGFibGU+JyArXG4gICAgICAgICAgICAodGhpcy5nZXRJc051bWJlcnNWaXNpYmxlKCkgP1xuICAgICAgICAgICAgICAgICc8dGhlYWQ+JyArXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyTnVtYmVyVHJIdG1sKHJvdykgK1xuICAgICAgICAgICAgICAgICAgICAnPC90aGVhZD4nIDpcbiAgICAgICAgICAgICAgICAnJykgK1xuICAgICAgICAgICAgJzwvdGFibGU+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JztcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmdldElzTnVtYmVyc1Zpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldElzRGF5TnVtYmVyc1Zpc2libGUoKSB8fFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJQcm9wcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlIHx8XG4gICAgICAgICAgICB0aGlzLnJlbmRlclByb3BzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZTtcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmdldElzRGF5TnVtYmVyc1Zpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd0NudCA+IDE7XG4gICAgfTtcbiAgICAvKiBHcmlkIE51bWJlciBSZW5kZXJpbmdcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlck51bWJlclRySHRtbCA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5jb250ZXh0LmlzUnRsO1xuICAgICAgICB2YXIgaW50cm8gPSB0aGlzLnJlbmRlclByb3BzLnJlbmRlck51bWJlckludHJvSHRtbChyb3csIHRoaXMpO1xuICAgICAgICByZXR1cm4gJycgK1xuICAgICAgICAgICAgJzx0cj4nICtcbiAgICAgICAgICAgIChpc1J0bCA/ICcnIDogaW50cm8pICtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyTnVtYmVyQ2VsbHNIdG1sKHJvdykgK1xuICAgICAgICAgICAgKGlzUnRsID8gaW50cm8gOiAnJykgK1xuICAgICAgICAgICAgJzwvdHI+JztcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLnJlbmRlck51bWJlckNlbGxzSHRtbCA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGh0bWxzID0gW107XG4gICAgICAgIHZhciBjb2w7XG4gICAgICAgIHZhciBkYXRlO1xuICAgICAgICBmb3IgKGNvbCA9IDA7IGNvbCA8IHRoaXMuY29sQ250OyBjb2wrKykge1xuICAgICAgICAgICAgZGF0ZSA9IHRoaXMucHJvcHMuY2VsbHNbcm93XVtjb2xdLmRhdGU7XG4gICAgICAgICAgICBodG1scy5wdXNoKHRoaXMucmVuZGVyTnVtYmVyQ2VsbEh0bWwoZGF0ZSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbnRleHQuaXNSdGwpIHtcbiAgICAgICAgICAgIGh0bWxzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaHRtbHMuam9pbignJyk7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgZm9yIHRoZSA8dGQ+cyBvZiB0aGUgXCJudW1iZXJcIiByb3cgaW4gdGhlIERheUdyaWQncyBjb250ZW50IHNrZWxldG9uLlxuICAgIC8vIFRoZSBudW1iZXIgcm93IHdpbGwgb25seSBleGlzdCBpZiBlaXRoZXIgZGF5IG51bWJlcnMgb3Igd2VlayBudW1iZXJzIGFyZSB0dXJuZWQgb24uXG4gICAgRGF5R3JpZC5wcm90b3R5cGUucmVuZGVyTnVtYmVyQ2VsbEh0bWwgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGRhdGVFbnYgPSBfYS5kYXRlRW52LCBvcHRpb25zID0gX2Eub3B0aW9ucztcbiAgICAgICAgdmFyIGh0bWwgPSAnJztcbiAgICAgICAgdmFyIGlzRGF0ZVZhbGlkID0gcmFuZ2VDb250YWluc01hcmtlcih0aGlzLnByb3BzLmRhdGVQcm9maWxlLmFjdGl2ZVJhbmdlLCBkYXRlKTsgLy8gVE9ETzogY2FsbGVkIHRvbyBmcmVxdWVudGx5LiBjYWNoZSBzb21laG93LlxuICAgICAgICB2YXIgaXNEYXlOdW1iZXJWaXNpYmxlID0gdGhpcy5nZXRJc0RheU51bWJlcnNWaXNpYmxlKCkgJiYgaXNEYXRlVmFsaWQ7XG4gICAgICAgIHZhciBjbGFzc2VzO1xuICAgICAgICB2YXIgd2Vla0NhbGNGaXJzdERvdztcbiAgICAgICAgaWYgKCFpc0RheU51bWJlclZpc2libGUgJiYgIXRoaXMucmVuZGVyUHJvcHMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSkge1xuICAgICAgICAgICAgLy8gbm8gbnVtYmVycyBpbiBkYXkgY2VsbCAod2VlayBudW1iZXIgbXVzdCBiZSBhbG9uZyB0aGUgc2lkZSlcbiAgICAgICAgICAgIHJldHVybiAnPHRkPjwvdGQ+JzsgLy8gIHdpbGwgY3JlYXRlIGFuIGVtcHR5IHNwYWNlIGFib3ZlIGV2ZW50cyA6KFxuICAgICAgICB9XG4gICAgICAgIGNsYXNzZXMgPSBnZXREYXlDbGFzc2VzKGRhdGUsIHRoaXMucHJvcHMuZGF0ZVByb2ZpbGUsIHRoaXMuY29udGV4dCk7XG4gICAgICAgIGNsYXNzZXMudW5zaGlmdCgnZmMtZGF5LXRvcCcpO1xuICAgICAgICBpZiAodGhpcy5yZW5kZXJQcm9wcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICB3ZWVrQ2FsY0ZpcnN0RG93ID0gZGF0ZUVudi53ZWVrRG93O1xuICAgICAgICB9XG4gICAgICAgIGh0bWwgKz0gJzx0ZCBjbGFzcz1cIicgKyBjbGFzc2VzLmpvaW4oJyAnKSArICdcIicgK1xuICAgICAgICAgICAgKGlzRGF0ZVZhbGlkID9cbiAgICAgICAgICAgICAgICAnIGRhdGEtZGF0ZT1cIicgKyBkYXRlRW52LmZvcm1hdElzbyhkYXRlLCB7IG9taXRUaW1lOiB0cnVlIH0pICsgJ1wiJyA6XG4gICAgICAgICAgICAgICAgJycpICtcbiAgICAgICAgICAgICc+JztcbiAgICAgICAgaWYgKHRoaXMucmVuZGVyUHJvcHMuY2VsbFdlZWtOdW1iZXJzVmlzaWJsZSAmJiAoZGF0ZS5nZXRVVENEYXkoKSA9PT0gd2Vla0NhbGNGaXJzdERvdykpIHtcbiAgICAgICAgICAgIGh0bWwgKz0gYnVpbGRHb3RvQW5jaG9ySHRtbChvcHRpb25zLCBkYXRlRW52LCB7IGRhdGU6IGRhdGUsIHR5cGU6ICd3ZWVrJyB9LCB7ICdjbGFzcyc6ICdmYy13ZWVrLW51bWJlcicgfSwgZGF0ZUVudi5mb3JtYXQoZGF0ZSwgV0VFS19OVU1fRk9STUFUKSAvLyBpbm5lciBIVE1MXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0RheU51bWJlclZpc2libGUpIHtcbiAgICAgICAgICAgIGh0bWwgKz0gYnVpbGRHb3RvQW5jaG9ySHRtbChvcHRpb25zLCBkYXRlRW52LCBkYXRlLCB7ICdjbGFzcyc6ICdmYy1kYXktbnVtYmVyJyB9LCBkYXRlRW52LmZvcm1hdChkYXRlLCBEQVlfTlVNX0ZPUk1BVCkgLy8gaW5uZXIgSFRNTFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBodG1sICs9ICc8L3RkPic7XG4gICAgICAgIHJldHVybiBodG1sO1xuICAgIH07XG4gICAgLyogU2l6aW5nXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBEYXlHcmlkLnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKGlzUmVzaXplKSB7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXMuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgZmlsbFJlbmRlcmVyID0gX2EuZmlsbFJlbmRlcmVyLCBldmVudFJlbmRlcmVyID0gX2EuZXZlbnRSZW5kZXJlciwgbWlycm9yUmVuZGVyZXIgPSBfYS5taXJyb3JSZW5kZXJlcjtcbiAgICAgICAgaWYgKGlzUmVzaXplIHx8XG4gICAgICAgICAgICB0aGlzLmlzQ2VsbFNpemVzRGlydHkgfHxcbiAgICAgICAgICAgIGNhbGVuZGFyLmlzRXZlbnRzVXBkYXRlZCAvLyBoYWNrXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5idWlsZFBvc2l0aW9uQ2FjaGVzKCk7XG4gICAgICAgICAgICB0aGlzLmlzQ2VsbFNpemVzRGlydHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmaWxsUmVuZGVyZXIuY29tcHV0ZVNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgZXZlbnRSZW5kZXJlci5jb21wdXRlU2l6ZXMoaXNSZXNpemUpO1xuICAgICAgICBtaXJyb3JSZW5kZXJlci5jb21wdXRlU2l6ZXMoaXNSZXNpemUpO1xuICAgICAgICBmaWxsUmVuZGVyZXIuYXNzaWduU2l6ZXMoaXNSZXNpemUpO1xuICAgICAgICBldmVudFJlbmRlcmVyLmFzc2lnblNpemVzKGlzUmVzaXplKTtcbiAgICAgICAgbWlycm9yUmVuZGVyZXIuYXNzaWduU2l6ZXMoaXNSZXNpemUpO1xuICAgIH07XG4gICAgRGF5R3JpZC5wcm90b3R5cGUuYnVpbGRQb3NpdGlvbkNhY2hlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5idWlsZENvbFBvc2l0aW9ucygpO1xuICAgICAgICB0aGlzLmJ1aWxkUm93UG9zaXRpb25zKCk7XG4gICAgfTtcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5idWlsZENvbFBvc2l0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb2xQb3NpdGlvbnMuYnVpbGQoKTtcbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLmJ1aWxkUm93UG9zaXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJvd1Bvc2l0aW9ucy5idWlsZCgpO1xuICAgICAgICB0aGlzLnJvd1Bvc2l0aW9ucy5ib3R0b21zW3RoaXMucm93Q250IC0gMV0gKz0gdGhpcy5ib3R0b21Db29yZFBhZGRpbmc7IC8vIGhhY2tcbiAgICB9O1xuICAgIC8qIEhpdCBTeXN0ZW1cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuICAgIERheUdyaWQucHJvdG90eXBlLnBvc2l0aW9uVG9IaXQgPSBmdW5jdGlvbiAobGVmdFBvc2l0aW9uLCB0b3BQb3NpdGlvbikge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBjb2xQb3NpdGlvbnMgPSBfYS5jb2xQb3NpdGlvbnMsIHJvd1Bvc2l0aW9ucyA9IF9hLnJvd1Bvc2l0aW9ucztcbiAgICAgICAgdmFyIGNvbCA9IGNvbFBvc2l0aW9ucy5sZWZ0VG9JbmRleChsZWZ0UG9zaXRpb24pO1xuICAgICAgICB2YXIgcm93ID0gcm93UG9zaXRpb25zLnRvcFRvSW5kZXgodG9wUG9zaXRpb24pO1xuICAgICAgICBpZiAocm93ICE9IG51bGwgJiYgY29sICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICAgICAgY29sOiBjb2wsXG4gICAgICAgICAgICAgICAgZGF0ZVNwYW46IHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IHRoaXMuZ2V0Q2VsbFJhbmdlKHJvdywgY29sKSxcbiAgICAgICAgICAgICAgICAgICAgYWxsRGF5OiB0cnVlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkYXlFbDogdGhpcy5nZXRDZWxsRWwocm93LCBjb2wpLFxuICAgICAgICAgICAgICAgIHJlbGF0aXZlUmVjdDoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiBjb2xQb3NpdGlvbnMubGVmdHNbY29sXSxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGNvbFBvc2l0aW9ucy5yaWdodHNbY29sXSxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiByb3dQb3NpdGlvbnMudG9wc1tyb3ddLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IHJvd1Bvc2l0aW9ucy5ib3R0b21zW3Jvd11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiBDZWxsIFN5c3RlbVxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgLy8gRllJOiB0aGUgZmlyc3QgY29sdW1uIGlzIHRoZSBsZWZ0bW9zdCBjb2x1bW4sIHJlZ2FyZGxlc3Mgb2YgZGF0ZVxuICAgIERheUdyaWQucHJvdG90eXBlLmdldENlbGxFbCA9IGZ1bmN0aW9uIChyb3csIGNvbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZWxsRWxzW3JvdyAqIHRoaXMuY29sQ250ICsgY29sXTtcbiAgICB9O1xuICAgIC8qIEV2ZW50IERyYWcgVmlzdWFsaXphdGlvblxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3JlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlci5oaWRlQnlIYXNoKHN0YXRlLmFmZmVjdGVkSW5zdGFuY2VzKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbFJlbmRlcmVyLnJlbmRlclNlZ3MoJ2hpZ2hsaWdodCcsIHRoaXMuY29udGV4dCwgc3RhdGUuc2Vncyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLl91bnJlbmRlckV2ZW50RHJhZyA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlci5zaG93QnlIYXNoKHN0YXRlLmFmZmVjdGVkSW5zdGFuY2VzKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbFJlbmRlcmVyLnVucmVuZGVyKCdoaWdobGlnaHQnLCB0aGlzLmNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiBFdmVudCBSZXNpemUgVmlzdWFsaXphdGlvblxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuX3JlbmRlckV2ZW50UmVzaXplID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFJlbmRlcmVyLmhpZGVCeUhhc2goc3RhdGUuYWZmZWN0ZWRJbnN0YW5jZXMpO1xuICAgICAgICAgICAgdGhpcy5maWxsUmVuZGVyZXIucmVuZGVyU2VncygnaGlnaGxpZ2h0JywgdGhpcy5jb250ZXh0LCBzdGF0ZS5zZWdzKTtcbiAgICAgICAgICAgIHRoaXMubWlycm9yUmVuZGVyZXIucmVuZGVyU2Vncyh0aGlzLmNvbnRleHQsIHN0YXRlLnNlZ3MsIHsgaXNSZXNpemluZzogdHJ1ZSwgc291cmNlU2VnOiBzdGF0ZS5zb3VyY2VTZWcgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERheUdyaWQucHJvdG90eXBlLl91bnJlbmRlckV2ZW50UmVzaXplID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFJlbmRlcmVyLnNob3dCeUhhc2goc3RhdGUuYWZmZWN0ZWRJbnN0YW5jZXMpO1xuICAgICAgICAgICAgdGhpcy5maWxsUmVuZGVyZXIudW5yZW5kZXIoJ2hpZ2hsaWdodCcsIHRoaXMuY29udGV4dCk7XG4gICAgICAgICAgICB0aGlzLm1pcnJvclJlbmRlcmVyLnVucmVuZGVyKHRoaXMuY29udGV4dCwgc3RhdGUuc2VncywgeyBpc1Jlc2l6aW5nOiB0cnVlLCBzb3VyY2VTZWc6IHN0YXRlLnNvdXJjZVNlZyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyogTW9yZSsgTGluayBQb3BvdmVyXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW1vdmVTZWdQb3BvdmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zZWdQb3BvdmVyKSB7XG4gICAgICAgICAgICB0aGlzLnNlZ1BvcG92ZXIuaGlkZSgpOyAvLyBpbiBoYW5kbGVyLCB3aWxsIGNhbGwgc2VnUG9wb3ZlcidzIHJlbW92ZUVsZW1lbnRcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gTGltaXRzIHRoZSBudW1iZXIgb2YgXCJsZXZlbHNcIiAodmVydGljYWxseSBzdGFja2luZyBsYXllcnMgb2YgZXZlbnRzKSBmb3IgZWFjaCByb3cgb2YgdGhlIGdyaWQuXG4gICAgLy8gYGxldmVsTGltaXRgIGNhbiBiZSBmYWxzZSAoZG9uJ3QgbGltaXQpLCBhIG51bWJlciwgb3IgdHJ1ZSAoc2hvdWxkIGJlIGNvbXB1dGVkKS5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5saW1pdFJvd3MgPSBmdW5jdGlvbiAobGV2ZWxMaW1pdCkge1xuICAgICAgICB2YXIgcm93U3RydWN0cyA9IHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzIHx8IFtdO1xuICAgICAgICB2YXIgcm93OyAvLyByb3cgI1xuICAgICAgICB2YXIgcm93TGV2ZWxMaW1pdDtcbiAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCByb3dTdHJ1Y3RzLmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgIHRoaXMudW5saW1pdFJvdyhyb3cpO1xuICAgICAgICAgICAgaWYgKCFsZXZlbExpbWl0KSB7XG4gICAgICAgICAgICAgICAgcm93TGV2ZWxMaW1pdCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGxldmVsTGltaXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgcm93TGV2ZWxMaW1pdCA9IGxldmVsTGltaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByb3dMZXZlbExpbWl0ID0gdGhpcy5jb21wdXRlUm93TGV2ZWxMaW1pdChyb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJvd0xldmVsTGltaXQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saW1pdFJvdyhyb3csIHJvd0xldmVsTGltaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBDb21wdXRlcyB0aGUgbnVtYmVyIG9mIGxldmVscyBhIHJvdyB3aWxsIGFjY29tb2RhdGUgd2l0aG91dCBnb2luZyBvdXRzaWRlIGl0cyBib3VuZHMuXG4gICAgLy8gQXNzdW1lcyB0aGUgcm93IGlzIFwicmlnaWRcIiAobWFpbnRhaW5zIGEgY29uc3RhbnQgaGVpZ2h0IHJlZ2FyZGxlc3Mgb2Ygd2hhdCBpcyBpbnNpZGUpLlxuICAgIC8vIGByb3dgIGlzIHRoZSByb3cgbnVtYmVyLlxuICAgIERheUdyaWQucHJvdG90eXBlLmNvbXB1dGVSb3dMZXZlbExpbWl0ID0gZnVuY3Rpb24gKHJvdykge1xuICAgICAgICB2YXIgcm93RWwgPSB0aGlzLnJvd0Vsc1tyb3ddOyAvLyB0aGUgY29udGFpbmluZyBcImZha2VcIiByb3cgZGl2XG4gICAgICAgIHZhciByb3dCb3R0b20gPSByb3dFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5ib3R0b207IC8vIHJlbGF0aXZlIHRvIHZpZXdwb3J0IVxuICAgICAgICB2YXIgdHJFbHMgPSBmaW5kQ2hpbGRyZW4odGhpcy5ldmVudFJlbmRlcmVyLnJvd1N0cnVjdHNbcm93XS50Ym9keUVsKTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB0ckVsO1xuICAgICAgICAvLyBSZXZlYWwgb25lIGxldmVsIDx0cj4gYXQgYSB0aW1lIGFuZCBzdG9wIHdoZW4gd2UgZmluZCBvbmUgb3V0IG9mIGJvdW5kc1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdHJFbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyRWwgPSB0ckVsc1tpXTtcbiAgICAgICAgICAgIHRyRWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtbGltaXRlZCcpOyAvLyByZXNldCB0byBvcmlnaW5hbCBzdGF0ZSAocmV2ZWFsKVxuICAgICAgICAgICAgaWYgKHRyRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuYm90dG9tID4gcm93Qm90dG9tKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBzaG91bGQgbm90IGxpbWl0IGF0IGFsbFxuICAgIH07XG4gICAgLy8gTGltaXRzIHRoZSBnaXZlbiBncmlkIHJvdyB0byB0aGUgbWF4aW11bSBudW1iZXIgb2YgbGV2ZWxzIGFuZCBpbmplY3RzIFwibW9yZVwiIGxpbmtzIGlmIG5lY2Vzc2FyeS5cbiAgICAvLyBgcm93YCBpcyB0aGUgcm93IG51bWJlci5cbiAgICAvLyBgbGV2ZWxMaW1pdGAgaXMgYSBudW1iZXIgZm9yIHRoZSBtYXhpbXVtIChpbmNsdXNpdmUpIG51bWJlciBvZiBsZXZlbHMgYWxsb3dlZC5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5saW1pdFJvdyA9IGZ1bmN0aW9uIChyb3csIGxldmVsTGltaXQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNvbENudCA9IHRoaXMuY29sQ250O1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmNvbnRleHQuaXNSdGw7XG4gICAgICAgIHZhciByb3dTdHJ1Y3QgPSB0aGlzLmV2ZW50UmVuZGVyZXIucm93U3RydWN0c1tyb3ddO1xuICAgICAgICB2YXIgbW9yZU5vZGVzID0gW107IC8vIGFycmF5IG9mIFwibW9yZVwiIDxhPiBsaW5rcyBhbmQgPHRkPiBET00gbm9kZXNcbiAgICAgICAgdmFyIGNvbCA9IDA7IC8vIGNvbCAjLCBsZWZ0LXRvLXJpZ2h0IChub3QgY2hyb25vbG9naWNhbGx5KVxuICAgICAgICB2YXIgbGV2ZWxTZWdzOyAvLyBhcnJheSBvZiBzZWdtZW50IG9iamVjdHMgaW4gdGhlIGxhc3QgYWxsb3dhYmxlIGxldmVsLCBvcmRlcmVkIGxlZnQtdG8tcmlnaHRcbiAgICAgICAgdmFyIGNlbGxNYXRyaXg7IC8vIGEgbWF0cml4IChieSBsZXZlbCwgdGhlbiBjb2x1bW4pIG9mIGFsbCA8dGQ+IGVsZW1lbnRzIGluIHRoZSByb3dcbiAgICAgICAgdmFyIGxpbWl0ZWROb2RlczsgLy8gYXJyYXkgb2YgdGVtcG9yYXJpbHkgaGlkZGVuIGxldmVsIDx0cj4gYW5kIHNlZ21lbnQgPHRkPiBET00gbm9kZXNcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBzZWc7XG4gICAgICAgIHZhciBzZWdzQmVsb3c7IC8vIGFycmF5IG9mIHNlZ21lbnQgb2JqZWN0cyBiZWxvdyBgc2VnYCBpbiB0aGUgY3VycmVudCBgY29sYFxuICAgICAgICB2YXIgdG90YWxTZWdzQmVsb3c7IC8vIHRvdGFsIG51bWJlciBvZiBzZWdtZW50cyBiZWxvdyBgc2VnYCBpbiBhbnkgb2YgdGhlIGNvbHVtbnMgYHNlZ2Agb2NjdXBpZXNcbiAgICAgICAgdmFyIGNvbFNlZ3NCZWxvdzsgLy8gYXJyYXkgb2Ygc2VnbWVudCBhcnJheXMsIGJlbG93IHNlZywgb25lIGZvciBlYWNoIGNvbHVtbiAob2Zmc2V0IGZyb20gc2VncydzIGZpcnN0IGNvbHVtbilcbiAgICAgICAgdmFyIHRkO1xuICAgICAgICB2YXIgcm93U3BhbjtcbiAgICAgICAgdmFyIHNlZ01vcmVOb2RlczsgLy8gYXJyYXkgb2YgXCJtb3JlXCIgPHRkPiBjZWxscyB0aGF0IHdpbGwgc3RhbmQtaW4gZm9yIHRoZSBjdXJyZW50IHNlZydzIGNlbGxcbiAgICAgICAgdmFyIGo7XG4gICAgICAgIHZhciBtb3JlVGQ7XG4gICAgICAgIHZhciBtb3JlV3JhcDtcbiAgICAgICAgdmFyIG1vcmVMaW5rO1xuICAgICAgICAvLyBJdGVyYXRlcyB0aHJvdWdoIGVtcHR5IGxldmVsIGNlbGxzIGFuZCBwbGFjZXMgXCJtb3JlXCIgbGlua3MgaW5zaWRlIGlmIG5lZWQgYmVcbiAgICAgICAgdmFyIGVtcHR5Q2VsbHNVbnRpbCA9IGZ1bmN0aW9uIChlbmRDb2wpIHtcbiAgICAgICAgICAgIHdoaWxlIChjb2wgPCBlbmRDb2wpIHtcbiAgICAgICAgICAgICAgICBzZWdzQmVsb3cgPSBfdGhpcy5nZXRDZWxsU2Vncyhyb3csIGNvbCwgbGV2ZWxMaW1pdCk7XG4gICAgICAgICAgICAgICAgaWYgKHNlZ3NCZWxvdy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGQgPSBjZWxsTWF0cml4W2xldmVsTGltaXQgLSAxXVtjb2xdO1xuICAgICAgICAgICAgICAgICAgICBtb3JlTGluayA9IF90aGlzLnJlbmRlck1vcmVMaW5rKHJvdywgY29sLCBzZWdzQmVsb3cpO1xuICAgICAgICAgICAgICAgICAgICBtb3JlV3JhcCA9IGNyZWF0ZUVsZW1lbnQoJ2RpdicsIG51bGwsIG1vcmVMaW5rKTtcbiAgICAgICAgICAgICAgICAgICAgdGQuYXBwZW5kQ2hpbGQobW9yZVdyYXApO1xuICAgICAgICAgICAgICAgICAgICBtb3JlTm9kZXMucHVzaChtb3JlV3JhcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAobGV2ZWxMaW1pdCAmJiBsZXZlbExpbWl0IDwgcm93U3RydWN0LnNlZ0xldmVscy5sZW5ndGgpIHsgLy8gaXMgaXQgYWN0dWFsbHkgb3ZlciB0aGUgbGltaXQ/XG4gICAgICAgICAgICBsZXZlbFNlZ3MgPSByb3dTdHJ1Y3Quc2VnTGV2ZWxzW2xldmVsTGltaXQgLSAxXTtcbiAgICAgICAgICAgIGNlbGxNYXRyaXggPSByb3dTdHJ1Y3QuY2VsbE1hdHJpeDtcbiAgICAgICAgICAgIGxpbWl0ZWROb2RlcyA9IGZpbmRDaGlsZHJlbihyb3dTdHJ1Y3QudGJvZHlFbCkuc2xpY2UobGV2ZWxMaW1pdCk7IC8vIGdldCBsZXZlbCA8dHI+IGVsZW1lbnRzIHBhc3QgdGhlIGxpbWl0XG4gICAgICAgICAgICBsaW1pdGVkTm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgICAgIG5vZGUuY2xhc3NMaXN0LmFkZCgnZmMtbGltaXRlZCcpOyAvLyBoaWRlIGVsZW1lbnRzIGFuZCBnZXQgYSBzaW1wbGUgRE9NLW5vZGVzIGFycmF5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIGl0ZXJhdGUgdGhvdWdoIHNlZ21lbnRzIGluIHRoZSBsYXN0IGFsbG93YWJsZSBsZXZlbFxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxldmVsU2Vncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNlZyA9IGxldmVsU2Vnc1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVmdENvbCA9IGlzUnRsID8gKGNvbENudCAtIDEgLSBzZWcubGFzdENvbCkgOiBzZWcuZmlyc3RDb2w7XG4gICAgICAgICAgICAgICAgdmFyIHJpZ2h0Q29sID0gaXNSdGwgPyAoY29sQ250IC0gMSAtIHNlZy5maXJzdENvbCkgOiBzZWcubGFzdENvbDtcbiAgICAgICAgICAgICAgICBlbXB0eUNlbGxzVW50aWwobGVmdENvbCk7IC8vIHByb2Nlc3MgZW1wdHkgY2VsbHMgYmVmb3JlIHRoZSBzZWdtZW50XG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lICphbGwqIHNlZ21lbnRzIGJlbG93IGBzZWdgIHRoYXQgb2NjdXB5IHRoZSBzYW1lIGNvbHVtbnNcbiAgICAgICAgICAgICAgICBjb2xTZWdzQmVsb3cgPSBbXTtcbiAgICAgICAgICAgICAgICB0b3RhbFNlZ3NCZWxvdyA9IDA7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGNvbCA8PSByaWdodENvbCkge1xuICAgICAgICAgICAgICAgICAgICBzZWdzQmVsb3cgPSB0aGlzLmdldENlbGxTZWdzKHJvdywgY29sLCBsZXZlbExpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgY29sU2Vnc0JlbG93LnB1c2goc2Vnc0JlbG93KTtcbiAgICAgICAgICAgICAgICAgICAgdG90YWxTZWdzQmVsb3cgKz0gc2Vnc0JlbG93Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgY29sKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0b3RhbFNlZ3NCZWxvdykgeyAvLyBkbyB3ZSBuZWVkIHRvIHJlcGxhY2UgdGhpcyBzZWdtZW50IHdpdGggb25lIG9yIG1hbnkgXCJtb3JlXCIgbGlua3M/XG4gICAgICAgICAgICAgICAgICAgIHRkID0gY2VsbE1hdHJpeFtsZXZlbExpbWl0IC0gMV1bbGVmdENvbF07IC8vIHRoZSBzZWdtZW50J3MgcGFyZW50IGNlbGxcbiAgICAgICAgICAgICAgICAgICAgcm93U3BhbiA9IHRkLnJvd1NwYW4gfHwgMTtcbiAgICAgICAgICAgICAgICAgICAgc2VnTW9yZU5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgIC8vIG1ha2UgYSByZXBsYWNlbWVudCA8dGQ+IGZvciBlYWNoIGNvbHVtbiB0aGUgc2VnbWVudCBvY2N1cGllcy4gd2lsbCBiZSBvbmUgZm9yIGVhY2ggY29sc3BhblxuICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgY29sU2Vnc0JlbG93Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb3JlVGQgPSBjcmVhdGVFbGVtZW50KCd0ZCcsIHsgY2xhc3NOYW1lOiAnZmMtbW9yZS1jZWxsJywgcm93U3Bhbjogcm93U3BhbiB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlZ3NCZWxvdyA9IGNvbFNlZ3NCZWxvd1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vcmVMaW5rID0gdGhpcy5yZW5kZXJNb3JlTGluayhyb3csIGxlZnRDb2wgKyBqLCBbc2VnXS5jb25jYXQoc2Vnc0JlbG93KSAvLyBjb3VudCBzZWcgYXMgaGlkZGVuIHRvb1xuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vcmVXcmFwID0gY3JlYXRlRWxlbWVudCgnZGl2JywgbnVsbCwgbW9yZUxpbmspO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW9yZVRkLmFwcGVuZENoaWxkKG1vcmVXcmFwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlZ01vcmVOb2Rlcy5wdXNoKG1vcmVUZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb3JlTm9kZXMucHVzaChtb3JlVGQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRkLmNsYXNzTGlzdC5hZGQoJ2ZjLWxpbWl0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0QWZ0ZXJFbGVtZW50KHRkLCBzZWdNb3JlTm9kZXMpO1xuICAgICAgICAgICAgICAgICAgICBsaW1pdGVkTm9kZXMucHVzaCh0ZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW1wdHlDZWxsc1VudGlsKHRoaXMuY29sQ250KTsgLy8gZmluaXNoIG9mZiB0aGUgbGV2ZWxcbiAgICAgICAgICAgIHJvd1N0cnVjdC5tb3JlRWxzID0gbW9yZU5vZGVzOyAvLyBmb3IgZWFzeSB1bmRvaW5nIGxhdGVyXG4gICAgICAgICAgICByb3dTdHJ1Y3QubGltaXRlZEVscyA9IGxpbWl0ZWROb2RlczsgLy8gZm9yIGVhc3kgdW5kb2luZyBsYXRlclxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBSZXZlYWxzIGFsbCBsZXZlbHMgYW5kIHJlbW92ZXMgYWxsIFwibW9yZVwiLXJlbGF0ZWQgZWxlbWVudHMgZm9yIGEgZ3JpZCdzIHJvdy5cbiAgICAvLyBgcm93YCBpcyBhIHJvdyBudW1iZXIuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUudW5saW1pdFJvdyA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIHJvd1N0cnVjdCA9IHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzW3Jvd107XG4gICAgICAgIGlmIChyb3dTdHJ1Y3QubW9yZUVscykge1xuICAgICAgICAgICAgcm93U3RydWN0Lm1vcmVFbHMuZm9yRWFjaChyZW1vdmVFbGVtZW50KTtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5tb3JlRWxzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocm93U3RydWN0LmxpbWl0ZWRFbHMpIHtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5saW1pdGVkRWxzLmZvckVhY2goZnVuY3Rpb24gKGxpbWl0ZWRFbCkge1xuICAgICAgICAgICAgICAgIGxpbWl0ZWRFbC5jbGFzc0xpc3QucmVtb3ZlKCdmYy1saW1pdGVkJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJvd1N0cnVjdC5saW1pdGVkRWxzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gUmVuZGVycyBhbiA8YT4gZWxlbWVudCB0aGF0IHJlcHJlc2VudHMgaGlkZGVuIGV2ZW50IGVsZW1lbnQgZm9yIGEgY2VsbC5cbiAgICAvLyBSZXNwb25zaWJsZSBmb3IgYXR0YWNoaW5nIGNsaWNrIGhhbmRsZXIgYXMgd2VsbC5cbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXJNb3JlTGluayA9IGZ1bmN0aW9uIChyb3csIGNvbCwgaGlkZGVuU2Vncykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3LCBkYXRlRW52ID0gX2EuZGF0ZUVudiwgb3B0aW9ucyA9IF9hLm9wdGlvbnMsIGlzUnRsID0gX2EuaXNSdGw7XG4gICAgICAgIHZhciBhID0gY3JlYXRlRWxlbWVudCgnYScsIHsgY2xhc3NOYW1lOiAnZmMtbW9yZScgfSk7XG4gICAgICAgIGEuaW5uZXJUZXh0ID0gdGhpcy5nZXRNb3JlTGlua1RleHQoaGlkZGVuU2Vncy5sZW5ndGgpO1xuICAgICAgICBhLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgY2xpY2tPcHRpb24gPSBvcHRpb25zLmV2ZW50TGltaXRDbGljaztcbiAgICAgICAgICAgIHZhciBfY29sID0gaXNSdGwgPyBfdGhpcy5jb2xDbnQgLSBjb2wgLSAxIDogY29sOyAvLyBIQUNLOiBwcm9wcy5jZWxscyBoYXMgZGlmZmVyZW50IGRpciBzeXN0ZW0/XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IF90aGlzLnByb3BzLmNlbGxzW3Jvd11bX2NvbF0uZGF0ZTtcbiAgICAgICAgICAgIHZhciBtb3JlRWwgPSBldi5jdXJyZW50VGFyZ2V0O1xuICAgICAgICAgICAgdmFyIGRheUVsID0gX3RoaXMuZ2V0Q2VsbEVsKHJvdywgY29sKTtcbiAgICAgICAgICAgIHZhciBhbGxTZWdzID0gX3RoaXMuZ2V0Q2VsbFNlZ3Mocm93LCBjb2wpO1xuICAgICAgICAgICAgLy8gcmVzY29wZSB0aGUgc2VnbWVudHMgdG8gYmUgd2l0aGluIHRoZSBjZWxsJ3MgZGF0ZVxuICAgICAgICAgICAgdmFyIHJlc2xpY2VkQWxsU2VncyA9IF90aGlzLnJlc2xpY2VEYXlTZWdzKGFsbFNlZ3MsIGRhdGUpO1xuICAgICAgICAgICAgdmFyIHJlc2xpY2VkSGlkZGVuU2VncyA9IF90aGlzLnJlc2xpY2VEYXlTZWdzKGhpZGRlblNlZ3MsIGRhdGUpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjbGlja09wdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIC8vIHRoZSByZXR1cm5lZCB2YWx1ZSBjYW4gYmUgYW4gYXRvbWljIG9wdGlvblxuICAgICAgICAgICAgICAgIGNsaWNrT3B0aW9uID0gY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudExpbWl0Q2xpY2snLCBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IGRhdGVFbnYudG9EYXRlKGRhdGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYWxsRGF5OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF5RWw6IGRheUVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW9yZUVsOiBtb3JlRWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZWdzOiByZXNsaWNlZEFsbFNlZ3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW5TZWdzOiByZXNsaWNlZEhpZGRlblNlZ3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IHZpZXdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNsaWNrT3B0aW9uID09PSAncG9wb3ZlcicpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zaG93U2VnUG9wb3Zlcihyb3csIGNvbCwgbW9yZUVsLCByZXNsaWNlZEFsbFNlZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGNsaWNrT3B0aW9uID09PSAnc3RyaW5nJykgeyAvLyBhIHZpZXcgbmFtZVxuICAgICAgICAgICAgICAgIGNhbGVuZGFyLnpvb21UbyhkYXRlLCBjbGlja09wdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9O1xuICAgIC8vIFJldmVhbHMgdGhlIHBvcG92ZXIgdGhhdCBkaXNwbGF5cyBhbGwgZXZlbnRzIHdpdGhpbiBhIGNlbGxcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5zaG93U2VnUG9wb3ZlciA9IGZ1bmN0aW9uIChyb3csIGNvbCwgbW9yZUxpbmssIHNlZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldywgdGhlbWUgPSBfYS50aGVtZSwgaXNSdGwgPSBfYS5pc1J0bDtcbiAgICAgICAgdmFyIF9jb2wgPSBpc1J0bCA/IHRoaXMuY29sQ250IC0gY29sIC0gMSA6IGNvbDsgLy8gSEFDSzogcHJvcHMuY2VsbHMgaGFzIGRpZmZlcmVudCBkaXIgc3lzdGVtP1xuICAgICAgICB2YXIgbW9yZVdyYXAgPSBtb3JlTGluay5wYXJlbnROb2RlOyAvLyB0aGUgPGRpdj4gd3JhcHBlciBhcm91bmQgdGhlIDxhPlxuICAgICAgICB2YXIgdG9wRWw7IC8vIHRoZSBlbGVtZW50IHdlIHdhbnQgdG8gbWF0Y2ggdGhlIHRvcCBjb29yZGluYXRlIG9mXG4gICAgICAgIHZhciBvcHRpb25zO1xuICAgICAgICBpZiAodGhpcy5yb3dDbnQgPT09IDEpIHtcbiAgICAgICAgICAgIHRvcEVsID0gdmlldy5lbDsgLy8gd2lsbCBjYXVzZSB0aGUgcG9wb3ZlciB0byBjb3ZlciBhbnkgc29ydCBvZiBoZWFkZXJcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRvcEVsID0gdGhpcy5yb3dFbHNbcm93XTsgLy8gd2lsbCBhbGlnbiB3aXRoIHRvcCBvZiByb3dcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zID0ge1xuICAgICAgICAgICAgY2xhc3NOYW1lOiAnZmMtbW9yZS1wb3BvdmVyICcgKyB0aGVtZS5nZXRDbGFzcygncG9wb3ZlcicpLFxuICAgICAgICAgICAgcGFyZW50RWw6IHZpZXcuZWwsXG4gICAgICAgICAgICB0b3A6IGNvbXB1dGVSZWN0KHRvcEVsKS50b3AsXG4gICAgICAgICAgICBhdXRvSGlkZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNlZ1BvcG92ZXJUaWxlID0gbmV3IERheVRpbGUoZWwpO1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZVNlZ1BvcG92ZXJUaWxlKF90aGlzLnByb3BzLmNlbGxzW3Jvd11bX2NvbF0uZGF0ZSwgc2Vncyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGlkZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNlZ1BvcG92ZXJUaWxlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZWdQb3BvdmVyVGlsZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2VnUG9wb3Zlci5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2VnUG9wb3ZlciA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIERldGVybWluZSBob3Jpem9udGFsIGNvb3JkaW5hdGUuXG4gICAgICAgIC8vIFdlIHVzZSB0aGUgbW9yZVdyYXAgaW5zdGVhZCBvZiB0aGUgPHRkPiB0byBhdm9pZCBib3JkZXIgY29uZnVzaW9uLlxuICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgIG9wdGlvbnMucmlnaHQgPSBjb21wdXRlUmVjdChtb3JlV3JhcCkucmlnaHQgKyAxOyAvLyArMSB0byBiZSBvdmVyIGNlbGwgYm9yZGVyXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zLmxlZnQgPSBjb21wdXRlUmVjdChtb3JlV3JhcCkubGVmdCAtIDE7IC8vIC0xIHRvIGJlIG92ZXIgY2VsbCBib3JkZXJcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlZ1BvcG92ZXIgPSBuZXcgUG9wb3ZlcihvcHRpb25zKTtcbiAgICAgICAgdGhpcy5zZWdQb3BvdmVyLnNob3coKTtcbiAgICAgICAgY2FsZW5kYXIucmVsZWFzZUFmdGVyU2l6aW5nVHJpZ2dlcnMoKTsgLy8gaGFjayBmb3IgZXZlbnRQb3NpdGlvbmVkXG4gICAgfTtcbiAgICAvLyBHaXZlbiB0aGUgZXZlbnRzIHdpdGhpbiBhbiBhcnJheSBvZiBzZWdtZW50IG9iamVjdHMsIHJlc2xpY2UgdGhlbSB0byBiZSBpbiBhIHNpbmdsZSBkYXlcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5yZXNsaWNlRGF5U2VncyA9IGZ1bmN0aW9uIChzZWdzLCBkYXlEYXRlKSB7XG4gICAgICAgIHZhciBkYXlTdGFydCA9IGRheURhdGU7XG4gICAgICAgIHZhciBkYXlFbmQgPSBhZGREYXlzKGRheVN0YXJ0LCAxKTtcbiAgICAgICAgdmFyIGRheVJhbmdlID0geyBzdGFydDogZGF5U3RhcnQsIGVuZDogZGF5RW5kIH07XG4gICAgICAgIHZhciBuZXdTZWdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc2Vnc18xID0gc2VnczsgX2kgPCBzZWdzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2VnID0gc2Vnc18xW19pXTtcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gc2VnLmV2ZW50UmFuZ2U7XG4gICAgICAgICAgICB2YXIgb3JpZ1JhbmdlID0gZXZlbnRSYW5nZS5yYW5nZTtcbiAgICAgICAgICAgIHZhciBzbGljZWRSYW5nZSA9IGludGVyc2VjdFJhbmdlcyhvcmlnUmFuZ2UsIGRheVJhbmdlKTtcbiAgICAgICAgICAgIGlmIChzbGljZWRSYW5nZSkge1xuICAgICAgICAgICAgICAgIG5ld1NlZ3MucHVzaChfX2Fzc2lnbih7fSwgc2VnLCB7IGV2ZW50UmFuZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogZXZlbnRSYW5nZS5kZWYsXG4gICAgICAgICAgICAgICAgICAgICAgICB1aTogX19hc3NpZ24oe30sIGV2ZW50UmFuZ2UudWksIHsgZHVyYXRpb25FZGl0YWJsZTogZmFsc2UgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZTogZXZlbnRSYW5nZS5pbnN0YW5jZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlOiBzbGljZWRSYW5nZVxuICAgICAgICAgICAgICAgICAgICB9LCBpc1N0YXJ0OiBzZWcuaXNTdGFydCAmJiBzbGljZWRSYW5nZS5zdGFydC52YWx1ZU9mKCkgPT09IG9yaWdSYW5nZS5zdGFydC52YWx1ZU9mKCksIGlzRW5kOiBzZWcuaXNFbmQgJiYgc2xpY2VkUmFuZ2UuZW5kLnZhbHVlT2YoKSA9PT0gb3JpZ1JhbmdlLmVuZC52YWx1ZU9mKCkgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdTZWdzO1xuICAgIH07XG4gICAgLy8gR2VuZXJhdGVzIHRoZSB0ZXh0IHRoYXQgc2hvdWxkIGJlIGluc2lkZSBhIFwibW9yZVwiIGxpbmssIGdpdmVuIHRoZSBudW1iZXIgb2YgZXZlbnRzIGl0IHJlcHJlc2VudHNcbiAgICBEYXlHcmlkLnByb3RvdHlwZS5nZXRNb3JlTGlua1RleHQgPSBmdW5jdGlvbiAobnVtKSB7XG4gICAgICAgIHZhciBvcHQgPSB0aGlzLmNvbnRleHQub3B0aW9ucy5ldmVudExpbWl0VGV4dDtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHQobnVtKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnKycgKyBudW0gKyAnICcgKyBvcHQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIFJldHVybnMgc2VnbWVudHMgd2l0aGluIGEgZ2l2ZW4gY2VsbC5cbiAgICAvLyBJZiBgc3RhcnRMZXZlbGAgaXMgc3BlY2lmaWVkLCByZXR1cm5zIG9ubHkgZXZlbnRzIGluY2x1ZGluZyBhbmQgYmVsb3cgdGhhdCBsZXZlbC4gT3RoZXJ3aXNlIHJldHVybnMgYWxsIHNlZ3MuXG4gICAgRGF5R3JpZC5wcm90b3R5cGUuZ2V0Q2VsbFNlZ3MgPSBmdW5jdGlvbiAocm93LCBjb2wsIHN0YXJ0TGV2ZWwpIHtcbiAgICAgICAgdmFyIHNlZ01hdHJpeCA9IHRoaXMuZXZlbnRSZW5kZXJlci5yb3dTdHJ1Y3RzW3Jvd10uc2VnTWF0cml4O1xuICAgICAgICB2YXIgbGV2ZWwgPSBzdGFydExldmVsIHx8IDA7XG4gICAgICAgIHZhciBzZWdzID0gW107XG4gICAgICAgIHZhciBzZWc7XG4gICAgICAgIHdoaWxlIChsZXZlbCA8IHNlZ01hdHJpeC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHNlZyA9IHNlZ01hdHJpeFtsZXZlbF1bY29sXTtcbiAgICAgICAgICAgIGlmIChzZWcpIHtcbiAgICAgICAgICAgICAgICBzZWdzLnB1c2goc2VnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldmVsKys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZ3M7XG4gICAgfTtcbiAgICByZXR1cm4gRGF5R3JpZDtcbn0oRGF0ZUNvbXBvbmVudCkpO1xuXG52YXIgV0VFS19OVU1fRk9STUFUJDEgPSBjcmVhdGVGb3JtYXR0ZXIoeyB3ZWVrOiAnbnVtZXJpYycgfSk7XG4vKiBBbiBhYnN0cmFjdCBjbGFzcyBmb3IgdGhlIGRheWdyaWQgdmlld3MsIGFzIHdlbGwgYXMgbW9udGggdmlldy4gUmVuZGVycyBvbmUgb3IgbW9yZSByb3dzIG9mIGRheSBjZWxscy5cbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLy8gSXQgaXMgYSBtYW5hZ2VyIGZvciBhIERheUdyaWQgc3ViY29tcG9uZW50LCB3aGljaCBkb2VzIG1vc3Qgb2YgdGhlIGhlYXZ5IGxpZnRpbmcuXG4vLyBJdCBpcyByZXNwb25zaWJsZSBmb3IgbWFuYWdpbmcgd2lkdGgvaGVpZ2h0LlxudmFyIEFic3RyYWN0RGF5R3JpZFZpZXcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEFic3RyYWN0RGF5R3JpZFZpZXcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWJzdHJhY3REYXlHcmlkVmlldygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnByb2Nlc3NPcHRpb25zID0gbWVtb2l6ZShfdGhpcy5fcHJvY2Vzc09wdGlvbnMpO1xuICAgICAgICBfdGhpcy5yZW5kZXJTa2VsZXRvbiA9IG1lbW9pemVSZW5kZXJpbmcoX3RoaXMuX3JlbmRlclNrZWxldG9uLCBfdGhpcy5fdW5yZW5kZXJTa2VsZXRvbik7XG4gICAgICAgIC8qIEhlYWRlciBSZW5kZXJpbmdcbiAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgd2lsbCBnbyBiZWZvcmUgdGhlIGRheS1vZiB3ZWVrIGhlYWRlciBjZWxsc1xuICAgICAgICBfdGhpcy5yZW5kZXJIZWFkSW50cm9IdG1sID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMuY29udGV4dCwgdGhlbWUgPSBfYS50aGVtZSwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcnICtcbiAgICAgICAgICAgICAgICAgICAgJzx0aCBjbGFzcz1cImZjLXdlZWstbnVtYmVyICcgKyB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0SGVhZGVyJykgKyAnXCIgJyArIF90aGlzLndlZWtOdW1iZXJTdHlsZUF0dHIoKSArICc+JyArXG4gICAgICAgICAgICAgICAgICAgICc8c3Bhbj4nICsgLy8gbmVlZGVkIGZvciBtYXRjaENlbGxXaWR0aHNcbiAgICAgICAgICAgICAgICAgICAgaHRtbEVzY2FwZShvcHRpb25zLndlZWtMYWJlbCkgK1xuICAgICAgICAgICAgICAgICAgICAnPC9zcGFuPicgK1xuICAgICAgICAgICAgICAgICAgICAnPC90aD4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9O1xuICAgICAgICAvKiBEYXkgR3JpZCBSZW5kZXJpbmdcbiAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgd2lsbCBnbyBiZWZvcmUgY29udGVudC1za2VsZXRvbiBjZWxscyB0aGF0IGRpc3BsYXkgdGhlIGRheS93ZWVrIG51bWJlcnNcbiAgICAgICAgX3RoaXMucmVuZGVyRGF5R3JpZE51bWJlckludHJvSHRtbCA9IGZ1bmN0aW9uIChyb3csIGRheUdyaWQpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLmNvbnRleHQsIG9wdGlvbnMgPSBfYS5vcHRpb25zLCBkYXRlRW52ID0gX2EuZGF0ZUVudjtcbiAgICAgICAgICAgIHZhciB3ZWVrU3RhcnQgPSBkYXlHcmlkLnByb3BzLmNlbGxzW3Jvd11bMF0uZGF0ZTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJycgK1xuICAgICAgICAgICAgICAgICAgICAnPHRkIGNsYXNzPVwiZmMtd2Vlay1udW1iZXJcIiAnICsgX3RoaXMud2Vla051bWJlclN0eWxlQXR0cigpICsgJz4nICtcbiAgICAgICAgICAgICAgICAgICAgYnVpbGRHb3RvQW5jaG9ySHRtbCgvLyBhc2lkZSBmcm9tIGxpbmssIGltcG9ydGFudCBmb3IgbWF0Y2hDZWxsV2lkdGhzXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMsIGRhdGVFbnYsIHsgZGF0ZTogd2Vla1N0YXJ0LCB0eXBlOiAnd2VlaycsIGZvcmNlT2ZmOiBkYXlHcmlkLmNvbENudCA9PT0gMSB9LCBkYXRlRW52LmZvcm1hdCh3ZWVrU3RhcnQsIFdFRUtfTlVNX0ZPUk1BVCQxKSAvLyBpbm5lciBIVE1MXG4gICAgICAgICAgICAgICAgICAgICkgK1xuICAgICAgICAgICAgICAgICAgICAnPC90ZD4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9O1xuICAgICAgICAvLyBHZW5lcmF0ZXMgdGhlIEhUTUwgdGhhdCBnb2VzIGJlZm9yZSB0aGUgZGF5IGJnIGNlbGxzIGZvciBlYWNoIGRheS1yb3dcbiAgICAgICAgX3RoaXMucmVuZGVyRGF5R3JpZEJnSW50cm9IdG1sID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHRoZW1lID0gX3RoaXMuY29udGV4dC50aGVtZTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJzx0ZCBjbGFzcz1cImZjLXdlZWstbnVtYmVyICcgKyB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0Q29udGVudCcpICsgJ1wiICcgKyBfdGhpcy53ZWVrTnVtYmVyU3R5bGVBdHRyKCkgKyAnPjwvdGQ+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfTtcbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSBIVE1MIHRoYXQgZ29lcyBiZWZvcmUgZXZlcnkgb3RoZXIgdHlwZSBvZiByb3cgZ2VuZXJhdGVkIGJ5IERheUdyaWQuXG4gICAgICAgIC8vIEFmZmVjdHMgbWlycm9yLXNrZWxldG9uIGFuZCBoaWdobGlnaHQtc2tlbGV0b24gcm93cy5cbiAgICAgICAgX3RoaXMucmVuZGVyRGF5R3JpZEludHJvSHRtbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2xXZWVrTnVtYmVyc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJzx0ZCBjbGFzcz1cImZjLXdlZWstbnVtYmVyXCIgJyArIF90aGlzLndlZWtOdW1iZXJTdHlsZUF0dHIoKSArICc+PC90ZD4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLl9wcm9jZXNzT3B0aW9ucyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zLndlZWtOdW1iZXJzKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy53ZWVrTnVtYmVyc1dpdGhpbkRheXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNlbGxXZWVrTnVtYmVyc1Zpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNlbGxXZWVrTnVtYmVyc1Zpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNvbFdlZWtOdW1iZXJzVmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwcm9wcywgY29udGV4dCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnJlbmRlci5jYWxsKHRoaXMsIHByb3BzLCBjb250ZXh0KTtcbiAgICAgICAgdGhpcy5wcm9jZXNzT3B0aW9ucyhjb250ZXh0Lm9wdGlvbnMpO1xuICAgICAgICB0aGlzLnJlbmRlclNrZWxldG9uKGNvbnRleHQpO1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMucmVuZGVyU2tlbGV0b24udW5yZW5kZXIoKTtcbiAgICB9O1xuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLl9yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LmFkZCgnZmMtZGF5R3JpZC12aWV3Jyk7XG4gICAgICAgIHRoaXMuZWwuaW5uZXJIVE1MID0gdGhpcy5yZW5kZXJTa2VsZXRvbkh0bWwoKTtcbiAgICAgICAgdGhpcy5zY3JvbGxlciA9IG5ldyBTY3JvbGxDb21wb25lbnQoJ2hpZGRlbicsIC8vIG92ZXJmbG93IHhcbiAgICAgICAgJ2F1dG8nIC8vIG92ZXJmbG93IHlcbiAgICAgICAgKTtcbiAgICAgICAgdmFyIGRheUdyaWRDb250YWluZXJFbCA9IHRoaXMuc2Nyb2xsZXIuZWw7XG4gICAgICAgIHRoaXMuZWwucXVlcnlTZWxlY3RvcignLmZjLWJvZHkgPiB0ciA+IHRkJykuYXBwZW5kQ2hpbGQoZGF5R3JpZENvbnRhaW5lckVsKTtcbiAgICAgICAgZGF5R3JpZENvbnRhaW5lckVsLmNsYXNzTGlzdC5hZGQoJ2ZjLWRheS1ncmlkLWNvbnRhaW5lcicpO1xuICAgICAgICB2YXIgZGF5R3JpZEVsID0gY3JlYXRlRWxlbWVudCgnZGl2JywgeyBjbGFzc05hbWU6ICdmYy1kYXktZ3JpZCcgfSk7XG4gICAgICAgIGRheUdyaWRDb250YWluZXJFbC5hcHBlbmRDaGlsZChkYXlHcmlkRWwpO1xuICAgICAgICB0aGlzLmRheUdyaWQgPSBuZXcgRGF5R3JpZChkYXlHcmlkRWwsIHtcbiAgICAgICAgICAgIHJlbmRlck51bWJlckludHJvSHRtbDogdGhpcy5yZW5kZXJEYXlHcmlkTnVtYmVySW50cm9IdG1sLFxuICAgICAgICAgICAgcmVuZGVyQmdJbnRyb0h0bWw6IHRoaXMucmVuZGVyRGF5R3JpZEJnSW50cm9IdG1sLFxuICAgICAgICAgICAgcmVuZGVySW50cm9IdG1sOiB0aGlzLnJlbmRlckRheUdyaWRJbnRyb0h0bWwsXG4gICAgICAgICAgICBjb2xXZWVrTnVtYmVyc1Zpc2libGU6IHRoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlLFxuICAgICAgICAgICAgY2VsbFdlZWtOdW1iZXJzVmlzaWJsZTogdGhpcy5jZWxsV2Vla051bWJlcnNWaXNpYmxlXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuX3VucmVuZGVyU2tlbGV0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LnJlbW92ZSgnZmMtZGF5R3JpZC12aWV3Jyk7XG4gICAgICAgIHRoaXMuZGF5R3JpZC5kZXN0cm95KCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsZXIuZGVzdHJveSgpO1xuICAgIH07XG4gICAgLy8gQnVpbGRzIHRoZSBIVE1MIHNrZWxldG9uIGZvciB0aGUgdmlldy5cbiAgICAvLyBUaGUgZGF5LWdyaWQgY29tcG9uZW50IHdpbGwgcmVuZGVyIGluc2lkZSBvZiBhIGNvbnRhaW5lciBkZWZpbmVkIGJ5IHRoaXMgSFRNTC5cbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5yZW5kZXJTa2VsZXRvbkh0bWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29udGV4dCwgdGhlbWUgPSBfYS50aGVtZSwgb3B0aW9ucyA9IF9hLm9wdGlvbnM7XG4gICAgICAgIHJldHVybiAnJyArXG4gICAgICAgICAgICAnPHRhYmxlIGNsYXNzPVwiJyArIHRoZW1lLmdldENsYXNzKCd0YWJsZUdyaWQnKSArICdcIj4nICtcbiAgICAgICAgICAgIChvcHRpb25zLmNvbHVtbkhlYWRlciA/XG4gICAgICAgICAgICAgICAgJzx0aGVhZCBjbGFzcz1cImZjLWhlYWRcIj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzx0cj4nICtcbiAgICAgICAgICAgICAgICAgICAgJzx0ZCBjbGFzcz1cImZjLWhlYWQtY29udGFpbmVyICcgKyB0aGVtZS5nZXRDbGFzcygnd2lkZ2V0SGVhZGVyJykgKyAnXCI+Jm5ic3A7PC90ZD4nICtcbiAgICAgICAgICAgICAgICAgICAgJzwvdHI+JyArXG4gICAgICAgICAgICAgICAgICAgICc8L3RoZWFkPicgOlxuICAgICAgICAgICAgICAgICcnKSArXG4gICAgICAgICAgICAnPHRib2R5IGNsYXNzPVwiZmMtYm9keVwiPicgK1xuICAgICAgICAgICAgJzx0cj4nICtcbiAgICAgICAgICAgICc8dGQgY2xhc3M9XCInICsgdGhlbWUuZ2V0Q2xhc3MoJ3dpZGdldENvbnRlbnQnKSArICdcIj48L3RkPicgK1xuICAgICAgICAgICAgJzwvdHI+JyArXG4gICAgICAgICAgICAnPC90Ym9keT4nICtcbiAgICAgICAgICAgICc8L3RhYmxlPic7XG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZXMgYW4gSFRNTCBhdHRyaWJ1dGUgc3RyaW5nIGZvciBzZXR0aW5nIHRoZSB3aWR0aCBvZiB0aGUgd2VlayBudW1iZXIgY29sdW1uLCBpZiBpdCBpcyBrbm93blxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLndlZWtOdW1iZXJTdHlsZUF0dHIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLndlZWtOdW1iZXJXaWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3N0eWxlPVwid2lkdGg6JyArIHRoaXMud2Vla051bWJlcldpZHRoICsgJ3B4XCInO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuICAgIC8vIERldGVybWluZXMgd2hldGhlciBlYWNoIHJvdyBzaG91bGQgaGF2ZSBhIGNvbnN0YW50IGhlaWdodFxuICAgIEFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmhhc1JpZ2lkUm93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGV2ZW50TGltaXQgPSB0aGlzLmNvbnRleHQub3B0aW9ucy5ldmVudExpbWl0O1xuICAgICAgICByZXR1cm4gZXZlbnRMaW1pdCAmJiB0eXBlb2YgZXZlbnRMaW1pdCAhPT0gJ251bWJlcic7XG4gICAgfTtcbiAgICAvKiBEaW1lbnNpb25zXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS51cGRhdGVTaXplID0gZnVuY3Rpb24gKGlzUmVzaXplLCB2aWV3SGVpZ2h0LCBpc0F1dG8pIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS51cGRhdGVTaXplLmNhbGwodGhpcywgaXNSZXNpemUsIHZpZXdIZWlnaHQsIGlzQXV0byk7IC8vIHdpbGwgY2FsbCB1cGRhdGVCYXNlU2l6ZS4gaW1wb3J0YW50IHRoYXQgZXhlY3V0ZXMgZmlyc3RcbiAgICAgICAgdGhpcy5kYXlHcmlkLnVwZGF0ZVNpemUoaXNSZXNpemUpO1xuICAgIH07XG4gICAgLy8gUmVmcmVzaGVzIHRoZSBob3Jpem9udGFsIGRpbWVuc2lvbnMgb2YgdGhlIHZpZXdcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS51cGRhdGVCYXNlU2l6ZSA9IGZ1bmN0aW9uIChpc1Jlc2l6ZSwgdmlld0hlaWdodCwgaXNBdXRvKSB7XG4gICAgICAgIHZhciBkYXlHcmlkID0gdGhpcy5kYXlHcmlkO1xuICAgICAgICB2YXIgZXZlbnRMaW1pdCA9IHRoaXMuY29udGV4dC5vcHRpb25zLmV2ZW50TGltaXQ7XG4gICAgICAgIHZhciBoZWFkUm93RWwgPSB0aGlzLmhlYWRlciA/IHRoaXMuaGVhZGVyLmVsIDogbnVsbDsgLy8gSEFDS1xuICAgICAgICB2YXIgc2Nyb2xsZXJIZWlnaHQ7XG4gICAgICAgIHZhciBzY3JvbGxiYXJXaWR0aHM7XG4gICAgICAgIC8vIGhhY2sgdG8gZ2l2ZSB0aGUgdmlldyBzb21lIGhlaWdodCBwcmlvciB0byBkYXlHcmlkJ3MgY29sdW1ucyBiZWluZyByZW5kZXJlZFxuICAgICAgICAvLyBUT0RPOiBzZXBhcmF0ZSBzZXR0aW5nIGhlaWdodCBmcm9tIHNjcm9sbGVyIFZTIGRheUdyaWQuXG4gICAgICAgIGlmICghZGF5R3JpZC5yb3dFbHMpIHtcbiAgICAgICAgICAgIGlmICghaXNBdXRvKSB7XG4gICAgICAgICAgICAgICAgc2Nyb2xsZXJIZWlnaHQgPSB0aGlzLmNvbXB1dGVTY3JvbGxlckhlaWdodCh2aWV3SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbGVyLnNldEhlaWdodChzY3JvbGxlckhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY29sV2Vla051bWJlcnNWaXNpYmxlKSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIHdlZWsgbnVtYmVyIGNlbGxzIHJ1bm5pbmcgZG93biB0aGUgc2lkZSBoYXZlIHRoZSBzYW1lIHdpZHRoLlxuICAgICAgICAgICAgdGhpcy53ZWVrTnVtYmVyV2lkdGggPSBtYXRjaENlbGxXaWR0aHMoZmluZEVsZW1lbnRzKHRoaXMuZWwsICcuZmMtd2Vlay1udW1iZXInKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzZXQgYWxsIGhlaWdodHMgdG8gYmUgbmF0dXJhbFxuICAgICAgICB0aGlzLnNjcm9sbGVyLmNsZWFyKCk7XG4gICAgICAgIGlmIChoZWFkUm93RWwpIHtcbiAgICAgICAgICAgIHVuY29tcGVuc2F0ZVNjcm9sbChoZWFkUm93RWwpO1xuICAgICAgICB9XG4gICAgICAgIGRheUdyaWQucmVtb3ZlU2VnUG9wb3ZlcigpOyAvLyBraWxsIHRoZSBcIm1vcmVcIiBwb3BvdmVyIGlmIGRpc3BsYXllZFxuICAgICAgICAvLyBpcyB0aGUgZXZlbnQgbGltaXQgYSBjb25zdGFudCBsZXZlbCBudW1iZXI/XG4gICAgICAgIGlmIChldmVudExpbWl0ICYmIHR5cGVvZiBldmVudExpbWl0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgZGF5R3JpZC5saW1pdFJvd3MoZXZlbnRMaW1pdCk7IC8vIGxpbWl0IHRoZSBsZXZlbHMgZmlyc3Qgc28gdGhlIGhlaWdodCBjYW4gcmVkaXN0cmlidXRlIGFmdGVyXG4gICAgICAgIH1cbiAgICAgICAgLy8gZGlzdHJpYnV0ZSB0aGUgaGVpZ2h0IHRvIHRoZSByb3dzXG4gICAgICAgIC8vICh2aWV3SGVpZ2h0IGlzIGEgXCJyZWNvbW1lbmRlZFwiIHZhbHVlIGlmIGlzQXV0bylcbiAgICAgICAgc2Nyb2xsZXJIZWlnaHQgPSB0aGlzLmNvbXB1dGVTY3JvbGxlckhlaWdodCh2aWV3SGVpZ2h0KTtcbiAgICAgICAgdGhpcy5zZXRHcmlkSGVpZ2h0KHNjcm9sbGVySGVpZ2h0LCBpc0F1dG8pO1xuICAgICAgICAvLyBpcyB0aGUgZXZlbnQgbGltaXQgZHluYW1pY2FsbHkgY2FsY3VsYXRlZD9cbiAgICAgICAgaWYgKGV2ZW50TGltaXQgJiYgdHlwZW9mIGV2ZW50TGltaXQgIT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBkYXlHcmlkLmxpbWl0Um93cyhldmVudExpbWl0KTsgLy8gbGltaXQgdGhlIGxldmVscyBhZnRlciB0aGUgZ3JpZCdzIHJvdyBoZWlnaHRzIGhhdmUgYmVlbiBzZXRcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzQXV0bykgeyAvLyBzaG91bGQgd2UgZm9yY2UgZGltZW5zaW9ucyBvZiB0aGUgc2Nyb2xsIGNvbnRhaW5lcj9cbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsZXIuc2V0SGVpZ2h0KHNjcm9sbGVySGVpZ2h0KTtcbiAgICAgICAgICAgIHNjcm9sbGJhcldpZHRocyA9IHRoaXMuc2Nyb2xsZXIuZ2V0U2Nyb2xsYmFyV2lkdGhzKCk7XG4gICAgICAgICAgICBpZiAoc2Nyb2xsYmFyV2lkdGhzLmxlZnQgfHwgc2Nyb2xsYmFyV2lkdGhzLnJpZ2h0KSB7IC8vIHVzaW5nIHNjcm9sbGJhcnM/XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRSb3dFbCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wZW5zYXRlU2Nyb2xsKGhlYWRSb3dFbCwgc2Nyb2xsYmFyV2lkdGhzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gZG9pbmcgdGhlIHNjcm9sbGJhciBjb21wZW5zYXRpb24gbWlnaHQgaGF2ZSBjcmVhdGVkIHRleHQgb3ZlcmZsb3cgd2hpY2ggY3JlYXRlZCBtb3JlIGhlaWdodC4gcmVkb1xuICAgICAgICAgICAgICAgIHNjcm9sbGVySGVpZ2h0ID0gdGhpcy5jb21wdXRlU2Nyb2xsZXJIZWlnaHQodmlld0hlaWdodCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxlci5zZXRIZWlnaHQoc2Nyb2xsZXJIZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZ3VhcmFudGVlcyB0aGUgc2FtZSBzY3JvbGxiYXIgd2lkdGhzXG4gICAgICAgICAgICB0aGlzLnNjcm9sbGVyLmxvY2tPdmVyZmxvdyhzY3JvbGxiYXJXaWR0aHMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBnaXZlbiBhIGRlc2lyZWQgdG90YWwgaGVpZ2h0IG9mIHRoZSB2aWV3LCByZXR1cm5zIHdoYXQgdGhlIGhlaWdodCBvZiB0aGUgc2Nyb2xsZXIgc2hvdWxkIGJlXG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuY29tcHV0ZVNjcm9sbGVySGVpZ2h0ID0gZnVuY3Rpb24gKHZpZXdIZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHZpZXdIZWlnaHQgLVxuICAgICAgICAgICAgc3VidHJhY3RJbm5lckVsSGVpZ2h0KHRoaXMuZWwsIHRoaXMuc2Nyb2xsZXIuZWwpOyAvLyBldmVyeXRoaW5nIHRoYXQncyBOT1QgdGhlIHNjcm9sbGVyXG4gICAgfTtcbiAgICAvLyBTZXRzIHRoZSBoZWlnaHQgb2YganVzdCB0aGUgRGF5R3JpZCBjb21wb25lbnQgaW4gdGhpcyB2aWV3XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuc2V0R3JpZEhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQsIGlzQXV0bykge1xuICAgICAgICBpZiAodGhpcy5jb250ZXh0Lm9wdGlvbnMubW9udGhNb2RlKSB7XG4gICAgICAgICAgICAvLyBpZiBhdXRvLCBtYWtlIHRoZSBoZWlnaHQgb2YgZWFjaCByb3cgdGhlIGhlaWdodCB0aGF0IGl0IHdvdWxkIGJlIGlmIHRoZXJlIHdlcmUgNiB3ZWVrc1xuICAgICAgICAgICAgaWYgKGlzQXV0bykge1xuICAgICAgICAgICAgICAgIGhlaWdodCAqPSB0aGlzLmRheUdyaWQucm93Q250IC8gNjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3RyaWJ1dGVIZWlnaHQodGhpcy5kYXlHcmlkLnJvd0VscywgaGVpZ2h0LCAhaXNBdXRvKTsgLy8gaWYgYXV0bywgZG9uJ3QgY29tcGVuc2F0ZSBmb3IgaGVpZ2h0LWhvZ2dpbmcgcm93c1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzQXV0bykge1xuICAgICAgICAgICAgICAgIHVuZGlzdHJpYnV0ZUhlaWdodCh0aGlzLmRheUdyaWQucm93RWxzKTsgLy8gbGV0IHRoZSByb3dzIGJlIHRoZWlyIG5hdHVyYWwgaGVpZ2h0IHdpdGggbm8gZXhwYW5kaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXN0cmlidXRlSGVpZ2h0KHRoaXMuZGF5R3JpZC5yb3dFbHMsIGhlaWdodCwgdHJ1ZSk7IC8vIHRydWUgPSBjb21wZW5zYXRlIGZvciBoZWlnaHQtaG9nZ2luZyByb3dzXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qIFNjcm9sbFxuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuY29tcHV0ZURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoZHVyYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIHsgdG9wOiAwIH07XG4gICAgfTtcbiAgICBBYnN0cmFjdERheUdyaWRWaWV3LnByb3RvdHlwZS5xdWVyeURhdGVTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7IHRvcDogdGhpcy5zY3JvbGxlci5nZXRTY3JvbGxUb3AoKSB9O1xuICAgIH07XG4gICAgQWJzdHJhY3REYXlHcmlkVmlldy5wcm90b3R5cGUuYXBwbHlEYXRlU2Nyb2xsID0gZnVuY3Rpb24gKHNjcm9sbCkge1xuICAgICAgICBpZiAoc2Nyb2xsLnRvcCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbGVyLnNldFNjcm9sbFRvcChzY3JvbGwudG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEFic3RyYWN0RGF5R3JpZFZpZXc7XG59KFZpZXcpKTtcbkFic3RyYWN0RGF5R3JpZFZpZXcucHJvdG90eXBlLmRhdGVQcm9maWxlR2VuZXJhdG9yQ2xhc3MgPSBEYXlHcmlkRGF0ZVByb2ZpbGVHZW5lcmF0b3I7XG5cbnZhciBTaW1wbGVEYXlHcmlkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhTaW1wbGVEYXlHcmlkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNpbXBsZURheUdyaWQoZGF5R3JpZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBkYXlHcmlkLmVsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zbGljZXIgPSBuZXcgRGF5R3JpZFNsaWNlcigpO1xuICAgICAgICBfdGhpcy5kYXlHcmlkID0gZGF5R3JpZDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTaW1wbGVEYXlHcmlkLnByb3RvdHlwZS5maXJzdENvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICBjb250ZXh0LmNhbGVuZGFyLnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcywgeyBlbDogdGhpcy5kYXlHcmlkLmVsIH0pO1xuICAgIH07XG4gICAgU2ltcGxlRGF5R3JpZC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuY29udGV4dC5jYWxlbmRhci51bnJlZ2lzdGVySW50ZXJhY3RpdmVDb21wb25lbnQodGhpcyk7XG4gICAgfTtcbiAgICBTaW1wbGVEYXlHcmlkLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGRheUdyaWQgPSB0aGlzLmRheUdyaWQ7XG4gICAgICAgIHZhciBkYXRlUHJvZmlsZSA9IHByb3BzLmRhdGVQcm9maWxlLCBkYXlUYWJsZSA9IHByb3BzLmRheVRhYmxlO1xuICAgICAgICBkYXlHcmlkLnJlY2VpdmVDb250ZXh0KGNvbnRleHQpOyAvLyBoYWNrIGJlY2F1c2UgY29udGV4dCBpcyB1c2VkIGluIHNsaWNlUHJvcHNcbiAgICAgICAgZGF5R3JpZC5yZWNlaXZlUHJvcHMoX19hc3NpZ24oe30sIHRoaXMuc2xpY2VyLnNsaWNlUHJvcHMocHJvcHMsIGRhdGVQcm9maWxlLCBwcm9wcy5uZXh0RGF5VGhyZXNob2xkLCBjb250ZXh0LmNhbGVuZGFyLCBkYXlHcmlkLCBkYXlUYWJsZSksIHsgZGF0ZVByb2ZpbGU6IGRhdGVQcm9maWxlLCBjZWxsczogZGF5VGFibGUuY2VsbHMsIGlzUmlnaWQ6IHByb3BzLmlzUmlnaWQgfSksIGNvbnRleHQpO1xuICAgIH07XG4gICAgU2ltcGxlRGF5R3JpZC5wcm90b3R5cGUuYnVpbGRQb3NpdGlvbkNhY2hlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXlHcmlkLmJ1aWxkUG9zaXRpb25DYWNoZXMoKTtcbiAgICB9O1xuICAgIFNpbXBsZURheUdyaWQucHJvdG90eXBlLnF1ZXJ5SGl0ID0gZnVuY3Rpb24gKHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3ApIHtcbiAgICAgICAgdmFyIHJhd0hpdCA9IHRoaXMuZGF5R3JpZC5wb3NpdGlvblRvSGl0KHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3ApO1xuICAgICAgICBpZiAocmF3SGl0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudDogdGhpcy5kYXlHcmlkLFxuICAgICAgICAgICAgICAgIGRhdGVTcGFuOiByYXdIaXQuZGF0ZVNwYW4sXG4gICAgICAgICAgICAgICAgZGF5RWw6IHJhd0hpdC5kYXlFbCxcbiAgICAgICAgICAgICAgICByZWN0OiB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IHJhd0hpdC5yZWxhdGl2ZVJlY3QubGVmdCxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IHJhd0hpdC5yZWxhdGl2ZVJlY3QucmlnaHQsXG4gICAgICAgICAgICAgICAgICAgIHRvcDogcmF3SGl0LnJlbGF0aXZlUmVjdC50b3AsXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbTogcmF3SGl0LnJlbGF0aXZlUmVjdC5ib3R0b21cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxheWVyOiAwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gU2ltcGxlRGF5R3JpZDtcbn0oRGF0ZUNvbXBvbmVudCkpO1xudmFyIERheUdyaWRTbGljZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKERheUdyaWRTbGljZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF5R3JpZFNsaWNlcigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBEYXlHcmlkU2xpY2VyLnByb3RvdHlwZS5zbGljZVJhbmdlID0gZnVuY3Rpb24gKGRhdGVSYW5nZSwgZGF5VGFibGUpIHtcbiAgICAgICAgcmV0dXJuIGRheVRhYmxlLnNsaWNlUmFuZ2UoZGF0ZVJhbmdlKTtcbiAgICB9O1xuICAgIHJldHVybiBEYXlHcmlkU2xpY2VyO1xufShTbGljZXIpKTtcblxudmFyIERheUdyaWRWaWV3ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXlHcmlkVmlldywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXlHcmlkVmlldygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmJ1aWxkRGF5VGFibGUgPSBtZW1vaXplKGJ1aWxkRGF5VGFibGUpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERheUdyaWRWaWV3LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZW5kZXIuY2FsbCh0aGlzLCBwcm9wcywgY29udGV4dCk7IC8vIHdpbGwgY2FsbCBfcmVuZGVyU2tlbGV0b24vX3VucmVuZGVyU2tlbGV0b25cbiAgICAgICAgdmFyIGRhdGVQcm9maWxlID0gdGhpcy5wcm9wcy5kYXRlUHJvZmlsZTtcbiAgICAgICAgdmFyIGRheVRhYmxlID0gdGhpcy5kYXlUYWJsZSA9XG4gICAgICAgICAgICB0aGlzLmJ1aWxkRGF5VGFibGUoZGF0ZVByb2ZpbGUsIHByb3BzLmRhdGVQcm9maWxlR2VuZXJhdG9yKTtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlci5yZWNlaXZlUHJvcHMoe1xuICAgICAgICAgICAgICAgIGRhdGVQcm9maWxlOiBkYXRlUHJvZmlsZSxcbiAgICAgICAgICAgICAgICBkYXRlczogZGF5VGFibGUuaGVhZGVyRGF0ZXMsXG4gICAgICAgICAgICAgICAgZGF0ZXNSZXBEaXN0aW5jdERheXM6IGRheVRhYmxlLnJvd0NudCA9PT0gMSxcbiAgICAgICAgICAgICAgICByZW5kZXJJbnRyb0h0bWw6IHRoaXMucmVuZGVySGVhZEludHJvSHRtbFxuICAgICAgICAgICAgfSwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zaW1wbGVEYXlHcmlkLnJlY2VpdmVQcm9wcyh7XG4gICAgICAgICAgICBkYXRlUHJvZmlsZTogZGF0ZVByb2ZpbGUsXG4gICAgICAgICAgICBkYXlUYWJsZTogZGF5VGFibGUsXG4gICAgICAgICAgICBidXNpbmVzc0hvdXJzOiBwcm9wcy5idXNpbmVzc0hvdXJzLFxuICAgICAgICAgICAgZGF0ZVNlbGVjdGlvbjogcHJvcHMuZGF0ZVNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IHByb3BzLmV2ZW50U3RvcmUsXG4gICAgICAgICAgICBldmVudFVpQmFzZXM6IHByb3BzLmV2ZW50VWlCYXNlcyxcbiAgICAgICAgICAgIGV2ZW50U2VsZWN0aW9uOiBwcm9wcy5ldmVudFNlbGVjdGlvbixcbiAgICAgICAgICAgIGV2ZW50RHJhZzogcHJvcHMuZXZlbnREcmFnLFxuICAgICAgICAgICAgZXZlbnRSZXNpemU6IHByb3BzLmV2ZW50UmVzaXplLFxuICAgICAgICAgICAgaXNSaWdpZDogdGhpcy5oYXNSaWdpZFJvd3MoKSxcbiAgICAgICAgICAgIG5leHREYXlUaHJlc2hvbGQ6IHRoaXMuY29udGV4dC5uZXh0RGF5VGhyZXNob2xkXG4gICAgICAgIH0sIGNvbnRleHQpO1xuICAgIH07XG4gICAgRGF5R3JpZFZpZXcucHJvdG90eXBlLl9yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuX3JlbmRlclNrZWxldG9uLmNhbGwodGhpcywgY29udGV4dCk7XG4gICAgICAgIGlmIChjb250ZXh0Lm9wdGlvbnMuY29sdW1uSGVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWRlciA9IG5ldyBEYXlIZWFkZXIodGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZmMtaGVhZC1jb250YWluZXInKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zaW1wbGVEYXlHcmlkID0gbmV3IFNpbXBsZURheUdyaWQodGhpcy5kYXlHcmlkKTtcbiAgICB9O1xuICAgIERheUdyaWRWaWV3LnByb3RvdHlwZS5fdW5yZW5kZXJTa2VsZXRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5fdW5yZW5kZXJTa2VsZXRvbi5jYWxsKHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5oZWFkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNpbXBsZURheUdyaWQuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIERheUdyaWRWaWV3O1xufShBYnN0cmFjdERheUdyaWRWaWV3KSk7XG5mdW5jdGlvbiBidWlsZERheVRhYmxlKGRhdGVQcm9maWxlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcikge1xuICAgIHZhciBkYXlTZXJpZXMgPSBuZXcgRGF5U2VyaWVzKGRhdGVQcm9maWxlLnJlbmRlclJhbmdlLCBkYXRlUHJvZmlsZUdlbmVyYXRvcik7XG4gICAgcmV0dXJuIG5ldyBEYXlUYWJsZShkYXlTZXJpZXMsIC95ZWFyfG1vbnRofHdlZWsvLnRlc3QoZGF0ZVByb2ZpbGUuY3VycmVudFJhbmdlVW5pdCkpO1xufVxuXG52YXIgbWFpbiA9IGNyZWF0ZVBsdWdpbih7XG4gICAgZGVmYXVsdFZpZXc6ICdkYXlHcmlkTW9udGgnLFxuICAgIHZpZXdzOiB7XG4gICAgICAgIGRheUdyaWQ6IERheUdyaWRWaWV3LFxuICAgICAgICBkYXlHcmlkRGF5OiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyBkYXlzOiAxIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5R3JpZFdlZWs6IHtcbiAgICAgICAgICAgIHR5cGU6ICdkYXlHcmlkJyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiB7IHdlZWtzOiAxIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5R3JpZE1vbnRoOiB7XG4gICAgICAgICAgICB0eXBlOiAnZGF5R3JpZCcsXG4gICAgICAgICAgICBkdXJhdGlvbjogeyBtb250aHM6IDEgfSxcbiAgICAgICAgICAgIG1vbnRoTW9kZTogdHJ1ZSxcbiAgICAgICAgICAgIGZpeGVkV2Vla0NvdW50OiB0cnVlXG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgbWFpbjtcbmV4cG9ydCB7IEFic3RyYWN0RGF5R3JpZFZpZXcsIERheUJnUm93LCBEYXlHcmlkLCBEYXlHcmlkU2xpY2VyLCBEYXlHcmlkVmlldywgU2ltcGxlRGF5R3JpZCwgYnVpbGREYXlUYWJsZSBhcyBidWlsZEJhc2ljRGF5VGFibGUgfTtcbiIsIi8qIVxuRnVsbENhbGVuZGFyIEludGVyYWN0aW9uIFBsdWdpbiB2NC40LjJcbkRvY3MgJiBMaWNlbnNlOiBodHRwczovL2Z1bGxjYWxlbmRhci5pby9cbihjKSAyMDE5IEFkYW0gU2hhd1xuKi9cblxuaW1wb3J0IHsgY29uZmlnLCBlbGVtZW50Q2xvc2VzdCwgRW1pdHRlck1peGluLCBhcHBseVN0eWxlLCB3aGVuVHJhbnNpdGlvbkRvbmUsIHJlbW92ZUVsZW1lbnQsIFNjcm9sbENvbnRyb2xsZXIsIEVsZW1lbnRTY3JvbGxDb250cm9sbGVyLCBjb21wdXRlSW5uZXJSZWN0LCBXaW5kb3dTY3JvbGxDb250cm9sbGVyLCBwcmV2ZW50U2VsZWN0aW9uLCBwcmV2ZW50Q29udGV4dE1lbnUsIGFsbG93U2VsZWN0aW9uLCBhbGxvd0NvbnRleHRNZW51LCBFbGVtZW50RHJhZ2dpbmcsIGNvbXB1dGVSZWN0LCBnZXRDbGlwcGluZ1BhcmVudHMsIHBvaW50SW5zaWRlUmVjdCwgaXNEYXRlU3BhbnNFcXVhbCwgY29uc3RyYWluUG9pbnQsIGludGVyc2VjdFJlY3RzLCBnZXRSZWN0Q2VudGVyLCBkaWZmUG9pbnRzLCBtYXBIYXNoLCByYW5nZUNvbnRhaW5zUmFuZ2UsIGludGVyYWN0aW9uU2V0dGluZ3NUb1N0b3JlLCBJbnRlcmFjdGlvbiwgZW5hYmxlQ3Vyc29yLCBkaXNhYmxlQ3Vyc29yLCBjb21wYXJlTnVtYmVycywgZ2V0RWxTZWcsIGdldFJlbGV2YW50RXZlbnRzLCBFdmVudEFwaSwgY3JlYXRlRW1wdHlFdmVudFN0b3JlLCBhcHBseU11dGF0aW9uVG9FdmVudFN0b3JlLCBpbnRlcmFjdGlvblNldHRpbmdzU3RvcmUsIHN0YXJ0T2ZEYXksIGRpZmZEYXRlcywgY3JlYXRlRHVyYXRpb24sIGV2ZW50VHVwbGVUb1N0b3JlLCBpc0ludGVyYWN0aW9uVmFsaWQsIHBhcnNlRHJhZ01ldGEsIGVsZW1lbnRNYXRjaGVzLCBwYXJzZUV2ZW50RGVmLCBjcmVhdGVFdmVudEluc3RhbmNlLCBnbG9iYWxEZWZhdWx0cywgY3JlYXRlUGx1Z2luIH0gZnJvbSAnQGZ1bGxjYWxlbmRhci9jb3JlJztcblxuLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxudmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH07XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufTtcblxuY29uZmlnLnRvdWNoTW91c2VJZ25vcmVXYWl0ID0gNTAwO1xudmFyIGlnbm9yZU1vdXNlRGVwdGggPSAwO1xudmFyIGxpc3RlbmVyQ250ID0gMDtcbnZhciBpc1dpbmRvd1RvdWNoTW92ZUNhbmNlbGxlZCA9IGZhbHNlO1xuLypcblVzZXMgYSBcInBvaW50ZXJcIiBhYnN0cmFjdGlvbiwgd2hpY2ggbW9uaXRvcnMgVUkgZXZlbnRzIGZvciBib3RoIG1vdXNlIGFuZCB0b3VjaC5cblRyYWNrcyB3aGVuIHRoZSBwb2ludGVyIFwiZHJhZ3NcIiBvbiBhIGNlcnRhaW4gZWxlbWVudCwgbWVhbmluZyBkb3duK21vdmUrdXAuXG5cbkFsc28sIHRyYWNrcyBpZiB0aGVyZSB3YXMgdG91Y2gtc2Nyb2xsaW5nLlxuQWxzbywgY2FuIHByZXZlbnQgdG91Y2gtc2Nyb2xsaW5nIGZyb20gaGFwcGVuaW5nLlxuQWxzbywgY2FuIGZpcmUgcG9pbnRlcm1vdmUgZXZlbnRzIHdoZW4gc2Nyb2xsaW5nIGhhcHBlbnMgdW5kZXJuZWF0aCwgZXZlbiB3aGVuIG5vIHJlYWwgcG9pbnRlciBtb3ZlbWVudC5cblxuZW1pdHM6XG4tIHBvaW50ZXJkb3duXG4tIHBvaW50ZXJtb3ZlXG4tIHBvaW50ZXJ1cFxuKi9cbnZhciBQb2ludGVyRHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUG9pbnRlckRyYWdnaW5nKGNvbnRhaW5lckVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3ViamVjdEVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5kb3duRWwgPSBudWxsO1xuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIGRpcmVjdGx5IGFzc2lnbmVkIGJ5IGNhbGxlclxuICAgICAgICB0aGlzLnNlbGVjdG9yID0gJyc7IC8vIHdpbGwgY2F1c2Ugc3ViamVjdEVsIGluIGFsbCBlbWl0dGVkIGV2ZW50cyB0byBiZSB0aGlzIGVsZW1lbnRcbiAgICAgICAgdGhpcy5oYW5kbGVTZWxlY3RvciA9ICcnO1xuICAgICAgICB0aGlzLnNob3VsZElnbm9yZU1vdmUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zaG91bGRXYXRjaFNjcm9sbCA9IHRydWU7IC8vIGZvciBzaW11bGF0aW5nIHBvaW50ZXJtb3ZlIG9uIHNjcm9sbFxuICAgICAgICAvLyBpbnRlcm5hbCBzdGF0ZXNcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNUb3VjaERyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMud2FzVG91Y2hTY3JvbGwgPSBmYWxzZTtcbiAgICAgICAgLy8gTW91c2VcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3VzZSgpICYmXG4gICAgICAgICAgICAgICAgaXNQcmltYXJ5TW91c2VCdXR0b24oZXYpICYmXG4gICAgICAgICAgICAgICAgX3RoaXMudHJ5U3RhcnQoZXYpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBldiA9IF90aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2LCB0cnVlKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgcGV2KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5pbml0U2Nyb2xsV2F0Y2gocGV2KTtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgX3RoaXMuaGFuZGxlTW91c2VNb3ZlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIF90aGlzLmhhbmRsZU1vdXNlVXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZU1vdXNlTW92ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIHBldiA9IF90aGlzLmNyZWF0ZUV2ZW50RnJvbU1vdXNlKGV2KTtcbiAgICAgICAgICAgIF90aGlzLnJlY29yZENvb3JkcyhwZXYpO1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIHBldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlTW91c2VVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgX3RoaXMuaGFuZGxlTW91c2VNb3ZlKTtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBfdGhpcy5oYW5kbGVNb3VzZVVwKTtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgX3RoaXMuY3JlYXRlRXZlbnRGcm9tTW91c2UoZXYpKTtcbiAgICAgICAgICAgIF90aGlzLmNsZWFudXAoKTsgLy8gY2FsbCBsYXN0IHNvIHRoYXQgcG9pbnRlcnVwIGhhcyBhY2Nlc3MgdG8gcHJvcHNcbiAgICAgICAgfTtcbiAgICAgICAgLy8gVG91Y2hcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICB0aGlzLmhhbmRsZVRvdWNoU3RhcnQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy50cnlTdGFydChldikpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc1RvdWNoRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBwZXYgPSBfdGhpcy5jcmVhdGVFdmVudEZyb21Ub3VjaChldiwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIHBldik7XG4gICAgICAgICAgICAgICAgX3RoaXMuaW5pdFNjcm9sbFdhdGNoKHBldik7XG4gICAgICAgICAgICAgICAgLy8gdW5saWtlIG1vdXNlLCBuZWVkIHRvIGF0dGFjaCB0byB0YXJnZXQsIG5vdCBkb2N1bWVudFxuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS80NTc2MDAxNFxuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSBldi50YXJnZXQ7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBfdGhpcy5oYW5kbGVUb3VjaE1vdmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0YXJnZXQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBfdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoY2FuY2VsJywgX3RoaXMuaGFuZGxlVG91Y2hFbmQpOyAvLyB0cmVhdCBpdCBhcyBhIHRvdWNoIGVuZFxuICAgICAgICAgICAgICAgIC8vIGF0dGFjaCBhIGhhbmRsZXIgdG8gZ2V0IGNhbGxlZCB3aGVuIEFOWSBzY3JvbGwgYWN0aW9uIGhhcHBlbnMgb24gdGhlIHBhZ2UuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB3YXMgaW1wb3NzaWJsZSB0byBkbyB3aXRoIG5vcm1hbCBvbi9vZmYgYmVjYXVzZSAnc2Nyb2xsJyBkb2Vzbid0IGJ1YmJsZS5cbiAgICAgICAgICAgICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMjk1NDU2NS85NjM0MlxuICAgICAgICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBfdGhpcy5oYW5kbGVUb3VjaFNjcm9sbCwgdHJ1ZSAvLyB1c2VDYXB0dXJlXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVUb3VjaE1vdmUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBwZXYgPSBfdGhpcy5jcmVhdGVFdmVudEZyb21Ub3VjaChldik7XG4gICAgICAgICAgICBfdGhpcy5yZWNvcmRDb29yZHMocGV2KTtcbiAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcm1vdmUnLCBwZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZVRvdWNoRW5kID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykgeyAvLyBkb25lIHRvIGd1YXJkIGFnYWluc3QgdG91Y2hlbmQgZm9sbG93ZWQgYnkgdG91Y2hjYW5jZWxcbiAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZXYudGFyZ2V0O1xuICAgICAgICAgICAgICAgIHRhcmdldC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBfdGhpcy5oYW5kbGVUb3VjaE1vdmUpO1xuICAgICAgICAgICAgICAgIHRhcmdldC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIF90aGlzLmhhbmRsZVRvdWNoRW5kKTtcbiAgICAgICAgICAgICAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCBfdGhpcy5oYW5kbGVUb3VjaEVuZCk7XG4gICAgICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIF90aGlzLmhhbmRsZVRvdWNoU2Nyb2xsLCB0cnVlKTsgLy8gdXNlQ2FwdHVyZWQ9dHJ1ZVxuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcnVwJywgX3RoaXMuY3JlYXRlRXZlbnRGcm9tVG91Y2goZXYpKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7IC8vIGNhbGwgbGFzdCBzbyB0aGF0IHBvaW50ZXJ1cCBoYXMgYWNjZXNzIHRvIHByb3BzXG4gICAgICAgICAgICAgICAgX3RoaXMuaXNUb3VjaERyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhcnRJZ25vcmluZ01vdXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlVG91Y2hTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy53YXNUb3VjaFNjcm9sbCA9IHRydWU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFnZVggPSAod2luZG93LnBhZ2VYT2Zmc2V0IC0gX3RoaXMucHJldlNjcm9sbFgpICsgX3RoaXMucHJldlBhZ2VYO1xuICAgICAgICAgICAgICAgIHZhciBwYWdlWSA9ICh3aW5kb3cucGFnZVlPZmZzZXQgLSBfdGhpcy5wcmV2U2Nyb2xsWSkgKyBfdGhpcy5wcmV2UGFnZVk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVybW92ZScsIHtcbiAgICAgICAgICAgICAgICAgICAgb3JpZ0V2ZW50OiBldixcbiAgICAgICAgICAgICAgICAgICAgaXNUb3VjaDogX3RoaXMuaXNUb3VjaERyYWdnaW5nLFxuICAgICAgICAgICAgICAgICAgICBzdWJqZWN0RWw6IF90aGlzLnN1YmplY3RFbCxcbiAgICAgICAgICAgICAgICAgICAgcGFnZVg6IHBhZ2VYLFxuICAgICAgICAgICAgICAgICAgICBwYWdlWTogcGFnZVksXG4gICAgICAgICAgICAgICAgICAgIGRlbHRhWDogcGFnZVggLSBfdGhpcy5vcmlnUGFnZVgsXG4gICAgICAgICAgICAgICAgICAgIGRlbHRhWTogcGFnZVkgLSBfdGhpcy5vcmlnUGFnZVlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbCA9IGNvbnRhaW5lckVsO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlck1peGluKCk7XG4gICAgICAgIGNvbnRhaW5lckVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuaGFuZGxlTW91c2VEb3duKTtcbiAgICAgICAgY29udGFpbmVyRWwuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuaGFuZGxlVG91Y2hTdGFydCwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgICBsaXN0ZW5lckNyZWF0ZWQoKTtcbiAgICB9XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuaGFuZGxlTW91c2VEb3duKTtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5oYW5kbGVUb3VjaFN0YXJ0LCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gICAgICAgIGxpc3RlbmVyRGVzdHJveWVkKCk7XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLnRyeVN0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHZhciBzdWJqZWN0RWwgPSB0aGlzLnF1ZXJ5U3ViamVjdEVsKGV2KTtcbiAgICAgICAgdmFyIGRvd25FbCA9IGV2LnRhcmdldDtcbiAgICAgICAgaWYgKHN1YmplY3RFbCAmJlxuICAgICAgICAgICAgKCF0aGlzLmhhbmRsZVNlbGVjdG9yIHx8IGVsZW1lbnRDbG9zZXN0KGRvd25FbCwgdGhpcy5oYW5kbGVTZWxlY3RvcikpKSB7XG4gICAgICAgICAgICB0aGlzLnN1YmplY3RFbCA9IHN1YmplY3RFbDtcbiAgICAgICAgICAgIHRoaXMuZG93bkVsID0gZG93bkVsO1xuICAgICAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTsgLy8gZG8gdGhpcyBmaXJzdCBzbyBjYW5jZWxUb3VjaFNjcm9sbCB3aWxsIHdvcmtcbiAgICAgICAgICAgIHRoaXMud2FzVG91Y2hTY3JvbGwgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY2xlYW51cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXNXaW5kb3dUb3VjaE1vdmVDYW5jZWxsZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc3ViamVjdEVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5kb3duRWwgPSBudWxsO1xuICAgICAgICAvLyBrZWVwIHdhc1RvdWNoU2Nyb2xsIGFyb3VuZCBmb3IgbGF0ZXIgYWNjZXNzXG4gICAgICAgIHRoaXMuZGVzdHJveVNjcm9sbFdhdGNoKCk7XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLnF1ZXJ5U3ViamVjdEVsID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudENsb3Nlc3QoZXYudGFyZ2V0LCB0aGlzLnNlbGVjdG9yKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lckVsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb2ludGVyRHJhZ2dpbmcucHJvdG90eXBlLnNob3VsZElnbm9yZU1vdXNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaWdub3JlTW91c2VEZXB0aCB8fCB0aGlzLmlzVG91Y2hEcmFnZ2luZztcbiAgICB9O1xuICAgIC8vIGNhbiBiZSBjYWxsZWQgYnkgdXNlciBvZiB0aGlzIGNsYXNzLCB0byBjYW5jZWwgdG91Y2gtYmFzZWQgc2Nyb2xsaW5nIGZvciB0aGUgY3VycmVudCBkcmFnXG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5jYW5jZWxUb3VjaFNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgaXNXaW5kb3dUb3VjaE1vdmVDYW5jZWxsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBTY3JvbGxpbmcgdGhhdCBzaW11bGF0ZXMgcG9pbnRlcm1vdmVzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuaW5pdFNjcm9sbFdhdGNoID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZFdhdGNoU2Nyb2xsKSB7XG4gICAgICAgICAgICB0aGlzLnJlY29yZENvb3Jkcyhldik7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVTY3JvbGwsIHRydWUpOyAvLyB1c2VDYXB0dXJlPXRydWVcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9pbnRlckRyYWdnaW5nLnByb3RvdHlwZS5yZWNvcmRDb29yZHMgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgaWYgKHRoaXMuc2hvdWxkV2F0Y2hTY3JvbGwpIHtcbiAgICAgICAgICAgIHRoaXMucHJldlBhZ2VYID0gZXYucGFnZVg7XG4gICAgICAgICAgICB0aGlzLnByZXZQYWdlWSA9IGV2LnBhZ2VZO1xuICAgICAgICAgICAgdGhpcy5wcmV2U2Nyb2xsWCA9IHdpbmRvdy5wYWdlWE9mZnNldDtcbiAgICAgICAgICAgIHRoaXMucHJldlNjcm9sbFkgPSB3aW5kb3cucGFnZVlPZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuZGVzdHJveVNjcm9sbFdhdGNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zaG91bGRXYXRjaFNjcm9sbCkge1xuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsLCB0cnVlKTsgLy8gdXNlQ2FwdHVyZWQ9dHJ1ZVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBFdmVudCBOb3JtYWxpemF0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY3JlYXRlRXZlbnRGcm9tTW91c2UgPSBmdW5jdGlvbiAoZXYsIGlzRmlyc3QpIHtcbiAgICAgICAgdmFyIGRlbHRhWCA9IDA7XG4gICAgICAgIHZhciBkZWx0YVkgPSAwO1xuICAgICAgICAvLyBUT0RPOiByZXBlYXQgY29kZVxuICAgICAgICBpZiAoaXNGaXJzdCkge1xuICAgICAgICAgICAgdGhpcy5vcmlnUGFnZVggPSBldi5wYWdlWDtcbiAgICAgICAgICAgIHRoaXMub3JpZ1BhZ2VZID0gZXYucGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkZWx0YVggPSBldi5wYWdlWCAtIHRoaXMub3JpZ1BhZ2VYO1xuICAgICAgICAgICAgZGVsdGFZID0gZXYucGFnZVkgLSB0aGlzLm9yaWdQYWdlWTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3JpZ0V2ZW50OiBldixcbiAgICAgICAgICAgIGlzVG91Y2g6IGZhbHNlLFxuICAgICAgICAgICAgc3ViamVjdEVsOiB0aGlzLnN1YmplY3RFbCxcbiAgICAgICAgICAgIHBhZ2VYOiBldi5wYWdlWCxcbiAgICAgICAgICAgIHBhZ2VZOiBldi5wYWdlWSxcbiAgICAgICAgICAgIGRlbHRhWDogZGVsdGFYLFxuICAgICAgICAgICAgZGVsdGFZOiBkZWx0YVlcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFBvaW50ZXJEcmFnZ2luZy5wcm90b3R5cGUuY3JlYXRlRXZlbnRGcm9tVG91Y2ggPSBmdW5jdGlvbiAoZXYsIGlzRmlyc3QpIHtcbiAgICAgICAgdmFyIHRvdWNoZXMgPSBldi50b3VjaGVzO1xuICAgICAgICB2YXIgcGFnZVg7XG4gICAgICAgIHZhciBwYWdlWTtcbiAgICAgICAgdmFyIGRlbHRhWCA9IDA7XG4gICAgICAgIHZhciBkZWx0YVkgPSAwO1xuICAgICAgICAvLyBpZiB0b3VjaCBjb29yZHMgYXZhaWxhYmxlLCBwcmVmZXIsXG4gICAgICAgIC8vIGJlY2F1c2UgRkYgd291bGQgZ2l2ZSBiYWQgZXYucGFnZVggZXYucGFnZVlcbiAgICAgICAgaWYgKHRvdWNoZXMgJiYgdG91Y2hlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHBhZ2VYID0gdG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgICAgIHBhZ2VZID0gdG91Y2hlc1swXS5wYWdlWTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBhZ2VYID0gZXYucGFnZVg7XG4gICAgICAgICAgICBwYWdlWSA9IGV2LnBhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IHJlcGVhdCBjb2RlXG4gICAgICAgIGlmIChpc0ZpcnN0KSB7XG4gICAgICAgICAgICB0aGlzLm9yaWdQYWdlWCA9IHBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5vcmlnUGFnZVkgPSBwYWdlWTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlbHRhWCA9IHBhZ2VYIC0gdGhpcy5vcmlnUGFnZVg7XG4gICAgICAgICAgICBkZWx0YVkgPSBwYWdlWSAtIHRoaXMub3JpZ1BhZ2VZO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBvcmlnRXZlbnQ6IGV2LFxuICAgICAgICAgICAgaXNUb3VjaDogdHJ1ZSxcbiAgICAgICAgICAgIHN1YmplY3RFbDogdGhpcy5zdWJqZWN0RWwsXG4gICAgICAgICAgICBwYWdlWDogcGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogcGFnZVksXG4gICAgICAgICAgICBkZWx0YVg6IGRlbHRhWCxcbiAgICAgICAgICAgIGRlbHRhWTogZGVsdGFZXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gUG9pbnRlckRyYWdnaW5nO1xufSgpKTtcbi8vIFJldHVybnMgYSBib29sZWFuIHdoZXRoZXIgdGhpcyB3YXMgYSBsZWZ0IG1vdXNlIGNsaWNrIGFuZCBubyBjdHJsIGtleSAod2hpY2ggbWVhbnMgcmlnaHQgY2xpY2sgb24gTWFjKVxuZnVuY3Rpb24gaXNQcmltYXJ5TW91c2VCdXR0b24oZXYpIHtcbiAgICByZXR1cm4gZXYuYnV0dG9uID09PSAwICYmICFldi5jdHJsS2V5O1xufVxuLy8gSWdub3JpbmcgZmFrZSBtb3VzZSBldmVudHMgZ2VuZXJhdGVkIGJ5IHRvdWNoXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBzdGFydElnbm9yaW5nTW91c2UoKSB7XG4gICAgaWdub3JlTW91c2VEZXB0aCsrO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZ25vcmVNb3VzZURlcHRoLS07XG4gICAgfSwgY29uZmlnLnRvdWNoTW91c2VJZ25vcmVXYWl0KTtcbn1cbi8vIFdlIHdhbnQgdG8gYXR0YWNoIHRvdWNobW92ZSBhcyBlYXJseSBhcyBwb3NzaWJsZSBmb3IgU2FmYXJpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5mdW5jdGlvbiBsaXN0ZW5lckNyZWF0ZWQoKSB7XG4gICAgaWYgKCEobGlzdGVuZXJDbnQrKykpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIG9uV2luZG93VG91Y2hNb3ZlLCB7IHBhc3NpdmU6IGZhbHNlIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGxpc3RlbmVyRGVzdHJveWVkKCkge1xuICAgIGlmICghKC0tbGlzdGVuZXJDbnQpKSB7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBvbldpbmRvd1RvdWNoTW92ZSwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICB9XG59XG5mdW5jdGlvbiBvbldpbmRvd1RvdWNoTW92ZShldikge1xuICAgIGlmIChpc1dpbmRvd1RvdWNoTW92ZUNhbmNlbGxlZCkge1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cblxuLypcbkFuIGVmZmVjdCBpbiB3aGljaCBhbiBlbGVtZW50IGZvbGxvd3MgdGhlIG1vdmVtZW50IG9mIGEgcG9pbnRlciBhY3Jvc3MgdGhlIHNjcmVlbi5cblRoZSBtb3ZpbmcgZWxlbWVudCBpcyBhIGNsb25lIG9mIHNvbWUgb3RoZXIgZWxlbWVudC5cbk11c3QgY2FsbCBzdGFydCArIGhhbmRsZU1vdmUgKyBzdG9wLlxuKi9cbnZhciBFbGVtZW50TWlycm9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEVsZW1lbnRNaXJyb3IoKSB7XG4gICAgICAgIHRoaXMuaXNWaXNpYmxlID0gZmFsc2U7IC8vIG11c3QgYmUgZXhwbGljaXRseSBlbmFibGVkXG4gICAgICAgIHRoaXMuc291cmNlRWwgPSBudWxsO1xuICAgICAgICB0aGlzLm1pcnJvckVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5zb3VyY2VFbFJlY3QgPSBudWxsOyAvLyBzY3JlZW4gY29vcmRzIHJlbGF0aXZlIHRvIHZpZXdwb3J0XG4gICAgICAgIC8vIG9wdGlvbnMgdGhhdCBjYW4gYmUgc2V0IGRpcmVjdGx5IGJ5IGNhbGxlclxuICAgICAgICB0aGlzLnBhcmVudE5vZGUgPSBkb2N1bWVudC5ib2R5O1xuICAgICAgICB0aGlzLnpJbmRleCA9IDk5OTk7XG4gICAgICAgIHRoaXMucmV2ZXJ0RHVyYXRpb24gPSAwO1xuICAgIH1cbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChzb3VyY2VFbCwgcGFnZVgsIHBhZ2VZKSB7XG4gICAgICAgIHRoaXMuc291cmNlRWwgPSBzb3VyY2VFbDtcbiAgICAgICAgdGhpcy5zb3VyY2VFbFJlY3QgPSB0aGlzLnNvdXJjZUVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLm9yaWdTY3JlZW5YID0gcGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQ7XG4gICAgICAgIHRoaXMub3JpZ1NjcmVlblkgPSBwYWdlWSAtIHdpbmRvdy5wYWdlWU9mZnNldDtcbiAgICAgICAgdGhpcy5kZWx0YVggPSAwO1xuICAgICAgICB0aGlzLmRlbHRhWSA9IDA7XG4gICAgICAgIHRoaXMudXBkYXRlRWxQb3NpdGlvbigpO1xuICAgIH07XG4gICAgRWxlbWVudE1pcnJvci5wcm90b3R5cGUuaGFuZGxlTW92ZSA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgdGhpcy5kZWx0YVggPSAocGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQpIC0gdGhpcy5vcmlnU2NyZWVuWDtcbiAgICAgICAgdGhpcy5kZWx0YVkgPSAocGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQpIC0gdGhpcy5vcmlnU2NyZWVuWTtcbiAgICAgICAgdGhpcy51cGRhdGVFbFBvc2l0aW9uKCk7XG4gICAgfTtcbiAgICAvLyBjYW4gYmUgY2FsbGVkIGJlZm9yZSBzdGFydFxuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLnNldElzVmlzaWJsZSA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIGlmIChib29sKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5taXJyb3JFbC5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaXNWaXNpYmxlID0gYm9vbDsgLy8gbmVlZHMgdG8gaGFwcGVuIGJlZm9yZSB1cGRhdGVFbFBvc2l0aW9uXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVFbFBvc2l0aW9uKCk7IC8vIGJlY2F1c2Ugd2FzIG5vdCB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgaW52aXNpYmxlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5taXJyb3JFbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pcnJvckVsLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaXNWaXNpYmxlID0gYm9vbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gYWx3YXlzIGFzeW5jXG4gICAgRWxlbWVudE1pcnJvci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uIChuZWVkc1JldmVydEFuaW1hdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGRvbmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAobmVlZHNSZXZlcnRBbmltYXRpb24gJiZcbiAgICAgICAgICAgIHRoaXMubWlycm9yRWwgJiZcbiAgICAgICAgICAgIHRoaXMuaXNWaXNpYmxlICYmXG4gICAgICAgICAgICB0aGlzLnJldmVydER1cmF0aW9uICYmIC8vIGlmIDAsIHRyYW5zaXRpb24gd29uJ3Qgd29ya1xuICAgICAgICAgICAgKHRoaXMuZGVsdGFYIHx8IHRoaXMuZGVsdGFZKSAvLyBpZiBzYW1lIGNvb3JkcywgdHJhbnNpdGlvbiB3b24ndCB3b3JrXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5kb1JldmVydEFuaW1hdGlvbihkb25lLCB0aGlzLnJldmVydER1cmF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZG9uZSwgMCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmRvUmV2ZXJ0QW5pbWF0aW9uID0gZnVuY3Rpb24gKGNhbGxiYWNrLCByZXZlcnREdXJhdGlvbikge1xuICAgICAgICB2YXIgbWlycm9yRWwgPSB0aGlzLm1pcnJvckVsO1xuICAgICAgICB2YXIgZmluYWxTb3VyY2VFbFJlY3QgPSB0aGlzLnNvdXJjZUVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyBiZWNhdXNlIGF1dG9zY3JvbGxpbmcgbWlnaHQgaGF2ZSBoYXBwZW5lZFxuICAgICAgICBtaXJyb3JFbC5zdHlsZS50cmFuc2l0aW9uID1cbiAgICAgICAgICAgICd0b3AgJyArIHJldmVydER1cmF0aW9uICsgJ21zLCcgK1xuICAgICAgICAgICAgICAgICdsZWZ0ICcgKyByZXZlcnREdXJhdGlvbiArICdtcyc7XG4gICAgICAgIGFwcGx5U3R5bGUobWlycm9yRWwsIHtcbiAgICAgICAgICAgIGxlZnQ6IGZpbmFsU291cmNlRWxSZWN0LmxlZnQsXG4gICAgICAgICAgICB0b3A6IGZpbmFsU291cmNlRWxSZWN0LnRvcFxuICAgICAgICB9KTtcbiAgICAgICAgd2hlblRyYW5zaXRpb25Eb25lKG1pcnJvckVsLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBtaXJyb3JFbC5zdHlsZS50cmFuc2l0aW9uID0gJyc7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmNsZWFudXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm1pcnJvckVsKSB7XG4gICAgICAgICAgICByZW1vdmVFbGVtZW50KHRoaXMubWlycm9yRWwpO1xuICAgICAgICAgICAgdGhpcy5taXJyb3JFbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zb3VyY2VFbCA9IG51bGw7XG4gICAgfTtcbiAgICBFbGVtZW50TWlycm9yLnByb3RvdHlwZS51cGRhdGVFbFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VFbCAmJiB0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgICAgICAgYXBwbHlTdHlsZSh0aGlzLmdldE1pcnJvckVsKCksIHtcbiAgICAgICAgICAgICAgICBsZWZ0OiB0aGlzLnNvdXJjZUVsUmVjdC5sZWZ0ICsgdGhpcy5kZWx0YVgsXG4gICAgICAgICAgICAgICAgdG9wOiB0aGlzLnNvdXJjZUVsUmVjdC50b3AgKyB0aGlzLmRlbHRhWVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEVsZW1lbnRNaXJyb3IucHJvdG90eXBlLmdldE1pcnJvckVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc291cmNlRWxSZWN0ID0gdGhpcy5zb3VyY2VFbFJlY3Q7XG4gICAgICAgIHZhciBtaXJyb3JFbCA9IHRoaXMubWlycm9yRWw7XG4gICAgICAgIGlmICghbWlycm9yRWwpIHtcbiAgICAgICAgICAgIG1pcnJvckVsID0gdGhpcy5taXJyb3JFbCA9IHRoaXMuc291cmNlRWwuY2xvbmVOb2RlKHRydWUpOyAvLyBjbG9uZUNoaWxkcmVuPXRydWVcbiAgICAgICAgICAgIC8vIHdlIGRvbid0IHdhbnQgbG9uZyB0YXBzIG9yIGFueSBtb3VzZSBpbnRlcmFjdGlvbiBjYXVzaW5nIHNlbGVjdGlvbi9tZW51cy5cbiAgICAgICAgICAgIC8vIHdvdWxkIHVzZSBwcmV2ZW50U2VsZWN0aW9uKCksIGJ1dCB0aGF0IHByZXZlbnRzIHNlbGVjdHN0YXJ0LCBjYXVzaW5nIHByb2JsZW1zLlxuICAgICAgICAgICAgbWlycm9yRWwuY2xhc3NMaXN0LmFkZCgnZmMtdW5zZWxlY3RhYmxlJyk7XG4gICAgICAgICAgICBtaXJyb3JFbC5jbGFzc0xpc3QuYWRkKCdmYy1kcmFnZ2luZycpO1xuICAgICAgICAgICAgYXBwbHlTdHlsZShtaXJyb3JFbCwge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnZml4ZWQnLFxuICAgICAgICAgICAgICAgIHpJbmRleDogdGhpcy56SW5kZXgsXG4gICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogJycsXG4gICAgICAgICAgICAgICAgYm94U2l6aW5nOiAnYm9yZGVyLWJveCcsXG4gICAgICAgICAgICAgICAgd2lkdGg6IHNvdXJjZUVsUmVjdC5yaWdodCAtIHNvdXJjZUVsUmVjdC5sZWZ0LFxuICAgICAgICAgICAgICAgIGhlaWdodDogc291cmNlRWxSZWN0LmJvdHRvbSAtIHNvdXJjZUVsUmVjdC50b3AsXG4gICAgICAgICAgICAgICAgcmlnaHQ6ICdhdXRvJyxcbiAgICAgICAgICAgICAgICBib3R0b206ICdhdXRvJyxcbiAgICAgICAgICAgICAgICBtYXJnaW46IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5wYXJlbnROb2RlLmFwcGVuZENoaWxkKG1pcnJvckVsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWlycm9yRWw7XG4gICAgfTtcbiAgICByZXR1cm4gRWxlbWVudE1pcnJvcjtcbn0oKSk7XG5cbi8qXG5JcyBhIGNhY2hlIGZvciBhIGdpdmVuIGVsZW1lbnQncyBzY3JvbGwgaW5mb3JtYXRpb24gKGFsbCB0aGUgaW5mbyB0aGF0IFNjcm9sbENvbnRyb2xsZXIgc3RvcmVzKVxuaW4gYWRkaXRpb24gdGhlIFwiY2xpZW50IHJlY3RhbmdsZVwiIG9mIHRoZSBlbGVtZW50Li4gdGhlIGFyZWEgd2l0aGluIHRoZSBzY3JvbGxiYXJzLlxuXG5UaGUgY2FjaGUgY2FuIGJlIGluIG9uZSBvZiB0d28gbW9kZXM6XG4tIGRvZXNMaXN0ZW5pbmc6ZmFsc2UgLSBpZ25vcmVzIHdoZW4gdGhlIGNvbnRhaW5lciBpcyBzY3JvbGxlZCBieSBzb21lb25lIGVsc2Vcbi0gZG9lc0xpc3RlbmluZzp0cnVlIC0gd2F0Y2ggZm9yIHNjcm9sbGluZyBhbmQgdXBkYXRlIHRoZSBjYWNoZVxuKi9cbnZhciBTY3JvbGxHZW9tQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFNjcm9sbEdlb21DYWNoZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTY3JvbGxHZW9tQ2FjaGUoc2Nyb2xsQ29udHJvbGxlciwgZG9lc0xpc3RlbmluZykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5oYW5kbGVTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5zY3JvbGxUb3AgPSBfdGhpcy5zY3JvbGxDb250cm9sbGVyLmdldFNjcm9sbFRvcCgpO1xuICAgICAgICAgICAgX3RoaXMuc2Nyb2xsTGVmdCA9IF90aGlzLnNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgX3RoaXMuaGFuZGxlU2Nyb2xsQ2hhbmdlKCk7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLnNjcm9sbENvbnRyb2xsZXIgPSBzY3JvbGxDb250cm9sbGVyO1xuICAgICAgICBfdGhpcy5kb2VzTGlzdGVuaW5nID0gZG9lc0xpc3RlbmluZztcbiAgICAgICAgX3RoaXMuc2Nyb2xsVG9wID0gX3RoaXMub3JpZ1Njcm9sbFRvcCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsVG9wKCk7XG4gICAgICAgIF90aGlzLnNjcm9sbExlZnQgPSBfdGhpcy5vcmlnU2Nyb2xsTGVmdCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsTGVmdCgpO1xuICAgICAgICBfdGhpcy5zY3JvbGxXaWR0aCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0U2Nyb2xsV2lkdGgoKTtcbiAgICAgICAgX3RoaXMuc2Nyb2xsSGVpZ2h0ID0gc2Nyb2xsQ29udHJvbGxlci5nZXRTY3JvbGxIZWlnaHQoKTtcbiAgICAgICAgX3RoaXMuY2xpZW50V2lkdGggPSBzY3JvbGxDb250cm9sbGVyLmdldENsaWVudFdpZHRoKCk7XG4gICAgICAgIF90aGlzLmNsaWVudEhlaWdodCA9IHNjcm9sbENvbnRyb2xsZXIuZ2V0Q2xpZW50SGVpZ2h0KCk7XG4gICAgICAgIF90aGlzLmNsaWVudFJlY3QgPSBfdGhpcy5jb21wdXRlQ2xpZW50UmVjdCgpOyAvLyBkbyBsYXN0IGluIGNhc2UgaXQgbmVlZHMgY2FjaGVkIHZhbHVlc1xuICAgICAgICBpZiAoX3RoaXMuZG9lc0xpc3RlbmluZykge1xuICAgICAgICAgICAgX3RoaXMuZ2V0RXZlbnRUYXJnZXQoKS5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBfdGhpcy5oYW5kbGVTY3JvbGwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmdldEV2ZW50VGFyZ2V0KCkucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oYW5kbGVTY3JvbGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldFNjcm9sbFRvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsVG9wO1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxMZWZ0O1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5zZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAodG9wKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udHJvbGxlci5zZXRTY3JvbGxUb3AodG9wKTtcbiAgICAgICAgaWYgKCF0aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSBub3QgcmVseWluZyBvbiB0aGUgZWxlbWVudCB0byBub3JtYWxpemUgb3V0LW9mLWJvdW5kcyBzY3JvbGwgdmFsdWVzXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIHNhbml0aXplIG91cnNlbHZlc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxUb3AgPSBNYXRoLm1heChNYXRoLm1pbih0b3AsIHRoaXMuZ2V0TWF4U2Nyb2xsVG9wKCkpLCAwKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNjcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICh0b3ApIHtcbiAgICAgICAgdGhpcy5zY3JvbGxDb250cm9sbGVyLnNldFNjcm9sbExlZnQodG9wKTtcbiAgICAgICAgaWYgKCF0aGlzLmRvZXNMaXN0ZW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSBub3QgcmVseWluZyBvbiB0aGUgZWxlbWVudCB0byBub3JtYWxpemUgb3V0LW9mLWJvdW5kcyBzY3JvbGwgdmFsdWVzXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIHNhbml0aXplIG91cnNlbHZlc1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxMZWZ0ID0gTWF0aC5tYXgoTWF0aC5taW4odG9wLCB0aGlzLmdldE1heFNjcm9sbExlZnQoKSksIDApO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVTY3JvbGxDaGFuZ2UoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRDbGllbnRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50V2lkdGg7XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldENsaWVudEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50SGVpZ2h0O1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRTY3JvbGxXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsV2lkdGg7XG4gICAgfTtcbiAgICBTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsSGVpZ2h0O1xuICAgIH07XG4gICAgU2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5oYW5kbGVTY3JvbGxDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgfTtcbiAgICByZXR1cm4gU2Nyb2xsR2VvbUNhY2hlO1xufShTY3JvbGxDb250cm9sbGVyKSk7XG52YXIgRWxlbWVudFNjcm9sbEdlb21DYWNoZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRWxlbWVudFNjcm9sbEdlb21DYWNoZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlKGVsLCBkb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuZXcgRWxlbWVudFNjcm9sbENvbnRyb2xsZXIoZWwpLCBkb2VzTGlzdGVuaW5nKSB8fCB0aGlzO1xuICAgIH1cbiAgICBFbGVtZW50U2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5nZXRFdmVudFRhcmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Nyb2xsQ29udHJvbGxlci5lbDtcbiAgICB9O1xuICAgIEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmNvbXB1dGVDbGllbnRSZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gY29tcHV0ZUlubmVyUmVjdCh0aGlzLnNjcm9sbENvbnRyb2xsZXIuZWwpO1xuICAgIH07XG4gICAgcmV0dXJuIEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGU7XG59KFNjcm9sbEdlb21DYWNoZSkpO1xudmFyIFdpbmRvd1Njcm9sbEdlb21DYWNoZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoV2luZG93U2Nyb2xsR2VvbUNhY2hlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFdpbmRvd1Njcm9sbEdlb21DYWNoZShkb2VzTGlzdGVuaW5nKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuZXcgV2luZG93U2Nyb2xsQ29udHJvbGxlcigpLCBkb2VzTGlzdGVuaW5nKSB8fCB0aGlzO1xuICAgIH1cbiAgICBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUucHJvdG90eXBlLmdldEV2ZW50VGFyZ2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gd2luZG93O1xuICAgIH07XG4gICAgV2luZG93U2Nyb2xsR2VvbUNhY2hlLnByb3RvdHlwZS5jb21wdXRlQ2xpZW50UmVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxlZnQ6IHRoaXMuc2Nyb2xsTGVmdCxcbiAgICAgICAgICAgIHJpZ2h0OiB0aGlzLnNjcm9sbExlZnQgKyB0aGlzLmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgdG9wOiB0aGlzLnNjcm9sbFRvcCxcbiAgICAgICAgICAgIGJvdHRvbTogdGhpcy5zY3JvbGxUb3AgKyB0aGlzLmNsaWVudEhlaWdodFxuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gdGhlIHdpbmRvdyBpcyB0aGUgb25seSBzY3JvbGwgb2JqZWN0IHRoYXQgY2hhbmdlcyBpdCdzIHJlY3RhbmdsZSByZWxhdGl2ZVxuICAgIC8vIHRvIHRoZSBkb2N1bWVudCdzIHRvcGxlZnQgYXMgaXQgc2Nyb2xsc1xuICAgIFdpbmRvd1Njcm9sbEdlb21DYWNoZS5wcm90b3R5cGUuaGFuZGxlU2Nyb2xsQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsaWVudFJlY3QgPSB0aGlzLmNvbXB1dGVDbGllbnRSZWN0KCk7XG4gICAgfTtcbiAgICByZXR1cm4gV2luZG93U2Nyb2xsR2VvbUNhY2hlO1xufShTY3JvbGxHZW9tQ2FjaGUpKTtcblxuLy8gSWYgYXZhaWxhYmxlIHdlIGFyZSB1c2luZyBuYXRpdmUgXCJwZXJmb3JtYW5jZVwiIEFQSSBpbnN0ZWFkIG9mIFwiRGF0ZVwiXG4vLyBSZWFkIG1vcmUgYWJvdXQgaXQgb24gTUROOlxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1BlcmZvcm1hbmNlXG52YXIgZ2V0VGltZSA9IHR5cGVvZiBwZXJmb3JtYW5jZSA9PT0gJ2Z1bmN0aW9uJyA/IHBlcmZvcm1hbmNlLm5vdyA6IERhdGUubm93O1xuLypcbkZvciBhIHBvaW50ZXIgaW50ZXJhY3Rpb24sIGF1dG9tYXRpY2FsbHkgc2Nyb2xscyBjZXJ0YWluIHNjcm9sbCBjb250YWluZXJzIHdoZW4gdGhlIHBvaW50ZXJcbmFwcHJvYWNoZXMgdGhlIGVkZ2UuXG5cblRoZSBjYWxsZXIgbXVzdCBjYWxsIHN0YXJ0ICsgaGFuZGxlTW92ZSArIHN0b3AuXG4qL1xudmFyIEF1dG9TY3JvbGxlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBBdXRvU2Nyb2xsZXIoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIG9wdGlvbnMgdGhhdCBjYW4gYmUgc2V0IGJ5IGNhbGxlclxuICAgICAgICB0aGlzLmlzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuc2Nyb2xsUXVlcnkgPSBbd2luZG93LCAnLmZjLXNjcm9sbGVyJ107XG4gICAgICAgIHRoaXMuZWRnZVRocmVzaG9sZCA9IDUwOyAvLyBwaXhlbHNcbiAgICAgICAgdGhpcy5tYXhWZWxvY2l0eSA9IDMwMDsgLy8gcGl4ZWxzIHBlciBzZWNvbmRcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWCA9IG51bGw7XG4gICAgICAgIHRoaXMucG9pbnRlclNjcmVlblkgPSBudWxsO1xuICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ2FjaGVzID0gbnVsbDtcbiAgICAgICAgLy8gcHJvdGVjdCBhZ2FpbnN0IHRoZSBpbml0aWFsIHBvaW50ZXJkb3duIGJlaW5nIHRvbyBjbG9zZSB0byBhbiBlZGdlIGFuZCBzdGFydGluZyB0aGUgc2Nyb2xsXG4gICAgICAgIHRoaXMuZXZlck1vdmVkVXAgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVyTW92ZWREb3duID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXZlck1vdmVkTGVmdCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmV2ZXJNb3ZlZFJpZ2h0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYW5pbWF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0FuaW1hdGluZykgeyAvLyB3YXNuJ3QgY2FuY2VsbGVkIGJldHdlZW4gYW5pbWF0aW9uIGNhbGxzXG4gICAgICAgICAgICAgICAgdmFyIGVkZ2UgPSBfdGhpcy5jb21wdXRlQmVzdEVkZ2UoX3RoaXMucG9pbnRlclNjcmVlblggKyB3aW5kb3cucGFnZVhPZmZzZXQsIF90aGlzLnBvaW50ZXJTY3JlZW5ZICsgd2luZG93LnBhZ2VZT2Zmc2V0KTtcbiAgICAgICAgICAgICAgICBpZiAoZWRnZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm93ID0gZ2V0VGltZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5oYW5kbGVTaWRlKGVkZ2UsIChub3cgLSBfdGhpcy5tc1NpbmNlUmVxdWVzdCkgLyAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVxdWVzdEFuaW1hdGlvbihub3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaXNBbmltYXRpbmcgPSBmYWxzZTsgLy8gd2lsbCBzdG9wIGFuaW1hdGlvblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENhY2hlcyA9IHRoaXMuYnVpbGRDYWNoZXMoKTtcbiAgICAgICAgICAgIHRoaXMucG9pbnRlclNjcmVlblggPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFVwID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZERvd24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZXZlck1vdmVkTGVmdCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ldmVyTW92ZWRSaWdodCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVNb3ZlKHBhZ2VYLCBwYWdlWSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUuaGFuZGxlTW92ZSA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB2YXIgcG9pbnRlclNjcmVlblggPSBwYWdlWCAtIHdpbmRvdy5wYWdlWE9mZnNldDtcbiAgICAgICAgICAgIHZhciBwb2ludGVyU2NyZWVuWSA9IHBhZ2VZIC0gd2luZG93LnBhZ2VZT2Zmc2V0O1xuICAgICAgICAgICAgdmFyIHlEZWx0YSA9IHRoaXMucG9pbnRlclNjcmVlblkgPT09IG51bGwgPyAwIDogcG9pbnRlclNjcmVlblkgLSB0aGlzLnBvaW50ZXJTY3JlZW5ZO1xuICAgICAgICAgICAgdmFyIHhEZWx0YSA9IHRoaXMucG9pbnRlclNjcmVlblggPT09IG51bGwgPyAwIDogcG9pbnRlclNjcmVlblggLSB0aGlzLnBvaW50ZXJTY3JlZW5YO1xuICAgICAgICAgICAgaWYgKHlEZWx0YSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZFVwID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHlEZWx0YSA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZERvd24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhEZWx0YSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZXJNb3ZlZExlZnQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoeERlbHRhID4gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlck1vdmVkUmlnaHQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWCA9IHBvaW50ZXJTY3JlZW5YO1xuICAgICAgICAgICAgdGhpcy5wb2ludGVyU2NyZWVuWSA9IHBvaW50ZXJTY3JlZW5ZO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzQW5pbWF0aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0FuaW1hdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0QW5pbWF0aW9uKGdldFRpbWUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7IC8vIHdpbGwgc3RvcCBhbmltYXRpb25cbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbENhY2hlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLnJlcXVlc3RBbmltYXRpb24gPSBmdW5jdGlvbiAobm93KSB7XG4gICAgICAgIHRoaXMubXNTaW5jZVJlcXVlc3QgPSBub3c7XG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLmFuaW1hdGUpO1xuICAgIH07XG4gICAgQXV0b1Njcm9sbGVyLnByb3RvdHlwZS5oYW5kbGVTaWRlID0gZnVuY3Rpb24gKGVkZ2UsIHNlY29uZHMpIHtcbiAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gZWRnZS5zY3JvbGxDYWNoZTtcbiAgICAgICAgdmFyIGVkZ2VUaHJlc2hvbGQgPSB0aGlzLmVkZ2VUaHJlc2hvbGQ7XG4gICAgICAgIHZhciBpbnZEaXN0YW5jZSA9IGVkZ2VUaHJlc2hvbGQgLSBlZGdlLmRpc3RhbmNlO1xuICAgICAgICB2YXIgdmVsb2NpdHkgPSAvLyB0aGUgY2xvc2VyIHRvIHRoZSBlZGdlLCB0aGUgZmFzdGVyIHdlIHNjcm9sbFxuICAgICAgICAgKGludkRpc3RhbmNlICogaW52RGlzdGFuY2UpIC8gKGVkZ2VUaHJlc2hvbGQgKiBlZGdlVGhyZXNob2xkKSAqIC8vIHF1YWRyYXRpY1xuICAgICAgICAgICAgdGhpcy5tYXhWZWxvY2l0eSAqIHNlY29uZHM7XG4gICAgICAgIHZhciBzaWduID0gMTtcbiAgICAgICAgc3dpdGNoIChlZGdlLm5hbWUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICAgICAgICAgIHNpZ24gPSAtMTtcbiAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgICAgICAgICBzY3JvbGxDYWNoZS5zZXRTY3JvbGxMZWZ0KHNjcm9sbENhY2hlLmdldFNjcm9sbExlZnQoKSArIHZlbG9jaXR5ICogc2lnbik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgICAgICAgIHNpZ24gPSAtMTtcbiAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgICAgICAgICAgc2Nyb2xsQ2FjaGUuc2V0U2Nyb2xsVG9wKHNjcm9sbENhY2hlLmdldFNjcm9sbFRvcCgpICsgdmVsb2NpdHkgKiBzaWduKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gbGVmdC90b3AgYXJlIHJlbGF0aXZlIHRvIGRvY3VtZW50IHRvcGxlZnRcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLmNvbXB1dGVCZXN0RWRnZSA9IGZ1bmN0aW9uIChsZWZ0LCB0b3ApIHtcbiAgICAgICAgdmFyIGVkZ2VUaHJlc2hvbGQgPSB0aGlzLmVkZ2VUaHJlc2hvbGQ7XG4gICAgICAgIHZhciBiZXN0U2lkZSA9IG51bGw7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnNjcm9sbENhY2hlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzY3JvbGxDYWNoZSA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciByZWN0ID0gc2Nyb2xsQ2FjaGUuY2xpZW50UmVjdDtcbiAgICAgICAgICAgIHZhciBsZWZ0RGlzdCA9IGxlZnQgLSByZWN0LmxlZnQ7XG4gICAgICAgICAgICB2YXIgcmlnaHREaXN0ID0gcmVjdC5yaWdodCAtIGxlZnQ7XG4gICAgICAgICAgICB2YXIgdG9wRGlzdCA9IHRvcCAtIHJlY3QudG9wO1xuICAgICAgICAgICAgdmFyIGJvdHRvbURpc3QgPSByZWN0LmJvdHRvbSAtIHRvcDtcbiAgICAgICAgICAgIC8vIGNvbXBsZXRlbHkgd2l0aGluIHRoZSByZWN0P1xuICAgICAgICAgICAgaWYgKGxlZnREaXN0ID49IDAgJiYgcmlnaHREaXN0ID49IDAgJiYgdG9wRGlzdCA+PSAwICYmIGJvdHRvbURpc3QgPj0gMCkge1xuICAgICAgICAgICAgICAgIGlmICh0b3BEaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRVcCAmJiBzY3JvbGxDYWNoZS5jYW5TY3JvbGxVcCgpICYmXG4gICAgICAgICAgICAgICAgICAgICghYmVzdFNpZGUgfHwgYmVzdFNpZGUuZGlzdGFuY2UgPiB0b3BEaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGU6IHNjcm9sbENhY2hlLCBuYW1lOiAndG9wJywgZGlzdGFuY2U6IHRvcERpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJvdHRvbURpc3QgPD0gZWRnZVRocmVzaG9sZCAmJiB0aGlzLmV2ZXJNb3ZlZERvd24gJiYgc2Nyb2xsQ2FjaGUuY2FuU2Nyb2xsRG93bigpICYmXG4gICAgICAgICAgICAgICAgICAgICghYmVzdFNpZGUgfHwgYmVzdFNpZGUuZGlzdGFuY2UgPiBib3R0b21EaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0U2lkZSA9IHsgc2Nyb2xsQ2FjaGU6IHNjcm9sbENhY2hlLCBuYW1lOiAnYm90dG9tJywgZGlzdGFuY2U6IGJvdHRvbURpc3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGxlZnREaXN0IDw9IGVkZ2VUaHJlc2hvbGQgJiYgdGhpcy5ldmVyTW92ZWRMZWZ0ICYmIHNjcm9sbENhY2hlLmNhblNjcm9sbExlZnQoKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIWJlc3RTaWRlIHx8IGJlc3RTaWRlLmRpc3RhbmNlID4gbGVmdERpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RTaWRlID0geyBzY3JvbGxDYWNoZTogc2Nyb2xsQ2FjaGUsIG5hbWU6ICdsZWZ0JywgZGlzdGFuY2U6IGxlZnREaXN0IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyaWdodERpc3QgPD0gZWRnZVRocmVzaG9sZCAmJiB0aGlzLmV2ZXJNb3ZlZFJpZ2h0ICYmIHNjcm9sbENhY2hlLmNhblNjcm9sbFJpZ2h0KCkgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFiZXN0U2lkZSB8fCBiZXN0U2lkZS5kaXN0YW5jZSA+IHJpZ2h0RGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFNpZGUgPSB7IHNjcm9sbENhY2hlOiBzY3JvbGxDYWNoZSwgbmFtZTogJ3JpZ2h0JywgZGlzdGFuY2U6IHJpZ2h0RGlzdCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmVzdFNpZGU7XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsZXIucHJvdG90eXBlLmJ1aWxkQ2FjaGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5xdWVyeVNjcm9sbEVscygpLm1hcChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbCA9PT0gd2luZG93KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBXaW5kb3dTY3JvbGxHZW9tQ2FjaGUoZmFsc2UpOyAvLyBmYWxzZSA9IGRvbid0IGxpc3RlbiB0byB1c2VyLWdlbmVyYXRlZCBzY3JvbGxzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEVsZW1lbnRTY3JvbGxHZW9tQ2FjaGUoZWwsIGZhbHNlKTsgLy8gZmFsc2UgPSBkb24ndCBsaXN0ZW4gdG8gdXNlci1nZW5lcmF0ZWQgc2Nyb2xsc1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEF1dG9TY3JvbGxlci5wcm90b3R5cGUucXVlcnlTY3JvbGxFbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlbHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsUXVlcnk7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcXVlcnkgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIHF1ZXJ5ID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIGVscy5wdXNoKHF1ZXJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGVscy5wdXNoLmFwcGx5KGVscywgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChxdWVyeSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxzO1xuICAgIH07XG4gICAgcmV0dXJuIEF1dG9TY3JvbGxlcjtcbn0oKSk7XG5cbi8qXG5Nb25pdG9ycyBkcmFnZ2luZyBvbiBhbiBlbGVtZW50LiBIYXMgYSBudW1iZXIgb2YgaGlnaC1sZXZlbCBmZWF0dXJlczpcbi0gbWluaW11bSBkaXN0YW5jZSByZXF1aXJlZCBiZWZvcmUgZHJhZ2dpbmdcbi0gbWluaW11bSB3YWl0IHRpbWUgKFwiZGVsYXlcIikgYmVmb3JlIGRyYWdnaW5nXG4tIGEgbWlycm9yIGVsZW1lbnQgdGhhdCBmb2xsb3dzIHRoZSBwb2ludGVyXG4qL1xudmFyIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhjb250YWluZXJFbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjb250YWluZXJFbCkgfHwgdGhpcztcbiAgICAgICAgLy8gb3B0aW9ucyB0aGF0IGNhbiBiZSBkaXJlY3RseSBzZXQgYnkgY2FsbGVyXG4gICAgICAgIC8vIHRoZSBjYWxsZXIgY2FuIGFsc28gc2V0IHRoZSBQb2ludGVyRHJhZ2dpbmcncyBvcHRpb25zIGFzIHdlbGxcbiAgICAgICAgX3RoaXMuZGVsYXkgPSBudWxsO1xuICAgICAgICBfdGhpcy5taW5EaXN0YW5jZSA9IDA7XG4gICAgICAgIF90aGlzLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IHRydWU7IC8vIHByZXZlbnRzIGRyYWcgZnJvbSBzdGFydGluZyBhbmQgYmxvY2tzIHNjcm9sbGluZyBkdXJpbmcgZHJhZ1xuICAgICAgICBfdGhpcy5taXJyb3JOZWVkc1JldmVydCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc0ludGVyYWN0aW5nID0gZmFsc2U7IC8vIGlzIHRoZSB1c2VyIHZhbGlkbHkgbW92aW5nIHRoZSBwb2ludGVyPyBsYXN0cyB1bnRpbCBwb2ludGVydXBcbiAgICAgICAgX3RoaXMuaXNEcmFnZ2luZyA9IGZhbHNlOyAvLyBpcyBpdCBJTlRFTlRGVUxMWSBkcmFnZ2luZz8gbGFzdHMgdW50aWwgYWZ0ZXIgcmV2ZXJ0IGFuaW1hdGlvblxuICAgICAgICBfdGhpcy5pc0RlbGF5RW5kZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5kZWxheVRpbWVvdXRJZCA9IG51bGw7XG4gICAgICAgIF90aGlzLm9uUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuaXNEcmFnZ2luZykgeyAvLyBzbyBuZXcgZHJhZyBkb2Vzbid0IGhhcHBlbiB3aGlsZSByZXZlcnQgYW5pbWF0aW9uIGlzIGdvaW5nXG4gICAgICAgICAgICAgICAgX3RoaXMuaXNJbnRlcmFjdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNEZWxheUVuZGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgX3RoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHByZXZlbnRTZWxlY3Rpb24oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgcHJldmVudENvbnRleHRNZW51KGRvY3VtZW50LmJvZHkpO1xuICAgICAgICAgICAgICAgIC8vIHByZXZlbnQgbGlua3MgZnJvbSBiZWluZyB2aXNpdGVkIGlmIHRoZXJlJ3MgYW4gZXZlbnR1YWwgZHJhZy5cbiAgICAgICAgICAgICAgICAvLyBhbHNvIHByZXZlbnRzIHNlbGVjdGlvbiBpbiBvbGRlciBicm93c2VycyAobWF5YmU/KS5cbiAgICAgICAgICAgICAgICAvLyBub3QgbmVjZXNzYXJ5IGZvciB0b3VjaCwgYmVzaWRlcywgYnJvd3NlciB3b3VsZCBjb21wbGFpbiBhYm91dCBwYXNzaXZlbmVzcy5cbiAgICAgICAgICAgICAgICBpZiAoIWV2LmlzVG91Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgZXYub3JpZ0V2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcigncG9pbnRlcmRvd24nLCBldik7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5wb2ludGVyLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYWN0aW9ucyByZWxhdGVkIHRvIGluaXRpYXRpbmcgZHJhZ3N0YXJ0K2RyYWdtb3ZlK2RyYWdlbmQuLi5cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubWlycm9yLnNldElzVmlzaWJsZShmYWxzZSk7IC8vIHJlc2V0LiBjYWxsZXIgbXVzdCBzZXQtdmlzaWJsZVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5taXJyb3Iuc3RhcnQoZXYuc3ViamVjdEVsLCBldi5wYWdlWCwgZXYucGFnZVkpOyAvLyBtdXN0IGhhcHBlbiBvbiBmaXJzdCBwb2ludGVyIGRvd25cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc3RhcnREZWxheShldik7XG4gICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMubWluRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmhhbmRsZURpc3RhbmNlU3VycGFzc2VkKGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMub25Qb2ludGVyTW92ZSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmlzSW50ZXJhY3RpbmcpIHsgLy8gaWYgZmFsc2UsIHN0aWxsIHdhaXRpbmcgZm9yIHByZXZpb3VzIGRyYWcncyByZXZlcnRcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJtb3ZlJywgZXYpO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWluRGlzdGFuY2UgPSBfdGhpcy5taW5EaXN0YW5jZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RhbmNlU3EgPSB2b2lkIDA7IC8vIGN1cnJlbnQgZGlzdGFuY2UgZnJvbSB0aGUgb3JpZ2luLCBzcXVhcmVkXG4gICAgICAgICAgICAgICAgICAgIHZhciBkZWx0YVggPSBldi5kZWx0YVgsIGRlbHRhWSA9IGV2LmRlbHRhWTtcbiAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2VTcSA9IGRlbHRhWCAqIGRlbHRhWCArIGRlbHRhWSAqIGRlbHRhWTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRpc3RhbmNlU3EgPj0gbWluRGlzdGFuY2UgKiBtaW5EaXN0YW5jZSkgeyAvLyB1c2UgcHl0aGFnb3JlYW4gdGhlb3JlbVxuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGFuZGxlRGlzdGFuY2VTdXJwYXNzZWQoZXYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGEgcmVhbCBwb2ludGVyIG1vdmU/IChub3Qgb25lIHNpbXVsYXRlZCBieSBzY3JvbGxpbmcpXG4gICAgICAgICAgICAgICAgICAgIGlmIChldi5vcmlnRXZlbnQudHlwZSAhPT0gJ3Njcm9sbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm1pcnJvci5oYW5kbGVNb3ZlKGV2LnBhZ2VYLCBldi5wYWdlWSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hdXRvU2Nyb2xsZXIuaGFuZGxlTW92ZShldi5wYWdlWCwgZXYucGFnZVkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ21vdmUnLCBldik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5vblBvaW50ZXJVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmlzSW50ZXJhY3RpbmcpIHsgLy8gaWYgZmFsc2UsIHN0aWxsIHdhaXRpbmcgZm9yIHByZXZpb3VzIGRyYWcncyByZXZlcnRcbiAgICAgICAgICAgICAgICBfdGhpcy5pc0ludGVyYWN0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYWxsb3dTZWxlY3Rpb24oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgICAgICAgICAgYWxsb3dDb250ZXh0TWVudShkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJ1cCcsIGV2KTsgLy8gY2FuIHBvdGVudGlhbGx5IHNldCBtaXJyb3JOZWVkc1JldmVydFxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmF1dG9TY3JvbGxlci5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRyeVN0b3BEcmFnKGV2KTsgLy8gd2hpY2ggd2lsbCBzdG9wIHRoZSBtaXJyb3JcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmRlbGF5VGltZW91dElkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChfdGhpcy5kZWxheVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRlbGF5VGltZW91dElkID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBwb2ludGVyID0gX3RoaXMucG9pbnRlciA9IG5ldyBQb2ludGVyRHJhZ2dpbmcoY29udGFpbmVyRWwpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgX3RoaXMub25Qb2ludGVyRG93bik7XG4gICAgICAgIHBvaW50ZXIuZW1pdHRlci5vbigncG9pbnRlcm1vdmUnLCBfdGhpcy5vblBvaW50ZXJNb3ZlKTtcbiAgICAgICAgcG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVydXAnLCBfdGhpcy5vblBvaW50ZXJVcCk7XG4gICAgICAgIF90aGlzLm1pcnJvciA9IG5ldyBFbGVtZW50TWlycm9yKCk7XG4gICAgICAgIF90aGlzLmF1dG9TY3JvbGxlciA9IG5ldyBBdXRvU2Nyb2xsZXIoKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBvaW50ZXIuZGVzdHJveSgpO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc3RhcnREZWxheSA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZGVsYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF5VGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZGVsYXlUaW1lb3V0SWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIF90aGlzLmhhbmRsZURlbGF5RW5kKGV2KTtcbiAgICAgICAgICAgIH0sIHRoaXMuZGVsYXkpOyAvLyBub3QgYXNzaWduYWJsZSB0byBudW1iZXIhXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZURlbGF5RW5kKGV2KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuaGFuZGxlRGVsYXlFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgdGhpcy5pc0RlbGF5RW5kZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnRyeVN0YXJ0RHJhZyhldik7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5oYW5kbGVEaXN0YW5jZVN1cnBhc3NlZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICB0aGlzLmlzRGlzdGFuY2VTdXJwYXNzZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnRyeVN0YXJ0RHJhZyhldik7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS50cnlTdGFydERyYWcgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNEZWxheUVuZGVkICYmIHRoaXMuaXNEaXN0YW5jZVN1cnBhc3NlZCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnBvaW50ZXIud2FzVG91Y2hTY3JvbGwgfHwgdGhpcy50b3VjaFNjcm9sbEFsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMubWlycm9yTmVlZHNSZXZlcnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9TY3JvbGxlci5zdGFydChldi5wYWdlWCwgZXYucGFnZVkpO1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnc3RhcnQnLCBldik7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudG91Y2hTY3JvbGxBbGxvd2VkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBvaW50ZXIuY2FuY2VsVG91Y2hTY3JvbGwoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnRyeVN0b3BEcmFnID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIC8vIC5zdG9wKCkgaXMgQUxXQVlTIGFzeW5jaHJvbm91cywgd2hpY2ggd2UgTkVFRCBiZWNhdXNlIHdlIHdhbnQgYWxsIHBvaW50ZXJ1cCBldmVudHNcbiAgICAgICAgLy8gdGhhdCBjb21lIGZyb20gdGhlIGRvY3VtZW50IHRvIGZpcmUgYmVmb3JlaGFuZC4gbXVjaCBtb3JlIGNvbnZlbmllbnQgdGhpcyB3YXkuXG4gICAgICAgIHRoaXMubWlycm9yLnN0b3AodGhpcy5taXJyb3JOZWVkc1JldmVydCwgdGhpcy5zdG9wRHJhZy5iaW5kKHRoaXMsIGV2KSAvLyBib3VuZCB3aXRoIGFyZ3NcbiAgICAgICAgKTtcbiAgICB9O1xuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnN0b3BEcmFnID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ2VuZCcsIGV2KTtcbiAgICB9O1xuICAgIC8vIGZpbGwgaW4gdGhlIGltcGxlbWVudGF0aW9ucy4uLlxuICAgIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLnNldElnbm9yZU1vdmUgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLnBvaW50ZXIuc2hvdWxkSWdub3JlTW92ZSA9IGJvb2w7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRNaXJyb3JJc1Zpc2libGUgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLm1pcnJvci5zZXRJc1Zpc2libGUoYm9vbCk7XG4gICAgfTtcbiAgICBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5zZXRNaXJyb3JOZWVkc1JldmVydCA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIHRoaXMubWlycm9yTmVlZHNSZXZlcnQgPSBib29sO1xuICAgIH07XG4gICAgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0QXV0b1Njcm9sbEVuYWJsZWQgPSBmdW5jdGlvbiAoYm9vbCkge1xuICAgICAgICB0aGlzLmF1dG9TY3JvbGxlci5pc0VuYWJsZWQgPSBib29sO1xuICAgIH07XG4gICAgcmV0dXJuIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmc7XG59KEVsZW1lbnREcmFnZ2luZykpO1xuXG4vKlxuV2hlbiB0aGlzIGNsYXNzIGlzIGluc3RhbnRpYXRlZCwgaXQgcmVjb3JkcyB0aGUgb2Zmc2V0IG9mIGFuIGVsZW1lbnQgKHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0b3BsZWZ0KSxcbmFuZCBjb250aW51ZXMgdG8gbW9uaXRvciBzY3JvbGxpbmcsIHVwZGF0aW5nIHRoZSBjYWNoZWQgY29vcmRpbmF0ZXMgaWYgaXQgbmVlZHMgdG8uXG5Eb2VzIG5vdCBhY2Nlc3MgdGhlIERPTSBhZnRlciBpbnN0YW50aWF0aW9uLCBzbyBoaWdobHkgcGVyZm9ybWFudC5cblxuQWxzbyBrZWVwcyB0cmFjayBvZiBhbGwgc2Nyb2xsaW5nL292ZXJmbG93OmhpZGRlbiBjb250YWluZXJzIHRoYXQgYXJlIHBhcmVudHMgb2YgdGhlIGdpdmVuIGVsZW1lbnRcbmFuZCBhbiBkZXRlcm1pbmUgaWYgYSBnaXZlbiBwb2ludCBpcyBpbnNpZGUgdGhlIGNvbWJpbmVkIGNsaXBwaW5nIHJlY3RhbmdsZS5cbiovXG52YXIgT2Zmc2V0VHJhY2tlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBPZmZzZXRUcmFja2VyKGVsKSB7XG4gICAgICAgIHRoaXMub3JpZ1JlY3QgPSBjb21wdXRlUmVjdChlbCk7XG4gICAgICAgIC8vIHdpbGwgd29yayBmaW5lIGZvciBkaXZzIHRoYXQgaGF2ZSBvdmVyZmxvdzpoaWRkZW5cbiAgICAgICAgdGhpcy5zY3JvbGxDYWNoZXMgPSBnZXRDbGlwcGluZ1BhcmVudHMoZWwpLm1hcChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRWxlbWVudFNjcm9sbEdlb21DYWNoZShlbCwgdHJ1ZSk7IC8vIGxpc3Rlbj10cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBPZmZzZXRUcmFja2VyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zY3JvbGxDYWNoZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICBzY3JvbGxDYWNoZS5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE9mZnNldFRyYWNrZXIucHJvdG90eXBlLmNvbXB1dGVMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGVmdCA9IHRoaXMub3JpZ1JlY3QubGVmdDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsQ2FjaGVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgbGVmdCArPSBzY3JvbGxDYWNoZS5vcmlnU2Nyb2xsTGVmdCAtIHNjcm9sbENhY2hlLmdldFNjcm9sbExlZnQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGVmdDtcbiAgICB9O1xuICAgIE9mZnNldFRyYWNrZXIucHJvdG90eXBlLmNvbXB1dGVUb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0b3AgPSB0aGlzLm9yaWdSZWN0LnRvcDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuc2Nyb2xsQ2FjaGVzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjcm9sbENhY2hlID0gX2FbX2ldO1xuICAgICAgICAgICAgdG9wICs9IHNjcm9sbENhY2hlLm9yaWdTY3JvbGxUb3AgLSBzY3JvbGxDYWNoZS5nZXRTY3JvbGxUb3AoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9wO1xuICAgIH07XG4gICAgT2Zmc2V0VHJhY2tlci5wcm90b3R5cGUuaXNXaXRoaW5DbGlwcGluZyA9IGZ1bmN0aW9uIChwYWdlWCwgcGFnZVkpIHtcbiAgICAgICAgdmFyIHBvaW50ID0geyBsZWZ0OiBwYWdlWCwgdG9wOiBwYWdlWSB9O1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zY3JvbGxDYWNoZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsQ2FjaGUgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAoIWlzSWdub3JlZENsaXBwaW5nKHNjcm9sbENhY2hlLmdldEV2ZW50VGFyZ2V0KCkpICYmXG4gICAgICAgICAgICAgICAgIXBvaW50SW5zaWRlUmVjdChwb2ludCwgc2Nyb2xsQ2FjaGUuY2xpZW50UmVjdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICByZXR1cm4gT2Zmc2V0VHJhY2tlcjtcbn0oKSk7XG4vLyBjZXJ0YWluIGNsaXBwaW5nIGNvbnRhaW5lcnMgc2hvdWxkIG5ldmVyIGNvbnN0cmFpbiBpbnRlcmFjdGlvbnMsIGxpa2UgPGh0bWw+IGFuZCA8Ym9keT5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mdWxsY2FsZW5kYXIvZnVsbGNhbGVuZGFyL2lzc3Vlcy8zNjE1XG5mdW5jdGlvbiBpc0lnbm9yZWRDbGlwcGluZyhub2RlKSB7XG4gICAgdmFyIHRhZ05hbWUgPSBub2RlLnRhZ05hbWU7XG4gICAgcmV0dXJuIHRhZ05hbWUgPT09ICdIVE1MJyB8fCB0YWdOYW1lID09PSAnQk9EWSc7XG59XG5cbi8qXG5UcmFja3MgbW92ZW1lbnQgb3ZlciBtdWx0aXBsZSBkcm9wcGFibGUgYXJlYXMgKGFrYSBcImhpdHNcIilcbnRoYXQgZXhpc3QgaW4gb25lIG9yIG1vcmUgRGF0ZUNvbXBvbmVudHMuXG5SZWxpZXMgb24gYW4gZXhpc3RpbmcgZHJhZ2dhYmxlLlxuXG5lbWl0czpcbi0gcG9pbnRlcmRvd25cbi0gZHJhZ3N0YXJ0XG4tIGhpdGNoYW5nZSAtIGZpcmVzIGluaXRpYWxseSwgZXZlbiBpZiBub3Qgb3ZlciBhIGhpdFxuLSBwb2ludGVydXBcbi0gKGhpdGNoYW5nZSAtIGFnYWluLCB0byBudWxsLCBpZiBlbmRlZCBvdmVyIGEgaGl0KVxuLSBkcmFnZW5kXG4qL1xudmFyIEhpdERyYWdnaW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEhpdERyYWdnaW5nKGRyYWdnaW5nLCBkcm9wcGFibGVTdG9yZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBvcHRpb25zIHRoYXQgY2FuIGJlIHNldCBieSBjYWxsZXJcbiAgICAgICAgdGhpcy51c2VTdWJqZWN0Q2VudGVyID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVxdWlyZUluaXRpYWwgPSB0cnVlOyAvLyBpZiBkb2Vzbid0IHN0YXJ0IG91dCBvbiBhIGhpdCwgd29uJ3QgZW1pdCBhbnkgZXZlbnRzXG4gICAgICAgIHRoaXMuaW5pdGlhbEhpdCA9IG51bGw7XG4gICAgICAgIHRoaXMubW92aW5nSGl0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5maW5hbEhpdCA9IG51bGw7IC8vIHdvbid0IGV2ZXIgYmUgcG9wdWxhdGVkIGlmIHNob3VsZElnbm9yZU1vdmVcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuZHJhZ2dpbmc7XG4gICAgICAgICAgICBfdGhpcy5pbml0aWFsSGl0ID0gbnVsbDtcbiAgICAgICAgICAgIF90aGlzLm1vdmluZ0hpdCA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5maW5hbEhpdCA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5wcmVwYXJlSGl0cygpO1xuICAgICAgICAgICAgX3RoaXMucHJvY2Vzc0ZpcnN0Q29vcmQoZXYpO1xuICAgICAgICAgICAgaWYgKF90aGlzLmluaXRpYWxIaXQgfHwgIV90aGlzLnJlcXVpcmVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZShmYWxzZSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVyZG93bicsIGV2KTsgLy8gVE9ETzogZmlyZSB0aGlzIGJlZm9yZSBjb21wdXRpbmcgcHJvY2Vzc0ZpcnN0Q29vcmQsIHNvIGxpc3RlbmVycyBjYW4gY2FuY2VsLiB0aGlzIGdldHMgZmlyZWQgYnkgYWxtb3N0IGV2ZXJ5IGhhbmRsZXIgOihcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdzdGFydCcsIGV2KTtcbiAgICAgICAgICAgIF90aGlzLmhhbmRsZU1vdmUoZXYsIHRydWUpOyAvLyBmb3JjZSA9IGZpcmUgZXZlbiBpZiBpbml0aWFsbHkgbnVsbFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdNb3ZlID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdtb3ZlJywgZXYpO1xuICAgICAgICAgICAgX3RoaXMuaGFuZGxlTW92ZShldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlclVwID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5yZWxlYXNlSGl0cygpO1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVydXAnLCBldik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLm1vdmluZ0hpdCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignaGl0dXBkYXRlJywgbnVsbCwgdHJ1ZSwgZXYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZmluYWxIaXQgPSBfdGhpcy5tb3ZpbmdIaXQ7XG4gICAgICAgICAgICBfdGhpcy5tb3ZpbmdIaXQgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdkcmFnZW5kJywgZXYpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmRyb3BwYWJsZVN0b3JlID0gZHJvcHBhYmxlU3RvcmU7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGRyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ21vdmUnLCB0aGlzLmhhbmRsZURyYWdNb3ZlKTtcbiAgICAgICAgZHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcnVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnZW5kJywgdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgdGhpcy5kcmFnZ2luZyA9IGRyYWdnaW5nO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlck1peGluKCk7XG4gICAgfVxuICAgIC8vIHNldHMgaW5pdGlhbEhpdFxuICAgIC8vIHNldHMgY29vcmRBZGp1c3RcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUucHJvY2Vzc0ZpcnN0Q29vcmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgdmFyIG9yaWdQb2ludCA9IHsgbGVmdDogZXYucGFnZVgsIHRvcDogZXYucGFnZVkgfTtcbiAgICAgICAgdmFyIGFkanVzdGVkUG9pbnQgPSBvcmlnUG9pbnQ7XG4gICAgICAgIHZhciBzdWJqZWN0RWwgPSBldi5zdWJqZWN0RWw7XG4gICAgICAgIHZhciBzdWJqZWN0UmVjdDtcbiAgICAgICAgaWYgKHN1YmplY3RFbCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgIHN1YmplY3RSZWN0ID0gY29tcHV0ZVJlY3Qoc3ViamVjdEVsKTtcbiAgICAgICAgICAgIGFkanVzdGVkUG9pbnQgPSBjb25zdHJhaW5Qb2ludChhZGp1c3RlZFBvaW50LCBzdWJqZWN0UmVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluaXRpYWxIaXQgPSB0aGlzLmluaXRpYWxIaXQgPSB0aGlzLnF1ZXJ5SGl0Rm9yT2Zmc2V0KGFkanVzdGVkUG9pbnQubGVmdCwgYWRqdXN0ZWRQb2ludC50b3ApO1xuICAgICAgICBpZiAoaW5pdGlhbEhpdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMudXNlU3ViamVjdENlbnRlciAmJiBzdWJqZWN0UmVjdCkge1xuICAgICAgICAgICAgICAgIHZhciBzbGljZWRTdWJqZWN0UmVjdCA9IGludGVyc2VjdFJlY3RzKHN1YmplY3RSZWN0LCBpbml0aWFsSGl0LnJlY3QpO1xuICAgICAgICAgICAgICAgIGlmIChzbGljZWRTdWJqZWN0UmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZFBvaW50ID0gZ2V0UmVjdENlbnRlcihzbGljZWRTdWJqZWN0UmVjdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jb29yZEFkanVzdCA9IGRpZmZQb2ludHMoYWRqdXN0ZWRQb2ludCwgb3JpZ1BvaW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29vcmRBZGp1c3QgPSB7IGxlZnQ6IDAsIHRvcDogMCB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUuaGFuZGxlTW92ZSA9IGZ1bmN0aW9uIChldiwgZm9yY2VIYW5kbGUpIHtcbiAgICAgICAgdmFyIGhpdCA9IHRoaXMucXVlcnlIaXRGb3JPZmZzZXQoZXYucGFnZVggKyB0aGlzLmNvb3JkQWRqdXN0LmxlZnQsIGV2LnBhZ2VZICsgdGhpcy5jb29yZEFkanVzdC50b3ApO1xuICAgICAgICBpZiAoZm9yY2VIYW5kbGUgfHwgIWlzSGl0c0VxdWFsKHRoaXMubW92aW5nSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICB0aGlzLm1vdmluZ0hpdCA9IGhpdDtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci50cmlnZ2VyKCdoaXR1cGRhdGUnLCBoaXQsIGZhbHNlLCBldik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhpdERyYWdnaW5nLnByb3RvdHlwZS5wcmVwYXJlSGl0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vZmZzZXRUcmFja2VycyA9IG1hcEhhc2godGhpcy5kcm9wcGFibGVTdG9yZSwgZnVuY3Rpb24gKGludGVyYWN0aW9uU2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uU2V0dGluZ3MuY29tcG9uZW50LmJ1aWxkUG9zaXRpb25DYWNoZXMoKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgT2Zmc2V0VHJhY2tlcihpbnRlcmFjdGlvblNldHRpbmdzLmVsKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIaXREcmFnZ2luZy5wcm90b3R5cGUucmVsZWFzZUhpdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvZmZzZXRUcmFja2VycyA9IHRoaXMub2Zmc2V0VHJhY2tlcnM7XG4gICAgICAgIGZvciAodmFyIGlkIGluIG9mZnNldFRyYWNrZXJzKSB7XG4gICAgICAgICAgICBvZmZzZXRUcmFja2Vyc1tpZF0uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub2Zmc2V0VHJhY2tlcnMgPSB7fTtcbiAgICB9O1xuICAgIEhpdERyYWdnaW5nLnByb3RvdHlwZS5xdWVyeUhpdEZvck9mZnNldCA9IGZ1bmN0aW9uIChvZmZzZXRMZWZ0LCBvZmZzZXRUb3ApIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgZHJvcHBhYmxlU3RvcmUgPSBfYS5kcm9wcGFibGVTdG9yZSwgb2Zmc2V0VHJhY2tlcnMgPSBfYS5vZmZzZXRUcmFja2VycztcbiAgICAgICAgdmFyIGJlc3RIaXQgPSBudWxsO1xuICAgICAgICBmb3IgKHZhciBpZCBpbiBkcm9wcGFibGVTdG9yZSkge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IGRyb3BwYWJsZVN0b3JlW2lkXS5jb21wb25lbnQ7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0VHJhY2tlciA9IG9mZnNldFRyYWNrZXJzW2lkXTtcbiAgICAgICAgICAgIGlmIChvZmZzZXRUcmFja2VyLmlzV2l0aGluQ2xpcHBpbmcob2Zmc2V0TGVmdCwgb2Zmc2V0VG9wKSkge1xuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5MZWZ0ID0gb2Zmc2V0VHJhY2tlci5jb21wdXRlTGVmdCgpO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5Ub3AgPSBvZmZzZXRUcmFja2VyLmNvbXB1dGVUb3AoKTtcbiAgICAgICAgICAgICAgICB2YXIgcG9zaXRpb25MZWZ0ID0gb2Zmc2V0TGVmdCAtIG9yaWdpbkxlZnQ7XG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uVG9wID0gb2Zmc2V0VG9wIC0gb3JpZ2luVG9wO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnUmVjdCA9IG9mZnNldFRyYWNrZXIub3JpZ1JlY3Q7XG4gICAgICAgICAgICAgICAgdmFyIHdpZHRoID0gb3JpZ1JlY3QucmlnaHQgLSBvcmlnUmVjdC5sZWZ0O1xuICAgICAgICAgICAgICAgIHZhciBoZWlnaHQgPSBvcmlnUmVjdC5ib3R0b20gLSBvcmlnUmVjdC50b3A7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIC8vIG11c3QgYmUgd2l0aGluIHRoZSBlbGVtZW50J3MgYm91bmRzXG4gICAgICAgICAgICAgICAgcG9zaXRpb25MZWZ0ID49IDAgJiYgcG9zaXRpb25MZWZ0IDwgd2lkdGggJiZcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25Ub3AgPj0gMCAmJiBwb3NpdGlvblRvcCA8IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaGl0ID0gY29tcG9uZW50LnF1ZXJ5SGl0KHBvc2l0aW9uTGVmdCwgcG9zaXRpb25Ub3AsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGl0ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtYWtlIHN1cmUgdGhlIGhpdCBpcyB3aXRoaW4gYWN0aXZlUmFuZ2UsIG1lYW5pbmcgaXQncyBub3QgYSBkZWFsIGNlbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICFjb21wb25lbnQucHJvcHMuZGF0ZVByb2ZpbGUgfHwgLy8gaGFjayBmb3IgRGF5VGlsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlQ29udGFpbnNSYW5nZShjb21wb25lbnQucHJvcHMuZGF0ZVByb2ZpbGUuYWN0aXZlUmFuZ2UsIGhpdC5kYXRlU3Bhbi5yYW5nZSkpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoIWJlc3RIaXQgfHwgaGl0LmxheWVyID4gYmVzdEhpdC5sYXllcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGJldHRlciB3YXkgdG8gcmUtb3JpZW50IHJlY3RhbmdsZVxuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QubGVmdCArPSBvcmlnaW5MZWZ0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaGl0LnJlY3QucmlnaHQgKz0gb3JpZ2luTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpdC5yZWN0LnRvcCArPSBvcmlnaW5Ub3A7XG4gICAgICAgICAgICAgICAgICAgICAgICBoaXQucmVjdC5ib3R0b20gKz0gb3JpZ2luVG9wO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVzdEhpdCA9IGhpdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmVzdEhpdDtcbiAgICB9O1xuICAgIHJldHVybiBIaXREcmFnZ2luZztcbn0oKSk7XG5mdW5jdGlvbiBpc0hpdHNFcXVhbChoaXQwLCBoaXQxKSB7XG4gICAgaWYgKCFoaXQwICYmICFoaXQxKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoQm9vbGVhbihoaXQwKSAhPT0gQm9vbGVhbihoaXQxKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBpc0RhdGVTcGFuc0VxdWFsKGhpdDAuZGF0ZVNwYW4sIGhpdDEuZGF0ZVNwYW4pO1xufVxuXG4vKlxuTW9uaXRvcnMgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYSBzcGVjaWZpYyBkYXRlL3RpbWUgb2YgYSBjb21wb25lbnQuXG5BIHBvaW50ZXJkb3duK3BvaW50ZXJ1cCBvbiB0aGUgc2FtZSBcImhpdFwiIGNvbnN0aXR1dGVzIGEgY2xpY2suXG4qL1xudmFyIERhdGVDbGlja2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRGF0ZUNsaWNraW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERhdGVDbGlja2luZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24gPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nO1xuICAgICAgICAgICAgLy8gZG8gdGhpcyBpbiBwb2ludGVyZG93biAobm90IGRyYWdlbmQpIGJlY2F1c2UgRE9NIG1pZ2h0IGJlIG11dGF0ZWQgYnkgdGhlIHRpbWUgZHJhZ2VuZCBpcyBmaXJlZFxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZSghX3RoaXMuY29tcG9uZW50LmlzVmFsaWREYXRlRG93bkVsKGRyYWdnaW5nLnBvaW50ZXIuZG93bkVsKSk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIHdvbid0IGV2ZW4gZmlyZSBpZiBtb3Zpbmcgd2FzIGlnbm9yZWRcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIHZhciBfYSA9IGNvbXBvbmVudC5jb250ZXh0LCBjYWxlbmRhciA9IF9hLmNhbGVuZGFyLCB2aWV3ID0gX2EudmlldztcbiAgICAgICAgICAgIHZhciBwb2ludGVyID0gX3RoaXMuZHJhZ2dpbmcucG9pbnRlcjtcbiAgICAgICAgICAgIGlmICghcG9pbnRlci53YXNUb3VjaFNjcm9sbCkge1xuICAgICAgICAgICAgICAgIHZhciBfYiA9IF90aGlzLmhpdERyYWdnaW5nLCBpbml0aWFsSGl0ID0gX2IuaW5pdGlhbEhpdCwgZmluYWxIaXQgPSBfYi5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbEhpdCAmJiBmaW5hbEhpdCAmJiBpc0hpdHNFcXVhbChpbml0aWFsSGl0LCBmaW5hbEhpdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIudHJpZ2dlckRhdGVDbGljayhpbml0aWFsSGl0LmRhdGVTcGFuLCBpbml0aWFsSGl0LmRheUVsLCB2aWV3LCBldi5vcmlnRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgLy8gd2UgRE8gd2FudCB0byB3YXRjaCBwb2ludGVyIG1vdmVzIGJlY2F1c2Ugb3RoZXJ3aXNlIGZpbmFsSGl0IHdvbid0IGdldCBwb3B1bGF0ZWRcbiAgICAgICAgX3RoaXMuZHJhZ2dpbmcgPSBuZXcgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhjb21wb25lbnQuZWwpO1xuICAgICAgICBfdGhpcy5kcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gZmFsc2U7XG4gICAgICAgIHZhciBoaXREcmFnZ2luZyA9IF90aGlzLmhpdERyYWdnaW5nID0gbmV3IEhpdERyYWdnaW5nKF90aGlzLmRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIF90aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIERhdGVDbGlja2luZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF0ZUNsaWNraW5nO1xufShJbnRlcmFjdGlvbikpO1xuXG4vKlxuVHJhY2tzIHdoZW4gdGhlIHVzZXIgc2VsZWN0cyBhIHBvcnRpb24gb2YgdGltZSBvZiBhIGNvbXBvbmVudCxcbmNvbnN0aXR1dGVkIGJ5IGEgZHJhZyBvdmVyIGRhdGUgY2VsbHMsIHdpdGggYSBwb3NzaWJsZSBkZWxheSBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBkcmFnLlxuKi9cbnZhciBEYXRlU2VsZWN0aW5nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEYXRlU2VsZWN0aW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERhdGVTZWxlY3Rpbmcoc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgc2V0dGluZ3MpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmRyYWdTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMsIGNvbXBvbmVudCA9IF9hLmNvbXBvbmVudCwgZHJhZ2dpbmcgPSBfYS5kcmFnZ2luZztcbiAgICAgICAgICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICAgICAgICAgIHZhciBjYW5TZWxlY3QgPSBvcHRpb25zLnNlbGVjdGFibGUgJiZcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuaXNWYWxpZERhdGVEb3duRWwoZXYub3JpZ0V2ZW50LnRhcmdldCk7XG4gICAgICAgICAgICAvLyBkb24ndCBib3RoZXIgdG8gd2F0Y2ggZXhwZW5zaXZlIG1vdmVzIGlmIGNvbXBvbmVudCB3b24ndCBkbyBzZWxlY3Rpb25cbiAgICAgICAgICAgIGRyYWdnaW5nLnNldElnbm9yZU1vdmUoIWNhblNlbGVjdCk7XG4gICAgICAgICAgICAvLyBpZiB0b3VjaCwgcmVxdWlyZSB1c2VyIHRvIGhvbGQgZG93blxuICAgICAgICAgICAgZHJhZ2dpbmcuZGVsYXkgPSBldi5pc1RvdWNoID8gZ2V0Q29tcG9uZW50VG91Y2hEZWxheShjb21wb25lbnQpIDogbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5jb21wb25lbnQuY29udGV4dC5jYWxlbmRhci51bnNlbGVjdChldik7IC8vIHVuc2VsZWN0IHByZXZpb3VzIHNlbGVjdGlvbnNcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlSGl0VXBkYXRlID0gZnVuY3Rpb24gKGhpdCwgaXNGaW5hbCkge1xuICAgICAgICAgICAgdmFyIGNhbGVuZGFyID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICB2YXIgZHJhZ1NlbGVjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB2YXIgaXNJbnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoaGl0KSB7XG4gICAgICAgICAgICAgICAgZHJhZ1NlbGVjdGlvbiA9IGpvaW5IaXRzSW50b1NlbGVjdGlvbihfdGhpcy5oaXREcmFnZ2luZy5pbml0aWFsSGl0LCBoaXQsIGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5kYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzKTtcbiAgICAgICAgICAgICAgICBpZiAoIWRyYWdTZWxlY3Rpb24gfHwgIV90aGlzLmNvbXBvbmVudC5pc0RhdGVTZWxlY3Rpb25WYWxpZChkcmFnU2VsZWN0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBkcmFnU2VsZWN0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZHJhZ1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1NFTEVDVF9EQVRFUycsIHNlbGVjdGlvbjogZHJhZ1NlbGVjdGlvbiB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFpc0ZpbmFsKSB7IC8vIG9ubHkgdW5zZWxlY3QgaWYgbW92ZWQgYXdheSB3aGlsZSBkcmFnZ2luZ1xuICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VMRUNUX0RBVEVTJyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZW5hYmxlQ3Vyc29yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXNhYmxlQ3Vyc29yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzRmluYWwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kcmFnU2VsZWN0aW9uID0gZHJhZ1NlbGVjdGlvbjsgLy8gb25seSBjbGVhciBpZiBtb3ZlZCBhd2F5IGZyb20gYWxsIGhpdHMgd2hpbGUgZHJhZ2dpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlclVwID0gZnVuY3Rpb24gKHBldikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmRyYWdTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBzZWxlY3Rpb24gaXMgYWxyZWFkeSByZW5kZXJlZCwgc28ganVzdCBuZWVkIHRvIHJlcG9ydCBzZWxlY3Rpb25cbiAgICAgICAgICAgICAgICBfdGhpcy5jb21wb25lbnQuY29udGV4dC5jYWxlbmRhci50cmlnZ2VyRGF0ZVNlbGVjdChfdGhpcy5kcmFnU2VsZWN0aW9uLCBwZXYpO1xuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdTZWxlY3Rpb24gPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gc2V0dGluZ3MuY29tcG9uZW50O1xuICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29tcG9uZW50LmVsKTtcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGRyYWdnaW5nLm1pbkRpc3RhbmNlID0gb3B0aW9ucy5zZWxlY3RNaW5EaXN0YW5jZSB8fCAwO1xuICAgICAgICBkcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gb3B0aW9ucy5kcmFnU2Nyb2xsO1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSBfdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyhfdGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1RvU3RvcmUoc2V0dGluZ3MpKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcmRvd24nLCBfdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2RyYWdzdGFydCcsIF90aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIF90aGlzLmhhbmRsZUhpdFVwZGF0ZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIF90aGlzLmhhbmRsZVBvaW50ZXJVcCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF0ZVNlbGVjdGluZy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kcmFnZ2luZy5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gRGF0ZVNlbGVjdGluZztcbn0oSW50ZXJhY3Rpb24pKTtcbmZ1bmN0aW9uIGdldENvbXBvbmVudFRvdWNoRGVsYXkoY29tcG9uZW50KSB7XG4gICAgdmFyIG9wdGlvbnMgPSBjb21wb25lbnQuY29udGV4dC5vcHRpb25zO1xuICAgIHZhciBkZWxheSA9IG9wdGlvbnMuc2VsZWN0TG9uZ1ByZXNzRGVsYXk7XG4gICAgaWYgKGRlbGF5ID09IG51bGwpIHtcbiAgICAgICAgZGVsYXkgPSBvcHRpb25zLmxvbmdQcmVzc0RlbGF5O1xuICAgIH1cbiAgICByZXR1cm4gZGVsYXk7XG59XG5mdW5jdGlvbiBqb2luSGl0c0ludG9TZWxlY3Rpb24oaGl0MCwgaGl0MSwgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVycykge1xuICAgIHZhciBkYXRlU3BhbjAgPSBoaXQwLmRhdGVTcGFuO1xuICAgIHZhciBkYXRlU3BhbjEgPSBoaXQxLmRhdGVTcGFuO1xuICAgIHZhciBtcyA9IFtcbiAgICAgICAgZGF0ZVNwYW4wLnJhbmdlLnN0YXJ0LFxuICAgICAgICBkYXRlU3BhbjAucmFuZ2UuZW5kLFxuICAgICAgICBkYXRlU3BhbjEucmFuZ2Uuc3RhcnQsXG4gICAgICAgIGRhdGVTcGFuMS5yYW5nZS5lbmRcbiAgICBdO1xuICAgIG1zLnNvcnQoY29tcGFyZU51bWJlcnMpO1xuICAgIHZhciBwcm9wcyA9IHt9O1xuICAgIGZvciAodmFyIF9pID0gMCwgZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyc18xID0gZGF0ZVNlbGVjdGlvblRyYW5zZm9ybWVyczsgX2kgPCBkYXRlU2VsZWN0aW9uVHJhbnNmb3JtZXJzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm1lciA9IGRhdGVTZWxlY3Rpb25UcmFuc2Zvcm1lcnNfMVtfaV07XG4gICAgICAgIHZhciByZXMgPSB0cmFuc2Zvcm1lcihoaXQwLCBoaXQxKTtcbiAgICAgICAgaWYgKHJlcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlcykge1xuICAgICAgICAgICAgX19hc3NpZ24ocHJvcHMsIHJlcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHJvcHMucmFuZ2UgPSB7IHN0YXJ0OiBtc1swXSwgZW5kOiBtc1szXSB9O1xuICAgIHByb3BzLmFsbERheSA9IGRhdGVTcGFuMC5hbGxEYXk7XG4gICAgcmV0dXJuIHByb3BzO1xufVxuXG52YXIgRXZlbnREcmFnZ2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRXZlbnREcmFnZ2luZywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFdmVudERyYWdnaW5nKHNldHRpbmdzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHNldHRpbmdzKSB8fCB0aGlzO1xuICAgICAgICAvLyBpbnRlcm5hbCBzdGF0ZVxuICAgICAgICBfdGhpcy5zdWJqZWN0U2VnID0gbnVsbDsgLy8gdGhlIHNlZyBiZWluZyBzZWxlY3RlZC9kcmFnZ2VkXG4gICAgICAgIF90aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuZXZlbnRSYW5nZSA9IG51bGw7XG4gICAgICAgIF90aGlzLnJlbGV2YW50RXZlbnRzID0gbnVsbDsgLy8gdGhlIGV2ZW50cyBiZWluZyBkcmFnZ2VkXG4gICAgICAgIF90aGlzLnJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG51bGw7XG4gICAgICAgIF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgb3JpZ1RhcmdldCA9IGV2Lm9yaWdFdmVudC50YXJnZXQ7XG4gICAgICAgICAgICB2YXIgX2EgPSBfdGhpcywgY29tcG9uZW50ID0gX2EuY29tcG9uZW50LCBkcmFnZ2luZyA9IF9hLmRyYWdnaW5nO1xuICAgICAgICAgICAgdmFyIG1pcnJvciA9IGRyYWdnaW5nLm1pcnJvcjtcbiAgICAgICAgICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICAgICAgICAgIHZhciBpbml0aWFsQ2FsZW5kYXIgPSBjb21wb25lbnQuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgICAgIHZhciBzdWJqZWN0U2VnID0gX3RoaXMuc3ViamVjdFNlZyA9IGdldEVsU2VnKGV2LnN1YmplY3RFbCk7XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IF90aGlzLmV2ZW50UmFuZ2UgPSBzdWJqZWN0U2VnLmV2ZW50UmFuZ2U7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZUlkID0gZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkO1xuICAgICAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBnZXRSZWxldmFudEV2ZW50cyhpbml0aWFsQ2FsZW5kYXIuc3RhdGUuZXZlbnRTdG9yZSwgZXZlbnRJbnN0YW5jZUlkKTtcbiAgICAgICAgICAgIGRyYWdnaW5nLm1pbkRpc3RhbmNlID0gZXYuaXNUb3VjaCA/IDAgOiBvcHRpb25zLmV2ZW50RHJhZ01pbkRpc3RhbmNlO1xuICAgICAgICAgICAgZHJhZ2dpbmcuZGVsYXkgPVxuICAgICAgICAgICAgICAgIC8vIG9ubHkgZG8gYSB0b3VjaCBkZWxheSBpZiB0b3VjaCBhbmQgdGhpcyBldmVudCBoYXNuJ3QgYmVlbiBzZWxlY3RlZCB5ZXRcbiAgICAgICAgICAgICAgICAoZXYuaXNUb3VjaCAmJiBldmVudEluc3RhbmNlSWQgIT09IGNvbXBvbmVudC5wcm9wcy5ldmVudFNlbGVjdGlvbikgP1xuICAgICAgICAgICAgICAgICAgICBnZXRDb21wb25lbnRUb3VjaERlbGF5JDEoY29tcG9uZW50KSA6XG4gICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgICAgICAgICBtaXJyb3IucGFyZW50Tm9kZSA9IGluaXRpYWxDYWxlbmRhci5lbDtcbiAgICAgICAgICAgIG1pcnJvci5yZXZlcnREdXJhdGlvbiA9IG9wdGlvbnMuZHJhZ1JldmVydER1cmF0aW9uO1xuICAgICAgICAgICAgdmFyIGlzVmFsaWQgPSBjb21wb25lbnQuaXNWYWxpZFNlZ0Rvd25FbChvcmlnVGFyZ2V0KSAmJlxuICAgICAgICAgICAgICAgICFlbGVtZW50Q2xvc2VzdChvcmlnVGFyZ2V0LCAnLmZjLXJlc2l6ZXInKTsgLy8gTk9UIG9uIGEgcmVzaXplclxuICAgICAgICAgICAgZHJhZ2dpbmcuc2V0SWdub3JlTW92ZSghaXNWYWxpZCk7XG4gICAgICAgICAgICAvLyBkaXNhYmxlIGRyYWdnaW5nIGZvciBlbGVtZW50cyB0aGF0IGFyZSByZXNpemFibGUgKGllLCBzZWxlY3RhYmxlKVxuICAgICAgICAgICAgLy8gYnV0IGFyZSBub3QgZHJhZ2dhYmxlXG4gICAgICAgICAgICBfdGhpcy5pc0RyYWdnaW5nID0gaXNWYWxpZCAmJlxuICAgICAgICAgICAgICAgIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLWRyYWdnYWJsZScpO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVEcmFnU3RhcnQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBjb250ZXh0ID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQ7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgICAgIHZhciBldmVudFJhbmdlID0gX3RoaXMuZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlSWQgPSBldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWQ7XG4gICAgICAgICAgICBpZiAoZXYuaXNUb3VjaCkge1xuICAgICAgICAgICAgICAgIC8vIG5lZWQgdG8gc2VsZWN0IGEgZGlmZmVyZW50IGV2ZW50P1xuICAgICAgICAgICAgICAgIGlmIChldmVudEluc3RhbmNlSWQgIT09IF90aGlzLmNvbXBvbmVudC5wcm9wcy5ldmVudFNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnU0VMRUNUX0VWRU5UJywgZXZlbnRJbnN0YW5jZUlkOiBldmVudEluc3RhbmNlSWQgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgbm93IHVzaW5nIG1vdXNlLCBidXQgd2FzIHByZXZpb3VzIHRvdWNoIGludGVyYWN0aW9uLCBjbGVhciBzZWxlY3RlZCBldmVudFxuICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFTEVDVF9FVkVOVCcgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhci51bnNlbGVjdChldik7IC8vIHVuc2VsZWN0ICpkYXRlKiBzZWxlY3Rpb25cbiAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudERyYWdTdGFydCcsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLnN1YmplY3RTZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGluaXRpYWxDYWxlbmRhciwgZXZlbnRSYW5nZS5kZWYsIGV2ZW50UmFuZ2UuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAganNFdmVudDogZXYub3JpZ0V2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlldzogY29udGV4dC52aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlSGl0VXBkYXRlID0gZnVuY3Rpb24gKGhpdCwgaXNGaW5hbCkge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlbGV2YW50RXZlbnRzID0gX3RoaXMucmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbEhpdCA9IF90aGlzLmhpdERyYWdnaW5nLmluaXRpYWxIaXQ7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICAvLyBzdGF0ZXMgYmFzZWQgb24gbmV3IGhpdFxuICAgICAgICAgICAgdmFyIHJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB2YXIgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogcmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBvcmlnU2VnOiBfdGhpcy5zdWJqZWN0U2VnXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGhpdCkge1xuICAgICAgICAgICAgICAgIHZhciByZWNlaXZpbmdDb21wb25lbnQgPSBoaXQuY29tcG9uZW50O1xuICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyID0gcmVjZWl2aW5nQ29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICAgICAgdmFyIHJlY2VpdmluZ09wdGlvbnMgPSByZWNlaXZpbmdDb21wb25lbnQuY29udGV4dC5vcHRpb25zO1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsQ2FsZW5kYXIgPT09IHJlY2VpdmluZ0NhbGVuZGFyIHx8XG4gICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ09wdGlvbnMuZWRpdGFibGUgJiYgcmVjZWl2aW5nT3B0aW9ucy5kcm9wcGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRpb24gPSBjb21wdXRlRXZlbnRNdXRhdGlvbihpbml0aWFsSGl0LCBoaXQsIHJlY2VpdmluZ0NhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudERyYWdNdXRhdGlvbk1hc3NhZ2Vycyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtdXRhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZShyZWxldmFudEV2ZW50cywgcmVjZWl2aW5nQ2FsZW5kYXIuZXZlbnRVaUJhc2VzLCBtdXRhdGlvbiwgcmVjZWl2aW5nQ2FsZW5kYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcmVjZWl2aW5nQ29tcG9uZW50LmlzSW50ZXJhY3Rpb25WYWxpZChpbnRlcmFjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBjcmVhdGVFbXB0eUV2ZW50U3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmRpc3BsYXlEcmFnKHJlY2VpdmluZ0NhbGVuZGFyLCBpbnRlcmFjdGlvbik7XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGluaXRpYWxDYWxlbmRhciA9PT0gcmVjZWl2aW5nQ2FsZW5kYXIgJiYgLy8gVE9ETzogd3JpdGUgdGVzdCBmb3IgdGhpc1xuICAgICAgICAgICAgICAgICAgICBpc0hpdHNFcXVhbChpbml0aWFsSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmcuc2V0TWlycm9yTmVlZHNSZXZlcnQoIW11dGF0aW9uKTtcbiAgICAgICAgICAgICAgICAvLyByZW5kZXIgdGhlIG1pcnJvciBpZiBubyBhbHJlYWR5LXJlbmRlcmVkIG1pcnJvclxuICAgICAgICAgICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgc29tZWhvdyB3YWl0IGZvciBkaXNwYXRjaCB0byBndWFyYW50ZWUgcmVuZGVyXG4gICAgICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmcuc2V0TWlycm9ySXNWaXNpYmxlKCFoaXQgfHwgIWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5mYy1taXJyb3InKSk7XG4gICAgICAgICAgICAgICAgLy8gYXNzaWduIHN0YXRlcyBiYXNlZCBvbiBuZXcgaGl0XG4gICAgICAgICAgICAgICAgX3RoaXMucmVjZWl2aW5nQ2FsZW5kYXIgPSByZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgICAgICAgICBfdGhpcy52YWxpZE11dGF0aW9uID0gbXV0YXRpb247XG4gICAgICAgICAgICAgICAgX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbXV0YXRlZFJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyVXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGVhbnVwKCk7IC8vIGJlY2F1c2UgaGFuZGxlRHJhZ0VuZCB3b24ndCBmaXJlXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdFbmQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRleHQgPSBfdGhpcy5jb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyXzEgPSBjb250ZXh0LmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgIHZhciBpbml0aWFsVmlldyA9IGNvbnRleHQudmlldztcbiAgICAgICAgICAgICAgICB2YXIgX2EgPSBfdGhpcywgcmVjZWl2aW5nQ2FsZW5kYXIgPSBfYS5yZWNlaXZpbmdDYWxlbmRhciwgdmFsaWRNdXRhdGlvbiA9IF9hLnZhbGlkTXV0YXRpb247XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50RGVmID0gX3RoaXMuZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50SW5zdGFuY2UgPSBfdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlO1xuICAgICAgICAgICAgICAgIHZhciBldmVudEFwaSA9IG5ldyBFdmVudEFwaShpbml0aWFsQ2FsZW5kYXJfMSwgZXZlbnREZWYsIGV2ZW50SW5zdGFuY2UpO1xuICAgICAgICAgICAgICAgIHZhciByZWxldmFudEV2ZW50c18xID0gX3RoaXMucmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgdmFyIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgICAgICB2YXIgZmluYWxIaXQgPSBfdGhpcy5oaXREcmFnZ2luZy5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGVhckRyYWcoKTsgLy8gbXVzdCBoYXBwZW4gYWZ0ZXIgcmV2ZXJ0IGFuaW1hdGlvblxuICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLnB1YmxpY2x5VHJpZ2dlcignZXZlbnREcmFnU3RvcCcsIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLnN1YmplY3RTZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiBpbml0aWFsVmlld1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbGlkTXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZHJvcHBlZCB3aXRoaW4gc2FtZSBjYWxlbmRhclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVjZWl2aW5nQ2FsZW5kYXIgPT09IGluaXRpYWxDYWxlbmRhcl8xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogbXV0YXRlZFJlbGV2YW50RXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lZCA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYiA9IGluaXRpYWxDYWxlbmRhcl8xLnBsdWdpblN5c3RlbS5ob29rcy5ldmVudERyb3BUcmFuc2Zvcm1lcnM7IF9pIDwgX2IubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybWVyID0gX2JbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9fYXNzaWduKHRyYW5zZm9ybWVkLCB0cmFuc2Zvcm1lcih2YWxpZE11dGF0aW9uLCBpbml0aWFsQ2FsZW5kYXJfMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50RHJvcEFyZyA9IF9fYXNzaWduKHt9LCB0cmFuc2Zvcm1lZCwgeyBlbDogZXYuc3ViamVjdEVsLCBkZWx0YTogdmFsaWRNdXRhdGlvbi5kYXRlc0RlbHRhLCBvbGRFdmVudDogZXZlbnRBcGksIGV2ZW50OiBuZXcgRXZlbnRBcGkoLy8gdGhlIGRhdGEgQUZURVIgdGhlIG11dGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEsIG11dGF0ZWRSZWxldmFudEV2ZW50cy5kZWZzW2V2ZW50RGVmLmRlZklkXSwgZXZlbnRJbnN0YW5jZSA/IG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSA6IG51bGwpLCByZXZlcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyXzEuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiByZWxldmFudEV2ZW50c18xXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCwgdmlldzogaW5pdGlhbFZpZXcgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50RHJvcCcsIFtldmVudERyb3BBcmddKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRyb3BwZWQgaW4gZGlmZmVyZW50IGNhbGVuZGFyXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAocmVjZWl2aW5nQ2FsZW5kYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRMZWF2ZScsIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnZWRFbDogZXYuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGluaXRpYWxWaWV3XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsQ2FsZW5kYXJfMS5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1JFTU9WRV9FVkVOVF9JTlNUQU5DRVMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlczogX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzLmluc3RhbmNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ01FUkdFX0VWRU5UUycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogX3RoaXMubXV0YXRlZFJlbGV2YW50RXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VMRUNUX0VWRU5UJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRJbnN0YW5jZUlkOiBldmVudEluc3RhbmNlLmluc3RhbmNlSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkcm9wQXJnID0gX19hc3NpZ24oe30sIHJlY2VpdmluZ0NhbGVuZGFyLmJ1aWxkRGF0ZVBvaW50QXBpKGZpbmFsSGl0LmRhdGVTcGFuKSwgeyBkcmFnZ2VkRWw6IGV2LnN1YmplY3RFbCwganNFdmVudDogZXYub3JpZ0V2ZW50LCB2aWV3OiBmaW5hbEhpdC5jb21wb25lbnQgLy8gc2hvdWxkIHRoaXMgYmUgZmluYWxIaXQuY29tcG9uZW50LnZpZXc/IFNlZSAjNDY0NFxuICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdkcm9wJywgW2Ryb3BBcmddKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZWNlaXZlJywgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dlZEVsOiBldi5zdWJqZWN0RWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkoLy8gdGhlIGRhdGEgQUZURVIgdGhlIG11dGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmluZ0NhbGVuZGFyLCBtdXRhdGVkUmVsZXZhbnRFdmVudHMuZGVmc1tldmVudERlZi5kZWZJZF0sIG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGZpbmFsSGl0LmNvbXBvbmVudCAvLyBzaG91bGQgdGhpcyBiZSBmaW5hbEhpdC5jb21wb25lbnQudmlldz8gU2VlICM0NjQ0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxDYWxlbmRhcl8xLnB1YmxpY2x5VHJpZ2dlcignX25vRXZlbnREcm9wJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuY2xlYW51cCgpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gX3RoaXMuY29tcG9uZW50O1xuICAgICAgICB2YXIgb3B0aW9ucyA9IGNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnM7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IF90aGlzLmRyYWdnaW5nID0gbmV3IEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcoY29tcG9uZW50LmVsKTtcbiAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9IEV2ZW50RHJhZ2dpbmcuU0VMRUNUT1I7XG4gICAgICAgIGRyYWdnaW5nLnRvdWNoU2Nyb2xsQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICBkcmFnZ2luZy5hdXRvU2Nyb2xsZXIuaXNFbmFibGVkID0gb3B0aW9ucy5kcmFnU2Nyb2xsO1xuICAgICAgICB2YXIgaGl0RHJhZ2dpbmcgPSBfdGhpcy5oaXREcmFnZ2luZyA9IG5ldyBIaXREcmFnZ2luZyhfdGhpcy5kcmFnZ2luZywgaW50ZXJhY3Rpb25TZXR0aW5nc1N0b3JlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcudXNlU3ViamVjdENlbnRlciA9IHNldHRpbmdzLnVzZUV2ZW50Q2VudGVyO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignaGl0dXBkYXRlJywgX3RoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbigncG9pbnRlcnVwJywgX3RoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIF90aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgLy8gcmVuZGVyIGEgZHJhZyBzdGF0ZSBvbiB0aGUgbmV4dCByZWNlaXZpbmdDYWxlbmRhclxuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmRpc3BsYXlEcmFnID0gZnVuY3Rpb24gKG5leHRDYWxlbmRhciwgc3RhdGUpIHtcbiAgICAgICAgdmFyIGluaXRpYWxDYWxlbmRhciA9IHRoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgIHZhciBwcmV2Q2FsZW5kYXIgPSB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyO1xuICAgICAgICAvLyBkb2VzIHRoZSBwcmV2aW91cyBjYWxlbmRhciBuZWVkIHRvIGJlIGNsZWFyZWQ/XG4gICAgICAgIGlmIChwcmV2Q2FsZW5kYXIgJiYgcHJldkNhbGVuZGFyICE9PSBuZXh0Q2FsZW5kYXIpIHtcbiAgICAgICAgICAgIC8vIGRvZXMgdGhlIGluaXRpYWwgY2FsZW5kYXIgbmVlZCB0byBiZSBjbGVhcmVkP1xuICAgICAgICAgICAgLy8gaWYgc28sIGRvbid0IGNsZWFyIGFsbCB0aGUgd2F5LiB3ZSBzdGlsbCBuZWVkIHRvIHRvIGhpZGUgdGhlIGFmZmVjdGVkRXZlbnRzXG4gICAgICAgICAgICBpZiAocHJldkNhbGVuZGFyID09PSBpbml0aWFsQ2FsZW5kYXIpIHtcbiAgICAgICAgICAgICAgICBwcmV2Q2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnU0VUX0VWRU5UX0RSQUcnLFxuICAgICAgICAgICAgICAgICAgICBzdGF0ZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWZmZWN0ZWRFdmVudHM6IHN0YXRlLmFmZmVjdGVkRXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0V2ZW50OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ1NlZzogc3RhdGUub3JpZ1NlZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gY29tcGxldGVseSBjbGVhciB0aGUgb2xkIGNhbGVuZGFyIGlmIGl0IHdhc24ndCB0aGUgaW5pdGlhbFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcHJldkNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0Q2FsZW5kYXIpIHtcbiAgICAgICAgICAgIG5leHRDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdTRVRfRVZFTlRfRFJBRycsIHN0YXRlOiBzdGF0ZSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnREcmFnZ2luZy5wcm90b3R5cGUuY2xlYXJEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5pdGlhbENhbGVuZGFyID0gdGhpcy5jb21wb25lbnQuY29udGV4dC5jYWxlbmRhcjtcbiAgICAgICAgdmFyIHJlY2VpdmluZ0NhbGVuZGFyID0gdGhpcy5yZWNlaXZpbmdDYWxlbmRhcjtcbiAgICAgICAgaWYgKHJlY2VpdmluZ0NhbGVuZGFyKSB7XG4gICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGUgaW5pdGlhbCBjYWxlbmRhciBtaWdodCBoYXZlIGFuIGR1bW15IGRyYWcgc3RhdGUgZnJvbSBkaXNwbGF5RHJhZ1xuICAgICAgICBpZiAoaW5pdGlhbENhbGVuZGFyICE9PSByZWNlaXZpbmdDYWxlbmRhcikge1xuICAgICAgICAgICAgaW5pdGlhbENhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VUX0VWRU5UX0RSQUcnIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudERyYWdnaW5nLnByb3RvdHlwZS5jbGVhbnVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnN1YmplY3RTZWcgPSBudWxsO1xuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVudFJhbmdlID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIHRoaXMucmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICB0aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgfTtcbiAgICBFdmVudERyYWdnaW5nLlNFTEVDVE9SID0gJy5mYy1kcmFnZ2FibGUsIC5mYy1yZXNpemFibGUnOyAvLyBUT0RPOiB0ZXN0IHRoaXMgaW4gSUUxMVxuICAgIHJldHVybiBFdmVudERyYWdnaW5nO1xufShJbnRlcmFjdGlvbikpO1xuZnVuY3Rpb24gY29tcHV0ZUV2ZW50TXV0YXRpb24oaGl0MCwgaGl0MSwgbWFzc2FnZXJzKSB7XG4gICAgdmFyIGRhdGVTcGFuMCA9IGhpdDAuZGF0ZVNwYW47XG4gICAgdmFyIGRhdGVTcGFuMSA9IGhpdDEuZGF0ZVNwYW47XG4gICAgdmFyIGRhdGUwID0gZGF0ZVNwYW4wLnJhbmdlLnN0YXJ0O1xuICAgIHZhciBkYXRlMSA9IGRhdGVTcGFuMS5yYW5nZS5zdGFydDtcbiAgICB2YXIgc3RhbmRhcmRQcm9wcyA9IHt9O1xuICAgIGlmIChkYXRlU3BhbjAuYWxsRGF5ICE9PSBkYXRlU3BhbjEuYWxsRGF5KSB7XG4gICAgICAgIHN0YW5kYXJkUHJvcHMuYWxsRGF5ID0gZGF0ZVNwYW4xLmFsbERheTtcbiAgICAgICAgc3RhbmRhcmRQcm9wcy5oYXNFbmQgPSBoaXQxLmNvbXBvbmVudC5jb250ZXh0Lm9wdGlvbnMuYWxsRGF5TWFpbnRhaW5EdXJhdGlvbjtcbiAgICAgICAgaWYgKGRhdGVTcGFuMS5hbGxEYXkpIHtcbiAgICAgICAgICAgIC8vIG1lYW5zIGRhdGUxIGlzIGFscmVhZHkgc3RhcnQtb2YtZGF5LFxuICAgICAgICAgICAgLy8gYnV0IGRhdGUwIG5lZWRzIHRvIGJlIGNvbnZlcnRlZFxuICAgICAgICAgICAgZGF0ZTAgPSBzdGFydE9mRGF5KGRhdGUwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgZGVsdGEgPSBkaWZmRGF0ZXMoZGF0ZTAsIGRhdGUxLCBoaXQwLmNvbXBvbmVudC5jb250ZXh0LmRhdGVFbnYsIGhpdDAuY29tcG9uZW50ID09PSBoaXQxLmNvbXBvbmVudCA/XG4gICAgICAgIGhpdDAuY29tcG9uZW50LmxhcmdlVW5pdCA6XG4gICAgICAgIG51bGwpO1xuICAgIGlmIChkZWx0YS5taWxsaXNlY29uZHMpIHsgLy8gaGFzIGhvdXJzL21pbnV0ZXMvc2Vjb25kc1xuICAgICAgICBzdGFuZGFyZFByb3BzLmFsbERheSA9IGZhbHNlO1xuICAgIH1cbiAgICB2YXIgbXV0YXRpb24gPSB7XG4gICAgICAgIGRhdGVzRGVsdGE6IGRlbHRhLFxuICAgICAgICBzdGFuZGFyZFByb3BzOiBzdGFuZGFyZFByb3BzXG4gICAgfTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIG1hc3NhZ2Vyc18xID0gbWFzc2FnZXJzOyBfaSA8IG1hc3NhZ2Vyc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgbWFzc2FnZXIgPSBtYXNzYWdlcnNfMVtfaV07XG4gICAgICAgIG1hc3NhZ2VyKG11dGF0aW9uLCBoaXQwLCBoaXQxKTtcbiAgICB9XG4gICAgcmV0dXJuIG11dGF0aW9uO1xufVxuZnVuY3Rpb24gZ2V0Q29tcG9uZW50VG91Y2hEZWxheSQxKGNvbXBvbmVudCkge1xuICAgIHZhciBvcHRpb25zID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucztcbiAgICB2YXIgZGVsYXkgPSBvcHRpb25zLmV2ZW50TG9uZ1ByZXNzRGVsYXk7XG4gICAgaWYgKGRlbGF5ID09IG51bGwpIHtcbiAgICAgICAgZGVsYXkgPSBvcHRpb25zLmxvbmdQcmVzc0RlbGF5O1xuICAgIH1cbiAgICByZXR1cm4gZGVsYXk7XG59XG5cbnZhciBFdmVudERyYWdnaW5nJDEgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEV2ZW50RHJhZ2dpbmcsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRXZlbnREcmFnZ2luZyhzZXR0aW5ncykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBzZXR0aW5ncykgfHwgdGhpcztcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RhdGVcbiAgICAgICAgX3RoaXMuZHJhZ2dpbmdTZWcgPSBudWxsOyAvLyBUT0RPOiByZW5hbWUgdG8gcmVzaXppbmdTZWc/IHN1YmplY3RTZWc/XG4gICAgICAgIF90aGlzLmV2ZW50UmFuZ2UgPSBudWxsO1xuICAgICAgICBfdGhpcy5yZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgIF90aGlzLnZhbGlkTXV0YXRpb24gPSBudWxsO1xuICAgICAgICBfdGhpcy5tdXRhdGVkUmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICBfdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIGNvbXBvbmVudCA9IF90aGlzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIHZhciBzZWcgPSBfdGhpcy5xdWVyeVNlZyhldik7XG4gICAgICAgICAgICB2YXIgZXZlbnRSYW5nZSA9IF90aGlzLmV2ZW50UmFuZ2UgPSBzZWcuZXZlbnRSYW5nZTtcbiAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLm1pbkRpc3RhbmNlID0gY29tcG9uZW50LmNvbnRleHQub3B0aW9ucy5ldmVudERyYWdNaW5EaXN0YW5jZTtcbiAgICAgICAgICAgIC8vIGlmIHRvdWNoLCBuZWVkIHRvIGJlIHdvcmtpbmcgd2l0aCBhIHNlbGVjdGVkIGV2ZW50XG4gICAgICAgICAgICBfdGhpcy5kcmFnZ2luZy5zZXRJZ25vcmVNb3ZlKCFfdGhpcy5jb21wb25lbnQuaXNWYWxpZFNlZ0Rvd25FbChldi5vcmlnRXZlbnQudGFyZ2V0KSB8fFxuICAgICAgICAgICAgICAgIChldi5pc1RvdWNoICYmIF90aGlzLmNvbXBvbmVudC5wcm9wcy5ldmVudFNlbGVjdGlvbiAhPT0gZXZlbnRSYW5nZS5pbnN0YW5jZS5pbnN0YW5jZUlkKSk7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3O1xuICAgICAgICAgICAgdmFyIGV2ZW50UmFuZ2UgPSBfdGhpcy5ldmVudFJhbmdlO1xuICAgICAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBnZXRSZWxldmFudEV2ZW50cyhjYWxlbmRhci5zdGF0ZS5ldmVudFN0b3JlLCBfdGhpcy5ldmVudFJhbmdlLmluc3RhbmNlLmluc3RhbmNlSWQpO1xuICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmdTZWcgPSBfdGhpcy5xdWVyeVNlZyhldik7XG4gICAgICAgICAgICBjYWxlbmRhci51bnNlbGVjdCgpO1xuICAgICAgICAgICAgY2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlc2l6ZVN0YXJ0JywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLmRyYWdnaW5nU2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKGNhbGVuZGFyLCBldmVudFJhbmdlLmRlZiwgZXZlbnRSYW5nZS5pbnN0YW5jZSksXG4gICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5oYW5kbGVIaXRVcGRhdGUgPSBmdW5jdGlvbiAoaGl0LCBpc0ZpbmFsLCBldikge1xuICAgICAgICAgICAgdmFyIGNhbGVuZGFyID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICB2YXIgcmVsZXZhbnRFdmVudHMgPSBfdGhpcy5yZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIHZhciBpbml0aWFsSGl0ID0gX3RoaXMuaGl0RHJhZ2dpbmcuaW5pdGlhbEhpdDtcbiAgICAgICAgICAgIHZhciBldmVudEluc3RhbmNlID0gX3RoaXMuZXZlbnRSYW5nZS5pbnN0YW5jZTtcbiAgICAgICAgICAgIHZhciBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB2YXIgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogcmVsZXZhbnRFdmVudHMsXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBvcmlnU2VnOiBfdGhpcy5kcmFnZ2luZ1NlZ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChoaXQpIHtcbiAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IGNvbXB1dGVNdXRhdGlvbihpbml0aWFsSGl0LCBoaXQsIGV2LnN1YmplY3RFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2ZjLXN0YXJ0LXJlc2l6ZXInKSwgZXZlbnRJbnN0YW5jZS5yYW5nZSwgY2FsZW5kYXIucGx1Z2luU3lzdGVtLmhvb2tzLmV2ZW50UmVzaXplSm9pblRyYW5zZm9ybXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG11dGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgbXV0YXRlZFJlbGV2YW50RXZlbnRzID0gYXBwbHlNdXRhdGlvblRvRXZlbnRTdG9yZShyZWxldmFudEV2ZW50cywgY2FsZW5kYXIuZXZlbnRVaUJhc2VzLCBtdXRhdGlvbiwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBtdXRhdGVkUmVsZXZhbnRFdmVudHM7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb21wb25lbnQuaXNJbnRlcmFjdGlvblZhbGlkKGludGVyYWN0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtdXRhdGVkUmVsZXZhbnRFdmVudHMpIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdTRVRfRVZFTlRfUkVTSVpFJyxcbiAgICAgICAgICAgICAgICAgICAgc3RhdGU6IGludGVyYWN0aW9uXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9SRVNJWkUnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBlbmFibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpc2FibGVDdXJzb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNGaW5hbCkge1xuICAgICAgICAgICAgICAgIGlmIChtdXRhdGlvbiAmJiBpc0hpdHNFcXVhbChpbml0aWFsSGl0LCBoaXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIG11dGF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG11dGF0aW9uO1xuICAgICAgICAgICAgICAgIF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cyA9IG11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMuY29tcG9uZW50LmNvbnRleHQsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIHZpZXcgPSBfYS52aWV3O1xuICAgICAgICAgICAgdmFyIGV2ZW50RGVmID0gX3RoaXMuZXZlbnRSYW5nZS5kZWY7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbnN0YW5jZSA9IF90aGlzLmV2ZW50UmFuZ2UuaW5zdGFuY2U7XG4gICAgICAgICAgICB2YXIgZXZlbnRBcGkgPSBuZXcgRXZlbnRBcGkoY2FsZW5kYXIsIGV2ZW50RGVmLCBldmVudEluc3RhbmNlKTtcbiAgICAgICAgICAgIHZhciByZWxldmFudEV2ZW50cyA9IF90aGlzLnJlbGV2YW50RXZlbnRzO1xuICAgICAgICAgICAgdmFyIG11dGF0ZWRSZWxldmFudEV2ZW50cyA9IF90aGlzLm11dGF0ZWRSZWxldmFudEV2ZW50cztcbiAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignZXZlbnRSZXNpemVTdG9wJywgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZWw6IF90aGlzLmRyYWdnaW5nU2VnLmVsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgIGpzRXZlbnQ6IGV2Lm9yaWdFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgaWYgKF90aGlzLnZhbGlkTXV0YXRpb24pIHtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdNRVJHRV9FVkVOVFMnLFxuICAgICAgICAgICAgICAgICAgICBldmVudFN0b3JlOiBtdXRhdGVkUmVsZXZhbnRFdmVudHNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2V2ZW50UmVzaXplJywgW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbDogX3RoaXMuZHJhZ2dpbmdTZWcuZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydERlbHRhOiBfdGhpcy52YWxpZE11dGF0aW9uLnN0YXJ0RGVsdGEgfHwgY3JlYXRlRHVyYXRpb24oMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBlbmREZWx0YTogX3RoaXMudmFsaWRNdXRhdGlvbi5lbmREZWx0YSB8fCBjcmVhdGVEdXJhdGlvbigwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZFdmVudDogZXZlbnRBcGksXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogbmV3IEV2ZW50QXBpKC8vIHRoZSBkYXRhIEFGVEVSIHRoZSBtdXRhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIsIG11dGF0ZWRSZWxldmFudEV2ZW50cy5kZWZzW2V2ZW50RGVmLmRlZklkXSwgZXZlbnRJbnN0YW5jZSA/IG11dGF0ZWRSZWxldmFudEV2ZW50cy5pbnN0YW5jZXNbZXZlbnRJbnN0YW5jZS5pbnN0YW5jZUlkXSA6IG51bGwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJ0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTdG9yZTogcmVsZXZhbnRFdmVudHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBqc0V2ZW50OiBldi5vcmlnRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGVuZGFyLnB1YmxpY2x5VHJpZ2dlcignX25vRXZlbnRSZXNpemUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJlc2V0IGFsbCBpbnRlcm5hbCBzdGF0ZVxuICAgICAgICAgICAgX3RoaXMuZHJhZ2dpbmdTZWcgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMucmVsZXZhbnRFdmVudHMgPSBudWxsO1xuICAgICAgICAgICAgX3RoaXMudmFsaWRNdXRhdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAvLyBva2F5IHRvIGtlZXAgZXZlbnRJbnN0YW5jZSBhcm91bmQuIHVzZWZ1bCB0byBzZXQgaXQgaW4gaGFuZGxlUG9pbnRlckRvd25cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBvbmVudCA9IHNldHRpbmdzLmNvbXBvbmVudDtcbiAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuZHJhZ2dpbmcgPSBuZXcgRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZyhjb21wb25lbnQuZWwpO1xuICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gJy5mYy1yZXNpemVyJztcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGRyYWdnaW5nLmF1dG9TY3JvbGxlci5pc0VuYWJsZWQgPSBjb21wb25lbnQuY29udGV4dC5vcHRpb25zLmRyYWdTY3JvbGw7XG4gICAgICAgIHZhciBoaXREcmFnZ2luZyA9IF90aGlzLmhpdERyYWdnaW5nID0gbmV3IEhpdERyYWdnaW5nKF90aGlzLmRyYWdnaW5nLCBpbnRlcmFjdGlvblNldHRpbmdzVG9TdG9yZShzZXR0aW5ncykpO1xuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ3N0YXJ0JywgX3RoaXMuaGFuZGxlRHJhZ1N0YXJ0KTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignaGl0dXBkYXRlJywgX3RoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIF90aGlzLmhhbmRsZURyYWdFbmQpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEV2ZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgRXZlbnREcmFnZ2luZy5wcm90b3R5cGUucXVlcnlTZWcgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgcmV0dXJuIGdldEVsU2VnKGVsZW1lbnRDbG9zZXN0KGV2LnN1YmplY3RFbCwgdGhpcy5jb21wb25lbnQuZmdTZWdTZWxlY3RvcikpO1xuICAgIH07XG4gICAgcmV0dXJuIEV2ZW50RHJhZ2dpbmc7XG59KEludGVyYWN0aW9uKSk7XG5mdW5jdGlvbiBjb21wdXRlTXV0YXRpb24oaGl0MCwgaGl0MSwgaXNGcm9tU3RhcnQsIGluc3RhbmNlUmFuZ2UsIHRyYW5zZm9ybXMpIHtcbiAgICB2YXIgZGF0ZUVudiA9IGhpdDAuY29tcG9uZW50LmNvbnRleHQuZGF0ZUVudjtcbiAgICB2YXIgZGF0ZTAgPSBoaXQwLmRhdGVTcGFuLnJhbmdlLnN0YXJ0O1xuICAgIHZhciBkYXRlMSA9IGhpdDEuZGF0ZVNwYW4ucmFuZ2Uuc3RhcnQ7XG4gICAgdmFyIGRlbHRhID0gZGlmZkRhdGVzKGRhdGUwLCBkYXRlMSwgZGF0ZUVudiwgaGl0MC5jb21wb25lbnQubGFyZ2VVbml0KTtcbiAgICB2YXIgcHJvcHMgPSB7fTtcbiAgICBmb3IgKHZhciBfaSA9IDAsIHRyYW5zZm9ybXNfMSA9IHRyYW5zZm9ybXM7IF9pIDwgdHJhbnNmb3Jtc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtID0gdHJhbnNmb3Jtc18xW19pXTtcbiAgICAgICAgdmFyIHJlcyA9IHRyYW5zZm9ybShoaXQwLCBoaXQxKTtcbiAgICAgICAgaWYgKHJlcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlcykge1xuICAgICAgICAgICAgX19hc3NpZ24ocHJvcHMsIHJlcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzRnJvbVN0YXJ0KSB7XG4gICAgICAgIGlmIChkYXRlRW52LmFkZChpbnN0YW5jZVJhbmdlLnN0YXJ0LCBkZWx0YSkgPCBpbnN0YW5jZVJhbmdlLmVuZCkge1xuICAgICAgICAgICAgcHJvcHMuc3RhcnREZWx0YSA9IGRlbHRhO1xuICAgICAgICAgICAgcmV0dXJuIHByb3BzO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZiAoZGF0ZUVudi5hZGQoaW5zdGFuY2VSYW5nZS5lbmQsIGRlbHRhKSA+IGluc3RhbmNlUmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgICAgIHByb3BzLmVuZERlbHRhID0gZGVsdGE7XG4gICAgICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbnZhciBVbnNlbGVjdEF1dG8gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVW5zZWxlY3RBdXRvKGNhbGVuZGFyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuaXNSZWNlbnRQb2ludGVyRGF0ZVNlbGVjdCA9IGZhbHNlOyAvLyB3aXNoIHdlIGNvdWxkIHVzZSBhIHNlbGVjdG9yIHRvIGRldGVjdCBkYXRlIHNlbGVjdGlvbiwgYnV0IHVzZXMgaGl0IHN5c3RlbVxuICAgICAgICB0aGlzLm9uU2VsZWN0ID0gZnVuY3Rpb24gKHNlbGVjdEluZm8pIHtcbiAgICAgICAgICAgIGlmIChzZWxlY3RJbmZvLmpzRXZlbnQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc1JlY2VudFBvaW50ZXJEYXRlU2VsZWN0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vbkRvY3VtZW50UG9pbnRlclVwID0gZnVuY3Rpb24gKHBldikge1xuICAgICAgICAgICAgdmFyIF9hID0gX3RoaXMsIGNhbGVuZGFyID0gX2EuY2FsZW5kYXIsIGRvY3VtZW50UG9pbnRlciA9IF9hLmRvY3VtZW50UG9pbnRlcjtcbiAgICAgICAgICAgIHZhciBzdGF0ZSA9IGNhbGVuZGFyLnN0YXRlO1xuICAgICAgICAgICAgLy8gdG91Y2gtc2Nyb2xsaW5nIHNob3VsZCBuZXZlciB1bmZvY3VzIGFueSB0eXBlIG9mIHNlbGVjdGlvblxuICAgICAgICAgICAgaWYgKCFkb2N1bWVudFBvaW50ZXIud2FzVG91Y2hTY3JvbGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZGF0ZVNlbGVjdGlvbiAmJiAvLyBhbiBleGlzdGluZyBkYXRlIHNlbGVjdGlvbj9cbiAgICAgICAgICAgICAgICAgICAgIV90aGlzLmlzUmVjZW50UG9pbnRlckRhdGVTZWxlY3QgLy8gYSBuZXcgcG9pbnRlci1pbml0aWF0ZWQgZGF0ZSBzZWxlY3Rpb24gc2luY2UgbGFzdCBvbkRvY3VtZW50UG9pbnRlclVwP1xuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdW5zZWxlY3RBdXRvID0gY2FsZW5kYXIudmlld09wdCgndW5zZWxlY3RBdXRvJyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB1bnNlbGVjdENhbmNlbCA9IGNhbGVuZGFyLnZpZXdPcHQoJ3Vuc2VsZWN0Q2FuY2VsJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1bnNlbGVjdEF1dG8gJiYgKCF1bnNlbGVjdEF1dG8gfHwgIWVsZW1lbnRDbG9zZXN0KGRvY3VtZW50UG9pbnRlci5kb3duRWwsIHVuc2VsZWN0Q2FuY2VsKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLnVuc2VsZWN0KHBldik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlLmV2ZW50U2VsZWN0aW9uICYmIC8vIGFuIGV4aXN0aW5nIGV2ZW50IHNlbGVjdGVkP1xuICAgICAgICAgICAgICAgICAgICAhZWxlbWVudENsb3Nlc3QoZG9jdW1lbnRQb2ludGVyLmRvd25FbCwgRXZlbnREcmFnZ2luZy5TRUxFQ1RPUikgLy8gaW50ZXJhY3Rpb24gRElETidUIHN0YXJ0IG9uIGFuIGV2ZW50XG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1VOU0VMRUNUX0VWRU5UJyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5pc1JlY2VudFBvaW50ZXJEYXRlU2VsZWN0ID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICAgICAgdmFyIGRvY3VtZW50UG9pbnRlciA9IHRoaXMuZG9jdW1lbnRQb2ludGVyID0gbmV3IFBvaW50ZXJEcmFnZ2luZyhkb2N1bWVudCk7XG4gICAgICAgIGRvY3VtZW50UG9pbnRlci5zaG91bGRJZ25vcmVNb3ZlID0gdHJ1ZTtcbiAgICAgICAgZG9jdW1lbnRQb2ludGVyLnNob3VsZFdhdGNoU2Nyb2xsID0gZmFsc2U7XG4gICAgICAgIGRvY3VtZW50UG9pbnRlci5lbWl0dGVyLm9uKCdwb2ludGVydXAnLCB0aGlzLm9uRG9jdW1lbnRQb2ludGVyVXApO1xuICAgICAgICAvKlxuICAgICAgICBUT0RPOiBiZXR0ZXIgd2F5IHRvIGtub3cgYWJvdXQgd2hldGhlciB0aGVyZSB3YXMgYSBzZWxlY3Rpb24gd2l0aCB0aGUgcG9pbnRlclxuICAgICAgICAqL1xuICAgICAgICBjYWxlbmRhci5vbignc2VsZWN0JywgdGhpcy5vblNlbGVjdCk7XG4gICAgfVxuICAgIFVuc2VsZWN0QXV0by5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhci5vZmYoJ3NlbGVjdCcsIHRoaXMub25TZWxlY3QpO1xuICAgICAgICB0aGlzLmRvY3VtZW50UG9pbnRlci5kZXN0cm95KCk7XG4gICAgfTtcbiAgICByZXR1cm4gVW5zZWxlY3RBdXRvO1xufSgpKTtcblxuLypcbkdpdmVuIGFuIGFscmVhZHkgaW5zdGFudGlhdGVkIGRyYWdnYWJsZSBvYmplY3QgZm9yIG9uZS1vci1tb3JlIGVsZW1lbnRzLFxuSW50ZXJwcmV0cyBhbnkgZHJhZ2dpbmcgYXMgYW4gYXR0ZW1wdCB0byBkcmFnIGFuIGV2ZW50cyB0aGF0IGxpdmVzIG91dHNpZGVcbm9mIGEgY2FsZW5kYXIgb250byBhIGNhbGVuZGFyLlxuKi9cbnZhciBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyhkcmFnZ2luZywgc3VwcGxpZWREcmFnTWV0YSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcm9wcGFibGVFdmVudCA9IG51bGw7IC8vIHdpbGwgZXhpc3QgZm9yIGFsbCBkcmFncywgZXZlbiBpZiBjcmVhdGU6ZmFsc2VcbiAgICAgICAgdGhpcy5zdXBwbGllZERyYWdNZXRhID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnTWV0YSA9IG51bGw7XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5kcmFnTWV0YSA9IF90aGlzLmJ1aWxkRHJhZ01ldGEoZXYuc3ViamVjdEVsKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVIaXRVcGRhdGUgPSBmdW5jdGlvbiAoaGl0LCBpc0ZpbmFsLCBldikge1xuICAgICAgICAgICAgdmFyIGRyYWdnaW5nID0gX3RoaXMuaGl0RHJhZ2dpbmcuZHJhZ2dpbmc7XG4gICAgICAgICAgICB2YXIgcmVjZWl2aW5nQ2FsZW5kYXIgPSBudWxsO1xuICAgICAgICAgICAgdmFyIGRyb3BwYWJsZUV2ZW50ID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBpc0ludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbnRlcmFjdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBhZmZlY3RlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgbXV0YXRlZEV2ZW50czogY3JlYXRlRW1wdHlFdmVudFN0b3JlKCksXG4gICAgICAgICAgICAgICAgaXNFdmVudDogX3RoaXMuZHJhZ01ldGEuY3JlYXRlLFxuICAgICAgICAgICAgICAgIG9yaWdTZWc6IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoaGl0KSB7XG4gICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIgPSBoaXQuY29tcG9uZW50LmNvbnRleHQuY2FsZW5kYXI7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNhbkRyb3BFbE9uQ2FsZW5kYXIoZXYuc3ViamVjdEVsLCByZWNlaXZpbmdDYWxlbmRhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJvcHBhYmxlRXZlbnQgPSBjb21wdXRlRXZlbnRGb3JEYXRlU3BhbihoaXQuZGF0ZVNwYW4sIF90aGlzLmRyYWdNZXRhLCByZWNlaXZpbmdDYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLm11dGF0ZWRFdmVudHMgPSBldmVudFR1cGxlVG9TdG9yZShkcm9wcGFibGVFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIGlzSW52YWxpZCA9ICFpc0ludGVyYWN0aW9uVmFsaWQoaW50ZXJhY3Rpb24sIHJlY2VpdmluZ0NhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24ubXV0YXRlZEV2ZW50cyA9IGNyZWF0ZUVtcHR5RXZlbnRTdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZHJvcHBhYmxlRXZlbnQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZGlzcGxheURyYWcocmVjZWl2aW5nQ2FsZW5kYXIsIGludGVyYWN0aW9uKTtcbiAgICAgICAgICAgIC8vIHNob3cgbWlycm9yIGlmIG5vIGFscmVhZHktcmVuZGVyZWQgbWlycm9yIGVsZW1lbnQgT1IgaWYgd2UgYXJlIHNodXR0aW5nIGRvd24gdGhlIG1pcnJvciAoPylcbiAgICAgICAgICAgIC8vIFRPRE86IHdpc2ggd2UgY291bGQgc29tZWhvdyB3YWl0IGZvciBkaXNwYXRjaCB0byBndWFyYW50ZWUgcmVuZGVyXG4gICAgICAgICAgICBkcmFnZ2luZy5zZXRNaXJyb3JJc1Zpc2libGUoaXNGaW5hbCB8fCAhZHJvcHBhYmxlRXZlbnQgfHwgIWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5mYy1taXJyb3InKSk7XG4gICAgICAgICAgICBpZiAoIWlzSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGVuYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzYWJsZUN1cnNvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0ZpbmFsKSB7XG4gICAgICAgICAgICAgICAgZHJhZ2dpbmcuc2V0TWlycm9yTmVlZHNSZXZlcnQoIWRyb3BwYWJsZUV2ZW50KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZWNlaXZpbmdDYWxlbmRhciA9IHJlY2VpdmluZ0NhbGVuZGFyO1xuICAgICAgICAgICAgICAgIF90aGlzLmRyb3BwYWJsZUV2ZW50ID0gZHJvcHBhYmxlRXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uIChwZXYpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLCByZWNlaXZpbmdDYWxlbmRhciA9IF9hLnJlY2VpdmluZ0NhbGVuZGFyLCBkcm9wcGFibGVFdmVudCA9IF9hLmRyb3BwYWJsZUV2ZW50O1xuICAgICAgICAgICAgX3RoaXMuY2xlYXJEcmFnKCk7XG4gICAgICAgICAgICBpZiAocmVjZWl2aW5nQ2FsZW5kYXIgJiYgZHJvcHBhYmxlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmluYWxIaXQgPSBfdGhpcy5oaXREcmFnZ2luZy5maW5hbEhpdDtcbiAgICAgICAgICAgICAgICB2YXIgZmluYWxWaWV3ID0gZmluYWxIaXQuY29tcG9uZW50LmNvbnRleHQudmlldztcbiAgICAgICAgICAgICAgICB2YXIgZHJhZ01ldGEgPSBfdGhpcy5kcmFnTWV0YTtcbiAgICAgICAgICAgICAgICB2YXIgYXJnID0gX19hc3NpZ24oe30sIHJlY2VpdmluZ0NhbGVuZGFyLmJ1aWxkRGF0ZVBvaW50QXBpKGZpbmFsSGl0LmRhdGVTcGFuKSwgeyBkcmFnZ2VkRWw6IHBldi5zdWJqZWN0RWwsIGpzRXZlbnQ6IHBldi5vcmlnRXZlbnQsIHZpZXc6IGZpbmFsVmlldyB9KTtcbiAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5wdWJsaWNseVRyaWdnZXIoJ2Ryb3AnLCBbYXJnXSk7XG4gICAgICAgICAgICAgICAgaWYgKGRyYWdNZXRhLmNyZWF0ZSkge1xuICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnTUVSR0VfRVZFTlRTJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50VHVwbGVUb1N0b3JlKGRyb3BwYWJsZUV2ZW50KVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBldi5pc1RvdWNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1NFTEVDVF9FVkVOVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRJbnN0YW5jZUlkOiBkcm9wcGFibGVFdmVudC5pbnN0YW5jZS5pbnN0YW5jZUlkXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBzaWduYWwgdGhhdCBhbiBleHRlcm5hbCBldmVudCBsYW5kZWRcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2aW5nQ2FsZW5kYXIucHVibGljbHlUcmlnZ2VyKCdldmVudFJlY2VpdmUnLCBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dlZEVsOiBwZXYuc3ViamVjdEVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBuZXcgRXZlbnRBcGkocmVjZWl2aW5nQ2FsZW5kYXIsIGRyb3BwYWJsZUV2ZW50LmRlZiwgZHJvcHBhYmxlRXZlbnQuaW5zdGFuY2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXc6IGZpbmFsVmlld1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5yZWNlaXZpbmdDYWxlbmRhciA9IG51bGw7XG4gICAgICAgICAgICBfdGhpcy5kcm9wcGFibGVFdmVudCA9IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBoaXREcmFnZ2luZyA9IHRoaXMuaGl0RHJhZ2dpbmcgPSBuZXcgSGl0RHJhZ2dpbmcoZHJhZ2dpbmcsIGludGVyYWN0aW9uU2V0dGluZ3NTdG9yZSk7XG4gICAgICAgIGhpdERyYWdnaW5nLnJlcXVpcmVJbml0aWFsID0gZmFsc2U7IC8vIHdpbGwgc3RhcnQgb3V0c2lkZSBvZiBhIGNvbXBvbmVudFxuICAgICAgICBoaXREcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIGhpdERyYWdnaW5nLmVtaXR0ZXIub24oJ2hpdHVwZGF0ZScsIHRoaXMuaGFuZGxlSGl0VXBkYXRlKTtcbiAgICAgICAgaGl0RHJhZ2dpbmcuZW1pdHRlci5vbignZHJhZ2VuZCcsIHRoaXMuaGFuZGxlRHJhZ0VuZCk7XG4gICAgICAgIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9IHN1cHBsaWVkRHJhZ01ldGE7XG4gICAgfVxuICAgIEV4dGVybmFsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5idWlsZERyYWdNZXRhID0gZnVuY3Rpb24gKHN1YmplY3RFbCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZURyYWdNZXRhKHRoaXMuc3VwcGxpZWREcmFnTWV0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHRoaXMuc3VwcGxpZWREcmFnTWV0YSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHBhcnNlRHJhZ01ldGEodGhpcy5zdXBwbGllZERyYWdNZXRhKHN1YmplY3RFbCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGdldERyYWdNZXRhRnJvbUVsKHN1YmplY3RFbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV4dGVybmFsRWxlbWVudERyYWdnaW5nLnByb3RvdHlwZS5kaXNwbGF5RHJhZyA9IGZ1bmN0aW9uIChuZXh0Q2FsZW5kYXIsIHN0YXRlKSB7XG4gICAgICAgIHZhciBwcmV2Q2FsZW5kYXIgPSB0aGlzLnJlY2VpdmluZ0NhbGVuZGFyO1xuICAgICAgICBpZiAocHJldkNhbGVuZGFyICYmIHByZXZDYWxlbmRhciAhPT0gbmV4dENhbGVuZGFyKSB7XG4gICAgICAgICAgICBwcmV2Q2FsZW5kYXIuZGlzcGF0Y2goeyB0eXBlOiAnVU5TRVRfRVZFTlRfRFJBRycgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5leHRDYWxlbmRhcikge1xuICAgICAgICAgICAgbmV4dENhbGVuZGFyLmRpc3BhdGNoKHsgdHlwZTogJ1NFVF9FVkVOVF9EUkFHJywgc3RhdGU6IHN0YXRlIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuY2xlYXJEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yZWNlaXZpbmdDYWxlbmRhcikge1xuICAgICAgICAgICAgdGhpcy5yZWNlaXZpbmdDYWxlbmRhci5kaXNwYXRjaCh7IHR5cGU6ICdVTlNFVF9FVkVOVF9EUkFHJyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXh0ZXJuYWxFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmNhbkRyb3BFbE9uQ2FsZW5kYXIgPSBmdW5jdGlvbiAoZWwsIHJlY2VpdmluZ0NhbGVuZGFyKSB7XG4gICAgICAgIHZhciBkcm9wQWNjZXB0ID0gcmVjZWl2aW5nQ2FsZW5kYXIub3B0KCdkcm9wQWNjZXB0Jyk7XG4gICAgICAgIGlmICh0eXBlb2YgZHJvcEFjY2VwdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIGRyb3BBY2NlcHQoZWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBkcm9wQWNjZXB0ID09PSAnc3RyaW5nJyAmJiBkcm9wQWNjZXB0KSB7XG4gICAgICAgICAgICByZXR1cm4gQm9vbGVhbihlbGVtZW50TWF0Y2hlcyhlbCwgZHJvcEFjY2VwdCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgcmV0dXJuIEV4dGVybmFsRWxlbWVudERyYWdnaW5nO1xufSgpKTtcbi8vIFV0aWxzIGZvciBjb21wdXRpbmcgZXZlbnQgc3RvcmUgZnJvbSB0aGUgRHJhZ01ldGFcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGNvbXB1dGVFdmVudEZvckRhdGVTcGFuKGRhdGVTcGFuLCBkcmFnTWV0YSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgZGVmUHJvcHMgPSBfX2Fzc2lnbih7fSwgZHJhZ01ldGEubGVmdG92ZXJQcm9wcyk7XG4gICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNhbGVuZGFyLnBsdWdpblN5c3RlbS5ob29rcy5leHRlcm5hbERlZlRyYW5zZm9ybXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBfYVtfaV07XG4gICAgICAgIF9fYXNzaWduKGRlZlByb3BzLCB0cmFuc2Zvcm0oZGF0ZVNwYW4sIGRyYWdNZXRhKSk7XG4gICAgfVxuICAgIHZhciBkZWYgPSBwYXJzZUV2ZW50RGVmKGRlZlByb3BzLCBkcmFnTWV0YS5zb3VyY2VJZCwgZGF0ZVNwYW4uYWxsRGF5LCBjYWxlbmRhci5vcHQoJ2ZvcmNlRXZlbnREdXJhdGlvbicpIHx8IEJvb2xlYW4oZHJhZ01ldGEuZHVyYXRpb24pLCAvLyBoYXNFbmRcbiAgICBjYWxlbmRhcik7XG4gICAgdmFyIHN0YXJ0ID0gZGF0ZVNwYW4ucmFuZ2Uuc3RhcnQ7XG4gICAgLy8gb25seSByZWx5IG9uIHRpbWUgaW5mbyBpZiBkcm9wIHpvbmUgaXMgYWxsLWRheSxcbiAgICAvLyBvdGhlcndpc2UsIHdlIGFscmVhZHkga25vdyB0aGUgdGltZVxuICAgIGlmIChkYXRlU3Bhbi5hbGxEYXkgJiYgZHJhZ01ldGEuc3RhcnRUaW1lKSB7XG4gICAgICAgIHN0YXJ0ID0gY2FsZW5kYXIuZGF0ZUVudi5hZGQoc3RhcnQsIGRyYWdNZXRhLnN0YXJ0VGltZSk7XG4gICAgfVxuICAgIHZhciBlbmQgPSBkcmFnTWV0YS5kdXJhdGlvbiA/XG4gICAgICAgIGNhbGVuZGFyLmRhdGVFbnYuYWRkKHN0YXJ0LCBkcmFnTWV0YS5kdXJhdGlvbikgOlxuICAgICAgICBjYWxlbmRhci5nZXREZWZhdWx0RXZlbnRFbmQoZGF0ZVNwYW4uYWxsRGF5LCBzdGFydCk7XG4gICAgdmFyIGluc3RhbmNlID0gY3JlYXRlRXZlbnRJbnN0YW5jZShkZWYuZGVmSWQsIHsgc3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZCB9KTtcbiAgICByZXR1cm4geyBkZWY6IGRlZiwgaW5zdGFuY2U6IGluc3RhbmNlIH07XG59XG4vLyBVdGlscyBmb3IgZXh0cmFjdGluZyBkYXRhIGZyb20gZWxlbWVudFxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gZ2V0RHJhZ01ldGFGcm9tRWwoZWwpIHtcbiAgICB2YXIgc3RyID0gZ2V0RW1iZWRkZWRFbERhdGEoZWwsICdldmVudCcpO1xuICAgIHZhciBvYmogPSBzdHIgP1xuICAgICAgICBKU09OLnBhcnNlKHN0cikgOlxuICAgICAgICB7IGNyZWF0ZTogZmFsc2UgfTsgLy8gaWYgbm8gZW1iZWRkZWQgZGF0YSwgYXNzdW1lIG5vIGV2ZW50IGNyZWF0aW9uXG4gICAgcmV0dXJuIHBhcnNlRHJhZ01ldGEob2JqKTtcbn1cbmNvbmZpZy5kYXRhQXR0clByZWZpeCA9ICcnO1xuZnVuY3Rpb24gZ2V0RW1iZWRkZWRFbERhdGEoZWwsIG5hbWUpIHtcbiAgICB2YXIgcHJlZml4ID0gY29uZmlnLmRhdGFBdHRyUHJlZml4O1xuICAgIHZhciBwcmVmaXhlZE5hbWUgPSAocHJlZml4ID8gcHJlZml4ICsgJy0nIDogJycpICsgbmFtZTtcbiAgICByZXR1cm4gZWwuZ2V0QXR0cmlidXRlKCdkYXRhLScgKyBwcmVmaXhlZE5hbWUpIHx8ICcnO1xufVxuXG4vKlxuTWFrZXMgYW4gZWxlbWVudCAodGhhdCBpcyAqZXh0ZXJuYWwqIHRvIGFueSBjYWxlbmRhcikgZHJhZ2dhYmxlLlxuQ2FuIHBhc3MgaW4gZGF0YSB0aGF0IGRldGVybWluZXMgaG93IGFuIGV2ZW50IHdpbGwgYmUgY3JlYXRlZCB3aGVuIGRyb3BwZWQgb250byBhIGNhbGVuZGFyLlxuTGV2ZXJhZ2VzIEZ1bGxDYWxlbmRhcidzIGludGVybmFsIGRyYWctbi1kcm9wIGZ1bmN0aW9uYWxpdHkgV0lUSE9VVCBhIHRoaXJkLXBhcnR5IGRyYWcgc3lzdGVtLlxuKi9cbnZhciBFeHRlcm5hbERyYWdnYWJsZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBFeHRlcm5hbERyYWdnYWJsZShlbCwgc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHNldHRpbmdzID09PSB2b2lkIDApIHsgc2V0dGluZ3MgPSB7fTsgfVxuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgZHJhZ2dpbmcgPSBfdGhpcy5kcmFnZ2luZztcbiAgICAgICAgICAgIHZhciBfYSA9IF90aGlzLnNldHRpbmdzLCBtaW5EaXN0YW5jZSA9IF9hLm1pbkRpc3RhbmNlLCBsb25nUHJlc3NEZWxheSA9IF9hLmxvbmdQcmVzc0RlbGF5O1xuICAgICAgICAgICAgZHJhZ2dpbmcubWluRGlzdGFuY2UgPVxuICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlICE9IG51bGwgP1xuICAgICAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSA6XG4gICAgICAgICAgICAgICAgICAgIChldi5pc1RvdWNoID8gMCA6IGdsb2JhbERlZmF1bHRzLmV2ZW50RHJhZ01pbkRpc3RhbmNlKTtcbiAgICAgICAgICAgIGRyYWdnaW5nLmRlbGF5ID1cbiAgICAgICAgICAgICAgICBldi5pc1RvdWNoID8gLy8gVE9ETzogZXZlbnR1YWxseSByZWFkIGV2ZW50TG9uZ1ByZXNzRGVsYXkgaW5zdGVhZCB2dnZcbiAgICAgICAgICAgICAgICAgICAgKGxvbmdQcmVzc0RlbGF5ICE9IG51bGwgPyBsb25nUHJlc3NEZWxheSA6IGdsb2JhbERlZmF1bHRzLmxvbmdQcmVzc0RlbGF5KSA6XG4gICAgICAgICAgICAgICAgICAgIDA7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoZXYuaXNUb3VjaCAmJlxuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLmRlbGF5ICYmXG4gICAgICAgICAgICAgICAgZXYuc3ViamVjdEVsLmNsYXNzTGlzdC5jb250YWlucygnZmMtZXZlbnQnKSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmRyYWdnaW5nLm1pcnJvci5nZXRNaXJyb3JFbCgpLmNsYXNzTGlzdC5hZGQoJ2ZjLXNlbGVjdGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcbiAgICAgICAgdmFyIGRyYWdnaW5nID0gdGhpcy5kcmFnZ2luZyA9IG5ldyBGZWF0dXJlZnVsRWxlbWVudERyYWdnaW5nKGVsKTtcbiAgICAgICAgZHJhZ2dpbmcudG91Y2hTY3JvbGxBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIGlmIChzZXR0aW5ncy5pdGVtU2VsZWN0b3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcucG9pbnRlci5zZWxlY3RvciA9IHNldHRpbmdzLml0ZW1TZWxlY3RvcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2V0dGluZ3MuYXBwZW5kVG8gIT0gbnVsbCkge1xuICAgICAgICAgICAgZHJhZ2dpbmcubWlycm9yLnBhcmVudE5vZGUgPSBzZXR0aW5ncy5hcHBlbmRUbzsgLy8gVE9ETzogd3JpdGUgdGVzdHNcbiAgICAgICAgfVxuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBkcmFnZ2luZy5lbWl0dGVyLm9uKCdkcmFnc3RhcnQnLCB0aGlzLmhhbmRsZURyYWdTdGFydCk7XG4gICAgICAgIG5ldyBFeHRlcm5hbEVsZW1lbnREcmFnZ2luZyhkcmFnZ2luZywgc2V0dGluZ3MuZXZlbnREYXRhKTtcbiAgICB9XG4gICAgRXh0ZXJuYWxEcmFnZ2FibGUucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcuZGVzdHJveSgpO1xuICAgIH07XG4gICAgcmV0dXJuIEV4dGVybmFsRHJhZ2dhYmxlO1xufSgpKTtcblxuLypcbkRldGVjdHMgd2hlbiBhICpUSElSRC1QQVJUWSogZHJhZy1uLWRyb3Agc3lzdGVtIGludGVyYWN0cyB3aXRoIGVsZW1lbnRzLlxuVGhlIHRoaXJkLXBhcnR5IHN5c3RlbSBpcyByZXNwb25zaWJsZSBmb3IgZHJhd2luZyB0aGUgdmlzdWFscyBlZmZlY3RzIG9mIHRoZSBkcmFnLlxuVGhpcyBjbGFzcyBzaW1wbHkgbW9uaXRvcnMgZm9yIHBvaW50ZXIgbW92ZW1lbnRzIGFuZCBmaXJlcyBldmVudHMuXG5JdCBhbHNvIGhhcyB0aGUgYWJpbGl0eSB0byBoaWRlIHRoZSBtb3ZpbmcgZWxlbWVudCAodGhlIFwibWlycm9yXCIpIGR1cmluZyB0aGUgZHJhZy5cbiovXG52YXIgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEluZmVycmVkRWxlbWVudERyYWdnaW5nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEluZmVycmVkRWxlbWVudERyYWdnaW5nKGNvbnRhaW5lckVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNvbnRhaW5lckVsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5zaG91bGRJZ25vcmVNb3ZlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLm1pcnJvclNlbGVjdG9yID0gJyc7XG4gICAgICAgIF90aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG51bGw7XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ3BvaW50ZXJkb3duJywgZXYpO1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5zaG91bGRJZ25vcmVNb3ZlKSB7XG4gICAgICAgICAgICAgICAgLy8gZmlyZSBkcmFnc3RhcnQgcmlnaHQgYXdheS4gZG9lcyBub3Qgc3VwcG9ydCBkZWxheSBvciBtaW4tZGlzdGFuY2VcbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdzdGFydCcsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuaGFuZGxlUG9pbnRlck1vdmUgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuc2hvdWxkSWdub3JlTW92ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmVtaXR0ZXIudHJpZ2dlcignZHJhZ21vdmUnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmhhbmRsZVBvaW50ZXJVcCA9IGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgX3RoaXMuZW1pdHRlci50cmlnZ2VyKCdwb2ludGVydXAnLCBldik7XG4gICAgICAgICAgICBpZiAoIV90aGlzLnNob3VsZElnbm9yZU1vdmUpIHtcbiAgICAgICAgICAgICAgICAvLyBmaXJlIGRyYWdlbmQgcmlnaHQgYXdheS4gZG9lcyBub3Qgc3VwcG9ydCBhIHJldmVydCBhbmltYXRpb25cbiAgICAgICAgICAgICAgICBfdGhpcy5lbWl0dGVyLnRyaWdnZXIoJ2RyYWdlbmQnLCBldik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBwb2ludGVyID0gX3RoaXMucG9pbnRlciA9IG5ldyBQb2ludGVyRHJhZ2dpbmcoY29udGFpbmVyRWwpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJkb3duJywgX3RoaXMuaGFuZGxlUG9pbnRlckRvd24pO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJtb3ZlJywgX3RoaXMuaGFuZGxlUG9pbnRlck1vdmUpO1xuICAgICAgICBwb2ludGVyLmVtaXR0ZXIub24oJ3BvaW50ZXJ1cCcsIF90aGlzLmhhbmRsZVBvaW50ZXJVcCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucG9pbnRlci5kZXN0cm95KCk7XG4gICAgfTtcbiAgICBJbmZlcnJlZEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0SWdub3JlTW92ZSA9IGZ1bmN0aW9uIChib29sKSB7XG4gICAgICAgIHRoaXMuc2hvdWxkSWdub3JlTW92ZSA9IGJvb2w7XG4gICAgfTtcbiAgICBJbmZlcnJlZEVsZW1lbnREcmFnZ2luZy5wcm90b3R5cGUuc2V0TWlycm9ySXNWaXNpYmxlID0gZnVuY3Rpb24gKGJvb2wpIHtcbiAgICAgICAgaWYgKGJvb2wpIHtcbiAgICAgICAgICAgIC8vIHJlc3RvcmUgYSBwcmV2aW91c2x5IGhpZGRlbiBlbGVtZW50LlxuICAgICAgICAgICAgLy8gdXNlIHRoZSByZWZlcmVuY2UgaW4gY2FzZSB0aGUgc2VsZWN0b3IgY2xhc3MgaGFzIGFscmVhZHkgYmVlbiByZW1vdmVkLlxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudE1pcnJvckVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TWlycm9yRWwuc3R5bGUudmlzaWJpbGl0eSA9ICcnO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudE1pcnJvckVsID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBtaXJyb3JFbCA9IHRoaXMubWlycm9yU2VsZWN0b3IgP1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5taXJyb3JTZWxlY3RvcikgOlxuICAgICAgICAgICAgICAgIG51bGw7XG4gICAgICAgICAgICBpZiAobWlycm9yRWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRNaXJyb3JFbCA9IG1pcnJvckVsO1xuICAgICAgICAgICAgICAgIG1pcnJvckVsLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEluZmVycmVkRWxlbWVudERyYWdnaW5nO1xufShFbGVtZW50RHJhZ2dpbmcpKTtcblxuLypcbkJyaWRnZXMgdGhpcmQtcGFydHkgZHJhZy1uLWRyb3Agc3lzdGVtcyB3aXRoIEZ1bGxDYWxlbmRhci5cbk11c3QgYmUgaW5zdGFudGlhdGVkIGFuZCBkZXN0cm95ZWQgYnkgY2FsbGVyLlxuKi9cbnZhciBUaGlyZFBhcnR5RHJhZ2dhYmxlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFRoaXJkUGFydHlEcmFnZ2FibGUoY29udGFpbmVyT3JTZXR0aW5ncywgc2V0dGluZ3MpIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lckVsID0gZG9jdW1lbnQ7XG4gICAgICAgIGlmIChcbiAgICAgICAgLy8gd2lzaCB3ZSBjb3VsZCBqdXN0IHRlc3QgaW5zdGFuY2VvZiBFdmVudFRhcmdldCwgYnV0IGRvZXNuJ3Qgd29yayBpbiBJRTExXG4gICAgICAgIGNvbnRhaW5lck9yU2V0dGluZ3MgPT09IGRvY3VtZW50IHx8XG4gICAgICAgICAgICBjb250YWluZXJPclNldHRpbmdzIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgICAgY29udGFpbmVyRWwgPSBjb250YWluZXJPclNldHRpbmdzO1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBzZXR0aW5ncyB8fCB7fTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzID0gKGNvbnRhaW5lck9yU2V0dGluZ3MgfHwge30pO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IHRoaXMuZHJhZ2dpbmcgPSBuZXcgSW5mZXJyZWRFbGVtZW50RHJhZ2dpbmcoY29udGFpbmVyRWwpO1xuICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzLml0ZW1TZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGRyYWdnaW5nLnBvaW50ZXIuc2VsZWN0b3IgPSBzZXR0aW5ncy5pdGVtU2VsZWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29udGFpbmVyRWwgPT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICBkcmFnZ2luZy5wb2ludGVyLnNlbGVjdG9yID0gJ1tkYXRhLWV2ZW50XSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy5taXJyb3JTZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGRyYWdnaW5nLm1pcnJvclNlbGVjdG9yID0gc2V0dGluZ3MubWlycm9yU2VsZWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgbmV3IEV4dGVybmFsRWxlbWVudERyYWdnaW5nKGRyYWdnaW5nLCBzZXR0aW5ncy5ldmVudERhdGEpO1xuICAgIH1cbiAgICBUaGlyZFBhcnR5RHJhZ2dhYmxlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRyYWdnaW5nLmRlc3Ryb3koKTtcbiAgICB9O1xuICAgIHJldHVybiBUaGlyZFBhcnR5RHJhZ2dhYmxlO1xufSgpKTtcblxudmFyIG1haW4gPSBjcmVhdGVQbHVnaW4oe1xuICAgIGNvbXBvbmVudEludGVyYWN0aW9uczogW0RhdGVDbGlja2luZywgRGF0ZVNlbGVjdGluZywgRXZlbnREcmFnZ2luZywgRXZlbnREcmFnZ2luZyQxXSxcbiAgICBjYWxlbmRhckludGVyYWN0aW9uczogW1Vuc2VsZWN0QXV0b10sXG4gICAgZWxlbWVudERyYWdnaW5nSW1wbDogRmVhdHVyZWZ1bEVsZW1lbnREcmFnZ2luZ1xufSk7XG5cbmV4cG9ydCBkZWZhdWx0IG1haW47XG5leHBvcnQgeyBFeHRlcm5hbERyYWdnYWJsZSBhcyBEcmFnZ2FibGUsIEZlYXR1cmVmdWxFbGVtZW50RHJhZ2dpbmcsIFBvaW50ZXJEcmFnZ2luZywgVGhpcmRQYXJ0eURyYWdnYWJsZSB9O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGlzQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtY2FsbGFibGUnKTtcbnZhciB0cnlUb1N0cmluZyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90cnktdG8tc3RyaW5nJyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xuXG4vLyBgQXNzZXJ0OiBJc0NhbGxhYmxlKGFyZ3VtZW50KSBpcyB0cnVlYFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgaWYgKGlzQ2FsbGFibGUoYXJndW1lbnQpKSByZXR1cm4gYXJndW1lbnQ7XG4gIHRocm93IG5ldyAkVHlwZUVycm9yKHRyeVRvU3RyaW5nKGFyZ3VtZW50KSArICcgaXMgbm90IGEgZnVuY3Rpb24nKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtb2JqZWN0Jyk7XG5cbnZhciAkU3RyaW5nID0gU3RyaW5nO1xudmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7XG5cbi8vIGBBc3NlcnQ6IFR5cGUoYXJndW1lbnQpIGlzIE9iamVjdGBcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gIGlmIChpc09iamVjdChhcmd1bWVudCkpIHJldHVybiBhcmd1bWVudDtcbiAgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJFN0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBhbiBvYmplY3QnKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG5cbnZhciB0b1N0cmluZyA9IHVuY3VycnlUaGlzKHt9LnRvU3RyaW5nKTtcbnZhciBzdHJpbmdTbGljZSA9IHVuY3VycnlUaGlzKCcnLnNsaWNlKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIHN0cmluZ1NsaWNlKHRvU3RyaW5nKGl0KSwgOCwgLTEpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tc3RyaW5nLXRhZy1zdXBwb3J0Jyk7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xudmFyIGNsYXNzb2ZSYXcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZi1yYXcnKTtcbnZhciB3ZWxsS25vd25TeW1ib2wgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvd2VsbC1rbm93bi1zeW1ib2wnKTtcblxudmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7XG52YXIgJE9iamVjdCA9IE9iamVjdDtcblxuLy8gRVMzIHdyb25nIGhlcmVcbnZhciBDT1JSRUNUX0FSR1VNRU5UUyA9IGNsYXNzb2ZSYXcoZnVuY3Rpb24gKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpID09PSAnQXJndW1lbnRzJztcblxuLy8gZmFsbGJhY2sgZm9yIElFMTEgU2NyaXB0IEFjY2VzcyBEZW5pZWQgZXJyb3JcbnZhciB0cnlHZXQgPSBmdW5jdGlvbiAoaXQsIGtleSkge1xuICB0cnkge1xuICAgIHJldHVybiBpdFtrZXldO1xuICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9XG59O1xuXG4vLyBnZXR0aW5nIHRhZyBmcm9tIEVTNisgYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgXG5tb2R1bGUuZXhwb3J0cyA9IFRPX1NUUklOR19UQUdfU1VQUE9SVCA/IGNsYXNzb2ZSYXcgOiBmdW5jdGlvbiAoaXQpIHtcbiAgdmFyIE8sIHRhZywgcmVzdWx0O1xuICByZXR1cm4gaXQgPT09IHVuZGVmaW5lZCA/ICdVbmRlZmluZWQnIDogaXQgPT09IG51bGwgPyAnTnVsbCdcbiAgICAvLyBAQHRvU3RyaW5nVGFnIGNhc2VcbiAgICA6IHR5cGVvZiAodGFnID0gdHJ5R2V0KE8gPSAkT2JqZWN0KGl0KSwgVE9fU1RSSU5HX1RBRykpID09ICdzdHJpbmcnID8gdGFnXG4gICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgOiBDT1JSRUNUX0FSR1VNRU5UUyA/IGNsYXNzb2ZSYXcoTylcbiAgICAvLyBFUzMgYXJndW1lbnRzIGZhbGxiYWNrXG4gICAgOiAocmVzdWx0ID0gY2xhc3NvZlJhdyhPKSkgPT09ICdPYmplY3QnICYmIGlzQ2FsbGFibGUoTy5jYWxsZWUpID8gJ0FyZ3VtZW50cycgOiByZXN1bHQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZGVmaW5lUHJvcGVydHlNb2R1bGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LWRlZmluZS1wcm9wZXJ0eScpO1xudmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9jcmVhdGUtcHJvcGVydHktZGVzY3JpcHRvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERFU0NSSVBUT1JTID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICByZXR1cm4gZGVmaW5lUHJvcGVydHlNb2R1bGUuZihvYmplY3QsIGtleSwgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDEsIHZhbHVlKSk7XG59IDogZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gb2JqZWN0O1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLFxuICAgIGNvbmZpZ3VyYWJsZTogIShiaXRtYXAgJiAyKSxcbiAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZTogdmFsdWVcbiAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xudmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL29iamVjdC1kZWZpbmUtcHJvcGVydHknKTtcbnZhciBtYWtlQnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9tYWtlLWJ1aWx0LWluJyk7XG52YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVmaW5lLWdsb2JhbC1wcm9wZXJ0eScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBrZXksIHZhbHVlLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9O1xuICB2YXIgc2ltcGxlID0gb3B0aW9ucy5lbnVtZXJhYmxlO1xuICB2YXIgbmFtZSA9IG9wdGlvbnMubmFtZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uYW1lIDoga2V5O1xuICBpZiAoaXNDYWxsYWJsZSh2YWx1ZSkpIG1ha2VCdWlsdEluKHZhbHVlLCBuYW1lLCBvcHRpb25zKTtcbiAgaWYgKG9wdGlvbnMuZ2xvYmFsKSB7XG4gICAgaWYgKHNpbXBsZSkgT1trZXldID0gdmFsdWU7XG4gICAgZWxzZSBkZWZpbmVHbG9iYWxQcm9wZXJ0eShrZXksIHZhbHVlKTtcbiAgfSBlbHNlIHtcbiAgICB0cnkge1xuICAgICAgaWYgKCFvcHRpb25zLnVuc2FmZSkgZGVsZXRlIE9ba2V5XTtcbiAgICAgIGVsc2UgaWYgKE9ba2V5XSkgc2ltcGxlID0gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9XG4gICAgaWYgKHNpbXBsZSkgT1trZXldID0gdmFsdWU7XG4gICAgZWxzZSBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKE8sIGtleSwge1xuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6ICFvcHRpb25zLm5vbkNvbmZpZ3VyYWJsZSxcbiAgICAgIHdyaXRhYmxlOiAhb3B0aW9ucy5ub25Xcml0YWJsZVxuICAgIH0pO1xuICB9IHJldHVybiBPO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZVxudmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gIHRyeSB7XG4gICAgZGVmaW5lUHJvcGVydHkoZ2xvYmFsLCBrZXksIHsgdmFsdWU6IHZhbHVlLCBjb25maWd1cmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGdsb2JhbFtrZXldID0gdmFsdWU7XG4gIH0gcmV0dXJuIHZhbHVlO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xuXG4vLyBEZXRlY3QgSUU4J3MgaW5jb21wbGV0ZSBkZWZpbmVQcm9wZXJ0eSBpbXBsZW1lbnRhdGlvblxubW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pWzFdICE9PSA3O1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW9iamVjdCcpO1xuXG52YXIgZG9jdW1lbnQgPSBnbG9iYWwuZG9jdW1lbnQ7XG4vLyB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBpcyAnb2JqZWN0JyBpbiBvbGQgSUVcbnZhciBFWElTVFMgPSBpc09iamVjdChkb2N1bWVudCkgJiYgaXNPYmplY3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBFWElTVFMgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGl0KSA6IHt9O1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gdHlwZW9mIG5hdmlnYXRvciAhPSAndW5kZWZpbmVkJyAmJiBTdHJpbmcobmF2aWdhdG9yLnVzZXJBZ2VudCkgfHwgJyc7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHVzZXJBZ2VudCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9lbmdpbmUtdXNlci1hZ2VudCcpO1xuXG52YXIgcHJvY2VzcyA9IGdsb2JhbC5wcm9jZXNzO1xudmFyIERlbm8gPSBnbG9iYWwuRGVubztcbnZhciB2ZXJzaW9ucyA9IHByb2Nlc3MgJiYgcHJvY2Vzcy52ZXJzaW9ucyB8fCBEZW5vICYmIERlbm8udmVyc2lvbjtcbnZhciB2OCA9IHZlcnNpb25zICYmIHZlcnNpb25zLnY4O1xudmFyIG1hdGNoLCB2ZXJzaW9uO1xuXG5pZiAodjgpIHtcbiAgbWF0Y2ggPSB2OC5zcGxpdCgnLicpO1xuICAvLyBpbiBvbGQgQ2hyb21lLCB2ZXJzaW9ucyBvZiBWOCBpc24ndCBWOCA9IENocm9tZSAvIDEwXG4gIC8vIGJ1dCB0aGVpciBjb3JyZWN0IHZlcnNpb25zIGFyZSBub3QgaW50ZXJlc3RpbmcgZm9yIHVzXG4gIHZlcnNpb24gPSBtYXRjaFswXSA+IDAgJiYgbWF0Y2hbMF0gPCA0ID8gMSA6ICsobWF0Y2hbMF0gKyBtYXRjaFsxXSk7XG59XG5cbi8vIEJyb3dzZXJGUyBOb2RlSlMgYHByb2Nlc3NgIHBvbHlmaWxsIGluY29ycmVjdGx5IHNldCBgLnY4YCB0byBgMC4wYFxuLy8gc28gY2hlY2sgYHVzZXJBZ2VudGAgZXZlbiBpZiBgLnY4YCBleGlzdHMsIGJ1dCAwXG5pZiAoIXZlcnNpb24gJiYgdXNlckFnZW50KSB7XG4gIG1hdGNoID0gdXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLyk7XG4gIGlmICghbWF0Y2ggfHwgbWF0Y2hbMV0gPj0gNzQpIHtcbiAgICBtYXRjaCA9IHVzZXJBZ2VudC5tYXRjaCgvQ2hyb21lXFwvKFxcZCspLyk7XG4gICAgaWYgKG1hdGNoKSB2ZXJzaW9uID0gK21hdGNoWzFdO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdmVyc2lvbjtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGV4ZWMpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gISFleGVjKCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tZnVuY3Rpb24tcHJvdG90eXBlLWJpbmQgLS0gc2FmZVxuICB2YXIgdGVzdCA9IChmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH0pLmJpbmQoKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXByb3RvdHlwZS1idWlsdGlucyAtLSBzYWZlXG4gIHJldHVybiB0eXBlb2YgdGVzdCAhPSAnZnVuY3Rpb24nIHx8IHRlc3QuaGFzT3duUHJvcGVydHkoJ3Byb3RvdHlwZScpO1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgTkFUSVZFX0JJTkQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tYmluZC1uYXRpdmUnKTtcblxudmFyIGNhbGwgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbDtcblxubW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfQklORCA/IGNhbGwuYmluZChjYWxsKSA6IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGNhbGwuYXBwbHkoY2FsbCwgYXJndW1lbnRzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xuXG52YXIgRnVuY3Rpb25Qcm90b3R5cGUgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWdldG93bnByb3BlcnR5ZGVzY3JpcHRvciAtLSBzYWZlXG52YXIgZ2V0RGVzY3JpcHRvciA9IERFU0NSSVBUT1JTICYmIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG5cbnZhciBFWElTVFMgPSBoYXNPd24oRnVuY3Rpb25Qcm90b3R5cGUsICduYW1lJyk7XG4vLyBhZGRpdGlvbmFsIHByb3RlY3Rpb24gZnJvbSBtaW5pZmllZCAvIG1hbmdsZWQgLyBkcm9wcGVkIGZ1bmN0aW9uIG5hbWVzXG52YXIgUFJPUEVSID0gRVhJU1RTICYmIChmdW5jdGlvbiBzb21ldGhpbmcoKSB7IC8qIGVtcHR5ICovIH0pLm5hbWUgPT09ICdzb21ldGhpbmcnO1xudmFyIENPTkZJR1VSQUJMRSA9IEVYSVNUUyAmJiAoIURFU0NSSVBUT1JTIHx8IChERVNDUklQVE9SUyAmJiBnZXREZXNjcmlwdG9yKEZ1bmN0aW9uUHJvdG90eXBlLCAnbmFtZScpLmNvbmZpZ3VyYWJsZSkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgRVhJU1RTOiBFWElTVFMsXG4gIFBST1BFUjogUFJPUEVSLFxuICBDT05GSUdVUkFCTEU6IENPTkZJR1VSQUJMRVxufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBOQVRJVkVfQklORCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi1iaW5kLW5hdGl2ZScpO1xuXG52YXIgRnVuY3Rpb25Qcm90b3R5cGUgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG52YXIgY2FsbCA9IEZ1bmN0aW9uUHJvdG90eXBlLmNhbGw7XG52YXIgdW5jdXJyeVRoaXNXaXRoQmluZCA9IE5BVElWRV9CSU5EICYmIEZ1bmN0aW9uUHJvdG90eXBlLmJpbmQuYmluZChjYWxsLCBjYWxsKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfQklORCA/IHVuY3VycnlUaGlzV2l0aEJpbmQgOiBmdW5jdGlvbiAoZm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gY2FsbC5hcHBseShmbiwgYXJndW1lbnRzKTtcbiAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtY2FsbGFibGUnKTtcblxudmFyIGFGdW5jdGlvbiA9IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICByZXR1cm4gaXNDYWxsYWJsZShhcmd1bWVudCkgPyBhcmd1bWVudCA6IHVuZGVmaW5lZDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWVzcGFjZSwgbWV0aG9kKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGFGdW5jdGlvbihnbG9iYWxbbmFtZXNwYWNlXSkgOiBnbG9iYWxbbmFtZXNwYWNlXSAmJiBnbG9iYWxbbmFtZXNwYWNlXVttZXRob2RdO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvYS1jYWxsYWJsZScpO1xudmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW51bGwtb3ItdW5kZWZpbmVkJyk7XG5cbi8vIGBHZXRNZXRob2RgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXRtZXRob2Rcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFYsIFApIHtcbiAgdmFyIGZ1bmMgPSBWW1BdO1xuICByZXR1cm4gaXNOdWxsT3JVbmRlZmluZWQoZnVuYykgPyB1bmRlZmluZWQgOiBhQ2FsbGFibGUoZnVuYyk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNoZWNrID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCAmJiBpdC5NYXRoID09PSBNYXRoICYmIGl0O1xufTtcblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzg2I2lzc3VlY29tbWVudC0xMTU3NTkwMjhcbm1vZHVsZS5leHBvcnRzID1cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLWdsb2JhbC10aGlzIC0tIHNhZmVcbiAgY2hlY2sodHlwZW9mIGdsb2JhbFRoaXMgPT0gJ29iamVjdCcgJiYgZ2xvYmFsVGhpcykgfHxcbiAgY2hlY2sodHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB3aW5kb3cpIHx8XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLWdsb2JhbHMgLS0gc2FmZVxuICBjaGVjayh0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmKSB8fFxuICBjaGVjayh0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCkgfHxcbiAgY2hlY2sodHlwZW9mIHRoaXMgPT0gJ29iamVjdCcgJiYgdGhpcykgfHxcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jIC0tIGZhbGxiYWNrXG4gIChmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9KSgpIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tb2JqZWN0Jyk7XG5cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IHVuY3VycnlUaGlzKHt9Lmhhc093blByb3BlcnR5KTtcblxuLy8gYEhhc093blByb3BlcnR5YCBhYnN0cmFjdCBvcGVyYXRpb25cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaGFzb3ducHJvcGVydHlcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtaGFzb3duIC0tIHNhZmVcbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0Lmhhc093biB8fCBmdW5jdGlvbiBoYXNPd24oaXQsIGtleSkge1xuICByZXR1cm4gaGFzT3duUHJvcGVydHkodG9PYmplY3QoaXQpLCBrZXkpO1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0ge307XG4iLCIndXNlIHN0cmljdCc7XG52YXIgREVTQ1JJUFRPUlMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVzY3JpcHRvcnMnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZG9jdW1lbnQtY3JlYXRlLWVsZW1lbnQnKTtcblxuLy8gVGhhbmtzIHRvIElFOCBmb3IgaXRzIGZ1bm55IGRlZmluZVByb3BlcnR5XG5tb2R1bGUuZXhwb3J0cyA9ICFERVNDUklQVE9SUyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nXG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3JlYXRlRWxlbWVudCgnZGl2JyksICdhJywge1xuICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfVxuICB9KS5hICE9PSA3O1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xudmFyIHN0b3JlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NoYXJlZC1zdG9yZScpO1xuXG52YXIgZnVuY3Rpb25Ub1N0cmluZyA9IHVuY3VycnlUaGlzKEZ1bmN0aW9uLnRvU3RyaW5nKTtcblxuLy8gdGhpcyBoZWxwZXIgYnJva2VuIGluIGBjb3JlLWpzQDMuNC4xLTMuNC40YCwgc28gd2UgY2FuJ3QgdXNlIGBzaGFyZWRgIGhlbHBlclxuaWYgKCFpc0NhbGxhYmxlKHN0b3JlLmluc3BlY3RTb3VyY2UpKSB7XG4gIHN0b3JlLmluc3BlY3RTb3VyY2UgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb25Ub1N0cmluZyhpdCk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RvcmUuaW5zcGVjdFNvdXJjZTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBOQVRJVkVfV0VBS19NQVAgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvd2Vhay1tYXAtYmFzaWMtZGV0ZWN0aW9uJyk7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW9iamVjdCcpO1xudmFyIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9jcmVhdGUtbm9uLWVudW1lcmFibGUtcHJvcGVydHknKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xudmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQtc3RvcmUnKTtcbnZhciBzaGFyZWRLZXkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvc2hhcmVkLWtleScpO1xudmFyIGhpZGRlbktleXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGlkZGVuLWtleXMnKTtcblxudmFyIE9CSkVDVF9BTFJFQURZX0lOSVRJQUxJWkVEID0gJ09iamVjdCBhbHJlYWR5IGluaXRpYWxpemVkJztcbnZhciBUeXBlRXJyb3IgPSBnbG9iYWwuVHlwZUVycm9yO1xudmFyIFdlYWtNYXAgPSBnbG9iYWwuV2Vha01hcDtcbnZhciBzZXQsIGdldCwgaGFzO1xuXG52YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaGFzKGl0KSA/IGdldChpdCkgOiBzZXQoaXQsIHt9KTtcbn07XG5cbnZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkge1xuICByZXR1cm4gZnVuY3Rpb24gKGl0KSB7XG4gICAgdmFyIHN0YXRlO1xuICAgIGlmICghaXNPYmplY3QoaXQpIHx8IChzdGF0ZSA9IGdldChpdCkpLnR5cGUgIT09IFRZUEUpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0luY29tcGF0aWJsZSByZWNlaXZlciwgJyArIFRZUEUgKyAnIHJlcXVpcmVkJyk7XG4gICAgfSByZXR1cm4gc3RhdGU7XG4gIH07XG59O1xuXG5pZiAoTkFUSVZFX1dFQUtfTUFQIHx8IHNoYXJlZC5zdGF0ZSkge1xuICB2YXIgc3RvcmUgPSBzaGFyZWQuc3RhdGUgfHwgKHNoYXJlZC5zdGF0ZSA9IG5ldyBXZWFrTWFwKCkpO1xuICAvKiBlc2xpbnQtZGlzYWJsZSBuby1zZWxmLWFzc2lnbiAtLSBwcm90b3R5cGUgbWV0aG9kcyBwcm90ZWN0aW9uICovXG4gIHN0b3JlLmdldCA9IHN0b3JlLmdldDtcbiAgc3RvcmUuaGFzID0gc3RvcmUuaGFzO1xuICBzdG9yZS5zZXQgPSBzdG9yZS5zZXQ7XG4gIC8qIGVzbGludC1lbmFibGUgbm8tc2VsZi1hc3NpZ24gLS0gcHJvdG90eXBlIG1ldGhvZHMgcHJvdGVjdGlvbiAqL1xuICBzZXQgPSBmdW5jdGlvbiAoaXQsIG1ldGFkYXRhKSB7XG4gICAgaWYgKHN0b3JlLmhhcyhpdCkpIHRocm93IG5ldyBUeXBlRXJyb3IoT0JKRUNUX0FMUkVBRFlfSU5JVElBTElaRUQpO1xuICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0O1xuICAgIHN0b3JlLnNldChpdCwgbWV0YWRhdGEpO1xuICAgIHJldHVybiBtZXRhZGF0YTtcbiAgfTtcbiAgZ2V0ID0gZnVuY3Rpb24gKGl0KSB7XG4gICAgcmV0dXJuIHN0b3JlLmdldChpdCkgfHwge307XG4gIH07XG4gIGhhcyA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBzdG9yZS5oYXMoaXQpO1xuICB9O1xufSBlbHNlIHtcbiAgdmFyIFNUQVRFID0gc2hhcmVkS2V5KCdzdGF0ZScpO1xuICBoaWRkZW5LZXlzW1NUQVRFXSA9IHRydWU7XG4gIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHtcbiAgICBpZiAoaGFzT3duKGl0LCBTVEFURSkpIHRocm93IG5ldyBUeXBlRXJyb3IoT0JKRUNUX0FMUkVBRFlfSU5JVElBTElaRUQpO1xuICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0O1xuICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShpdCwgU1RBVEUsIG1ldGFkYXRhKTtcbiAgICByZXR1cm4gbWV0YWRhdGE7XG4gIH07XG4gIGdldCA9IGZ1bmN0aW9uIChpdCkge1xuICAgIHJldHVybiBoYXNPd24oaXQsIFNUQVRFKSA/IGl0W1NUQVRFXSA6IHt9O1xuICB9O1xuICBoYXMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gaGFzT3duKGl0LCBTVEFURSk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6IHNldCxcbiAgZ2V0OiBnZXQsXG4gIGhhczogaGFzLFxuICBlbmZvcmNlOiBlbmZvcmNlLFxuICBnZXR0ZXJGb3I6IGdldHRlckZvclxufTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtSXNIVE1MRERBLWludGVybmFsLXNsb3RcbnZhciBkb2N1bWVudEFsbCA9IHR5cGVvZiBkb2N1bWVudCA9PSAnb2JqZWN0JyAmJiBkb2N1bWVudC5hbGw7XG5cbi8vIGBJc0NhbGxhYmxlYCBhYnN0cmFjdCBvcGVyYXRpb25cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXNjYWxsYWJsZVxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vbm8tdHlwZW9mLXVuZGVmaW5lZCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xubW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgZG9jdW1lbnRBbGwgPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnRBbGwgIT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbicgfHwgYXJndW1lbnQgPT09IGRvY3VtZW50QWxsO1xufSA6IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbic7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gd2UgY2FuJ3QgdXNlIGp1c3QgYGl0ID09IG51bGxgIHNpbmNlIG9mIGBkb2N1bWVudC5hbGxgIHNwZWNpYWwgY2FzZVxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1Jc0hUTUxEREEtaW50ZXJuYWwtc2xvdC1hZWNcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCA9PT0gbnVsbCB8fCBpdCA9PT0gdW5kZWZpbmVkO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBpc0NhbGxhYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWNhbGxhYmxlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiB0eXBlb2YgaXQgPT0gJ29iamVjdCcgPyBpdCAhPT0gbnVsbCA6IGlzQ2FsbGFibGUoaXQpO1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZmFsc2U7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2V0QnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nZXQtYnVpbHQtaW4nKTtcbnZhciBpc0NhbGxhYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWNhbGxhYmxlJyk7XG52YXIgaXNQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9vYmplY3QtaXMtcHJvdG90eXBlLW9mJyk7XG52YXIgVVNFX1NZTUJPTF9BU19VSUQgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdXNlLXN5bWJvbC1hcy11aWQnKTtcblxudmFyICRPYmplY3QgPSBPYmplY3Q7XG5cbm1vZHVsZS5leHBvcnRzID0gVVNFX1NZTUJPTF9BU19VSUQgPyBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJztcbn0gOiBmdW5jdGlvbiAoaXQpIHtcbiAgdmFyICRTeW1ib2wgPSBnZXRCdWlsdEluKCdTeW1ib2wnKTtcbiAgcmV0dXJuIGlzQ2FsbGFibGUoJFN5bWJvbCkgJiYgaXNQcm90b3R5cGVPZigkU3ltYm9sLnByb3RvdHlwZSwgJE9iamVjdChpdCkpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciB1bmN1cnJ5VGhpcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi11bmN1cnJ5LXRoaXMnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mYWlscycpO1xudmFyIGlzQ2FsbGFibGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtY2FsbGFibGUnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgQ09ORklHVVJBQkxFX0ZVTkNUSU9OX05BTUUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tbmFtZScpLkNPTkZJR1VSQUJMRTtcbnZhciBpbnNwZWN0U291cmNlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2luc3BlY3Qtc291cmNlJyk7XG52YXIgSW50ZXJuYWxTdGF0ZU1vZHVsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pbnRlcm5hbC1zdGF0ZScpO1xuXG52YXIgZW5mb3JjZUludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLmVuZm9yY2U7XG52YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0O1xudmFyICRTdHJpbmcgPSBTdHJpbmc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHNhZmVcbnZhciBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcbnZhciBzdHJpbmdTbGljZSA9IHVuY3VycnlUaGlzKCcnLnNsaWNlKTtcbnZhciByZXBsYWNlID0gdW5jdXJyeVRoaXMoJycucmVwbGFjZSk7XG52YXIgam9pbiA9IHVuY3VycnlUaGlzKFtdLmpvaW4pO1xuXG52YXIgQ09ORklHVVJBQkxFX0xFTkdUSCA9IERFU0NSSVBUT1JTICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBkZWZpbmVQcm9wZXJ0eShmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH0sICdsZW5ndGgnLCB7IHZhbHVlOiA4IH0pLmxlbmd0aCAhPT0gODtcbn0pO1xuXG52YXIgVEVNUExBVEUgPSBTdHJpbmcoU3RyaW5nKS5zcGxpdCgnU3RyaW5nJyk7XG5cbnZhciBtYWtlQnVpbHRJbiA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lLCBvcHRpb25zKSB7XG4gIGlmIChzdHJpbmdTbGljZSgkU3RyaW5nKG5hbWUpLCAwLCA3KSA9PT0gJ1N5bWJvbCgnKSB7XG4gICAgbmFtZSA9ICdbJyArIHJlcGxhY2UoJFN0cmluZyhuYW1lKSwgL15TeW1ib2xcXCgoW14pXSopXFwpLiokLywgJyQxJykgKyAnXSc7XG4gIH1cbiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5nZXR0ZXIpIG5hbWUgPSAnZ2V0ICcgKyBuYW1lO1xuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnNldHRlcikgbmFtZSA9ICdzZXQgJyArIG5hbWU7XG4gIGlmICghaGFzT3duKHZhbHVlLCAnbmFtZScpIHx8IChDT05GSUdVUkFCTEVfRlVOQ1RJT05fTkFNRSAmJiB2YWx1ZS5uYW1lICE9PSBuYW1lKSkge1xuICAgIGlmIChERVNDUklQVE9SUykgZGVmaW5lUHJvcGVydHkodmFsdWUsICduYW1lJywgeyB2YWx1ZTogbmFtZSwgY29uZmlndXJhYmxlOiB0cnVlIH0pO1xuICAgIGVsc2UgdmFsdWUubmFtZSA9IG5hbWU7XG4gIH1cbiAgaWYgKENPTkZJR1VSQUJMRV9MRU5HVEggJiYgb3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2FyaXR5JykgJiYgdmFsdWUubGVuZ3RoICE9PSBvcHRpb25zLmFyaXR5KSB7XG4gICAgZGVmaW5lUHJvcGVydHkodmFsdWUsICdsZW5ndGgnLCB7IHZhbHVlOiBvcHRpb25zLmFyaXR5IH0pO1xuICB9XG4gIHRyeSB7XG4gICAgaWYgKG9wdGlvbnMgJiYgaGFzT3duKG9wdGlvbnMsICdjb25zdHJ1Y3RvcicpICYmIG9wdGlvbnMuY29uc3RydWN0b3IpIHtcbiAgICAgIGlmIChERVNDUklQVE9SUykgZGVmaW5lUHJvcGVydHkodmFsdWUsICdwcm90b3R5cGUnLCB7IHdyaXRhYmxlOiBmYWxzZSB9KTtcbiAgICAvLyBpbiBWOCB+IENocm9tZSA1MywgcHJvdG90eXBlcyBvZiBzb21lIG1ldGhvZHMsIGxpa2UgYEFycmF5LnByb3RvdHlwZS52YWx1ZXNgLCBhcmUgbm9uLXdyaXRhYmxlXG4gICAgfSBlbHNlIGlmICh2YWx1ZS5wcm90b3R5cGUpIHZhbHVlLnByb3RvdHlwZSA9IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfVxuICB2YXIgc3RhdGUgPSBlbmZvcmNlSW50ZXJuYWxTdGF0ZSh2YWx1ZSk7XG4gIGlmICghaGFzT3duKHN0YXRlLCAnc291cmNlJykpIHtcbiAgICBzdGF0ZS5zb3VyY2UgPSBqb2luKFRFTVBMQVRFLCB0eXBlb2YgbmFtZSA9PSAnc3RyaW5nJyA/IG5hbWUgOiAnJyk7XG4gIH0gcmV0dXJuIHZhbHVlO1xufTtcblxuLy8gYWRkIGZha2UgRnVuY3Rpb24jdG9TdHJpbmcgZm9yIGNvcnJlY3Qgd29yayB3cmFwcGVkIG1ldGhvZHMgLyBjb25zdHJ1Y3RvcnMgd2l0aCBtZXRob2RzIGxpa2UgTG9EYXNoIGlzTmF0aXZlXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZXh0ZW5kLW5hdGl2ZSAtLSByZXF1aXJlZFxuRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nID0gbWFrZUJ1aWx0SW4oZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gIHJldHVybiBpc0NhbGxhYmxlKHRoaXMpICYmIGdldEludGVybmFsU3RhdGUodGhpcykuc291cmNlIHx8IGluc3BlY3RTb3VyY2UodGhpcyk7XG59LCAndG9TdHJpbmcnKTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9kZXNjcmlwdG9ycycpO1xudmFyIElFOF9ET01fREVGSU5FID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2llOC1kb20tZGVmaW5lJyk7XG52YXIgVjhfUFJPVE9UWVBFX0RFRklORV9CVUcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdjgtcHJvdG90eXBlLWRlZmluZS1idWcnKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcbnZhciB0b1Byb3BlcnR5S2V5ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXByb3BlcnR5LWtleScpO1xuXG52YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZVxudmFyICRkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmVcbnZhciAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcbnZhciBFTlVNRVJBQkxFID0gJ2VudW1lcmFibGUnO1xudmFyIENPTkZJR1VSQUJMRSA9ICdjb25maWd1cmFibGUnO1xudmFyIFdSSVRBQkxFID0gJ3dyaXRhYmxlJztcblxuLy8gYE9iamVjdC5kZWZpbmVQcm9wZXJ0eWAgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5kZWZpbmVwcm9wZXJ0eVxuZXhwb3J0cy5mID0gREVTQ1JJUFRPUlMgPyBWOF9QUk9UT1RZUEVfREVGSU5FX0JVRyA/IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1Byb3BlcnR5S2V5KFApO1xuICBhbk9iamVjdChBdHRyaWJ1dGVzKTtcbiAgaWYgKHR5cGVvZiBPID09PSAnZnVuY3Rpb24nICYmIFAgPT09ICdwcm90b3R5cGUnICYmICd2YWx1ZScgaW4gQXR0cmlidXRlcyAmJiBXUklUQUJMRSBpbiBBdHRyaWJ1dGVzICYmICFBdHRyaWJ1dGVzW1dSSVRBQkxFXSkge1xuICAgIHZhciBjdXJyZW50ID0gJGdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKTtcbiAgICBpZiAoY3VycmVudCAmJiBjdXJyZW50W1dSSVRBQkxFXSkge1xuICAgICAgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gICAgICBBdHRyaWJ1dGVzID0ge1xuICAgICAgICBjb25maWd1cmFibGU6IENPTkZJR1VSQUJMRSBpbiBBdHRyaWJ1dGVzID8gQXR0cmlidXRlc1tDT05GSUdVUkFCTEVdIDogY3VycmVudFtDT05GSUdVUkFCTEVdLFxuICAgICAgICBlbnVtZXJhYmxlOiBFTlVNRVJBQkxFIGluIEF0dHJpYnV0ZXMgPyBBdHRyaWJ1dGVzW0VOVU1FUkFCTEVdIDogY3VycmVudFtFTlVNRVJBQkxFXSxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlXG4gICAgICB9O1xuICAgIH1cbiAgfSByZXR1cm4gJGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpO1xufSA6ICRkZWZpbmVQcm9wZXJ0eSA6IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1Byb3BlcnR5S2V5KFApO1xuICBhbk9iamVjdChBdHRyaWJ1dGVzKTtcbiAgaWYgKElFOF9ET01fREVGSU5FKSB0cnkge1xuICAgIHJldHVybiAkZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJ0FjY2Vzc29ycyBub3Qgc3VwcG9ydGVkJyk7XG4gIGlmICgndmFsdWUnIGluIEF0dHJpYnV0ZXMpIE9bUF0gPSBBdHRyaWJ1dGVzLnZhbHVlO1xuICByZXR1cm4gTztcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgdW5jdXJyeVRoaXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZnVuY3Rpb24tdW5jdXJyeS10aGlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gdW5jdXJyeVRoaXMoe30uaXNQcm90b3R5cGVPZik7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydCcpO1xudmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvY2xhc3NvZicpO1xuXG4vLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kIGltcGxlbWVudGF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmdcbm1vZHVsZS5leHBvcnRzID0gVE9fU1RSSU5HX1RBR19TVVBQT1JUID8ge30udG9TdHJpbmcgOiBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgcmV0dXJuICdbb2JqZWN0ICcgKyBjbGFzc29mKHRoaXMpICsgJ10nO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjYWxsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLWNhbGwnKTtcbnZhciBpc0NhbGxhYmxlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLWNhbGxhYmxlJyk7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaXMtb2JqZWN0Jyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xuXG4vLyBgT3JkaW5hcnlUb1ByaW1pdGl2ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9yZGluYXJ5dG9wcmltaXRpdmVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGlucHV0LCBwcmVmKSB7XG4gIHZhciBmbiwgdmFsO1xuICBpZiAocHJlZiA9PT0gJ3N0cmluZycgJiYgaXNDYWxsYWJsZShmbiA9IGlucHV0LnRvU3RyaW5nKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKGlzQ2FsbGFibGUoZm4gPSBpbnB1dC52YWx1ZU9mKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKHByZWYgIT09ICdzdHJpbmcnICYmIGlzQ2FsbGFibGUoZm4gPSBpbnB1dC50b1N0cmluZykgJiYgIWlzT2JqZWN0KHZhbCA9IGNhbGwoZm4sIGlucHV0KSkpIHJldHVybiB2YWw7XG4gIHRocm93IG5ldyAkVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcblxuLy8gYFJlZ0V4cC5wcm90b3R5cGUuZmxhZ3NgIGdldHRlciBpbXBsZW1lbnRhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXQtcmVnZXhwLnByb3RvdHlwZS5mbGFnc1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciB0aGF0ID0gYW5PYmplY3QodGhpcyk7XG4gIHZhciByZXN1bHQgPSAnJztcbiAgaWYgKHRoYXQuaGFzSW5kaWNlcykgcmVzdWx0ICs9ICdkJztcbiAgaWYgKHRoYXQuZ2xvYmFsKSByZXN1bHQgKz0gJ2cnO1xuICBpZiAodGhhdC5pZ25vcmVDYXNlKSByZXN1bHQgKz0gJ2knO1xuICBpZiAodGhhdC5tdWx0aWxpbmUpIHJlc3VsdCArPSAnbSc7XG4gIGlmICh0aGF0LmRvdEFsbCkgcmVzdWx0ICs9ICdzJztcbiAgaWYgKHRoYXQudW5pY29kZSkgcmVzdWx0ICs9ICd1JztcbiAgaWYgKHRoYXQudW5pY29kZVNldHMpIHJlc3VsdCArPSAndic7XG4gIGlmICh0aGF0LnN0aWNreSkgcmVzdWx0ICs9ICd5JztcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgY2FsbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9mdW5jdGlvbi1jYWxsJyk7XG52YXIgaGFzT3duID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2hhcy1vd24tcHJvcGVydHknKTtcbnZhciBpc1Byb3RvdHlwZU9mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL29iamVjdC1pcy1wcm90b3R5cGUtb2YnKTtcbnZhciByZWdFeHBGbGFncyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWdleHAtZmxhZ3MnKTtcblxudmFyIFJlZ0V4cFByb3RvdHlwZSA9IFJlZ0V4cC5wcm90b3R5cGU7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFIpIHtcbiAgdmFyIGZsYWdzID0gUi5mbGFncztcbiAgcmV0dXJuIGZsYWdzID09PSB1bmRlZmluZWQgJiYgISgnZmxhZ3MnIGluIFJlZ0V4cFByb3RvdHlwZSkgJiYgIWhhc093bihSLCAnZmxhZ3MnKSAmJiBpc1Byb3RvdHlwZU9mKFJlZ0V4cFByb3RvdHlwZSwgUilcbiAgICA/IGNhbGwocmVnRXhwRmxhZ3MsIFIpIDogZmxhZ3M7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2lzLW51bGwtb3ItdW5kZWZpbmVkJyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xuXG4vLyBgUmVxdWlyZU9iamVjdENvZXJjaWJsZWAgYWJzdHJhY3Qgb3BlcmF0aW9uXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXJlcXVpcmVvYmplY3Rjb2VyY2libGVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIGlmIChpc051bGxPclVuZGVmaW5lZChpdCkpIHRocm93IG5ldyAkVHlwZUVycm9yKFwiQ2FuJ3QgY2FsbCBtZXRob2Qgb24gXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgc2hhcmVkID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3NoYXJlZCcpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91aWQnKTtcblxudmFyIGtleXMgPSBzaGFyZWQoJ2tleXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiBrZXlzW2tleV0gfHwgKGtleXNba2V5XSA9IHVpZChrZXkpKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgSVNfUFVSRSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1wdXJlJyk7XG52YXIgZ2xvYmFsVGhpcyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9nbG9iYWwnKTtcbnZhciBkZWZpbmVHbG9iYWxQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9kZWZpbmUtZ2xvYmFsLXByb3BlcnR5Jyk7XG5cbnZhciBTSEFSRUQgPSAnX19jb3JlLWpzX3NoYXJlZF9fJztcbnZhciBzdG9yZSA9IG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsVGhpc1tTSEFSRURdIHx8IGRlZmluZUdsb2JhbFByb3BlcnR5KFNIQVJFRCwge30pO1xuXG4oc3RvcmUudmVyc2lvbnMgfHwgKHN0b3JlLnZlcnNpb25zID0gW10pKS5wdXNoKHtcbiAgdmVyc2lvbjogJzMuMzcuMScsXG4gIG1vZGU6IElTX1BVUkUgPyAncHVyZScgOiAnZ2xvYmFsJyxcbiAgY29weXJpZ2h0OiAnwqkgMjAxNC0yMDI0IERlbmlzIFB1c2hrYXJldiAoemxvaXJvY2sucnUpJyxcbiAgbGljZW5zZTogJ2h0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2Jsb2IvdjMuMzcuMS9MSUNFTlNFJyxcbiAgc291cmNlOiAnaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMnXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBzdG9yZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQtc3RvcmUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICByZXR1cm4gc3RvcmVba2V5XSB8fCAoc3RvcmVba2V5XSA9IHZhbHVlIHx8IHt9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vKiBlc2xpbnQtZGlzYWJsZSBlcy9uby1zeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbnZhciBWOF9WRVJTSU9OID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2VuZ2luZS12OC12ZXJzaW9uJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG5cbnZhciAkU3RyaW5nID0gZ2xvYmFsLlN0cmluZztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eXN5bWJvbHMgLS0gcmVxdWlyZWQgZm9yIHRlc3Rpbmdcbm1vZHVsZS5leHBvcnRzID0gISFPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzICYmICFmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHZhciBzeW1ib2wgPSBTeW1ib2woJ3N5bWJvbCBkZXRlY3Rpb24nKTtcbiAgLy8gQ2hyb21lIDM4IFN5bWJvbCBoYXMgaW5jb3JyZWN0IHRvU3RyaW5nIGNvbnZlcnNpb25cbiAgLy8gYGdldC1vd24tcHJvcGVydHktc3ltYm9sc2AgcG9seWZpbGwgc3ltYm9scyBjb252ZXJ0ZWQgdG8gb2JqZWN0IGFyZSBub3QgU3ltYm9sIGluc3RhbmNlc1xuICAvLyBuYjogRG8gbm90IGNhbGwgYFN0cmluZ2AgZGlyZWN0bHkgdG8gYXZvaWQgdGhpcyBiZWluZyBvcHRpbWl6ZWQgb3V0IHRvIGBzeW1ib2wrJydgIHdoaWNoIHdpbGwsXG4gIC8vIG9mIGNvdXJzZSwgZmFpbC5cbiAgcmV0dXJuICEkU3RyaW5nKHN5bWJvbCkgfHwgIShPYmplY3Qoc3ltYm9sKSBpbnN0YW5jZW9mIFN5bWJvbCkgfHxcbiAgICAvLyBDaHJvbWUgMzgtNDAgc3ltYm9scyBhcmUgbm90IGluaGVyaXRlZCBmcm9tIERPTSBjb2xsZWN0aW9ucyBwcm90b3R5cGVzIHRvIGluc3RhbmNlc1xuICAgICFTeW1ib2wuc2hhbSAmJiBWOF9WRVJTSU9OICYmIFY4X1ZFUlNJT04gPCA0MTtcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHJlcXVpcmVPYmplY3RDb2VyY2libGUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvcmVxdWlyZS1vYmplY3QtY29lcmNpYmxlJyk7XG5cbnZhciAkT2JqZWN0ID0gT2JqZWN0O1xuXG4vLyBgVG9PYmplY3RgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b29iamVjdFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgcmV0dXJuICRPYmplY3QocmVxdWlyZU9iamVjdENvZXJjaWJsZShhcmd1bWVudCkpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjYWxsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLWNhbGwnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1vYmplY3QnKTtcbnZhciBpc1N5bWJvbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1zeW1ib2wnKTtcbnZhciBnZXRNZXRob2QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2V0LW1ldGhvZCcpO1xudmFyIG9yZGluYXJ5VG9QcmltaXRpdmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb3JkaW5hcnktdG8tcHJpbWl0aXZlJyk7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG5cbnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yO1xudmFyIFRPX1BSSU1JVElWRSA9IHdlbGxLbm93blN5bWJvbCgndG9QcmltaXRpdmUnKTtcblxuLy8gYFRvUHJpbWl0aXZlYCBhYnN0cmFjdCBvcGVyYXRpb25cbi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9wcmltaXRpdmVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGlucHV0LCBwcmVmKSB7XG4gIGlmICghaXNPYmplY3QoaW5wdXQpIHx8IGlzU3ltYm9sKGlucHV0KSkgcmV0dXJuIGlucHV0O1xuICB2YXIgZXhvdGljVG9QcmltID0gZ2V0TWV0aG9kKGlucHV0LCBUT19QUklNSVRJVkUpO1xuICB2YXIgcmVzdWx0O1xuICBpZiAoZXhvdGljVG9QcmltKSB7XG4gICAgaWYgKHByZWYgPT09IHVuZGVmaW5lZCkgcHJlZiA9ICdkZWZhdWx0JztcbiAgICByZXN1bHQgPSBjYWxsKGV4b3RpY1RvUHJpbSwgaW5wdXQsIHByZWYpO1xuICAgIGlmICghaXNPYmplY3QocmVzdWx0KSB8fCBpc1N5bWJvbChyZXN1bHQpKSByZXR1cm4gcmVzdWx0O1xuICAgIHRocm93IG5ldyAkVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xuICB9XG4gIGlmIChwcmVmID09PSB1bmRlZmluZWQpIHByZWYgPSAnbnVtYmVyJztcbiAgcmV0dXJuIG9yZGluYXJ5VG9QcmltaXRpdmUoaW5wdXQsIHByZWYpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciB0b1ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy90by1wcmltaXRpdmUnKTtcbnZhciBpc1N5bWJvbCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1zeW1ib2wnKTtcblxuLy8gYFRvUHJvcGVydHlLZXlgIGFic3RyYWN0IG9wZXJhdGlvblxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b3Byb3BlcnR5a2V5XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkge1xuICB2YXIga2V5ID0gdG9QcmltaXRpdmUoYXJndW1lbnQsICdzdHJpbmcnKTtcbiAgcmV0dXJuIGlzU3ltYm9sKGtleSkgPyBrZXkgOiBrZXkgKyAnJztcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgd2VsbEtub3duU3ltYm9sID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3dlbGwta25vd24tc3ltYm9sJyk7XG5cbnZhciBUT19TVFJJTkdfVEFHID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpO1xudmFyIHRlc3QgPSB7fTtcblxudGVzdFtUT19TVFJJTkdfVEFHXSA9ICd6JztcblxubW9kdWxlLmV4cG9ydHMgPSBTdHJpbmcodGVzdCkgPT09ICdbb2JqZWN0IHpdJztcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjbGFzc29mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2NsYXNzb2YnKTtcblxudmFyICRTdHJpbmcgPSBTdHJpbmc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7XG4gIGlmIChjbGFzc29mKGFyZ3VtZW50KSA9PT0gJ1N5bWJvbCcpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IGEgU3ltYm9sIHZhbHVlIHRvIGEgc3RyaW5nJyk7XG4gIHJldHVybiAkU3RyaW5nKGFyZ3VtZW50KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJFN0cmluZyA9IFN0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gJFN0cmluZyhhcmd1bWVudCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuICdPYmplY3QnO1xuICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHVuY3VycnlUaGlzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLXVuY3VycnktdGhpcycpO1xuXG52YXIgaWQgPSAwO1xudmFyIHBvc3RmaXggPSBNYXRoLnJhbmRvbSgpO1xudmFyIHRvU3RyaW5nID0gdW5jdXJyeVRoaXMoMS4wLnRvU3RyaW5nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiAnU3ltYm9sKCcgKyAoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSkgKyAnKV8nICsgdG9TdHJpbmcoKytpZCArIHBvc3RmaXgsIDM2KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vKiBlc2xpbnQtZGlzYWJsZSBlcy9uby1zeW1ib2wgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcgKi9cbnZhciBOQVRJVkVfU1lNQk9MID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N5bWJvbC1jb25zdHJ1Y3Rvci1kZXRlY3Rpb24nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfU1lNQk9MXG4gICYmICFTeW1ib2wuc2hhbVxuICAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnO1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Rlc2NyaXB0b3JzJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcblxuLy8gVjggfiBDaHJvbWUgMzYtXG4vLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0zMzM0XG5tb2R1bGUuZXhwb3J0cyA9IERFU0NSSVBUT1JTICYmIGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSByZXF1aXJlZCBmb3IgdGVzdGluZ1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfSwgJ3Byb3RvdHlwZScsIHtcbiAgICB2YWx1ZTogNDIsXG4gICAgd3JpdGFibGU6IGZhbHNlXG4gIH0pLnByb3RvdHlwZSAhPT0gNDI7XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZ2xvYmFsJyk7XG52YXIgaXNDYWxsYWJsZSA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9pcy1jYWxsYWJsZScpO1xuXG52YXIgV2Vha01hcCA9IGdsb2JhbC5XZWFrTWFwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzQ2FsbGFibGUoV2Vha01hcCkgJiYgL25hdGl2ZSBjb2RlLy50ZXN0KFN0cmluZyhXZWFrTWFwKSk7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2dsb2JhbCcpO1xudmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9zaGFyZWQnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvaGFzLW93bi1wcm9wZXJ0eScpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91aWQnKTtcbnZhciBOQVRJVkVfU1lNQk9MID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3N5bWJvbC1jb25zdHJ1Y3Rvci1kZXRlY3Rpb24nKTtcbnZhciBVU0VfU1lNQk9MX0FTX1VJRCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy91c2Utc3ltYm9sLWFzLXVpZCcpO1xuXG52YXIgU3ltYm9sID0gZ2xvYmFsLlN5bWJvbDtcbnZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpO1xudmFyIGNyZWF0ZVdlbGxLbm93blN5bWJvbCA9IFVTRV9TWU1CT0xfQVNfVUlEID8gU3ltYm9sWydmb3InXSB8fCBTeW1ib2wgOiBTeW1ib2wgJiYgU3ltYm9sLndpdGhvdXRTZXR0ZXIgfHwgdWlkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gIGlmICghaGFzT3duKFdlbGxLbm93blN5bWJvbHNTdG9yZSwgbmFtZSkpIHtcbiAgICBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPSBOQVRJVkVfU1lNQk9MICYmIGhhc093bihTeW1ib2wsIG5hbWUpXG4gICAgICA/IFN5bWJvbFtuYW1lXVxuICAgICAgOiBjcmVhdGVXZWxsS25vd25TeW1ib2woJ1N5bWJvbC4nICsgbmFtZSk7XG4gIH0gcmV0dXJuIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vLyBUT0RPOiBSZW1vdmUgZnJvbSBgY29yZS1qc0A0YFxudmFyIHVuY3VycnlUaGlzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLXVuY3VycnktdGhpcycpO1xudmFyIGRlZmluZUJ1aWx0SW4gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVmaW5lLWJ1aWx0LWluJyk7XG5cbnZhciBEYXRlUHJvdG90eXBlID0gRGF0ZS5wcm90b3R5cGU7XG52YXIgSU5WQUxJRF9EQVRFID0gJ0ludmFsaWQgRGF0ZSc7XG52YXIgVE9fU1RSSU5HID0gJ3RvU3RyaW5nJztcbnZhciBuYXRpdmVEYXRlVG9TdHJpbmcgPSB1bmN1cnJ5VGhpcyhEYXRlUHJvdG90eXBlW1RPX1NUUklOR10pO1xudmFyIHRoaXNUaW1lVmFsdWUgPSB1bmN1cnJ5VGhpcyhEYXRlUHJvdG90eXBlLmdldFRpbWUpO1xuXG4vLyBgRGF0ZS5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1kYXRlLnByb3RvdHlwZS50b3N0cmluZ1xuaWYgKFN0cmluZyhuZXcgRGF0ZShOYU4pKSAhPT0gSU5WQUxJRF9EQVRFKSB7XG4gIGRlZmluZUJ1aWx0SW4oRGF0ZVByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICB2YXIgdmFsdWUgPSB0aGlzVGltZVZhbHVlKHRoaXMpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWNvbXBhcmUgLS0gTmFOIGNoZWNrXG4gICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSA/IG5hdGl2ZURhdGVUb1N0cmluZyh0aGlzKSA6IElOVkFMSURfREFURTtcbiAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG52YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL3RvLXN0cmluZy10YWctc3VwcG9ydCcpO1xudmFyIGRlZmluZUJ1aWx0SW4gPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZGVmaW5lLWJ1aWx0LWluJyk7XG52YXIgdG9TdHJpbmcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvb2JqZWN0LXRvLXN0cmluZycpO1xuXG4vLyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AgbWV0aG9kXG4vLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmdcbmlmICghVE9fU1RSSU5HX1RBR19TVVBQT1JUKSB7XG4gIGRlZmluZUJ1aWx0SW4oT2JqZWN0LnByb3RvdHlwZSwgJ3RvU3RyaW5nJywgdG9TdHJpbmcsIHsgdW5zYWZlOiB0cnVlIH0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIFBST1BFUl9GVU5DVElPTl9OQU1FID0gcmVxdWlyZSgnLi4vaW50ZXJuYWxzL2Z1bmN0aW9uLW5hbWUnKS5QUk9QRVI7XG52YXIgZGVmaW5lQnVpbHRJbiA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9kZWZpbmUtYnVpbHQtaW4nKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9hbi1vYmplY3QnKTtcbnZhciAkdG9TdHJpbmcgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvdG8tc3RyaW5nJyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbHMvZmFpbHMnKTtcbnZhciBnZXRSZWdFeHBGbGFncyA9IHJlcXVpcmUoJy4uL2ludGVybmFscy9yZWdleHAtZ2V0LWZsYWdzJyk7XG5cbnZhciBUT19TVFJJTkcgPSAndG9TdHJpbmcnO1xudmFyIFJlZ0V4cFByb3RvdHlwZSA9IFJlZ0V4cC5wcm90b3R5cGU7XG52YXIgbmF0aXZlVG9TdHJpbmcgPSBSZWdFeHBQcm90b3R5cGVbVE9fU1RSSU5HXTtcblxudmFyIE5PVF9HRU5FUklDID0gZmFpbHMoZnVuY3Rpb24gKCkgeyByZXR1cm4gbmF0aXZlVG9TdHJpbmcuY2FsbCh7IHNvdXJjZTogJ2EnLCBmbGFnczogJ2InIH0pICE9PSAnL2EvYic7IH0pO1xuLy8gRkY0NC0gUmVnRXhwI3RvU3RyaW5nIGhhcyBhIHdyb25nIG5hbWVcbnZhciBJTkNPUlJFQ1RfTkFNRSA9IFBST1BFUl9GVU5DVElPTl9OQU1FICYmIG5hdGl2ZVRvU3RyaW5nLm5hbWUgIT09IFRPX1NUUklORztcblxuLy8gYFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmdgIG1ldGhvZFxuLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG5pZiAoTk9UX0dFTkVSSUMgfHwgSU5DT1JSRUNUX05BTUUpIHtcbiAgZGVmaW5lQnVpbHRJbihSZWdFeHBQcm90b3R5cGUsIFRPX1NUUklORywgZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgdmFyIFIgPSBhbk9iamVjdCh0aGlzKTtcbiAgICB2YXIgcGF0dGVybiA9ICR0b1N0cmluZyhSLnNvdXJjZSk7XG4gICAgdmFyIGZsYWdzID0gJHRvU3RyaW5nKGdldFJlZ0V4cEZsYWdzKFIpKTtcbiAgICByZXR1cm4gJy8nICsgcGF0dGVybiArICcvJyArIGZsYWdzO1xuICB9LCB7IHVuc2FmZTogdHJ1ZSB9KTtcbn1cbiIsInZhciBnO1xuXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxuZyA9IChmdW5jdGlvbigpIHtcblx0cmV0dXJuIHRoaXM7XG59KSgpO1xuXG50cnkge1xuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcblx0ZyA9IGcgfHwgbmV3IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKTtcbn0gY2F0Y2ggKGUpIHtcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcblx0aWYgKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpIGcgPSB3aW5kb3c7XG59XG5cbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XG5cbm1vZHVsZS5leHBvcnRzID0gZztcbiJdLCJzb3VyY2VSb290IjoiIn0=