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